summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Norbye <tnorbye@google.com>2014-08-19 22:27:03 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2014-08-19 21:25:05 +0000
commit4ca751c002784c4bfd349cc5240b045b62277c80 (patch)
treedfc17b31990e2429535609b85f6d080c4fa0d9fe
parent890d9a2952301682ffecaed4495f5f65c84c3642 (diff)
parent060e58b3afea3ea39f5ba1cb5a443ca3ebda28c8 (diff)
downloadidea-4ca751c002784c4bfd349cc5240b045b62277c80.tar.gz
Merge "Merge remote-tracking branch 'aosp/upstream-master' into merge"
-rwxr-xr-x.idea/codeStyleSettings.xml7
-rw-r--r--.idea/libraries/Kryo.xml14
-rw-r--r--.idea/modules.xml4
-rw-r--r--RegExpSupport/src/org/intellij/lang/regexp/RegExpFile.java27
-rw-r--r--bin/win/runnerw.exebin106088 -> 99840 bytes
-rw-r--r--build/conf/nsis/DeleteSettings.ini30
-rw-r--r--build/conf/nsis/UninstallOldVersions.ini114
-rw-r--r--build/conf/nsis/idea.nsi84
-rw-r--r--build/conf/nsis/idea_en.nsi11
-rw-r--r--build/scripts/common_tests.gant1
-rw-r--r--build/scripts/layouts.gant15
-rw-r--r--build/scripts/libLicenses.gant4
-rw-r--r--build/scripts/tests.gant1
-rw-r--r--build/scripts/utils.gant19
-rw-r--r--colorSchemes/src/colorSchemes/Darcula.xml8
-rw-r--r--java/compiler/impl/compiler-impl.iml1
-rw-r--r--java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java8
-rw-r--r--java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactUtil.java31
-rw-r--r--java/compiler/impl/src/org/jetbrains/builtInWebServer/ArtifactWebServerRootsProvider.java39
-rw-r--r--java/compiler/javac2/src/com/intellij/ant/Javac2.java2
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/actions/CustomizeContextViewAction.java28
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessEvents.java30
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/engine/JavaBreakpointHandler.java19
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/engine/JavaExecutionStack.java7
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/engine/JavaStackFrame.java23
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/engine/JavaValueMarker.java3
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/engine/SuspendManagerImpl.java16
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/MethodEvaluator.java21
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/impl/DebuggerManagerImpl.java4
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/impl/JavaEditorTextProviderImpl.java4
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/settings/CompoundRendererConfigurable.java139
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/settings/DebuggerLaunchingConfigurable.java39
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/settings/DebuggerSteppingConfigurable.java59
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/settings/JavaDebuggerSettings.java59
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/settings/JavaHotSwapConfigurableUi.java (renamed from java/debugger/impl/src/com/intellij/debugger/settings/DebuggerHotswapConfigurable.java)45
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/settings/UserRenderersConfigurable.java130
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/ui/DebuggerPanelsManager.java2
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/ui/JavaDebuggerSupport.java38
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/ui/XBreakpointGroupingByPackageRule.java2
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/AnyExceptionBreakpoint.java2
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/Breakpoint.java17
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointWithHighlighter.java10
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/ExceptionBreakpoint.java2
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointTypeBase.java2
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/RunToCursorBreakpoint.java5
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/WildcardMethodBreakpoint.java2
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ValueDescriptorImpl.java8
-rw-r--r--java/execution/impl/src/com/intellij/execution/application/ApplicationConfigurable.java2
-rw-r--r--java/execution/impl/src/com/intellij/execution/application/ApplicationConfiguration.java9
-rw-r--r--java/execution/impl/src/com/intellij/execution/impl/DefaultJavaProgramRunner.java3
-rw-r--r--java/idea-ui/src/com/intellij/ide/projectWizard/NewProjectWizard.java1
-rw-r--r--java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypeStep.java4
-rw-r--r--java/idea-ui/src/com/intellij/ide/util/newProjectWizard/impl/FrameworkSupportModelBase.java2
-rw-r--r--java/idea-ui/src/com/intellij/ide/util/projectWizard/NamePathComponent.java57
-rw-r--r--java/idea-ui/src/com/intellij/openapi/projectRoots/ui/SdkEditor.java11
-rw-r--r--java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/JavaContentEntriesEditor.java4
-rw-r--r--java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModulesConfigurator.form8
-rw-r--r--java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectConfigurable.java8
-rw-r--r--java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectJdksConfigurable.java5
-rw-r--r--java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectStructureConfigurable.java6
-rw-r--r--java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/SidePanel.java13
-rw-r--r--java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactEditorImpl.java21
-rw-r--r--java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactsEditorImpl.form2
-rw-r--r--java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactsStructureConfigurable.java20
-rw-r--r--java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/LayoutTreeComponent.java5
-rw-r--r--java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/LibraryRootsComponent.java6
-rw-r--r--java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/BaseStructureConfigurable.java3
-rw-r--r--java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/FacetStructureConfigurable.java9
-rw-r--r--java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/FacetsTreeCellRenderer.java12
-rw-r--r--java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ModuleStructureConfigurable.java7
-rw-r--r--java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java26
-rw-r--r--java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java17
-rw-r--r--java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java8
-rw-r--r--java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeLambdaInspection.java14
-rw-r--r--java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/Analysis.java5
-rw-r--r--java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisConverter.java359
-rw-r--r--java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisConverterImpl.java206
-rw-r--r--java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisIndex.java166
-rw-r--r--java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/ClassDataIndexer.java19
-rw-r--r--java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/Contracts.java2
-rw-r--r--java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/Parameters.java19
-rw-r--r--java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/ProjectBytecodeAnalysis.java260
-rw-r--r--java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/Solver.java152
-rw-r--r--java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractInference.java21
-rw-r--r--java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/MethodContract.java14
-rw-r--r--java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java10
-rw-r--r--java/java-analysis-impl/src/com/intellij/codeInspection/xml/DeprecatedClassUsageInspection.java8
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java2
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddMethodQualifierFix.java11
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AnonymousTargetClassPreselectionUtil.java45
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageBaseFix.java9
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/editorActions/CopyPasteReferenceProcessor.java11
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/editorActions/JavaCopyPasteReferenceProcessor.java3
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/MissingCatchBodyFixer.java5
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/PlainEnterProcessor.java20
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/hint/api/impls/MethodParameterInfoHandler.java16
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/intention/impl/FieldFromParameterUtils.java12
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/CastExpressionPostfixTemplate.java10
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IntroduceFieldPostfixTemplate.java10
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IntroduceVariablePostfixTemplate.java10
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/JavaPostfixTemplateProvider.java2
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/JavaPostfixTemplateWithChooser.java42
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NotExpressionPostfixTemplate.java16
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ParenthesizedExpressionPostfixTemplate.java12
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/template/postfix/util/JavaPostfixTemplatesUtils.java10
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/ex/GlobalJavaInspectionContextImpl.java4
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/sameParameterValue/SameParameterValueInspection.java2
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/unusedParameters/UnusedParametersInspection.java2
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/varScopeCanBeNarrowed/FieldCanBeLocalInspection.java10
-rw-r--r--java/java-impl/src/com/intellij/ide/projectView/impl/PackageViewPane.java34
-rw-r--r--java/java-impl/src/com/intellij/ide/util/gotoByName/DefaultClassNavigationContributor.java24
-rw-r--r--java/java-impl/src/com/intellij/openapi/roots/impl/ExcludeCompilerOutputPolicy.java34
-rw-r--r--java/java-impl/src/com/intellij/psi/codeStyle/arrangement/JavaArrangementVisitor.java1
-rw-r--r--java/java-impl/src/com/intellij/psi/impl/search/JspIndexPatternBuilder.java3
-rw-r--r--java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FilePathReferenceProvider.java2
-rw-r--r--java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/MethodPropertyReference.java5
-rw-r--r--java/java-impl/src/com/intellij/refactoring/anonymousToInner/AnonymousToInnerDialog.java29
-rw-r--r--java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java6
-rw-r--r--java/java-impl/src/com/intellij/refactoring/introduceField/BaseExpressionToFieldHandler.java10
-rw-r--r--java/java-impl/src/com/intellij/refactoring/introduceField/LocalToFieldHandler.java8
-rw-r--r--java/java-impl/src/com/intellij/refactoring/rename/RenameJavaMethodProcessor.java14
-rw-r--r--java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java2
-rw-r--r--java/java-impl/src/com/intellij/testIntegration/createTest/MissedTestsDialog.java26
-rw-r--r--java/java-impl/src/com/intellij/usages/impl/rules/JavaUsageTypeProvider.java3
-rw-r--r--java/java-psi-api/src/com/intellij/codeInsight/AnnotationTargetUtil.java136
-rw-r--r--java/java-psi-api/src/com/intellij/codeInsight/AnnotationUtil.java4
-rw-r--r--java/java-psi-api/src/com/intellij/codeInsight/NullableNotNullManager.java72
-rw-r--r--java/java-psi-api/src/com/intellij/psi/GenericsUtil.java3
-rw-r--r--java/java-psi-api/src/com/intellij/psi/infos/MethodCandidateInfo.java8
-rw-r--r--java/java-psi-api/src/com/intellij/psi/util/MethodSignatureUtil.java10
-rw-r--r--java/java-psi-api/src/com/intellij/psi/util/PsiUtil.java5
-rw-r--r--java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java499
-rw-r--r--java/java-psi-impl/src/com/intellij/codeInsight/CustomExceptionHandler.java13
-rw-r--r--java/java-psi-impl/src/com/intellij/codeInsight/ExceptionUtil.java5
-rw-r--r--java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilderBase.java8
-rw-r--r--java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/ParameterNameFoldingManager.java6
-rw-r--r--java/java-psi-impl/src/com/intellij/codeInsight/javadoc/ColorUtil.java14
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/PsiDiamondTypeImpl.java22
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/InheritanceImplUtil.java102
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java132
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java8
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/compiled/StubBuildingVisitor.java49
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiMethodStubImpl.java50
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveCache.java5
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java29
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceVariable.java9
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ExpressionCompatibilityConstraint.java8
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/PsiMethodReferenceCompatibilityConstraint.java10
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaSourceUtil.java38
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/AnnotationParamListElement.java111
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/ClassElement.java52
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/ParameterListElement.java56
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiAnnotationParamListImpl.java26
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiArrayInitializerMemberValueImpl.java69
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiCommaSeparatedListImpl.java85
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiExpressionListImpl.java21
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java46
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiReferenceParameterListImpl.java37
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/TypeParameterListElement.java37
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java15
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/scope/processor/MethodCandidatesProcessor.java2
-rw-r--r--java/java-structure-view/src/com/intellij/ide/structureView/impl/java/PsiMethodTreeElement.java6
-rw-r--r--java/java-tests/testData/codeInsight/clsHighlighting/IDEA127714.java9
-rw-r--r--java/java-tests/testData/codeInsight/clsHighlighting/libs/IDEA127714.jarbin0 -> 1972 bytes
-rw-r--r--java/java-tests/testData/codeInsight/completeStatement/AlreadyCompleteCatch.java12
-rw-r--r--java/java-tests/testData/codeInsight/completeStatement/AlreadyCompleteCatch_after.java12
-rw-r--r--java/java-tests/testData/codeInsight/completion/normal/MulticaretCompletionFromNonPrimaryCaret.java4
-rw-r--r--java/java-tests/testData/codeInsight/completion/smartType/DontSuggestWildcardGenerics-out.java16
-rw-r--r--java/java-tests/testData/codeInsight/completion/smartType/DontSuggestWildcardGenerics.java11
-rw-r--r--java/java-tests/testData/codeInsight/completion/smartTypeSorting/PreferFieldsToConstants.java17
-rw-r--r--java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/PolymorphicTypeCast.java92
-rw-r--r--java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/IDEA128101.java29
-rw-r--r--java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/IDEA128174.java24
-rw-r--r--java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/InferFromConditionalExpressionCondition.java14
-rw-r--r--java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/PrimitiveWrapperConditionInReturnConstraint.java15
-rw-r--r--java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/EffectiveFinal.java16
-rw-r--r--java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/IDEA127765.java19
-rw-r--r--java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/afterOnVarargsPlace.java10
-rw-r--r--java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/beforeOnVarargsPlace.java13
-rw-r--r--java/java-tests/testData/codeInsight/template/postfix/templates/null/singleExclamationIgnored.java5
-rw-r--r--java/java-tests/testData/codeInsight/template/postfix/templates/null/singleExclamationIgnored_after.java5
-rw-r--r--java/java-tests/testData/codeInsight/typing/invalidInitialSyntax_after.java7
-rw-r--r--java/java-tests/testData/codeInsight/typing/invalidInitialSyntax_before.java7
-rw-r--r--java/java-tests/testData/find/findInEditor/BasicFind.gold4
-rw-r--r--java/java-tests/testData/find/findInEditor/EmacsLikeFallback.gold12
-rw-r--r--java/java-tests/testData/find/findInEditor/ReplacementWithEmptyString.gold16
-rw-r--r--java/java-tests/testData/inspection/dataFlow/CheckedExceptionDominance/src/Test.java2
-rw-r--r--java/java-tests/testData/inspection/dataFlow/IDEADEV10489/expected.xml2
-rw-r--r--java/java-tests/testData/inspection/dataFlow/IDEADEV10489/src/IDEADEV10489.java8
-rw-r--r--java/java-tests/testData/inspection/dataFlow/fixture/AssertFailInCatch.java4
-rw-r--r--java/java-tests/testData/inspection/dataFlow/fixture/CatchThrowable.java4
-rw-r--r--java/java-tests/testData/inspection/dataFlow/fixture/ContractWithNoArgs.java24
-rw-r--r--java/java-tests/testData/inspection/dataFlow/fixture/CustomTypeQualifierDefault.java25
-rw-r--r--java/java-tests/testData/inspection/dataFlow/fixture/FloatComparisons.java7
-rw-r--r--java/java-tests/testData/refactoring/renameCollisions/RenameMethodNoCollisionWithOtherSignatureMethodRef.java9
-rw-r--r--java/java-tests/testData/refactoring/renameCollisions/RenameMethodNoCollisionWithOtherSignatureMethodRef.java.after9
-rw-r--r--java/java-tests/testSrc/com/intellij/codeInsight/ClsGenerics18HighlightingTest.java2
-rw-r--r--java/java-tests/testSrc/com/intellij/codeInsight/CompleteStatementTest.java17
-rw-r--r--java/java-tests/testSrc/com/intellij/codeInsight/JavaTypingTest.java9
-rw-r--r--java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy5
-rw-r--r--java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionOrderingTest.groovy4
-rw-r--r--java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java6
-rw-r--r--java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GraphInferenceHighlightingTest.java16
-rw-r--r--java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/MethodRefHighlightingTest.java4
-rw-r--r--java/java-tests/testSrc/com/intellij/codeInsight/folding/JavaFoldingGotoTest.java59
-rw-r--r--java/java-tests/testSrc/com/intellij/codeInsight/folding/JavaFoldingTest.groovy16
-rw-r--r--java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/NullPostfixTemplateTest.java5
-rw-r--r--java/java-tests/testSrc/com/intellij/codeInspection/ContractInferenceFromSourceTest.groovy28
-rw-r--r--java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java38
-rw-r--r--java/java-tests/testSrc/com/intellij/codeInspection/NullableStuffInspectionTest.java11
-rw-r--r--java/java-tests/testSrc/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisTest.java4
-rw-r--r--java/java-tests/testSrc/com/intellij/find/FindInEditorMultiCaretTest.java28
-rw-r--r--java/java-tests/testSrc/com/intellij/find/FindManagerTest.java47
-rw-r--r--java/java-tests/testSrc/com/intellij/navigation/ChooseByNameTest.groovy28
-rw-r--r--java/java-tests/testSrc/com/intellij/openapi/roots/impl/DirectoryIndexTest.java198
-rw-r--r--java/java-tests/testSrc/com/intellij/psi/MiscPsiTest.java16
-rw-r--r--java/java-tests/testSrc/com/intellij/psi/codeStyle/arrangement/JavaRearrangerFieldReferenceTest.groovy24
-rw-r--r--java/java-tests/testSrc/com/intellij/refactoring/RenameCollisionsTest.java4
-rw-r--r--java/java-tests/testSrc/com/intellij/roots/ModuleScopesTest.java31
-rw-r--r--java/java-tests/testSrc/com/intellij/slicer/SliceTreeTest.java3
-rw-r--r--java/jsp-openapi/src/com/intellij/psi/jsp/JavaJspElementVisitor.java3
-rw-r--r--java/openapi/src/com/intellij/ui/classFilter/ClassFilter.java17
-rw-r--r--java/remote-servers/impl/remote-servers-java-impl.iml1
-rw-r--r--java/remote-servers/impl/src/META-INF/RemoteServersJava.xml2
-rw-r--r--java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudApplicationConfigurable.java142
-rw-r--r--java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudApplicationConfiguration.java15
-rw-r--r--java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudModuleBuilder.java64
-rw-r--r--java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudModuleBuilderContribution.java48
-rw-r--r--java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudModuleBuilderContributionBase.java142
-rw-r--r--java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudModuleBuilderContributionFactory.java39
-rw-r--r--java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudModuleBuilderSourceContribution.java191
-rw-r--r--java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudModuleWizardStep.java25
-rw-r--r--java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudSourceApplicationConfigurable.java165
-rw-r--r--java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudSourceApplicationConfiguration.java36
-rw-r--r--java/testFramework/src/com/intellij/debugger/impl/DescriptorTestCase.java29
-rw-r--r--java/testFramework/src/com/intellij/find/FindManagerTestUtils.java6
-rw-r--r--jps/jps-builders/jps-builders.iml1
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Callbacks.java1
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectMultiMaplet.java15
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectPersistentMultiMaplet.java2
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectTransientMultiMaplet.java2
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Mappings.java283
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/ClassProcessingBuilder.java2
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildDataManager.java2
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/jps/builders/JavacFileEncodingTest.kt (renamed from jps/jps-builders/testSrc/org/jetbrains/jps/builders/JavacFileEncodingTest.groovy)7
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/jps/builders/JpsBuildTestCase.java6
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/jps/builders/ModuleClasspathTest.kt98
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/ArtifactRebuildTest.kt (renamed from jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/ArtifactRebuildTest.groovy)70
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/JpsRebuildTestCase.groovy98
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/JpsRebuildTestCase.kt86
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/ModuleRebuildTest.kt (renamed from jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/ModuleRebuildTest.groovy)14
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/PathMacroUtil.java37
-rw-r--r--jps/standalone-builder/src/org/jetbrains/jps/idea/IdeaProjectLoader.java30
-rw-r--r--native/runner/runnerw/.gitignore1
-rw-r--r--native/runner/runnerw/runnerw.cpp80
-rw-r--r--platform/analysis-api/src/com/intellij/codeInspection/ex/ScopeToolState.java9
-rw-r--r--platform/analysis-api/src/com/intellij/codeInspection/reference/RefManager.java1
-rw-r--r--platform/analysis-api/src/com/intellij/codeInspection/ui/OptionAccessor.java10
-rw-r--r--platform/analysis-api/src/com/intellij/problems/WolfTheProblemSolver.java1
-rw-r--r--platform/analysis-api/src/com/intellij/psi/search/GlobalSearchScopesCore.java8
-rw-r--r--platform/analysis-api/src/com/intellij/util/ui/CheckBox.java40
-rw-r--r--platform/analysis-impl/src/com/intellij/codeInspection/ex/InspectionProfileImpl.java50
-rw-r--r--platform/analysis-impl/src/com/intellij/codeInspection/ex/ToolsImpl.java52
-rw-r--r--platform/analysis-impl/src/com/intellij/codeInspection/reference/RefManagerImpl.java5
-rw-r--r--platform/analysis-impl/src/com/intellij/codeInspection/ui/ConventionOptionsPanel.java54
-rw-r--r--platform/core-api/src/com/intellij/ide/caches/FileContent.java2
-rw-r--r--platform/core-api/src/com/intellij/ide/util/PropertiesComponent.java8
-rw-r--r--platform/core-api/src/com/intellij/lexer/DelegateLexer.java2
-rw-r--r--platform/core-api/src/com/intellij/openapi/progress/ProgressManager.java16
-rw-r--r--platform/core-api/src/com/intellij/openapi/roots/FileIndexFacade.java1
-rw-r--r--platform/core-api/src/com/intellij/openapi/vfs/JarFile.java2
-rw-r--r--platform/core-api/src/com/intellij/openapi/vfs/VfsUtilCore.java14
-rw-r--r--platform/core-api/src/com/intellij/psi/PsiInvalidElementAccessException.java2
-rw-r--r--platform/core-impl/src/com/intellij/core/CoreApplicationEnvironment.java6
-rw-r--r--platform/core-impl/src/com/intellij/ide/plugins/PluginDescriptorComparator.java79
-rw-r--r--platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java73
-rw-r--r--platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java58
-rw-r--r--platform/core-impl/src/com/intellij/mock/MockFileIndexFacade.java5
-rw-r--r--platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java59
-rw-r--r--platform/core-impl/src/com/intellij/openapi/editor/impl/RangeMarkerTree.java2
-rw-r--r--platform/core-impl/src/com/intellij/pom/core/impl/PomModelImpl.java17
-rw-r--r--platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java2
-rw-r--r--platform/core-impl/src/com/intellij/psi/impl/PsiToDocumentSynchronizer.java8
-rw-r--r--platform/core-impl/src/com/intellij/psi/impl/source/text/DiffLog.java9
-rw-r--r--platform/core-impl/src/com/intellij/psi/search/ProjectScopeImpl.java3
-rw-r--r--platform/core-impl/src/com/intellij/psi/text/BlockSupport.java2
-rw-r--r--platform/dvcs/src/com/intellij/dvcs/repo/Repository.java3
-rw-r--r--platform/dvcs/src/com/intellij/dvcs/repo/RepositoryImpl.java3
-rw-r--r--platform/dvcs/src/com/intellij/dvcs/repo/RepositoryUtil.java10
-rw-r--r--platform/dvcs/src/com/intellij/dvcs/ui/VcsLogAction.java85
-rw-r--r--platform/dvcs/src/com/intellij/dvcs/ui/VcsLogOneCommitPerRepoAction.java69
-rw-r--r--platform/dvcs/src/com/intellij/dvcs/ui/VcsLogSingleCommitAction.java46
-rw-r--r--platform/editor-ui-api/src/com/intellij/ide/ui/UISettings.java1
-rw-r--r--platform/editor-ui-ex/src/com/intellij/psi/impl/search/LexerEditorHighlighterLexer.java (renamed from platform/lang-impl/src/com/intellij/psi/impl/search/LexerEditorHighlighterLexer.java)36
-rw-r--r--platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DataNode.java12
-rw-r--r--platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DefaultExternalFilter.java62
-rw-r--r--platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DefaultExternalPlugin.java (renamed from platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/SteppingConfigurable.java)33
-rw-r--r--platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DefaultExternalProject.java243
-rw-r--r--platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DefaultExternalSourceDirectorySet.java124
-rw-r--r--platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DefaultExternalSourceSet.java66
-rw-r--r--platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DefaultExternalTask.java86
-rw-r--r--platform/external-system-api/src/com/intellij/openapi/externalSystem/model/ExternalFilter.java34
-rw-r--r--platform/external-system-api/src/com/intellij/openapi/externalSystem/model/ExternalPlugin.java30
-rw-r--r--platform/external-system-api/src/com/intellij/openapi/externalSystem/model/ExternalProject.java87
-rw-r--r--platform/external-system-api/src/com/intellij/openapi/externalSystem/model/ExternalSourceDirectorySet.java (renamed from platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatePsiInfoBase.java)35
-rw-r--r--platform/external-system-api/src/com/intellij/openapi/externalSystem/model/ExternalSourceSet.java39
-rw-r--r--platform/external-system-api/src/com/intellij/openapi/externalSystem/model/ExternalTask.java36
-rw-r--r--platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/ExternalSystemSourceType.java74
-rw-r--r--platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/IExternalSystemSourceType.java32
-rw-r--r--platform/external-system-api/src/com/intellij/openapi/externalSystem/util/ExternalSystemApiUtil.java5
-rw-r--r--platform/external-system-api/src/com/intellij/openapi/externalSystem/util/ExternalSystemConstants.java1
-rw-r--r--platform/external-system-impl/external-system-impl.iml1
-rw-r--r--platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/ProjectStructureServices.java42
-rw-r--r--platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ContentRootDataService.java19
-rw-r--r--platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ModuleDataService.java1
-rw-r--r--platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ProjectDataManager.java21
-rw-r--r--platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/settings/AbstractImportFromExternalSystemControl.java5
-rw-r--r--platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/test/ExternalSystemTestCase.java140
-rw-r--r--platform/icons/src/actions/GroupByFile.pngbin0 -> 266 bytes
-rw-r--r--platform/icons/src/actions/GroupByFile@2x.pngbin0 -> 599 bytes
-rw-r--r--platform/icons/src/actions/GroupByFile@2x_dark.pngbin0 -> 599 bytes
-rw-r--r--platform/icons/src/actions/GroupByFile_dark.pngbin0 -> 266 bytes
-rw-r--r--platform/icons/src/general/projectConfigurableBanner.pngbin0 -> 119 bytes
-rw-r--r--platform/icons/src/general/projectConfigurableBanner@2x.pngbin0 -> 1019 bytes
-rw-r--r--platform/icons/src/general/projectConfigurableSelected.pngbin0 -> 122 bytes
-rw-r--r--platform/icons/src/general/projectConfigurableSelected@2x.pngbin0 -> 1098 bytes
-rw-r--r--platform/indexing-impl/src/com/intellij/openapi/module/impl/scopes/ModuleWithDependentsScope.java6
-rw-r--r--platform/indexing-impl/src/com/intellij/psi/impl/cache/impl/id/IdTableBuilding.java4
-rw-r--r--platform/indexing-impl/src/com/intellij/psi/impl/file/impl/ResolveScopeManagerImpl.java8
-rw-r--r--platform/lang-api/src/com/intellij/codeInsight/completion/CompletionInitializationContext.java22
-rw-r--r--platform/lang-api/src/com/intellij/codeInsight/completion/CompletionResultSet.java7
-rw-r--r--platform/lang-api/src/com/intellij/codeInsight/lookup/LookupElementBuilder.java36
-rw-r--r--platform/lang-api/src/com/intellij/execution/ui/RunContentDescriptor.java9
-rw-r--r--platform/lang-api/src/com/intellij/find/FindManager.java12
-rw-r--r--platform/lang-api/src/com/intellij/find/FindModel.java107
-rw-r--r--platform/lang-api/src/com/intellij/ide/util/projectWizard/WizardContext.java10
-rw-r--r--platform/lang-api/src/com/intellij/lexer/LexerUtil.java10
-rw-r--r--platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettings.java22
-rw-r--r--platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java1
-rw-r--r--platform/lang-impl/src/com/intellij/application/options/codeStyle/OptionTableWithPreviewPanel.java3
-rw-r--r--platform/lang-impl/src/com/intellij/application/options/codeStyle/RightMarginForm.form44
-rw-r--r--platform/lang-impl/src/com/intellij/application/options/codeStyle/RightMarginForm.java120
-rw-r--r--platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRulesControl.java36
-rw-r--r--platform/lang-impl/src/com/intellij/application/options/editor/EditorTabsConfigurable.form35
-rw-r--r--platform/lang-impl/src/com/intellij/application/options/editor/EditorTabsConfigurable.java26
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java11
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java3
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java47
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/InjectedGeneralHighlightingPass.java2
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/WolfHighlightingPass.java2
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java22
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/editorActions/CopyHandler.java4
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/editorActions/IndentingBackspaceHandler.java90
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/editorActions/TypedHandler.java9
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java45
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/navigation/NavigationUtil.java256
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/problems/MockWolfTheProblemSolver.java5
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/problems/WolfTheProblemSolverImpl.java6
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java7
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/ChooserExpressionSelector.java (renamed from platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/ExpressionPostfixTemplateWithChooser.java)66
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/NotPostfixTemplate.java22
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/ParenthesizedPostfixTemplate.java19
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateExpressionSelector.java54
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatePsiInfo.java35
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateWithExpressionSelector.java83
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatesUtils.java18
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/StatementWrapPostfixTemplate.java6
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/StringBasedPostfixTemplate.java8
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/SurroundPostfixTemplateBase.java12
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/TopmostExpressionSelector.java58
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/TypedPostfixTemplate.java42
-rw-r--r--platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionManagerEx.java2
-rw-r--r--platform/lang-impl/src/com/intellij/execution/ProgramRunnerUtil.java2
-rw-r--r--platform/lang-impl/src/com/intellij/execution/console/ConsoleHistoryController.java63
-rw-r--r--platform/lang-impl/src/com/intellij/execution/console/DuplexConsoleView.java47
-rw-r--r--platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java6
-rw-r--r--platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationBeforeRunProvider.java10
-rw-r--r--platform/lang-impl/src/com/intellij/execution/runners/AbstractConsoleRunnerWithHistory.java76
-rw-r--r--platform/lang-impl/src/com/intellij/execution/runners/RestartAction.java9
-rw-r--r--platform/lang-impl/src/com/intellij/execution/runners/RunContentBuilder.java6
-rw-r--r--platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java11
-rw-r--r--platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java6
-rw-r--r--platform/lang-impl/src/com/intellij/find/FindSettings.java9
-rw-r--r--platform/lang-impl/src/com/intellij/find/FindUtil.java4
-rw-r--r--platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleExceptCommentsAction.java38
-rw-r--r--platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleExceptCommentsAndLiteralsAction.java38
-rw-r--r--platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleExceptLiteralsAction.java38
-rw-r--r--platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleInCommentsAction.java4
-rw-r--r--platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleInLiteralsOnlyAction.java4
-rw-r--r--platform/lang-impl/src/com/intellij/find/findInProject/FindInProjectManager.java11
-rw-r--r--platform/lang-impl/src/com/intellij/find/findUsages/CommonFindUsagesDialog.java11
-rw-r--r--platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesHandler.java5
-rw-r--r--platform/lang-impl/src/com/intellij/find/impl/FindDialog.java91
-rw-r--r--platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java58
-rw-r--r--platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java11
-rw-r--r--platform/lang-impl/src/com/intellij/find/impl/FindManagerImpl.java204
-rw-r--r--platform/lang-impl/src/com/intellij/find/impl/FindResultUsageInfo.java10
-rw-r--r--platform/lang-impl/src/com/intellij/find/impl/FindSettingsImpl.java47
-rw-r--r--platform/lang-impl/src/com/intellij/find/impl/RegExHelpPopup.java39
-rw-r--r--platform/lang-impl/src/com/intellij/formatting/FormatterEx.java11
-rw-r--r--platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java53
-rw-r--r--platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/DetectionExcludesConfigurable.java33
-rw-r--r--platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/InvalidExcludeListItem.java4
-rw-r--r--platform/lang-impl/src/com/intellij/ide/actions/GotoRelatedFileAction.java14
-rw-r--r--platform/lang-impl/src/com/intellij/ide/actions/GotoRelatedSymbolAction.java279
-rw-r--r--platform/lang-impl/src/com/intellij/ide/actions/SearchAgainAction.java5
-rw-r--r--platform/lang-impl/src/com/intellij/ide/actions/SearchBackAction.java5
-rw-r--r--platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java10
-rw-r--r--platform/lang-impl/src/com/intellij/ide/projectView/impl/AbstractProjectViewPane.java23
-rw-r--r--platform/lang-impl/src/com/intellij/ide/todo/ChangeListTodosPanel.java7
-rw-r--r--platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java25
-rw-r--r--platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java144
-rw-r--r--platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNamePopup.java2
-rw-r--r--platform/lang-impl/src/com/intellij/ide/util/gotoByName/DefaultChooseByNameItemProvider.java1
-rw-r--r--platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionItemProvider.java7
-rw-r--r--platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java27
-rw-r--r--platform/lang-impl/src/com/intellij/internal/DumpLookupElementWeights.java8
-rw-r--r--platform/lang-impl/src/com/intellij/lang/parser/GeneratedParserUtilBase.java22
-rw-r--r--platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectAllOccurrencesAction.java7
-rw-r--r--platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectNextOccurrenceAction.java9
-rw-r--r--platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectOccurrencesActionHandler.java21
-rw-r--r--platform/lang-impl/src/com/intellij/openapi/editor/actions/UnselectPreviousOccurrenceAction.java10
-rw-r--r--platform/lang-impl/src/com/intellij/openapi/editor/richcopy/FontMapper.java8
-rw-r--r--platform/lang-impl/src/com/intellij/openapi/editor/richcopy/TextWithMarkupProcessor.java14
-rw-r--r--platform/lang-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexImpl.java150
-rw-r--r--platform/lang-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerComponent.java6
-rw-r--r--platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/DetectedRootsChooserDialog.java41
-rw-r--r--platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/SuggestedChildRootInfo.java7
-rw-r--r--platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/CommonContentEntriesEditor.java41
-rw-r--r--platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentRootPanel.java21
-rw-r--r--platform/lang-impl/src/com/intellij/profile/codeInspection/ui/AddScopeUtil.java117
-rw-r--r--platform/lang-impl/src/com/intellij/profile/codeInspection/ui/AdvancedSettingsAction.java209
-rw-r--r--platform/lang-impl/src/com/intellij/profile/codeInspection/ui/InspectionToolsConfigurable.java4
-rw-r--r--platform/lang-impl/src/com/intellij/profile/codeInspection/ui/LevelChooserAction.java6
-rw-r--r--platform/lang-impl/src/com/intellij/profile/codeInspection/ui/MultiScopeSeverityIcon.java58
-rw-r--r--platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ScopeOrderComparator.java62
-rw-r--r--platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ScopesChooser.java60
-rw-r--r--platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ScopesOrderDialog.java121
-rw-r--r--platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java109
-rw-r--r--platform/lang-impl/src/com/intellij/profile/codeInspection/ui/filter/InspectionFilterAction.java18
-rw-r--r--platform/lang-impl/src/com/intellij/profile/codeInspection/ui/filter/InspectionsFilter.java19
-rw-r--r--platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/InspectionsConfigTreeTable.java70
-rw-r--r--platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/MultiScopeSeverityIcon.java19
-rw-r--r--platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/ScopesAndSeveritiesHintTable.java32
-rw-r--r--platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/ScopesAndSeveritiesTable.java94
-rw-r--r--platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/SeverityRenderer.java31
-rw-r--r--platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/SeverityState.java40
-rw-r--r--platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/ThreeStateCheckBoxRenderer.java22
-rw-r--r--platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerRunnable.java4
-rw-r--r--platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java71
-rw-r--r--platform/lang-impl/src/com/intellij/refactoring/introduce/inplace/KeyboardComboSwitcher.java2
-rw-r--r--platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java1
-rw-r--r--platform/lang-impl/src/com/intellij/util/indexing/ContentHashesSupport.java2
-rw-r--r--platform/lang-impl/src/com/intellij/util/indexing/DebugAssertions.java2
-rw-r--r--platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java51
-rw-r--r--platform/lang-impl/src/com/intellij/util/indexing/IndexingStamp.java2
-rw-r--r--platform/lang-impl/src/com/intellij/util/indexing/MapReduceIndex.java6
-rw-r--r--platform/lang-impl/src/com/intellij/webcore/packaging/ManagePackagesDialog.java18
-rw-r--r--platform/lang-impl/src/com/intellij/webcore/packaging/PackagesNotificationPanel.java58
-rw-r--r--platform/lang-impl/testData/editor/indentingBackspace/beforeBrace-after.java4
-rw-r--r--platform/lang-impl/testData/editor/indentingBackspace/beforeBrace.java5
-rw-r--r--platform/lang-impl/testData/editor/indentingBackspace/spacingInsert-after.java3
-rw-r--r--platform/lang-impl/testData/editor/indentingBackspace/spacingInsert.java4
-rw-r--r--platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart-after.java3
-rw-r--r--platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart.java4
-rw-r--r--platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart2-after.java3
-rw-r--r--platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart2.java4
-rw-r--r--platform/lang-impl/testSources/com/intellij/codeInsight/editorActions/IndentingBackspaceHandlerUncommittedDocumentTest.java52
-rw-r--r--platform/lvcs-impl/src/com/intellij/history/core/Paths.java15
-rw-r--r--platform/platform-api/src/com/intellij/ide/BrowserUtil.java8
-rw-r--r--platform/platform-api/src/com/intellij/ide/browsers/BrowserFamily.java6
-rw-r--r--platform/platform-api/src/com/intellij/ide/browsers/BrowserLauncherAppless.java36
-rw-r--r--platform/platform-api/src/com/intellij/ide/browsers/BrowserSpecificSettings.java6
-rw-r--r--platform/platform-api/src/com/intellij/ide/browsers/chrome/ChromeSettings.java25
-rw-r--r--platform/platform-api/src/com/intellij/ide/browsers/firefox/FirefoxSettingsConfigurable.java16
-rw-r--r--platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java4
-rw-r--r--platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ComboBoxAction.java11
-rw-r--r--platform/platform-api/src/com/intellij/openapi/diff/DiffRequestFactory.java9
-rw-r--r--platform/platform-api/src/com/intellij/openapi/diff/FragmentContent.java14
-rw-r--r--platform/platform-api/src/com/intellij/openapi/diff/MergeRequest.java2
-rw-r--r--platform/platform-api/src/com/intellij/openapi/editor/EditorCopyPasteHelper.java53
-rw-r--r--platform/platform-api/src/com/intellij/openapi/editor/EditorModificationUtil.java97
-rw-r--r--platform/platform-api/src/com/intellij/openapi/editor/LazyRangeMarkerFactory.java263
-rw-r--r--platform/platform-api/src/com/intellij/openapi/editor/actionSystem/DialogAwareDataContext.java54
-rw-r--r--platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorAction.java8
-rw-r--r--platform/platform-api/src/com/intellij/openapi/editor/highlighter/FragmentedEditorHighlighter.java46
-rw-r--r--platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooserDescriptorFactory.java27
-rw-r--r--platform/platform-api/src/com/intellij/openapi/fileEditor/FileEditorManager.java2
-rw-r--r--platform/platform-api/src/com/intellij/openapi/fileEditor/OpenFileDescriptor.java15
-rw-r--r--platform/platform-api/src/com/intellij/openapi/ui/Banner.java20
-rw-r--r--platform/platform-api/src/com/intellij/openapi/ui/ComboBoxTableRenderer.java7
-rw-r--r--platform/platform-api/src/com/intellij/openapi/ui/DetailsComponent.java17
-rw-r--r--platform/platform-api/src/com/intellij/openapi/ui/FixedComboBoxEditor.java16
-rw-r--r--platform/platform-api/src/com/intellij/openapi/ui/MasterDetailsComponent.java14
-rw-r--r--platform/platform-api/src/com/intellij/openapi/ui/NamedConfigurable.java9
-rw-r--r--platform/platform-api/src/com/intellij/openapi/ui/OnePixelDivider.java233
-rw-r--r--platform/platform-api/src/com/intellij/openapi/wm/FocusCommand.java2
-rw-r--r--platform/platform-api/src/com/intellij/ui/AnActionButton.java19
-rw-r--r--platform/platform-api/src/com/intellij/ui/CheckboxTreeAdapter.java (renamed from jps/standalone-builder/src/org/jetbrains/jps/idea/IdeaProjectLoader.groovy)27
-rw-r--r--platform/platform-api/src/com/intellij/ui/CheckboxTreeBase.java266
-rw-r--r--platform/platform-api/src/com/intellij/ui/CheckboxTreeHelper.java (renamed from platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/CheckboxTreeTable.java)223
-rw-r--r--platform/platform-api/src/com/intellij/ui/CheckboxTreeListener.java31
-rw-r--r--platform/platform-api/src/com/intellij/ui/CommonActionsPanel.java5
-rw-r--r--platform/platform-api/src/com/intellij/ui/JBSplitter.java8
-rw-r--r--platform/platform-api/src/com/intellij/ui/OnePixelSplitter.java59
-rw-r--r--platform/platform-api/src/com/intellij/ui/border/CustomLineBorder.java11
-rw-r--r--platform/platform-api/src/com/intellij/ui/table/BaseTableView.java8
-rw-r--r--platform/platform-api/src/com/intellij/ui/table/JBTable.java8
-rw-r--r--platform/platform-api/src/com/intellij/ui/tabs/TabInfo.java9
-rw-r--r--platform/platform-api/src/com/intellij/ui/tabs/impl/DragHelper.java2
-rw-r--r--platform/platform-api/src/com/intellij/ui/tabs/impl/JBEditorTabs.java12
-rw-r--r--platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java22
-rw-r--r--platform/platform-api/src/com/intellij/ui/tabs/impl/TabLabel.java13
-rw-r--r--platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayout.java4
-rw-r--r--platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java33
-rw-r--r--platform/platform-api/src/com/intellij/ui/treeStructure/treetable/TreeTableTree.java4
-rw-r--r--platform/platform-api/src/com/intellij/util/net/HttpConfigurable.java6
-rw-r--r--platform/platform-api/src/com/intellij/util/ui/FormBuilder.java5
-rw-r--r--platform/platform-api/src/org/jetbrains/ide/HttpRequestHandler.java2
-rw-r--r--platform/platform-impl/src/com/intellij/codeInsight/editorActions/TextBlockTransferable.java (renamed from platform/platform-api/src/com/intellij/codeInsight/editorActions/TextBlockTransferable.java)0
-rw-r--r--platform/platform-impl/src/com/intellij/codeInsight/editorActions/TextBlockTransferableData.java (renamed from platform/platform-api/src/com/intellij/codeInsight/editorActions/TextBlockTransferableData.java)0
-rw-r--r--platform/platform-impl/src/com/intellij/execution/DelayedDocumentWatcher.java4
-rw-r--r--platform/platform-impl/src/com/intellij/help/impl/MacHelpUtil.java2
-rw-r--r--platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java20
-rw-r--r--platform/platform-impl/src/com/intellij/ide/IdeRepaintManager.java22
-rw-r--r--platform/platform-impl/src/com/intellij/ide/XmlRpcServerImpl.java6
-rw-r--r--platform/platform-impl/src/com/intellij/ide/actions/ChooseComponentsToExportDialog.java14
-rw-r--r--platform/platform-impl/src/com/intellij/ide/actions/ExportSettingsAction.java40
-rw-r--r--platform/platform-impl/src/com/intellij/ide/actions/ImportSettingsAction.java14
-rw-r--r--platform/platform-impl/src/com/intellij/ide/actions/SendFeedbackAction.java9
-rw-r--r--platform/platform-impl/src/com/intellij/ide/actions/SplitterActionBase.java25
-rw-r--r--platform/platform-impl/src/com/intellij/ide/actions/Switcher.java2
-rw-r--r--platform/platform-impl/src/com/intellij/ide/actions/TabsAlphabeticalModeSwitcher.java5
-rw-r--r--platform/platform-impl/src/com/intellij/ide/actions/UnsplitAllAction.java6
-rw-r--r--platform/platform-impl/src/com/intellij/ide/customize/CustomizeUIThemeStepPanel.java11
-rw-r--r--platform/platform-impl/src/com/intellij/ide/passwordSafe/PasswordStorage.java62
-rw-r--r--platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/PasswordSafeImpl.java37
-rw-r--r--platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/PasswordSafeProvider.java21
-rw-r--r--platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/BasePasswordSafeProvider.java28
-rw-r--r--platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterKeyPasswordSafe.java10
-rw-r--r--platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/memory/MemoryPasswordSafe.java4
-rw-r--r--platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/nil/NilProvider.java13
-rw-r--r--platform/platform-impl/src/com/intellij/ide/passwordSafe/ui/PasswordSafePromptDialog.java23
-rw-r--r--platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java2
-rw-r--r--platform/platform-impl/src/com/intellij/ide/plugins/RepositoryHelper.java2
-rw-r--r--platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java4
-rw-r--r--platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java2
-rw-r--r--platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.properties7
-rw-r--r--platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaCheckBoxMenuItemUI.java81
-rw-r--r--platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaMenuItemUIBase.java208
-rw-r--r--platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaRadioButtonMenuItemUI.java85
-rw-r--r--platform/platform-impl/src/com/intellij/ide/util/ElementsChooser.java611
-rw-r--r--platform/platform-impl/src/com/intellij/ide/util/MultiStateElementsChooser.java692
-rw-r--r--platform/platform-impl/src/com/intellij/internal/statistic/ideSettings/IdeSettingsStatisticsUtils.java29
-rw-r--r--platform/platform-impl/src/com/intellij/notification/impl/ui/NotificationsConfigurablePanel.java20
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/application/ConfigImportHelper.java10
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/application/ConfigImportSettings.java10
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/command/impl/UndoManagerImpl.java5
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/diff/actions/CompareClipboardWithSelection.java3
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/diff/ex/DiffPanelOptions.java15
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java36
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffSplitter.java7
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ui/MergePanel2.java61
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/DiffRequestFactoryImpl.java31
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/MergeRequestImpl.java58
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/CaretStateTransferableData.java (renamed from platform/platform-api/src/com/intellij/openapi/editor/CaretStateTransferableData.java)0
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/ClipboardTextPerCaretSplitter.java (renamed from platform/platform-api/src/com/intellij/openapi/editor/ClipboardTextPerCaretSplitter.java)0
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretAbove.java23
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretActionHandler.java113
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretBelow.java27
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java76
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorCopyPasteHelperImpl.java (renamed from platform/platform-api/src/com/intellij/openapi/editor/CopyPasteSupport.java)114
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java11
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorHighlighterCache.java33
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java132
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java67
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/impl/LazyRangeMarkerFactoryImpl.java323
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/impl/SelectionModelImpl.java2
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java9
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/impl/TrailingSpacesStripper.java (renamed from platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/TrailingSpacesStripper.java)19
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorTabbedContainer.java2
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java19
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java1
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java2
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/NonProjectFileWritingAccessProvider.java8
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorProvider.java27
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeMouseEventDispatcher.java18
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/keymap/impl/KeymapManagerImpl.java4
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/keymap/impl/ModifierKeyDoubleClickHandler.java12
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapPanel.java2
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/options/ConfigurableBase.java46
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/options/ConfigurableUi.java15
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/options/SimpleConfigurable.java52
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/options/TabbedConfigurable.java1
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditor.java4
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsTree.java62
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java17
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java18
-rwxr-xr-xplatform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java19
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/HttpFileSystemBase.java4
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/HttpVirtualFileImpl.java (renamed from platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/VirtualFileImpl.java)9
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/RemoteFileManagerImpl.java22
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarHandler.java20
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/wm/ex/IdeFocusTraversalPolicy.java16
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeGlassPaneImpl.java18
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeadlessManagerImpl.java408
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/wm/impl/X11UiUtil.java36
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/wm/impl/commands/RequestFocusInEditorComponentCmd.java13
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/RecentProjectPanel.java9
-rw-r--r--platform/platform-impl/src/com/intellij/remote/RemoteConnectionCredentialsWrapper.java21
-rw-r--r--platform/platform-impl/src/com/intellij/remote/VagrantSupport.java5
-rw-r--r--platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java1
-rw-r--r--platform/platform-impl/src/com/intellij/ui/AppUIUtil.java6
-rw-r--r--platform/platform-impl/src/com/intellij/ui/BalloonImpl.java5
-rw-r--r--platform/platform-impl/src/com/intellij/ui/CheckboxTree.java9
-rw-r--r--platform/platform-impl/src/com/intellij/ui/CheckboxTreeTable.java47
-rw-r--r--platform/platform-impl/src/com/intellij/ui/JBTabsPaneImpl.java45
-rw-r--r--platform/platform-impl/src/com/intellij/ui/SplitterWithSecondHideable.java7
-rw-r--r--platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java68
-rw-r--r--platform/platform-impl/src/com/intellij/ui/popup/OurHeavyWeightPopup.java35
-rw-r--r--platform/platform-impl/src/com/intellij/ui/popup/PopupComponent.java9
-rw-r--r--platform/platform-impl/src/com/intellij/util/ui/SwingHelper.java92
-rw-r--r--platform/platform-impl/src/org/jetbrains/io/BuiltInServer.java2
-rw-r--r--platform/platform-impl/src/org/jetbrains/io/PortUnificationServerHandler.java2
-rw-r--r--platform/platform-resources-en/src/messages/ActionsBundle.properties6
-rw-r--r--platform/platform-resources-en/src/messages/ApplicationBundle.properties1
-rw-r--r--platform/platform-resources-en/src/messages/CommonBundle.properties1
-rw-r--r--platform/platform-resources-en/src/messages/DiffBundle.properties2
-rw-r--r--platform/platform-resources-en/src/messages/FindBundle.properties9
-rw-r--r--platform/platform-resources-en/src/messages/VcsBundle.properties2
-rw-r--r--platform/platform-resources-en/src/messages/XDebuggerBundle.properties2
-rw-r--r--platform/platform-resources-en/src/messages/XmlBundle.properties3
-rw-r--r--platform/platform-resources/src/META-INF/PlatformExtensions.xml6
-rw-r--r--platform/platform-resources/src/META-INF/XmlPlugin.xml17
-rw-r--r--platform/platform-resources/src/META-INF/xdebugger.xml4
-rw-r--r--platform/platform-resources/src/brokenPlugins.txt11
-rw-r--r--platform/platform-resources/src/idea/Keymap_Default.xml3
-rw-r--r--platform/platform-resources/src/idea/Keymap_EclipseMac.xml4
-rw-r--r--platform/platform-resources/src/idea/PlatformActions.xml1
-rw-r--r--platform/platform-resources/src/idea/VcsActions.xml2
-rw-r--r--platform/platform-tests/testSrc/com/intellij/codeInsight/actions/ReformatFilesWithFiltersTest.java24
-rw-r--r--platform/platform-tests/testSrc/com/intellij/history/core/PathsTest.java5
-rw-r--r--platform/platform-tests/testSrc/com/intellij/lang/PsiBuilderQuickTest.java211
-rw-r--r--platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/EditorCloneCaretAboveBelowTest.java106
-rw-r--r--platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/AbstractEditorTest.java15
-rw-r--r--platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorImplTest.java24
-rw-r--r--platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/RangeMarkerTest.java44
-rw-r--r--platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/StripTrailingSpacesTest.java (renamed from platform/platform-tests/testSrc/com/intellij/openapi/editor/StripTrailingSpacesTest.java)4
-rw-r--r--platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/NonProjectFileAccessTest.java2
-rw-r--r--platform/platform-tests/testSrc/com/intellij/openapi/keymap/impl/ModifierKeyDoubleClickHandlerTest.java40
-rw-r--r--platform/projectModel-api/src/com/intellij/openapi/roots/ProjectFileIndex.java10
-rw-r--r--platform/projectModel-impl/src/com/intellij/ide/projectView/impl/ProjectRootsUtil.java12
-rw-r--r--platform/projectModel-impl/src/com/intellij/openapi/roots/OrderEnumerationHandler.java9
-rw-r--r--platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryIndex.java17
-rw-r--r--platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexExcludePolicy.java4
-rw-r--r--platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryInfo.java17
-rw-r--r--platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryInfoImpl.java149
-rw-r--r--platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ModuleFileIndexImpl.java4
-rw-r--r--platform/projectModel-impl/src/com/intellij/openapi/roots/impl/NonProjectDirectoryInfo.java24
-rw-r--r--platform/projectModel-impl/src/com/intellij/openapi/roots/impl/OrderEnumeratorBase.java32
-rw-r--r--platform/projectModel-impl/src/com/intellij/openapi/roots/impl/OrderRootsEnumeratorImpl.java1
-rw-r--r--platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectFileIndexFacade.java5
-rw-r--r--platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectFileIndexImpl.java7
-rw-r--r--platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerImpl.java5
-rw-r--r--platform/projectModel-impl/src/com/intellij/openapi/roots/impl/RootIndex.java117
-rw-r--r--platform/projectModel-impl/src/com/intellij/openapi/roots/impl/RootModelImpl.java11
-rw-r--r--platform/projectModel-impl/src/com/intellij/openapi/roots/impl/libraries/LibraryImpl.java6
-rw-r--r--platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ServerConnectionManagerImpl.java21
-rw-r--r--platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/ServersToolWindowContent.java24
-rw-r--r--platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudAccountSelectionEditor.java58
-rw-r--r--platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudRunConfigurationUtil.java93
-rwxr-xr-xplatform/script-debugger/backend/src/org/jetbrains/debugger/Breakpoint.java5
-rw-r--r--platform/script-debugger/backend/src/org/jetbrains/debugger/DebugEventAdapter.java2
-rwxr-xr-xplatform/script-debugger/backend/src/org/jetbrains/debugger/DebugEventListener.java2
-rw-r--r--platform/script-debugger/backend/src/org/jetbrains/debugger/VmBase.java1
-rw-r--r--platform/script-debugger/backend/src/org/jetbrains/debugger/sourcemap/SourceMapDecoder.java4
-rw-r--r--platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/LazyVariablesGroup.java33
-rw-r--r--platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/BoxableType.java1
-rw-r--r--platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ClassScope.java4
-rw-r--r--platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/DomainGenerator.java21
-rw-r--r--platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/Generator.java83
-rw-r--r--platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/InputClassScope.java63
-rw-r--r--platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/MemberScope.java2
-rw-r--r--platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/MyCreateStandaloneTypeBindingVisitorBase.java4
-rw-r--r--platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/OutputClassScope.java19
-rw-r--r--platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ParserRootInterfaceItem.java2
-rw-r--r--platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ResolveAndGenerateScope.java2
-rw-r--r--platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TypeData.java47
-rw-r--r--platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TypeDescriptor.java (renamed from platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/QualifiedTypeData.java)25
-rw-r--r--platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonField.java (renamed from platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonField.java)3
-rw-r--r--platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonNullable.java (renamed from platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonNullable.java)2
-rw-r--r--platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonOptionalField.java (renamed from platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonOptionalField.java)2
-rw-r--r--platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonParseMethod.java (renamed from platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonParseMethod.java)2
-rw-r--r--platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonReaders.java2
-rw-r--r--platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonSubtype.java (renamed from platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonSubtype.java)2
-rw-r--r--platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonSubtypeCasting.java (renamed from platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonSubtypeCasting.java)2
-rw-r--r--platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonType.java (renamed from platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonType.java)2
-rw-r--r--platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/FieldProcessor.java5
-rw-r--r--platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/InterfaceReader.java6
-rw-r--r--platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/ReaderRoot.java2
-rw-r--r--platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/TextOutput.java10
-rw-r--r--platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/ValueReader.java6
-rw-r--r--platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ItemDescriptor.java2
-rw-r--r--platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ProtocolMetaModel.java4
-rw-r--r--platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ProtocolSchemaReader.java1
-rw-r--r--platform/smRunner/src/com/intellij/execution/testframework/sm/runner/GeneralToSMTRunnerEventsConvertor.java6
-rw-r--r--platform/smRunner/src/com/intellij/execution/testframework/sm/runner/states/SuiteInProgressState.java3
-rw-r--r--platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/CompiledPattern.java2
-rw-r--r--platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/PatternCompiler.java8
-rw-r--r--platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/EditVarConstraintsDialog.java27
-rw-r--r--platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/SubstitutionShortInfoHandler.java13
-rw-r--r--platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/UIUtil.java43
-rw-r--r--platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/UsageViewContext.java13
-rw-r--r--platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralReplaceTest.java29
-rw-r--r--platform/testFramework/src/com/intellij/FileSetTestCase.java7
-rw-r--r--platform/testFramework/src/com/intellij/GroupBasedTestClassFilter.java9
-rw-r--r--platform/testFramework/src/com/intellij/TestCaseLoader.java36
-rw-r--r--platform/testFramework/src/com/intellij/testFramework/LightPlatformCodeInsightTestCase.java2
-rw-r--r--platform/testFramework/src/com/intellij/testFramework/PlatformTestUtil.java27
-rw-r--r--platform/testFramework/src/com/intellij/testFramework/PsiTestUtil.java4
-rw-r--r--platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java8
-rw-r--r--platform/testFramework/src/com/intellij/testFramework/fixtures/CodeInsightTestFixture.java2
-rw-r--r--platform/testFramework/src/com/intellij/testFramework/fixtures/HeavyIdeaTestFixture.java5
-rw-r--r--platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java56
-rw-r--r--platform/testFramework/src/com/intellij/testFramework/fixtures/impl/HeavyIdeaTestFixtureImpl.java2
-rw-r--r--platform/testFramework/src/com/intellij/util/io/TestFileSystemBuilder.java8
-rw-r--r--platform/testFramework/testSrc/com/intellij/openapi/keymap/KeymapsTestCase.java3
-rw-r--r--platform/testFramework/testSrc/com/intellij/testFramework/vcs/MockChangeListManager.java5
-rw-r--r--platform/usageView/src/com/intellij/usages/ChunkExtractor.java84
-rw-r--r--platform/usageView/src/com/intellij/usages/FindUsagesProcessPresentation.java11
-rw-r--r--platform/usageView/src/com/intellij/usages/TextChunk.java12
-rw-r--r--platform/usageView/src/com/intellij/usages/UsageInfo2UsageAdapter.java51
-rw-r--r--platform/usageView/src/com/intellij/usages/impl/SearchForUsagesRunnable.java64
-rw-r--r--platform/usageView/src/com/intellij/usages/impl/SyntaxHighlighterOverEditorHighlighter.java108
-rw-r--r--platform/usageView/src/com/intellij/usages/impl/UsageViewManagerImpl.java42
-rw-r--r--platform/usageView/src/com/intellij/usages/impl/rules/UsageTypeGroupingRule.java9
-rw-r--r--platform/usageView/usageView.iml1
-rw-r--r--platform/util/resources/misc/registry.properties (renamed from platform/platform-resources-en/src/misc/registry.properties)17
-rw-r--r--platform/util/src/com/intellij/icons/AllIcons.java3
-rw-r--r--platform/util/src/com/intellij/openapi/ui/Divider.java (renamed from plugins/properties/resources/icons/PropertiesIcons.java)22
-rw-r--r--platform/util/src/com/intellij/openapi/ui/Splitter.java10
-rw-r--r--platform/util/src/com/intellij/openapi/util/io/FileUtil.java9
-rw-r--r--platform/util/src/com/intellij/openapi/util/io/win32/IdeaWin32.java2
-rw-r--r--platform/util/src/com/intellij/openapi/util/text/StringUtil.java73
-rw-r--r--platform/util/src/com/intellij/ui/JBColor.java120
-rw-r--r--platform/util/src/com/intellij/util/EventDispatcher.java8
-rw-r--r--platform/util/src/com/intellij/util/PatternUtil.java46
-rw-r--r--platform/util/src/com/intellij/util/ReflectionUtil.java20
-rw-r--r--platform/util/src/com/intellij/util/Restarter.java11
-rw-r--r--platform/util/src/com/intellij/util/containers/ContainerUtil.java1
-rw-r--r--platform/util/src/com/intellij/util/containers/LongStack.java75
-rw-r--r--platform/util/src/com/intellij/util/diff/DiffTree.java8
-rw-r--r--platform/util/src/com/intellij/util/io/LongInlineKeyDescriptor.java (renamed from platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/GeneralConfigurable.java)41
-rw-r--r--platform/util/src/com/intellij/util/text/StringSearcher.java3
-rw-r--r--platform/util/src/com/intellij/util/ui/UIUtil.java8
-rw-r--r--platform/util/src/com/intellij/util/xmlb/XmlSerializerImpl.java13
-rw-r--r--platform/util/testSrc/com/intellij/util/text/StringUtilTest.java19
-rw-r--r--platform/util/testSrc/com/intellij/util/xmlb/XmlSerializerTest.java16
-rw-r--r--platform/util/util.iml1
-rw-r--r--platform/vcs-api/src/com/intellij/openapi/vcs/ProjectLevelVcsManager.java1
-rw-r--r--platform/vcs-api/src/com/intellij/openapi/vcs/changes/ChangeListManager.java1
-rw-r--r--platform/vcs-api/src/com/intellij/openapi/vcs/changes/IgnoredFileBean.java16
-rw-r--r--platform/vcs-api/src/com/intellij/openapi/vcs/changes/VcsDirtyScopeModifier.java4
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerImpl.java183
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerSerialization.java57
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/changes/FragmentedContent.java59
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/changes/FragmentedDiffRequestFromChange.java5
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/changes/IgnoredFilesComponent.java46
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/changes/LocalChangeListImpl.java19
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/changes/PreparedFragmentedContent.java58
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/changes/UpdatingChangeListBuilder.java19
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsDirtyScopeImpl.java11
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsGuess.java2
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ConflictedDiffRequestPresentable.java7
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchAction.java2
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/MergedDiffRequestPresentable.java5
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/FilePathChangesTreeList.java9
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/IgnoredSettingsPanel.java42
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTrackerDrawing.java13
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/ex/RollbackLineStatusAction.java5
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/history/BaseDiffFromHistoryHandler.java197
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/impl/DefaultFileIndexFacade.java5
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ProjectLevelVcsManagerImpl.java16
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/impl/VcsRootIterator.java28
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/impl/projectlevelman/NewMappings.java11
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/roots/VcsRootErrorsFinder.java12
-rw-r--r--platform/vcs-impl/testSrc/com/intellij/openapi/vcs/Executor.java8
-rw-r--r--platform/vcs-impl/testSrc/com/intellij/openapi/vcs/changes/ConvertExcludedToIgnoredTest.java94
-rw-r--r--platform/vcs-impl/vcs-impl.iml1
-rw-r--r--platform/vcs-log/api/src/com/intellij/vcs/log/TimedVcsCommit.java10
-rw-r--r--platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogProvider.java4
-rw-r--r--platform/vcs-log/api/src/com/intellij/vcs/log/VcsShortCommitDetails.java11
-rw-r--r--platform/vcs-log/graph-api/src/com/intellij/vcs/log/graph/GraphCommit.java6
-rw-r--r--platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogJoiner.java13
-rw-r--r--platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogMultiRepoJoiner.java26
-rw-r--r--platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogRefreshNotEnoughDataException.java25
-rw-r--r--platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogRefresherImpl.java89
-rw-r--r--platform/vcs-log/impl/src/com/intellij/vcs/log/graph/GraphColorManagerImpl.java4
-rw-r--r--platform/vcs-log/impl/test/com/intellij/vcs/log/data/VcsLogJoinerTest.java141
-rw-r--r--platform/vcs-log/impl/test/com/intellij/vcs/log/data/VcsLogJoinerTest.kt468
-rw-r--r--platform/vcs-log/impl/test/com/intellij/vcs/log/impl/TestVcsLogProvider.java8
-rw-r--r--platform/vcs-log/impl/vcs-log-impl.iml1
-rw-r--r--platform/xdebugger-api/src/com/intellij/xdebugger/evaluation/XDebuggerEvaluator.java2
-rw-r--r--platform/xdebugger-api/src/com/intellij/xdebugger/settings/DebuggerConfigurableProvider.java42
-rw-r--r--platform/xdebugger-api/src/com/intellij/xdebugger/settings/DebuggerSettingsCategory.java6
-rw-r--r--platform/xdebugger-api/src/com/intellij/xdebugger/settings/XDebuggerSettings.java23
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/DebuggerSupport.java6
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java31
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerSupport.java12
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/ForceStepIntoAction.java3
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/BreakpointState.java4
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointBase.java8
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointActionsPanel.java2
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.form2
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.java2
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/grouping/XBreakpointFileGroupingRule.java2
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEvaluationDialog.java13
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XQuickEvaluateHandler.java9
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XValueHint.java4
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XWatchesViewImpl.java35
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/DataViewsConfigurable.java6
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/DebuggerConfigurable.java173
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/DebuggerConfigurableProvider.java86
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/DebuggerSettingsPanelProvider.java23
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/MergedCompositeConfigurable.java78
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/SubCompositeConfigurable.java20
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/XDebuggerConfigurableProvider.java74
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/XDebuggerSettingsPanelProviderImpl.java70
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/DebuggerSessionTabBase.java22
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebugSessionTab.java15
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XDebuggerTree.java11
-rw-r--r--platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XDebuggerSettingsTest.java8
-rw-r--r--plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml4
-rw-r--r--plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties6
-rw-r--r--plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/BaseInspectionVisitor.java13
-rw-r--r--plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/DeclareCollectionAsInterfaceInspection.java6
-rw-r--r--plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/MismatchedArrayReadWriteInspection.java84
-rw-r--r--plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javabeans/PropertyValueSetToItselfInspection.java102
-rw-r--r--plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/IfCanBeSwitchInspection.java5
-rw-r--r--plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ImportUtils.java2
-rw-r--r--plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/InstanceOfUtils.java4
-rw-r--r--plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/WeakestTypeFinder.java37
-rw-r--r--plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/SimplifiableAnnotationInspection.java93
-rw-r--r--plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/StringBufferReplaceableByStringInspection.java6
-rw-r--r--plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryEnumModifierInspection.java7
-rw-r--r--plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryInterfaceModifierInspection.java5
-rw-r--r--plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarySemicolonInspection.java15
-rw-r--r--plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/HighlightUtils.java9
-rw-r--r--plugins/InspectionGadgets/src/com/siyeh/ig/ui/TextField.java28
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/AmbiguousFieldAccess.html4
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/PropertyValueSetToItself.html10
-rw-r--r--plugins/InspectionGadgets/src/inspectionDescriptions/ReturnNull.html8
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/MethodCallOnString.after.java5
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/MethodCallOnString.java6
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/declare_collection_as_interface/DeclareCollectionAsInterface.java10
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/AutoClosableTest.java4
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/NumberAdderDemo.java4
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/TypeMayBeWeakened.java22
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/sub/NumberAdder.java9
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/sub/NumberAdderExtension.java12
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/sub/NumberAdderImpl.java13
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/castConflictingInstanceof/orInstanceofOrInstanceof/OrInstanceofOrInstanceof.java30
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/castConflictingInstanceof/orInstanceofOrInstanceof/expected.xml4
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/mismatched_array_read_write/MismatchedArrayReadWrite.java13
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/style/simplifiable_annotation/SimplifiableAnnotation.java10
-rw-r--r--plugins/InspectionGadgets/testsrc/com/siyeh/ig/abstraction/TypeMayBeWeakenedInspectionTest.java56
-rw-r--r--plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/CastConflictsWithInstanceofInspectionTest.java4
-rw-r--r--plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/style/StringBufferReplaceableByStringFixTest.java1
-rw-r--r--plugins/InspectionGadgets/testsrc/com/siyeh/ig/inheritance/ExtendsConcreteCollectionInspectionTest.java2
-rw-r--r--plugins/InspectionGadgets/testsrc/com/siyeh/ig/javabeans/PropertyValueSetToItselfInspectionTest.java56
-rw-r--r--plugins/IntelliLang/java-support/resources/javaInjections.xml7
-rw-r--r--plugins/IntelliLang/src/META-INF/plugin.xml1
-rw-r--r--plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectorUtils.java66
-rw-r--r--plugins/IntentionPowerPak/src/com/siyeh/IntentionPowerPackBundle.properties2
-rw-r--r--plugins/IntentionPowerPak/src/com/siyeh/ipp/annotation/ExpandToNormalAnnotationIntention.java59
-rw-r--r--plugins/IntentionPowerPak/src/com/siyeh/ipp/asserttoif/ObjectsRequireNonNullIntention.java9
-rw-r--r--plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/annotation/ExpandToNormalAnnotationIntentionTest.java7
-rw-r--r--plugins/ant/jps-plugin/testSrc/org/jetbrains/jps/ant/JpsAntArtifactBuilderTaskTest.java7
-rw-r--r--plugins/ant/src/com/intellij/lang/ant/AntIntrospector.java7
-rw-r--r--plugins/ant/src/com/intellij/lang/ant/config/execution/OutputParser.java11
-rw-r--r--plugins/coverage-common/src/com/intellij/coverage/SrcFileAnnotator.java6
-rw-r--r--plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/actions/merge/MergeAction.java8
-rw-r--r--plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsstatuses/CvsChangeProvider.java17
-rw-r--r--plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/ui/experts/importToCvs/ImportTree.java21
-rw-r--r--plugins/devkit/resources/META-INF/plugin.xml22
-rw-r--r--plugins/devkit/resources/org/jetbrains/idea/devkit/DevKitBundle.properties (renamed from plugins/devkit/resources/DevKitBundle.properties)0
-rw-r--r--plugins/devkit/src/DevKitBundle.java2
-rw-r--r--plugins/devkit/src/actions/ShowSerializedXmlAction.java12
-rw-r--r--plugins/devkit/src/build/PrepareToDeployAction.java1
-rw-r--r--plugins/devkit/src/dom/DependencyConfigFileConverter.java4
-rw-r--r--plugins/devkit/src/dom/impl/PluginXmlDomFileDescription.java33
-rw-r--r--plugins/devkit/testData/codeInsight/deprecatedExtensionAttribute.xml2
-rw-r--r--plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudGitDeploymentRuntime.java6
-rw-r--r--plugins/git4idea/src/META-INF/plugin.xml11
-rw-r--r--plugins/git4idea/src/git4idea/GitUtil.java15
-rw-r--r--plugins/git4idea/src/git4idea/actions/GitLogSingleCommitAction.java70
-rw-r--r--plugins/git4idea/src/git4idea/branch/GitBranchOperation.java67
-rw-r--r--plugins/git4idea/src/git4idea/branch/GitBranchUiHandler.java12
-rw-r--r--plugins/git4idea/src/git4idea/branch/GitBranchUiHandlerImpl.java4
-rw-r--r--plugins/git4idea/src/git4idea/branch/GitCheckoutNewBranchOperation.java6
-rw-r--r--plugins/git4idea/src/git4idea/branch/GitCheckoutOperation.java15
-rw-r--r--plugins/git4idea/src/git4idea/branch/GitDeleteBranchOperation.java2
-rw-r--r--plugins/git4idea/src/git4idea/branch/GitMergeOperation.java11
-rw-r--r--plugins/git4idea/src/git4idea/branch/GitSmartOperationDialog.java19
-rw-r--r--plugins/git4idea/src/git4idea/changes/GitCommittedChangeListProvider.java10
-rw-r--r--plugins/git4idea/src/git4idea/checkin/GitCheckinEnvironment.java5
-rw-r--r--plugins/git4idea/src/git4idea/checkin/GitCommitAuthorCorrector.java2
-rw-r--r--plugins/git4idea/src/git4idea/cherrypick/GitCherryPickAction.java17
-rw-r--r--plugins/git4idea/src/git4idea/commands/Git.java4
-rw-r--r--plugins/git4idea/src/git4idea/commands/GitCommandResult.java19
-rw-r--r--plugins/git4idea/src/git4idea/commands/GitHandler.java16
-rw-r--r--plugins/git4idea/src/git4idea/commands/GitHttpAuthService.java5
-rw-r--r--plugins/git4idea/src/git4idea/commands/GitHttpAuthServiceImpl.java7
-rw-r--r--plugins/git4idea/src/git4idea/commands/GitHttpGuiAuthenticator.java21
-rw-r--r--plugins/git4idea/src/git4idea/commands/GitImpl.java21
-rw-r--r--plugins/git4idea/src/git4idea/commands/GitLocalChangesWouldBeOverwrittenDetector.java31
-rw-r--r--plugins/git4idea/src/git4idea/commands/GitSSHGUIHandler.java15
-rw-r--r--plugins/git4idea/src/git4idea/commands/GitTask.java1
-rw-r--r--plugins/git4idea/src/git4idea/config/GitVcsSettings.java11
-rw-r--r--plugins/git4idea/src/git4idea/history/GitDiffFromHistoryHandler.java136
-rw-r--r--plugins/git4idea/src/git4idea/history/GitHistoryUtils.java25
-rw-r--r--plugins/git4idea/src/git4idea/i18n/GitBundle.properties4
-rw-r--r--plugins/git4idea/src/git4idea/log/GitBekParentFixer.java55
-rw-r--r--plugins/git4idea/src/git4idea/log/GitLogProvider.java15
-rw-r--r--plugins/git4idea/src/git4idea/merge/GitPullDialog.java68
-rw-r--r--plugins/git4idea/src/git4idea/remote/GitHttpAuthDataProvider.java3
-rw-r--r--plugins/git4idea/src/git4idea/repo/GitRepositoryImpl.java2
-rw-r--r--plugins/git4idea/src/git4idea/repo/GitUntrackedFilesHolder.java5
-rw-r--r--plugins/git4idea/src/git4idea/reset/GitNewResetDialog.java144
-rw-r--r--plugins/git4idea/src/git4idea/reset/GitResetAction.java65
-rw-r--r--plugins/git4idea/src/git4idea/reset/GitResetMode.java59
-rw-r--r--plugins/git4idea/src/git4idea/reset/GitResetOperation.java191
-rw-r--r--plugins/git4idea/src/git4idea/ui/GitUnstashDialog.java63
-rw-r--r--plugins/git4idea/src/git4idea/ui/branch/GitBranchWidget.java2
-rw-r--r--plugins/git4idea/src/git4idea/update/GitMergeUpdater.java19
-rw-r--r--plugins/git4idea/tests/git4idea/branch/GitBranchWorkerTest.groovy63
-rw-r--r--plugins/git4idea/tests/git4idea/log/GitLogProviderTest.java8
-rw-r--r--plugins/git4idea/tests/git4idea/log/GitRefManagerTest.java8
-rw-r--r--plugins/git4idea/tests/git4idea/test/GitExecutor.java7
-rw-r--r--plugins/git4idea/tests/git4idea/test/GitHttpAuthTestService.java5
-rw-r--r--plugins/git4idea/tests/git4idea/test/GitMockRepositoryManager.java84
-rw-r--r--plugins/git4idea/tests/git4idea/test/GitPlatformTest.java100
-rw-r--r--plugins/git4idea/tests/git4idea/test/GitScenarios.groovy7
-rw-r--r--plugins/git4idea/tests/git4idea/test/GitTestRepositoryManager.java86
-rw-r--r--plugins/git4idea/tests/git4idea/test/GitTestUtil.java4
-rw-r--r--plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java2
-rw-r--r--plugins/github/src/org/jetbrains/plugins/github/GithubShareAction.java9
-rw-r--r--plugins/github/src/org/jetbrains/plugins/github/extensions/GithubCheckoutProvider.java2
-rw-r--r--plugins/github/src/org/jetbrains/plugins/github/extensions/GithubHttpAuthDataProvider.java5
-rw-r--r--plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepositoryEditor.java3
-rw-r--r--plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.java7
-rw-r--r--plugins/github/src/org/jetbrains/plugins/github/util/GithubAuthData.java5
-rw-r--r--plugins/github/src/org/jetbrains/plugins/github/util/GithubAuthDataHolder.java6
-rw-r--r--plugins/github/src/org/jetbrains/plugins/github/util/GithubSettings.java23
-rw-r--r--plugins/github/src/org/jetbrains/plugins/github/util/GithubUtil.java6
-rw-r--r--plugins/github/test/org/jetbrains/plugins/github/GithubCreateGistTestBase.java6
-rw-r--r--plugins/github/test/org/jetbrains/plugins/github/GithubRequestPagingTest.java2
-rw-r--r--plugins/github/test/org/jetbrains/plugins/github/GithubShareProjectTest.java2
-rw-r--r--plugins/github/test/org/jetbrains/plugins/github/GithubShareProjectTestBase.java2
-rw-r--r--plugins/github/test/org/jetbrains/plugins/github/test/GithubTest.java2
-rw-r--r--plugins/google-app-engine/jps-plugin/src/org/jetbrains/jps/appengine/build/AppEngineEnhancerBuilder.java4
-rw-r--r--plugins/google-app-engine/jps-plugin/src/org/jetbrains/jps/appengine/model/JpsAppEngineModuleExtension.java2
-rw-r--r--plugins/google-app-engine/jps-plugin/src/org/jetbrains/jps/appengine/model/impl/JpsAppEngineModuleExtensionImpl.java5
-rw-r--r--plugins/google-app-engine/source/com/intellij/appengine/actions/UploadApplicationAction.java9
-rw-r--r--plugins/gradle/gradle.iml4
-rw-r--r--plugins/gradle/jps-plugin/gradle-jps-plugin.iml44
-rw-r--r--plugins/gradle/jps-plugin/src/META-INF/services/org.jetbrains.jps.gradle.model.JpsGradleExtensionService16
-rw-r--r--plugins/gradle/jps-plugin/src/META-INF/services/org.jetbrains.jps.incremental.BuilderService16
-rw-r--r--plugins/gradle/jps-plugin/src/META-INF/services/org.jetbrains.jps.model.java.impl.JpsJavaDependenciesEnumerationHandler$Factory16
-rw-r--r--plugins/gradle/jps-plugin/src/META-INF/services/org.jetbrains.jps.model.serialization.JpsModelSerializerExtension16
-rw-r--r--plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/compiler/ChainingFilterTransformer.java111
-rw-r--r--plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/compiler/GradleBuilderService.java44
-rw-r--r--plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/compiler/GradleResourceFileProcessor.java94
-rw-r--r--plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/compiler/GradleResourcesBuilder.java128
-rw-r--r--plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/JpsGradleExtensionService.java49
-rw-r--r--plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/JpsGradleModuleExtension.java25
-rw-r--r--plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/FilePattern.java38
-rw-r--r--plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/GradleModuleResourceConfiguration.java81
-rw-r--r--plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/GradleProjectConfiguration.java35
-rw-r--r--plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/GradleResourceFileFilter.java81
-rw-r--r--plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/GradleResourceRootDescriptor.java88
-rw-r--r--plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/GradleResourcesTarget.java161
-rw-r--r--plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/GradleResourcesTargetType.java78
-rw-r--r--plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/JpsGradleDependenciesEnumerationHandler.java57
-rw-r--r--plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/JpsGradleExtensionServiceImpl.java136
-rw-r--r--plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/JpsGradleModelSerializationExtension.java59
-rw-r--r--plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/JpsGradleModuleExtensionImpl.java43
-rw-r--r--plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/ModuleVersion.java64
-rw-r--r--plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/ResourceRootConfiguration.java59
-rw-r--r--plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/ResourceRootFilter.java75
-rw-r--r--plugins/gradle/src/META-INF/gradle-maven-integration.xml1
-rw-r--r--plugins/gradle/src/META-INF/plugin.xml6
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/compiler/GradleBuildProcessParametersProvider.java93
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleResourceCompilerConfigurationGenerator.java186
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/execution/GradleOrderEnumeratorHandler.java112
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/AbstractProjectResolverExtension.java6
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java83
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java3
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolverExtension.java3
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleStartupActivity.java22
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/ProjectResolverContext.java8
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/data/ExternalProjectDataService.java233
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/data/ExternalProjectSerializer.java262
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/wizard/GradleProjectOpenProcessor.java97
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/GradleSystemSettingsControl.java5
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleEnvironment.java12
-rw-r--r--plugins/gradle/testSources/org/jetbrains/plugins/gradle/compiler/GradleCompilingTestCase.java89
-rw-r--r--plugins/gradle/testSources/org/jetbrains/plugins/gradle/compiler/GradleResourceFilteringTest.java132
-rw-r--r--plugins/gradle/testSources/org/jetbrains/plugins/gradle/compiler/GradleResourceProcessingTest.java176
-rw-r--r--plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/ModuleExtendedModel.java3
-rw-r--r--plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/ProjectImportAction.java51
-rw-r--r--plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/tooling/ErrorMessageBuilder.java12
-rw-r--r--plugins/gradle/tooling-extension-impl/gradle-tooling-extension-impl.iml1
-rw-r--r--plugins/gradle/tooling-extension-impl/src/META-INF/services/org.jetbrains.plugins.gradle.tooling.ModelBuilderService1
-rw-r--r--plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/ExternalProjectBuilderImpl.groovy231
-rw-r--r--plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/WarModelBuilderImpl.groovy21
-rw-r--r--plugins/gradle/tooling-extension-impl/testSources/org/jetbrains/plugins/gradle/tooling/builder/AbstractModelBuilderTest.java4
-rw-r--r--plugins/groovy/groovy-psi/src/resources/groovyInjections.xml9
-rw-r--r--plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java24
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyDebuggerSettings.java43
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyDebuggerSettingsConfigurable.java97
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyHotSwapConfigurableUi.form (renamed from plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyDebuggerSettingsConfigurable.form)3
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyHotSwapConfigurableUi.java50
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovySteppingConfigurable.java37
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/editor/GroovyReferenceCopyPasteProcessor.java2
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/GroovySdkWizardStepBase.java6
-rw-r--r--plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTest.groovy43
-rw-r--r--plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTestCase.java8
-rw-r--r--plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/optimizeImports/OptimizeImportsTest.groovy3
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/action/HgLogSingleCommitAction.java69
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/execution/HgCommandAuthenticator.java25
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/log/HgLogProvider.java9
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgDiffFromHistoryHandler.java119
-rw-r--r--plugins/hg4idea/testSrc/hg4idea/test/HgExecutor.java2
-rw-r--r--plugins/java-i18n/src/com/intellij/codeInspection/i18n/folding/I18nMessageGotoDeclarationHandler.java2
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFXNSDescriptor.java2
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxPropertyElementDescriptor.java2
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderEditorProvider.java2
-rw-r--r--plugins/junit/src/com/intellij/execution/junit/TestObject.java4
-rw-r--r--plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurationModel.java2
-rw-r--r--plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/model/MavenExplicitProfiles.java77
-rw-r--r--plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/server/MavenServer.java3
-rw-r--r--plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/server/MavenServerEmbedder.java11
-rw-r--r--plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/server/ProfileApplicationResult.java8
-rw-r--r--plugins/maven/maven2-server-impl/src/org/jetbrains/idea/maven/server/Maven2ServerImpl.java3
-rw-r--r--plugins/maven/maven2-server-impl/src/org/jetbrains/idea/maven/server/embedder/Maven2ServerEmbedderImpl.java22
-rw-r--r--plugins/maven/maven2-server-impl/src/org/jetbrains/maven/embedder/MavenEmbedder.java9
-rw-r--r--plugins/maven/maven2-server-impl/test/org/jetbrains/idea/maven/embedder/MavenServerEmbedderTest.java31
-rw-r--r--plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerEmbedderImpl.java33
-rw-r--r--plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerImpl.java3
-rw-r--r--plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/MavenEffectivePomDumper.java6
-rw-r--r--plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/MavenLeakDetector.java5
-rw-r--r--plugins/maven/pom.xml8
-rw-r--r--plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenDomProjectProcessorUtils.java5
-rw-r--r--plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenPropertyResolver.java12
-rw-r--r--plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenConfigurationProducer.java5
-rw-r--r--plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunnerParameters.java8
-rw-r--r--plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenRootModelAdapter.java13
-rw-r--r--plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/MavenProjectsNavigatorPanel.java5
-rw-r--r--plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/actions/MavenExecuteGoalAction.java3
-rw-r--r--plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProject.java9
-rw-r--r--plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectReader.java51
-rw-r--r--plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectReaderResult.java5
-rw-r--r--plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectSettings.java7
-rw-r--r--plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManager.java25
-rw-r--r--plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManagerWatcher.java7
-rw-r--r--plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsTree.java91
-rw-r--r--plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenWorkspaceSettings.java6
-rw-r--r--plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenWorkspaceSettingsComponent.java5
-rw-r--r--plugins/maven/src/main/java/org/jetbrains/idea/maven/project/actions/RunBuildAction.java5
-rw-r--r--plugins/maven/src/main/java/org/jetbrains/idea/maven/project/actions/ToggleProfileAction.java112
-rw-r--r--plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenEmbedderWrapper.java22
-rw-r--r--plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenServerManager.java3
-rw-r--r--plugins/maven/src/main/java/org/jetbrains/idea/maven/tasks/MavenBeforeRunTasksProvider.java6
-rw-r--r--plugins/maven/src/main/java/org/jetbrains/idea/maven/tasks/MavenKeymapExtension.java5
-rw-r--r--plugins/maven/src/main/java/org/jetbrains/idea/maven/tasks/MavenTasksManager.java7
-rw-r--r--plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenDataKeys.java4
-rw-r--r--plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenModuleBuilderHelper.java4
-rw-r--r--plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenProjectBuilder.java55
-rw-r--r--plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenProjectOpenProcessor.java4
-rw-r--r--plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/SelectProfilesStep.java147
-rw-r--r--plugins/maven/src/main/resources/ProjectBundle.properties1
-rw-r--r--plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenImportingTestCase.java5
-rw-r--r--plugins/maven/src/test/java/org/jetbrains/idea/maven/compiler/ResourceFilteringTest.java3
-rw-r--r--plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenPropertyCompletionAndResolutionTest.java5
-rw-r--r--plugins/maven/src/test/java/org/jetbrains/idea/maven/execution/MavenExecutionTest.java5
-rw-r--r--plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/MavenPerformanceTest.java3
-rw-r--r--plugins/maven/src/test/java/org/jetbrains/idea/maven/navigator/MavenProjectsNavigatorTest.java3
-rw-r--r--plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenFoldersImporterTest.java19
-rw-r--r--plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectReaderTest.java4
-rw-r--r--plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectsManagerTest.java5
-rw-r--r--plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectsTreeReadingTest.java23
-rw-r--r--plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectsTreeTestCase.java5
-rw-r--r--plugins/properties/properties-psi-api/resources/icons/xmlProperties.png (renamed from plugins/properties/resources/icons/xmlProperties.png)bin542 -> 542 bytes
-rw-r--r--plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/PropertiesImplUtil.java15
-rw-r--r--plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleImpl.java5
-rw-r--r--plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/structureView/PropertiesSeparatorManager.java135
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/NestedCopiesBuilder.java4
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/StatusReceiver.java1
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/StatusWalkerPartner.java11
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProvider.java2
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProviderContext.java15
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/SvnDiffProvider.java11
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/SvnEditFileProvider.java6
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFormatSelector.java109
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java21
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java22
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/actions/AbstractShowPropertiesDiffAction.java104
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CreateExternalAction.java31
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SetPropertyAction.java4
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SvnExcludingIgnoredOperation.java18
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SvnMergeProvider.java8
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandExecutor.java13
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandUtil.java3
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/config/SvnConfigureProxiesDialog.java12
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/BranchConfigurationDialog.java25
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/PropertiesComponent.java37
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserComponent.java16
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserDialog.java27
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SelectLocationDialog.java69
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SetPropertyDialog.java30
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CmdDiffClient.java54
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/diff/DiffClient.java5
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/diff/DirectoryWithBranchComparer.java14
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/diff/SvnKitDiffClient.java31
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnDiffFromHistoryHandler.java80
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnEditCommitMessageAction.java4
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java2
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistorySession.java5
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/ignore/SvnPropertyService.java31
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/GatheringChangelistBuilder.java17
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/BranchInfo.java14
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneRecursiveShotMergeInfoWorker.java15
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/properties/CmdPropertyClient.java77
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/properties/ExternalsDefinitionParser.java106
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertiesMap.java24
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertyClient.java33
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertyConsumer.java33
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertyData.java53
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertyValue.java53
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/properties/SvnKitPropertyClient.java109
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/rollback/SvnRollbackEnvironment.java23
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/svnkit/SvnKitAdminAreaFactorySelector.java137
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/svnkit/SvnKitManager.java3
-rw-r--r--plugins/svn4idea/testSource/org/jetbrains/idea/svn/ExternalsDefinitionParserTest.java62
-rw-r--r--plugins/tasks/tasks-core/src/com/intellij/tasks/config/TaskConfigurable.java4
-rw-r--r--plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/live/TrelloIntegrationTest.java22
-rw-r--r--plugins/terminal/lib/jediterm-pty-2.0.jarbin226732 -> 231844 bytes
-rw-r--r--plugins/terminal/resources/META-INF/terminal.xml8
-rw-r--r--plugins/terminal/src/org/jetbrains/plugins/terminal/LocalTerminalDirectRunner.java16
-rw-r--r--plugins/terminal/src/org/jetbrains/plugins/terminal/OpenLocalTerminalAction.java53
-rw-r--r--plugins/terminal/src/org/jetbrains/plugins/terminal/TerminalView.java23
-rw-r--r--plugins/testng/src/com/theoryinpractice/testng/configuration/SearchingForTestsTask.java2
-rw-r--r--plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGRunnableState.java2
-rw-r--r--plugins/ui-designer/src/com/intellij/uiDesigner/PsiPropertiesProvider.java4
-rw-r--r--plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/editors/ColorEditor.java203
-rw-r--r--plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/associations/impl/FileAssociationsConfigurable.java20
-rw-r--r--python/IntelliLang-python/IntelliLang-python.iml1
-rw-r--r--python/IntelliLang-python/resources/META-INF/intellilang-python-support.xml (renamed from python/IntelliLang-python/src/META-INF/intellilang-python-support.xml)2
-rw-r--r--python/IntelliLang-python/resources/META-INF/plugin.xml16
-rw-r--r--python/IntelliLang-python/src/com/jetbrains/python/intelliLang/PyLanguageInjectionSupport.java2
-rw-r--r--python/IntelliLang-python/src/resources/pyInjections.xml (renamed from python/IntelliLang-python/src/pyInjections.xml)0
-rw-r--r--python/build/paths.nsi2
-rw-r--r--python/build/pycharm64_community_launcher.properties3
-rw-r--r--python/build/pycharm_community_build.gant6
-rw-r--r--python/edu/build/DMG_background.pngbin0 -> 20543 bytes
-rw-r--r--python/edu/build/build.xml46
-rw-r--r--python/edu/build/paths.nsi6
-rw-r--r--python/edu/build/plugin-list.txt11
-rw-r--r--python/edu/build/pycharm_edu_build.gant393
-rw-r--r--python/edu/build/pycharm_edu_launcher.properties3
-rw-r--r--python/edu/build/python-edu-build.iml14
-rw-r--r--python/edu/build/resources/PC_instCom.icobin0 -> 17542 bytes
-rw-r--r--python/edu/build/resources/PC_uninstCom.icobin0 -> 17542 bytes
-rw-r--r--python/edu/build/resources/headerlogo.bmpbin0 -> 25818 bytes
-rw-r--r--python/edu/build/resources/logo.bmpbin0 -> 154544 bytes
-rw-r--r--python/edu/build/resources/pycharm_inst.icobin0 -> 26694 bytes
-rw-r--r--python/edu/build/resources/pycharm_uninst.icobin0 -> 26694 bytes
-rw-r--r--python/edu/build/strings.nsi13
-rw-r--r--python/edu/main_pycharm_edu.iml21
-rw-r--r--python/edu/python-educational.iml29
-rw-r--r--python/edu/resources/idea/PyCharmEduApplicationInfo.xml23
-rw-r--r--python/edu/src/META-INF/PyCharmEduPlugin.xml36
-rw-r--r--python/edu/src/com/jetbrains/python/edu/PyCharmEduInitialConfigurator.java247
-rw-r--r--python/helpers/pycharm/_bdd_utils.py201
-rw-r--r--python/helpers/pycharm/behave_runner.py242
-rw-r--r--python/helpers/pycharm/lettuce_runner.py158
-rw-r--r--python/helpers/pycharm/tcunittest.py87
-rw-r--r--python/ide/src/com/jetbrains/python/newProject/PyCharmNewProjectDialog.java6
-rw-r--r--python/ide/src/com/jetbrains/python/newProject/actions/AbstractProjectSettingsStep.java85
-rw-r--r--python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificSettingsStep.java7
-rw-r--r--python/ide/src/com/jetbrains/python/newProject/actions/PyCharmNewProjectStep.java10
-rw-r--r--python/openapi/src/com/jetbrains/python/newProject/PythonProjectGenerator.java2
-rw-r--r--python/psi-api/src/com/jetbrains/python/psi/PyElementGenerator.java31
-rw-r--r--python/psi-api/src/com/jetbrains/python/psi/PyElsePart.java7
-rw-r--r--python/psi-api/src/com/jetbrains/python/psi/PyStatementPart.java6
-rw-r--r--python/psi-api/src/com/jetbrains/python/psi/PyWithStatement.java2
-rw-r--r--python/psi-api/src/com/jetbrains/python/psi/StructuredDocString.java9
-rw-r--r--python/python-rest/src/com/jetbrains/rest/run/RestCommandLineState.java4
-rw-r--r--python/src/META-INF/python-core.xml12
-rw-r--r--python/src/com/jetbrains/python/PyAddImportFix.java55
-rw-r--r--python/src/com/jetbrains/python/PyBundle.properties2
-rw-r--r--python/src/com/jetbrains/python/actions/ExecuteInConsoleAction.java3
-rw-r--r--python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/PySmartEnterProcessor.java2
-rw-r--r--python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/enterProcessors/PyPlainEnterProcessor.java17
-rw-r--r--python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyArgumentListFixer.java34
-rw-r--r--python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyClassFixer.java33
-rw-r--r--python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyConditionalStatementPartFixer.java53
-rw-r--r--python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyExceptFixer.java40
-rw-r--r--python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyFixer.java20
-rw-r--r--python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyForPartFixer.java66
-rw-r--r--python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyFunctionFixer.java25
-rw-r--r--python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyMissingBracesFixer.java15
-rw-r--r--python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyParameterListFixer.java30
-rw-r--r--python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyParenthesizedFixer.java19
-rw-r--r--python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyStringLiteralFixer.java50
-rw-r--r--python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyUnconditionalStatementPartFixer.java28
-rw-r--r--python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyWithFixer.java74
-rw-r--r--python/src/com/jetbrains/python/console/PydevConsoleRunner.java116
-rw-r--r--python/src/com/jetbrains/python/console/PythonConsoleToolWindow.java127
-rw-r--r--python/src/com/jetbrains/python/console/PythonConsoleToolWindowFactory.java33
-rw-r--r--python/src/com/jetbrains/python/console/RunPythonConsoleAction.java8
-rw-r--r--python/src/com/jetbrains/python/documentation/EpydocString.java7
-rw-r--r--python/src/com/jetbrains/python/documentation/PyDocstringGenerator.java11
-rw-r--r--python/src/com/jetbrains/python/documentation/PyDocumentationSettings.java24
-rw-r--r--python/src/com/jetbrains/python/documentation/SphinxDocString.java9
-rw-r--r--python/src/com/jetbrains/python/documentation/StructuredDocStringBase.java26
-rw-r--r--python/src/com/jetbrains/python/inspections/PyInspectionVisitor.java4
-rw-r--r--python/src/com/jetbrains/python/inspections/PyShadowingNamesInspection.java2
-rw-r--r--python/src/com/jetbrains/python/inspections/quickfix/PyRemoveArgumentQuickFix.java1
-rw-r--r--python/src/com/jetbrains/python/psi/PyUtil.java19
-rw-r--r--python/src/com/jetbrains/python/psi/impl/PyElementGeneratorImpl.java22
-rw-r--r--python/src/com/jetbrains/python/psi/impl/PyElsePartImpl.java14
-rw-r--r--python/src/com/jetbrains/python/psi/impl/PyFileImpl.java5
-rw-r--r--python/src/com/jetbrains/python/psi/impl/PyFunctionBuilder.java30
-rw-r--r--python/src/com/jetbrains/python/psi/impl/PyStarImportElementImpl.java21
-rw-r--r--python/src/com/jetbrains/python/psi/impl/PyStatementPartImpl.java14
-rw-r--r--python/src/com/jetbrains/python/psi/impl/PyWithStatementImpl.java10
-rw-r--r--python/src/com/jetbrains/python/psi/resolve/PyResolveUtil.java38
-rw-r--r--python/src/com/jetbrains/python/run/PyRemoteTracebackFilter.java57
-rw-r--r--python/src/com/jetbrains/python/run/PythonCommandLineState.java26
-rw-r--r--python/src/com/jetbrains/python/run/PythonRunConfiguration.java8
-rw-r--r--python/src/com/jetbrains/python/run/PythonScriptCommandLineState.java7
-rw-r--r--python/src/com/jetbrains/python/run/PythonTracebackFilter.java14
-rw-r--r--python/src/com/jetbrains/python/sdk/PyDetectedSdk.java4
-rw-r--r--python/src/com/jetbrains/python/testing/PythonTestCommandLineStateBase.java8
-rw-r--r--python/src/com/jetbrains/python/testing/pytest/PyTestCommandLineState.java2
-rw-r--r--python/testData/codeInsight/smartEnter/withExpressionMissing.py1
-rw-r--r--python/testData/codeInsight/smartEnter/withExpressionMissing_after.py1
-rw-r--r--python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportBeforeStarDunderAll/a.py3
-rw-r--r--python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportBeforeStarDunderAll/b.py0
-rw-r--r--python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportBeforeStarDunderAll/p1/__init__.py1
-rw-r--r--python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportBeforeStarDunderAll/p1/m1.py2
-rw-r--r--python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportBeforeStarImport/a.py5
-rw-r--r--python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportBeforeStarImport/m1.py1
-rw-r--r--python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportBeforeStarImport/m2.py1
-rw-r--r--python/testSrc/com/jetbrains/python/PySmartEnterTest.java5
-rw-r--r--python/testSrc/com/jetbrains/python/fixtures/PyTestCase.java44
-rw-r--r--python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java10
-rw-r--r--resources-en/src/messages/DebuggerBundle.properties6
-rw-r--r--resources/src/META-INF/IdeaPlugin.xml5
-rw-r--r--resources/src/idea/RichPlatformActions.xml6
-rw-r--r--resources/src/idea/RichPlatformPlugin.xml3
-rw-r--r--spellchecker/src/com/intellij/spellchecker/jetbrains.dic2
-rw-r--r--xml/impl/src/com/intellij/application/options/CodeStyleHtmlPanel.form21
-rw-r--r--xml/impl/src/com/intellij/application/options/CodeStyleHtmlPanel.java10
-rw-r--r--xml/impl/src/com/intellij/application/options/CodeStyleXmlPanel.form17
-rw-r--r--xml/impl/src/com/intellij/application/options/CodeStyleXmlPanel.java10
-rw-r--r--xml/impl/src/com/intellij/application/options/HtmlLanguageCodeStyleSettings.java11
-rw-r--r--xml/impl/src/com/intellij/application/options/XmlLanguageCodeStyleSettingsProvider.java9
-rw-r--r--xml/impl/src/com/intellij/codeInsight/completion/HtmlTextCompletionConfidence.java4
-rw-r--r--xml/impl/src/com/intellij/codeInsight/template/emmet/filters/TrimZenCodingFilter.java25
-rw-r--r--xml/impl/src/com/intellij/ide/browsers/BrowserLauncherImpl.java17
-rw-r--r--xml/impl/src/com/intellij/ide/browsers/BrowserSelector.java4
-rw-r--r--xml/impl/src/com/intellij/ide/browsers/BrowserSettingsPanel.form2
-rw-r--r--xml/impl/src/com/intellij/ide/browsers/BrowserSettingsPanel.java216
-rw-r--r--xml/impl/src/com/intellij/ide/browsers/ConfigurableWebBrowser.java11
-rw-r--r--xml/impl/src/com/intellij/ide/browsers/DefaultBrowserPolicy.java (renamed from java/jsp-openapi/src/com/intellij/psi/jsp/JspImplicitVariable.java)18
-rw-r--r--xml/impl/src/com/intellij/ide/browsers/WebBrowserManager.java105
-rw-r--r--xml/impl/src/com/intellij/ide/browsers/actions/BaseOpenInBrowserAction.java2
-rw-r--r--xml/impl/src/com/intellij/ide/browsers/actions/OpenFileInDefaultBrowserAction.java12
-rw-r--r--xml/impl/src/com/intellij/ide/browsers/impl/WebBrowserServiceImpl.java11
-rw-r--r--xml/impl/src/com/intellij/psi/formatter/xml/AbstractXmlBlock.java28
-rw-r--r--xml/impl/src/org/jetbrains/builtInWebServer/BuiltInServerConfigurableUi.form40
-rw-r--r--xml/impl/src/org/jetbrains/builtInWebServer/BuiltInServerConfigurableUi.java47
-rw-r--r--xml/impl/src/org/jetbrains/builtInWebServer/BuiltInServerOptions.java116
-rw-r--r--xml/impl/src/org/jetbrains/builtInWebServer/BuiltInWebBrowserUrlProvider.java78
-rw-r--r--xml/impl/src/org/jetbrains/builtInWebServer/BuiltInWebServer.java231
-rw-r--r--xml/impl/src/org/jetbrains/builtInWebServer/DefaultWebServerPathHandler.java102
-rw-r--r--xml/impl/src/org/jetbrains/builtInWebServer/DefaultWebServerRootsProvider.java150
-rw-r--r--xml/impl/src/org/jetbrains/builtInWebServer/PathInfo.java47
-rw-r--r--xml/impl/src/org/jetbrains/builtInWebServer/PrefixlessWebServerRootsProvider.java18
-rw-r--r--xml/impl/src/org/jetbrains/builtInWebServer/WebServerFileHandler.java35
-rw-r--r--xml/impl/src/org/jetbrains/builtInWebServer/WebServerPathHandler.java57
-rw-r--r--xml/impl/src/org/jetbrains/builtInWebServer/WebServerPathHandlerAdapter.java37
-rw-r--r--xml/impl/src/org/jetbrains/builtInWebServer/WebServerPathToFileManager.java142
-rw-r--r--xml/impl/src/org/jetbrains/builtInWebServer/WebServerRootsProvider.java21
-rw-r--r--xml/impl/src/org/jetbrains/io/fastCgi/FastCgiChannelHandler.java108
-rw-r--r--xml/impl/src/org/jetbrains/io/fastCgi/FastCgiConstants.java5
-rw-r--r--xml/impl/src/org/jetbrains/io/fastCgi/FastCgiDecoder.java149
-rw-r--r--xml/impl/src/org/jetbrains/io/fastCgi/FastCgiRequest.java149
-rw-r--r--xml/impl/src/org/jetbrains/io/fastCgi/FastCgiResponse.java21
-rw-r--r--xml/impl/src/org/jetbrains/io/fastCgi/FastCgiService.java249
-rw-r--r--xml/impl/src/org/jetbrains/notification/SingletonNotificationManager.java86
-rw-r--r--xml/impl/xml.iml2
-rw-r--r--xml/xml-psi-impl/src/com/intellij/javaee/ExternalResourceManagerExImpl.java4
-rw-r--r--xml/xml-psi-impl/src/com/intellij/psi/impl/source/html/HtmlFileImpl.java15
1307 files changed, 29181 insertions, 12379 deletions
diff --git a/.idea/codeStyleSettings.xml b/.idea/codeStyleSettings.xml
index 33a693a1ec86..2faab0e8ef91 100755
--- a/.idea/codeStyleSettings.xml
+++ b/.idea/codeStyleSettings.xml
@@ -289,6 +289,13 @@
<option name="TAB_SIZE" value="8" />
</indentOptions>
</codeStyleSettings>
+ <codeStyleSettings language="jet">
+ <indentOptions>
+ <option name="INDENT_SIZE" value="2" />
+ <option name="CONTINUATION_INDENT_SIZE" value="4" />
+ <option name="TAB_SIZE" value="2" />
+ </indentOptions>
+ </codeStyleSettings>
<codeStyleSettings language="ruby">
<option name="KEEP_LINE_BREAKS" value="false" />
<option name="PARENT_SETTINGS_INSTALLED" value="true" />
diff --git a/.idea/libraries/Kryo.xml b/.idea/libraries/Kryo.xml
new file mode 100644
index 000000000000..b11f03b83ef2
--- /dev/null
+++ b/.idea/libraries/Kryo.xml
@@ -0,0 +1,14 @@
+<component name="libraryTable">
+ <library name="Kryo">
+ <CLASSES>
+ <root url="jar://$PROJECT_DIR$/lib/minlog-1.2.jar!/" />
+ <root url="jar://$PROJECT_DIR$/lib/kryo-2.22.jar!/" />
+ <root url="jar://$PROJECT_DIR$/lib/reflectasm-1.07.jar!/" />
+ <root url="jar://$PROJECT_DIR$/lib/objenesis-1.2.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES>
+ <root url="jar://$PROJECT_DIR$/lib/src/kryo-src.zip!/src" />
+ </SOURCES>
+ </library>
+</component> \ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
index ebc8d48f9899..a06e083797db 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -79,6 +79,7 @@
<module fileurl="file://$PROJECT_DIR$/../studio/cloud/login/google-login.iml" filepath="$PROJECT_DIR$/../studio/cloud/login/google-login.iml" group="plugins/Google" />
<module fileurl="file://$PROJECT_DIR$/plugins/gradle/gradle.iml" filepath="$PROJECT_DIR$/plugins/gradle/gradle.iml" group="community/plugins/gradle" />
<module fileurl="file://$PROJECT_DIR$/../base/gradle-import/gradle-import.iml" filepath="$PROJECT_DIR$/../base/gradle-import/gradle-import.iml" group="plugins/Android/android-sdk" />
+ <module fileurl="file://$PROJECT_DIR$/plugins/gradle/jps-plugin/gradle-jps-plugin.iml" filepath="$PROJECT_DIR$/plugins/gradle/jps-plugin/gradle-jps-plugin.iml" group="community/plugins/gradle" />
<module fileurl="file://$PROJECT_DIR$/plugins/gradle/tooling-extension-api/gradle-tooling-extension-api.iml" filepath="$PROJECT_DIR$/plugins/gradle/tooling-extension-api/gradle-tooling-extension-api.iml" group="community/plugins/gradle" />
<module fileurl="file://$PROJECT_DIR$/plugins/gradle/tooling-extension-impl/gradle-tooling-extension-impl.iml" filepath="$PROJECT_DIR$/plugins/gradle/tooling-extension-impl/gradle-tooling-extension-impl.iml" group="community/plugins/gradle" />
<module fileurl="file://$PROJECT_DIR$/plugins/groovy/jps-plugin/groovy-jps-plugin.iml" filepath="$PROJECT_DIR$/plugins/groovy/jps-plugin/groovy-jps-plugin.iml" group="plugins/Groovy" />
@@ -135,6 +136,7 @@
<module fileurl="file://$PROJECT_DIR$/platform/lvcs-impl/lvcs-impl.iml" filepath="$PROJECT_DIR$/platform/lvcs-impl/lvcs-impl.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/python/main_idea_python_plugin.iml" filepath="$PROJECT_DIR$/python/main_idea_python_plugin.iml" group="python" />
<module fileurl="file://$PROJECT_DIR$/python/main_pycharm_ce.iml" filepath="$PROJECT_DIR$/python/main_pycharm_ce.iml" group="python" />
+ <module fileurl="file://$PROJECT_DIR$/python/edu/main_pycharm_edu.iml" filepath="$PROJECT_DIR$/python/edu/main_pycharm_edu.iml" group="python/educational" />
<module fileurl="file://$PROJECT_DIR$/java/manifest/manifest.iml" filepath="$PROJECT_DIR$/java/manifest/manifest.iml" group="java" />
<module fileurl="file://$PROJECT_DIR$/../base/build-system/manifest-merger/manifest-merger.iml" filepath="$PROJECT_DIR$/../base/build-system/manifest-merger/manifest-merger.iml" group="plugins/Android/android-sdk" />
<module fileurl="file://$PROJECT_DIR$/plugins/maven/maven.iml" filepath="$PROJECT_DIR$/plugins/maven/maven.iml" group="plugins/maven" />
@@ -164,6 +166,8 @@
<module fileurl="file://$PROJECT_DIR$/python/build/python-community-build.iml" filepath="$PROJECT_DIR$/python/build/python-community-build.iml" group="python" />
<module fileurl="file://$PROJECT_DIR$/python/pluginSrc/python-community-plugin.iml" filepath="$PROJECT_DIR$/python/pluginSrc/python-community-plugin.iml" group="python" />
<module fileurl="file://$PROJECT_DIR$/python/testSrc/python-community-tests.iml" filepath="$PROJECT_DIR$/python/testSrc/python-community-tests.iml" group="python" />
+ <module fileurl="file://$PROJECT_DIR$/python/edu/build/python-edu-build.iml" filepath="$PROJECT_DIR$/python/edu/build/python-edu-build.iml" group="python/educational" />
+ <module fileurl="file://$PROJECT_DIR$/python/edu/python-educational.iml" filepath="$PROJECT_DIR$/python/edu/python-educational.iml" group="python/educational" />
<module fileurl="file://$PROJECT_DIR$/python/python-helpers.iml" filepath="$PROJECT_DIR$/python/python-helpers.iml" group="python" />
<module fileurl="file://$PROJECT_DIR$/python/ide/python-ide-community.iml" filepath="$PROJECT_DIR$/python/ide/python-ide-community.iml" group="python" />
<module fileurl="file://$PROJECT_DIR$/python/openapi/python-openapi.iml" filepath="$PROJECT_DIR$/python/openapi/python-openapi.iml" group="python" />
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/RegExpFile.java b/RegExpSupport/src/org/intellij/lang/regexp/RegExpFile.java
index 298e1c663a34..197364969340 100644
--- a/RegExpSupport/src/org/intellij/lang/regexp/RegExpFile.java
+++ b/RegExpSupport/src/org/intellij/lang/regexp/RegExpFile.java
@@ -19,16 +19,29 @@ import com.intellij.extapi.psi.PsiFileBase;
import com.intellij.lang.Language;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.psi.FileViewProvider;
+import com.intellij.psi.util.PsiTreeUtil;
+import org.intellij.lang.regexp.psi.RegExpGroup;
import org.jetbrains.annotations.NotNull;
+import java.util.Collection;
+
+
public class RegExpFile extends PsiFileBase {
- public RegExpFile(FileViewProvider viewProvider, final Language language) {
- super(viewProvider, language);
- }
+ public RegExpFile(FileViewProvider viewProvider, final Language language) {
+ super(viewProvider, language);
+ }
+
+ @NotNull
+ public FileType getFileType() {
+ return RegExpFileType.INSTANCE;
+ }
- @NotNull
- public FileType getFileType() {
- return RegExpFileType.INSTANCE;
- }
+ /**
+ * @return Regexp groups this file has
+ */
+ @NotNull
+ public Collection<RegExpGroup> getGroups() {
+ return PsiTreeUtil.findChildrenOfType(this, RegExpGroup.class);
+ }
}
diff --git a/bin/win/runnerw.exe b/bin/win/runnerw.exe
index 5c5f103adca8..29c5d336d08c 100644
--- a/bin/win/runnerw.exe
+++ b/bin/win/runnerw.exe
Binary files differ
diff --git a/build/conf/nsis/DeleteSettings.ini b/build/conf/nsis/DeleteSettings.ini
index 2c93ebfede7e..c43b9124fd78 100644
--- a/build/conf/nsis/DeleteSettings.ini
+++ b/build/conf/nsis/DeleteSettings.ini
@@ -1,26 +1,40 @@
[Settings]
-NumFields=3
+NumFields=5
[Field 1]
Type=label
-Left=0
+Left=5
Right=-1
Top=0
-Bottom=40
+Bottom=10
[Field 2]
-Type=checkbox
+Type=label
Left=5
Right=-1
+Top=15
+Bottom=35
+
+[Field 3]
+Type=GroupBox
+Left=0
+Right=-1
Top=40
-Bottom=50
+Bottom=90
+
+[Field 4]
+Type=checkbox
+Left=5
+Right=-1
+Top=55
+Bottom=65
State=0
-[Field 3]
+[Field 5]
Type=checkbox
Left=5
Right=-1
-Top=60
-Bottom=70
+Top=70
+Bottom=80
State=0
diff --git a/build/conf/nsis/UninstallOldVersions.ini b/build/conf/nsis/UninstallOldVersions.ini
index 0a8f760498c6..f8444c383a8a 100644
--- a/build/conf/nsis/UninstallOldVersions.ini
+++ b/build/conf/nsis/UninstallOldVersions.ini
@@ -1,5 +1,5 @@
[Settings]
-NumFields=10
+NumFields=13
[Field 1]
Type=label
@@ -7,94 +7,112 @@ Text=List of JB products
Left=5
Right=-1
Top=0
-Bottom=15
+Bottom=10
[Field 2]
Type=checkbox
-Text=Uninstall old version
-Left=12
-Right=200
-Top=25
-Bottom=35
+Text=Uninstall silently (settings and configuration from old versions will not be deleted)
+Left=5
+Right=-1
+Top=123
+Bottom=133
State=0
-Flags=NOTIFY
[Field 3]
Type=checkbox
-Text=Quick uninstallation
+Text=An old installation
Left=12
-Right=200
-Top=123
-Bottom=133
+Right=-1
+Top=12
+Bottom=22
State=0
-Flags=DISABLED
[Field 4]
Type=checkbox
Text=An old installation
-Left=20
-Right=300
-Top=39
-Bottom=49
+Left=12
+Right=-1
+Top=22
+Bottom=32
State=0
-Flags=DISABLED
[Field 5]
Type=checkbox
Text=An old installation
-Left=20
-Right=300
-Top=51
-Bottom=61
+Left=12
+Right=-1
+Top=32
+Bottom=42
State=0
-Flags=DISABLED
[Field 6]
Type=checkbox
Text=An old installation
-Left=20
-Right=300
-Top=63
-Bottom=73
+Left=12
+Right=-1
+Top=42
+Bottom=52
State=0
-Flags=DISABLED
[Field 7]
Type=checkbox
Text=An old installation
-Left=20
-Right=300
-Top=75
-Bottom=85
+Left=12
+Right=-1
+Top=52
+Bottom=62
State=0
-Flags=DISABLED
[Field 8]
Type=checkbox
Text=An old installation
-Left=20
-Right=300
-Top=87
-Bottom=97
+Left=12
+Right=-1
+Top=62
+Bottom=72
State=0
-Flags=DISABLED
[Field 9]
Type=checkbox
Text=An old installation
-Left=20
-Right=300
-Top=99
-Bottom=109
+Left=12
+Right=-1
+Top=72
+Bottom=82
State=0
-Flags=DISABLED
[Field 10]
Type=checkbox
Text=An old installation
-Left=20
-Right=300
-Top=111
-Bottom=121
+Left=12
+Right=-1
+Top=82
+Bottom=92
+State=0
+
+[Field 11]
+Type=checkbox
+Text=An old installation
+Left=12
+Right=-1
+Top=92
+Bottom=102
+State=0
+
+[Field 12]
+Type=checkbox
+Text=An old installation
+Left=12
+Right=-1
+Top=102
+Bottom=112
+State=0
+
+[Field 13]
+Type=checkbox
+Text=An old installation
+Left=12
+Right=-1
+Top=112
+Bottom=122
State=0
-Flags=DISABLED \ No newline at end of file
diff --git a/build/conf/nsis/idea.nsi b/build/conf/nsis/idea.nsi
index 5f31dc3c9f3f..e9f4b49f101c 100644
--- a/build/conf/nsis/idea.nsi
+++ b/build/conf/nsis/idea.nsi
@@ -342,7 +342,7 @@ FunctionEnd
!insertmacro MUI_PAGE_WELCOME
-Page custom uninstallOldVersionDialog leaveUninstallOldVersionDialog
+Page custom uninstallOldVersionDialog
Var control_fields
Var max_fields
@@ -367,7 +367,7 @@ Page custom ConfirmDesktopShortcut
!insertmacro MUI_PAGE_FINISH
!define MUI_UNINSTALLER
-!insertmacro MUI_UNPAGE_CONFIRM
+;!insertmacro MUI_UNPAGE_CONFIRM
UninstPage custom un.ConfirmDeleteSettings
!insertmacro MUI_UNPAGE_INSTFILES
@@ -473,10 +473,10 @@ remove_previous_installation:
CopyFiles "$3\bin\${PRODUCT_EXE_FILE}_copy" "$3\bin\${PRODUCT_EXE_FILE}"
Delete "$3\bin\${PRODUCT_EXE_FILE}_copy"
IfErrors 0 +3
- MessageBox MB_YESNOCANCEL|MB_ICONQUESTION|MB_TOPMOST "$(application_running)" IDYES remove_previous_installation IDNO complete
+ MessageBox MB_OKCANCEL|MB_ICONQUESTION|MB_TOPMOST "$(application_running)" IDOK remove_previous_installation IDCANCEL complete
goto complete
; uninstallation mode
- !insertmacro INSTALLOPTIONS_READ $9 "UninstallOldVersions.ini" "Field 3" "State"
+ !insertmacro INSTALLOPTIONS_READ $9 "UninstallOldVersions.ini" "Field 2" "State"
${If} $9 == "1"
ExecWait '"$3\bin\Uninstall.exe" /S'
${else}
@@ -518,8 +518,8 @@ FunctionEnd
Function uninstallOldVersionDialog
- StrCpy $control_fields 3
- StrCpy $max_fields 10
+ StrCpy $control_fields 2
+ StrCpy $max_fields 13
StrCpy $0 "HKLM"
StrCpy $4 0
ReserveFile "UninstallOldVersions.ini"
@@ -562,10 +562,11 @@ ${If} $8 > $control_fields
StrCpy $2 ""
!insertmacro MUI_HEADER_TEXT "$(uninstall_previous_installations_title)" "$(uninstall_previous_installations)"
!insertmacro INSTALLOPTIONS_WRITE "UninstallOldVersions.ini" "Field 1" "Text" "$(uninstall_previous_installations_prompt)"
+ !insertmacro INSTALLOPTIONS_WRITE "UninstallOldVersions.ini" "Field 3" "Flags" "FOCUS"
!insertmacro INSTALLOPTIONS_DISPLAY "UninstallOldVersions.ini"
;uninstall chosen installation(s)
- StrCmp $2 "OK" loop finish
+ ;no disabled controls. StrCmp $2 "OK" loop finish
loop:
!insertmacro INSTALLOPTIONS_READ $0 "UninstallOldVersions.ini" "Field $8" "State"
!insertmacro INSTALLOPTIONS_READ $3 "UninstallOldVersions.ini" "Field $8" "Text"
@@ -579,65 +580,6 @@ finish:
FunctionEnd
-Function leaveUninstallOldVersionDialog
- Push $1
- Push $4
- !insertmacro INSTALLOPTIONS_READ $2 "UninstallOldVersions.ini" "Settings" "State"
- StrCmp $2 2 enable_disable
- Goto done
-
-enable_disable:
- !insertmacro INSTALLOPTIONS_READ $0 "UninstallOldVersions.ini" "Field 2" "State"
- StrCmp $0 1 enable disable
-enable:
- StrCpy $1 ""
- Goto setFlag
-disable:
- Call setState
- StrCpy $1 "DISABLED"
-
-setFlag:
- Push $1
- Call setFlags
-done:
- Pop $4
- Pop $1
- StrCmp $2 0 skip_abort
- Pop $2
- Abort
-skip_abort:
- StrCpy $2 "OK"
-FunctionEnd
-
-Function setFlags
- Pop $1
- !insertmacro INSTALLOPTIONS_READ $max_fields "UninstallOldVersions.ini" "Settings" "NumFields"
- StrCpy $4 3
- ; change flags of fields in according of master checkbox
-loop:
- !insertmacro INSTALLOPTIONS_READ $1 "UninstallOldVersions.ini" "Field $4" "HWND"
- EnableWindow $1 $0
- !insertmacro INSTALLOPTIONS_WRITE "UninstallOldVersions.ini" "Field $4" "Flags" "$1"
- IntOp $4 $4 + 1
- ${If} $4 <= $max_fields
- Goto loop
- ${EndIf}
-FunctionEnd
-
-Function setState
- !insertmacro INSTALLOPTIONS_READ $max_fields "UninstallOldVersions.ini" "Settings" "NumFields"
- StrCpy $4 3
- ; change state of fields in according of master checkbox
-loop:
- !insertmacro INSTALLOPTIONS_READ $1 "UninstallOldVersions.ini" "Field $4" "HWND"
- SendMessage $1 ${BM_SETCHECK} 0 "0"
- !insertmacro INSTALLOPTIONS_WRITE "UninstallOldVersions.ini" "Field $4" "State" 0
- IntOp $4 $4 + 1
- ${If} $4 <= $max_fields
- Goto loop
- ${EndIf}
-FunctionEnd
-
Function getInstallationPath
Push $1
Push $2
@@ -1054,8 +996,10 @@ FunctionEnd
Function un.ConfirmDeleteSettings
!insertmacro MUI_HEADER_TEXT "$(uninstall_options)" "$(uninstall_options_prompt)"
!insertmacro INSTALLOPTIONS_WRITE "DeleteSettings.ini" "Field 1" "Text" "$(prompt_delete_settings)"
- !insertmacro INSTALLOPTIONS_WRITE "DeleteSettings.ini" "Field 2" "Text" "$(confirm_delete_caches)"
- !insertmacro INSTALLOPTIONS_WRITE "DeleteSettings.ini" "Field 3" "Text" "$(confirm_delete_settings)"
+ !insertmacro INSTALLOPTIONS_WRITE "DeleteSettings.ini" "Field 2" "Text" $INSTDIR
+ !insertmacro INSTALLOPTIONS_WRITE "DeleteSettings.ini" "Field 3" "Text" "$(text_delete_settings)"
+ !insertmacro INSTALLOPTIONS_WRITE "DeleteSettings.ini" "Field 4" "Text" "$(confirm_delete_caches)"
+ !insertmacro INSTALLOPTIONS_WRITE "DeleteSettings.ini" "Field 5" "Text" "$(confirm_delete_settings)"
!insertmacro INSTALLOPTIONS_DISPLAY "DeleteSettings.ini"
FunctionEnd
@@ -1133,7 +1077,7 @@ Section "Uninstall"
; Uninstaller is in the \bin directory, we need upper level dir
StrCpy $INSTDIR $INSTDIR\..
- !insertmacro INSTALLOPTIONS_READ $R2 "DeleteSettings.ini" "Field 2" "State"
+ !insertmacro INSTALLOPTIONS_READ $R2 "DeleteSettings.ini" "Field 4" "State"
DetailPrint "Data: $DOCUMENTS\..\${PRODUCT_SETTINGS_DIR}\"
StrCmp $R2 1 "" skip_delete_caches
;find the path to caches (system) folder
@@ -1147,7 +1091,7 @@ Section "Uninstall"
; RmDir /r $DOCUMENTS\..\${PRODUCT_SETTINGS_DIR}\system
skip_delete_caches:
- !insertmacro INSTALLOPTIONS_READ $R3 "DeleteSettings.ini" "Field 3" "State"
+ !insertmacro INSTALLOPTIONS_READ $R3 "DeleteSettings.ini" "Field 5" "State"
StrCmp $R3 1 "" skip_delete_settings
;find the path to settings (config) folder
StrCpy $0 "config"
diff --git a/build/conf/nsis/idea_en.nsi b/build/conf/nsis/idea_en.nsi
index 65d9171c881f..1cb4408d1143 100644
--- a/build/conf/nsis/idea_en.nsi
+++ b/build/conf/nsis/idea_en.nsi
@@ -7,15 +7,16 @@ LangString install_for_current_user_only ${LANG_ENGLISH} "Install for current us
; Uninstall options page
LangString uninstall_options ${LANG_ENGLISH} "Uninstall ${MUI_PRODUCT}"
-LangString uninstall_options_prompt ${LANG_ENGLISH} "Remove ${MUI_PRODUCT} from your computer"
-LangString prompt_delete_settings ${LANG_ENGLISH} "Please confirm if you would like to delete the caches and settings of ${MUI_PRODUCT}."
+LangString uninstall_options_prompt ${LANG_ENGLISH} ""
+LangString prompt_delete_settings ${LANG_ENGLISH} "${MUI_PRODUCT} will be uninstalled from the following folder:"
+LangString text_delete_settings ${LANG_ENGLISH} "Please confirm if you would like to delete the caches and settings:"
LangString confirm_delete_caches ${LANG_ENGLISH} "Delete ${MUI_PRODUCT} ${MUI_VERSION_MAJOR} caches and local history"
LangString confirm_delete_settings ${LANG_ENGLISH} "Delete ${MUI_PRODUCT} ${MUI_VERSION_MAJOR} settings and installed plugins"
; Installation message boxes
LangString current_version_already_installed ${LANG_ENGLISH} "Current version of ${MUI_PRODUCT} is already installed. Do you wish to continue?"
LangString uninstall_previous_installations_title ${LANG_ENGLISH} "Uninstall old versions"
-LangString uninstall_previous_installations ${LANG_ENGLISH} "Installation found old versions of ${MUI_PRODUCT}. You can see list of the installations below."
-LangString uninstall_previous_installations_prompt ${LANG_ENGLISH} "Please select the version$2 of ${MUI_PRODUCT} which you would like to uninstall and mode of uninstallation."
+LangString uninstall_previous_installations ${LANG_ENGLISH} ""
+LangString uninstall_previous_installations_prompt ${LANG_ENGLISH} "Select the ${MUI_PRODUCT} version$2 that you want to uninstall."
LangString empty_or_upgrade_folder ${LANG_ENGLISH} "Please select an empty folder or a folder where ${MUI_PRODUCT} ${UPGRADE_VERSION} is installed as the target for installing ${MUI_PRODUCT}."
-LangString application_running ${LANG_ENGLISH} "Installation detects that $3 is running. Can you stop the application and then continue uninstallation please?"
+LangString application_running ${LANG_ENGLISH} "$3 is running. Close the application and retry the installation."
diff --git a/build/scripts/common_tests.gant b/build/scripts/common_tests.gant
index a74f7d43a0b3..eb21bac9d8a4 100644
--- a/build/scripts/common_tests.gant
+++ b/build/scripts/common_tests.gant
@@ -55,6 +55,7 @@ target('run_tests': 'Run java tests') {
pass("idea.test.group")
pass("idea.test.patterns")
pass("idea.fast.only")
+ pass("idea.coverage.enabled.build")
pass("teamcity.build.tempDir")
pass("teamcity.tests.recentlyFailedTests.file")
jvmarg(value: "-Didea.platform.prefix=Idea")
diff --git a/build/scripts/layouts.gant b/build/scripts/layouts.gant
index 626095994a8b..4c04f9d339bb 100644
--- a/build/scripts/layouts.gant
+++ b/build/scripts/layouts.gant
@@ -345,6 +345,10 @@ public def layoutCommunityPlugins(String home) {
}
layoutPlugin("gradle") {
+ jar("gradle-jps-plugin.jar") {
+ module("gradle-jps-plugin")
+ }
+
jar("gradle-tooling-extension-api.jar") {
module("gradle-tooling-extension-api")
}
@@ -353,6 +357,13 @@ public def layoutCommunityPlugins(String home) {
module("gradle-tooling-extension-impl")
}
fileset(dir: "$home/plugins/gradle/lib") { include(name: "*.jar") }
+ // add kryo lib
+ fileset(dir: "$home/lib/") {
+ include(name: "kryo-*.jar")
+ include(name: "reflectasm-*.jar")
+ include(name: "objenesis-*.jar")
+ include(name: "minlog-*.jar")
+ }
}
layoutPlugin("git4idea") {
@@ -893,6 +904,7 @@ def layoutJps(String home, String targetDir, String buildNumber, Closure additio
jar("maven-jps-plugin.jar") { module("maven-jps-plugin") }
+ jar("gradle-jps-plugin.jar") { module("gradle-jps-plugin") }
fileset(dir: "$home/plugins/maven/maven3-server-impl/lib/maven3/lib") {include(name: "plexus-utils-*.jar")}
jar("eclipse-jps-plugin.jar") {
@@ -945,8 +957,9 @@ def layout_core(String home, String target) {
module("annotations")
}
- jar("intellij-core-analysis-api.jar") {
+ jar("intellij-core-analysis.jar") {
analysisApiModules.each { module it; }
+ analysisImplModules.each { module it; }
}
fileset(dir: "$home/lib") {
diff --git a/build/scripts/libLicenses.gant b/build/scripts/libLicenses.gant
index eaeb82e1c4b4..d495f952b7a8 100644
--- a/build/scripts/libLicenses.gant
+++ b/build/scripts/libLicenses.gant
@@ -50,7 +50,8 @@ def String getLibraryName(JpsLibrary lib) {
def name = lib.name
if (name.startsWith("#")) {
if (lib.getRoots(JpsOrderRootType.COMPILED).size() != 1) {
- projectBuilder.warning("Non-single entry module library $name: $lib.classpath");
+ def urls = lib.getRoots(JpsOrderRootType.COMPILED).collect {it.url}
+ projectBuilder.warning("Non-single entry module library $name: $urls");
}
File file = lib.getFiles(JpsOrderRootType.COMPILED)[0]
return file.name
@@ -213,6 +214,7 @@ libraryLicense(name: "maven-core", version: "3.0.5", libraryNames: ["maven-core-
libraryLicense(name: "plexus-component-annotations", version: "1.5.5", libraryNames: ["plexus-component-annotations-1.5.5.jar"], license: "Apache 2.0", url: "http://maven.apache.org/", licenseUrl: "http://maven.apache.org/license.html")
libraryLicense(name: "Maven3", libraryNames: ["Maven3", "maven-dependency-tree-1.2.jar", "archetype-catalog-2.2.jar", "archetype-common-2.2.jar"], version: "3.0.5", license: "Apache 2.0", url: "http://maven.apache.org/", licenseUrl: "http://maven.apache.org/license.html")
libraryLicense(name: "Gradle", version: "1.12", license: "Apache 2.0", url: "http://gradle.org/", licenseUrl: "http://gradle.org/license")
+libraryLicense(name: "gradle-tooling-api-2.0.jar", version: "2.0", license: "Apache 2.0", url: "http://gradle.org/", licenseUrl: "http://gradle.org/license")
libraryLicense(name: "GradleJnaPosix", version: "1.0.3", license: "LGPL 2.1", url: "http://www.jruby.org/", licenseUrl: "http://www.gnu.org/licenses/lgpl-2.1.txt")
libraryLicense(name: "Slf4j", version: "1.7.2", license: "MIT License", url: "http://slf4j.org/", licenseUrl: "http://slf4j.org/license.html")
libraryLicense(name: "GradleGuava", version: "14.0.1", license: "Apache 2.0", url: "http://code.google.com/p/guava-libraries/", licenseUrl: "http://apache.org/licenses/LICENSE-2.0")
diff --git a/build/scripts/tests.gant b/build/scripts/tests.gant
index d10d72b14112..03b740ccf434 100644
--- a/build/scripts/tests.gant
+++ b/build/scripts/tests.gant
@@ -9,6 +9,7 @@ def isMac = System.getProperty("os.name").toLowerCase().startsWith("mac")
def args = [
"-Xmx1024m",
"-XX:MaxPermSize=630m",
+ "-XX:ReservedCodeCacheSize=96m"
]
if (isMac) args << "-d32";
diff --git a/build/scripts/utils.gant b/build/scripts/utils.gant
index e5eb3eb90c25..f30d8a2c7af2 100644
--- a/build/scripts/utils.gant
+++ b/build/scripts/utils.gant
@@ -53,12 +53,12 @@ binding.setVariable("isEap", {
return "true" == p("component.version.eap")
})
-binding.setVariable("mem32", "-server -Xms128m -Xmx512m -XX:MaxPermSize=250m -XX:ReservedCodeCacheSize=64m")
-binding.setVariable("mem64", "-Xms128m -Xmx750m -XX:MaxPermSize=350m -XX:ReservedCodeCacheSize=96m")
+binding.setVariable("mem32", "-server -Xms128m -Xmx512m -XX:MaxPermSize=250m -XX:ReservedCodeCacheSize=150m")
+binding.setVariable("mem64", "-Xms128m -Xmx750m -XX:MaxPermSize=350m -XX:ReservedCodeCacheSize=225m")
binding.setVariable("common_vmoptions", "-ea -Dsun.io.useCanonCaches=false -Djava.net.preferIPv4Stack=true " +
"-Didea.project.structure.max.errors.to.show=0 " +
"-Djsse.enableSNIExtension=false " +
- "-XX:+UseCodeCacheFlushing -XX:+UseConcMarkSweepGC -XX:SoftRefLRUPolicyMSPerMB=50")
+ "-XX:+UseConcMarkSweepGC -XX:SoftRefLRUPolicyMSPerMB=50")
binding.setVariable("vmOptions", { "$common_vmoptions ${isEap() ? '-XX:+HeapDumpOnOutOfMemoryError' : ''}".trim() })
binding.setVariable("vmOptions32", { "$mem32 ${vmOptions()}".trim() })
@@ -942,3 +942,16 @@ binding.setVariable("analysisApiModules", [
"xml-psi-api",
"xml-structure-view-api",
])
+binding.setVariable("analysisImplModules", [
+ "analysis-impl",
+ "core-impl",
+ "indexing-impl",
+ "java-analysis-impl",
+ "java-indexing-impl",
+ "java-psi-impl",
+ "projectModel-impl",
+ "structure-view-impl",
+ "xml-analysis-impl",
+ "xml-psi-impl",
+ "xml-structure-view-impl",
+])
diff --git a/colorSchemes/src/colorSchemes/Darcula.xml b/colorSchemes/src/colorSchemes/Darcula.xml
index ec6fcc3f3e46..9691e1db6a5e 100644
--- a/colorSchemes/src/colorSchemes/Darcula.xml
+++ b/colorSchemes/src/colorSchemes/Darcula.xml
@@ -702,9 +702,9 @@
</option>
<option name="IDENTIFIER_UNDER_CARET_ATTRIBUTES">
<value>
- <option name="EFFECT_COLOR" value="5d8730" />
- <option name="EFFECT_TYPE" value="1" />
+ <option name="BACKGROUND" value="344134" />
<option name="ERROR_STRIPE_COLOR" value="5d8e48" />
+ <option name="EFFECT_TYPE" value="1" />
</value>
</option>
<option name="IMPLICIT_ANONYMOUS_CLASS_PARAMETER_ATTRIBUTES">
@@ -1572,9 +1572,9 @@
</option>
<option name="WRITE_IDENTIFIER_UNDER_CARET_ATTRIBUTES">
<value>
- <option name="EFFECT_COLOR" value="cc7832" />
- <option name="EFFECT_TYPE" value="1" />
+ <option name="BACKGROUND" value="40332b" />
<option name="ERROR_STRIPE_COLOR" value="cc7832" />
+ <option name="EFFECT_TYPE" value="1" />
</value>
</option>
<option name="WRITE_SEARCH_RESULT_ATTRIBUTES">
diff --git a/java/compiler/impl/compiler-impl.iml b/java/compiler/impl/compiler-impl.iml
index 08d3ca179fc0..c6e3e4f81eab 100644
--- a/java/compiler/impl/compiler-impl.iml
+++ b/java/compiler/impl/compiler-impl.iml
@@ -28,6 +28,7 @@
<orderEntry type="module" module-name="testFramework-java" scope="TEST" />
<orderEntry type="module" module-name="jps-model-impl" />
<orderEntry type="module" module-name="java-analysis-impl" />
+ <orderEntry type="module" module-name="xml" />
</component>
<component name="copyright">
<Base>
diff --git a/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java b/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java
index 03ff006eea40..01da3bc62541 100644
--- a/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java
+++ b/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java
@@ -128,8 +128,6 @@ public class BuildManager implements ApplicationComponent{
private static final String COMPILER_PROCESS_JDK_PROPERTY = "compiler.process.jdk";
public static final String SYSTEM_ROOT = "compile-server";
public static final String TEMP_DIR_NAME = "_temp_";
- private static final int MAKE_TRIGGER_DELAY = 300 /*300 ms*/;
- private static final int DOCUMENT_SAVE_TRIGGER_DELAY = 1500 /*1.5 sec*/;
private final boolean IS_UNIT_TEST_MODE;
private static final String IWS_EXTENSION = ".iws";
private static final String IPR_EXTENSION = ".ipr";
@@ -161,7 +159,7 @@ public class BuildManager implements ApplicationComponent{
private final BuildManagerPeriodicTask myAutoMakeTask = new BuildManagerPeriodicTask() {
@Override
protected int getDelay() {
- return Registry.intValue("compiler.automake.trigger.delay", MAKE_TRIGGER_DELAY);
+ return Registry.intValue("compiler.automake.trigger.delay");
}
@Override
@@ -173,7 +171,7 @@ public class BuildManager implements ApplicationComponent{
private final BuildManagerPeriodicTask myDocumentSaveTask = new BuildManagerPeriodicTask() {
@Override
protected int getDelay() {
- return Registry.intValue("compiler.document.save.trigger.delay", DOCUMENT_SAVE_TRIGGER_DELAY);
+ return Registry.intValue("compiler.document.save.trigger.delay");
}
private final Semaphore mySemaphore = new Semaphore();
@@ -624,7 +622,7 @@ public class BuildManager implements ApplicationComponent{
data = new ProjectData(new SequentialTaskExecutor(PooledThreadExecutor.INSTANCE));
myProjectDataMap.put(projectPath, data);
}
- if (isRebuild || (isAutomake && Registry.is("compiler.automake.force.fs.rescan", false))) {
+ if (isRebuild || (isAutomake && Registry.is("compiler.automake.force.fs.rescan"))) {
data.dropChanges();
}
if (IS_UNIT_TEST_MODE) {
diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactUtil.java b/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactUtil.java
index 5752c3f5f77b..3fcfc8df5529 100644
--- a/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactUtil.java
+++ b/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/ArtifactUtil.java
@@ -26,10 +26,7 @@ import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.packaging.artifacts.Artifact;
-import com.intellij.packaging.artifacts.ArtifactManager;
-import com.intellij.packaging.artifacts.ArtifactProperties;
-import com.intellij.packaging.artifacts.ArtifactType;
+import com.intellij.packaging.artifacts.*;
import com.intellij.packaging.elements.*;
import com.intellij.packaging.impl.elements.*;
import com.intellij.util.PathUtil;
@@ -599,5 +596,31 @@ public class ArtifactUtil {
public static String suggestArtifactFileName(String artifactName) {
return PathUtil.suggestFileName(artifactName, true, true);
}
+
+ @Nullable
+ public static Artifact addArtifact(@NotNull ModifiableArtifactModel artifactModel,
+ @NotNull ArtifactType type,
+ @NotNull ArtifactTemplate artifactTemplate) {
+ final ArtifactTemplate.NewArtifactConfiguration configuration = artifactTemplate.createArtifact();
+ if (configuration == null) {
+ return null;
+ }
+
+ final String baseName = configuration.getArtifactName();
+ String name = baseName;
+ int i = 2;
+ while (artifactModel.findArtifact(name) != null) {
+ name = baseName + i;
+ i++;
+ }
+
+ ArtifactType actualType = configuration.getArtifactType();
+ if (actualType == null) {
+ actualType = type;
+ }
+ final ModifiableArtifact artifact = artifactModel.addArtifact(name, actualType, configuration.getRootElement());
+ artifactTemplate.setUpArtifact(artifact, configuration);
+ return artifact;
+ }
}
diff --git a/java/compiler/impl/src/org/jetbrains/builtInWebServer/ArtifactWebServerRootsProvider.java b/java/compiler/impl/src/org/jetbrains/builtInWebServer/ArtifactWebServerRootsProvider.java
new file mode 100644
index 000000000000..4733ca3747ec
--- /dev/null
+++ b/java/compiler/impl/src/org/jetbrains/builtInWebServer/ArtifactWebServerRootsProvider.java
@@ -0,0 +1,39 @@
+package org.jetbrains.builtInWebServer;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VfsUtilCore;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.packaging.artifacts.Artifact;
+import com.intellij.packaging.artifacts.ArtifactManager;
+import com.intellij.util.PairFunction;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+final class ArtifactWebServerRootsProvider extends PrefixlessWebServerRootsProvider {
+ @Nullable
+ @Override
+ public PathInfo resolve(@NotNull String path, @NotNull Project project, @NotNull PairFunction<String, VirtualFile, VirtualFile> resolver) {
+ for (Artifact artifact : ArtifactManager.getInstance(project).getArtifacts()) {
+ VirtualFile root = artifact.getOutputFile();
+ if (root != null) {
+ VirtualFile file = root.findFileByRelativePath(path);
+ if (file != null) {
+ return new PathInfo(file, root);
+ }
+ }
+ }
+ return null;
+ }
+
+ @Nullable
+ @Override
+ public PathInfo getRoot(@NotNull VirtualFile file, @NotNull Project project) {
+ for (Artifact artifact : ArtifactManager.getInstance(project).getArtifacts()) {
+ VirtualFile root = artifact.getOutputFile();
+ if (root != null && VfsUtilCore.isAncestor(root, file, true)) {
+ return new PathInfo(file, root);
+ }
+ }
+ return null;
+ }
+} \ No newline at end of file
diff --git a/java/compiler/javac2/src/com/intellij/ant/Javac2.java b/java/compiler/javac2/src/com/intellij/ant/Javac2.java
index 88095a9cdc36..e5b8aee7130a 100644
--- a/java/compiler/javac2/src/com/intellij/ant/Javac2.java
+++ b/java/compiler/javac2/src/com/intellij/ant/Javac2.java
@@ -466,7 +466,7 @@ public class Javac2 extends Javac {
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
classfileVersion[0] = version;
}
- }, 0);
+ }, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
return classfileVersion[0];
}
diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/CustomizeContextViewAction.java b/java/debugger/impl/src/com/intellij/debugger/actions/CustomizeContextViewAction.java
index 01d6fcc6e7e8..6214a9e44d7f 100644
--- a/java/debugger/impl/src/com/intellij/debugger/actions/CustomizeContextViewAction.java
+++ b/java/debugger/impl/src/com/intellij/debugger/actions/CustomizeContextViewAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,14 +17,12 @@ package com.intellij.debugger.actions;
import com.intellij.debugger.DebuggerBundle;
import com.intellij.debugger.engine.JavaDebugProcess;
-import com.intellij.debugger.settings.DebuggerDataViewsConfigurable;
+import com.intellij.debugger.settings.JavaDebuggerSettings;
import com.intellij.debugger.settings.NodeRendererSettings;
-import com.intellij.debugger.settings.UserRenderersConfigurable;
import com.intellij.idea.ActionsBundle;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
-import com.intellij.openapi.options.CompositeConfigurable;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.options.TabbedConfigurable;
@@ -40,16 +38,9 @@ import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
-import java.util.ArrayList;
import java.util.List;
-/**
- * User: lex
- * Date: Sep 26, 2003
- * Time: 4:39:53 PM
- */
public class CustomizeContextViewAction extends XDebuggerTreeActionBase {
-
@Override
public void actionPerformed(AnActionEvent e) {
perform(null, "", e);
@@ -58,15 +49,11 @@ public class CustomizeContextViewAction extends XDebuggerTreeActionBase {
@Override
protected void perform(XValueNodeImpl node, @NotNull String nodeName, AnActionEvent e) {
final Project project = CommonDataKeys.PROJECT.getData(e.getDataContext());
-
Disposable disposable = Disposer.newDisposable();
- final CompositeConfigurable configurable = new TabbedConfigurable(disposable) {
+ SingleConfigurableEditor editor = new SingleConfigurableEditor(project, new TabbedConfigurable(disposable) {
@Override
protected List<Configurable> createConfigurables() {
- ArrayList<Configurable> array = new ArrayList<Configurable>();
- array.add(new DebuggerDataViewsConfigurable(project));
- array.add(new UserRenderersConfigurable(project));
- return array;
+ return JavaDebuggerSettings.createDataViewsConfigurable();
}
@Override
@@ -89,13 +76,12 @@ public class CustomizeContextViewAction extends XDebuggerTreeActionBase {
protected void createConfigurableTabs() {
for (Configurable configurable : getConfigurables()) {
JComponent component = configurable.createComponent();
- component.setBorder(new EmptyBorder(8,8,8,8));
+ assert component != null;
+ component.setBorder(new EmptyBorder(8, 8, 8, 8));
myTabbedPane.addTab(configurable.getDisplayName(), component);
}
}
- };
-
- SingleConfigurableEditor editor = new SingleConfigurableEditor(project, configurable);
+ });
Disposer.register(editor.getDisposable(), disposable);
editor.show();
}
diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessEvents.java b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessEvents.java
index 1db0ed60774e..4714ca49bd06 100644
--- a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessEvents.java
+++ b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessEvents.java
@@ -322,10 +322,15 @@ public class DebugProcessEvents extends DebugProcessImpl {
myDebugProcessDispatcher.getMulticaster().processAttached(this);
// breakpoints should be initialized after all processAttached listeners work
- XDebugSession session = getSession().getXDebugSession();
- if (session != null) {
- session.initBreakpoints();
- }
+ ApplicationManager.getApplication().runReadAction(new Runnable() {
+ @Override
+ public void run() {
+ XDebugSession session = getSession().getXDebugSession();
+ if (session != null) {
+ session.initBreakpoints();
+ }
+ }
+ });
final String addressDisplayName = DebuggerBundle.getAddressDisplayName(getConnection());
final String transportName = DebuggerBundle.getTransportName(getConnection());
@@ -459,13 +464,18 @@ public class DebugProcessEvents extends DebugProcessImpl {
if (requestHit && requestor instanceof Breakpoint) {
// if requestor is a breakpoint and this breakpoint was hit, no matter its suspend policy
- XDebugSession session = getSession().getXDebugSession();
- if (session != null) {
- XBreakpoint breakpoint = ((Breakpoint)requestor).getXBreakpoint();
- if (breakpoint != null) {
- ((XDebugSessionImpl)session).processDependencies(breakpoint);
+ ApplicationManager.getApplication().runReadAction(new Runnable() {
+ @Override
+ public void run() {
+ XDebugSession session = getSession().getXDebugSession();
+ if (session != null) {
+ XBreakpoint breakpoint = ((Breakpoint)requestor).getXBreakpoint();
+ if (breakpoint != null) {
+ ((XDebugSessionImpl)session).processDependencies(breakpoint);
+ }
+ }
}
- }
+ });
}
if(!requestHit || resumePreferred) {
diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/JavaBreakpointHandler.java b/java/debugger/impl/src/com/intellij/debugger/engine/JavaBreakpointHandler.java
index ad2c881d1336..75897417bd2e 100644
--- a/java/debugger/impl/src/com/intellij/debugger/engine/JavaBreakpointHandler.java
+++ b/java/debugger/impl/src/com/intellij/debugger/engine/JavaBreakpointHandler.java
@@ -49,13 +49,17 @@ public class JavaBreakpointHandler extends XBreakpointHandler {
if (javaBreakpoint != null) {
final Breakpoint bpt = javaBreakpoint;
BreakpointManager.addBreakpoint(bpt);
- // must use invoke to stay in the current request,
- // otherwise dependent breakpoints do not get enabled on not-suspending parents hit
- myProcess.getManagerThread().invoke(new DebuggerCommandImpl() {
+ // use schedule not to block initBreakpoints
+ myProcess.getManagerThread().schedule(new DebuggerCommandImpl() {
@Override
protected void action() throws Exception {
bpt.createRequest(myProcess);
}
+
+ @Override
+ public Priority getPriority() {
+ return Priority.HIGH;
+ }
});
}
}
@@ -64,12 +68,17 @@ public class JavaBreakpointHandler extends XBreakpointHandler {
public void unregisterBreakpoint(@NotNull final XBreakpoint breakpoint, boolean temporary) {
final Breakpoint javaBreakpoint = BreakpointManager.getJavaBreakpoint(breakpoint);
if (javaBreakpoint != null) {
- // must use invoke to stay in the current request, see comment in registerBreakpoint
- myProcess.getManagerThread().invoke(new DebuggerCommandImpl() {
+ // use schedule not to block initBreakpoints
+ myProcess.getManagerThread().schedule(new DebuggerCommandImpl() {
@Override
protected void action() throws Exception {
javaBreakpoint.delete();
}
+
+ @Override
+ public Priority getPriority() {
+ return Priority.HIGH;
+ }
});
}
}
diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/JavaExecutionStack.java b/java/debugger/impl/src/com/intellij/debugger/engine/JavaExecutionStack.java
index 793438ebbe05..f2cb40008ad5 100644
--- a/java/debugger/impl/src/com/intellij/debugger/engine/JavaExecutionStack.java
+++ b/java/debugger/impl/src/com/intellij/debugger/engine/JavaExecutionStack.java
@@ -26,6 +26,7 @@ import com.intellij.debugger.jdi.ThreadGroupReferenceProxyImpl;
import com.intellij.debugger.jdi.ThreadReferenceProxyImpl;
import com.intellij.debugger.settings.DebuggerSettings;
import com.intellij.debugger.ui.impl.watch.MethodsTracker;
+import com.intellij.debugger.ui.impl.watch.NodeManagerImpl;
import com.intellij.icons.AllIcons;
import com.intellij.xdebugger.frame.XExecutionStack;
import com.sun.jdi.ThreadReference;
@@ -43,6 +44,7 @@ import java.util.Iterator;
public class JavaExecutionStack extends XExecutionStack {
private final ThreadReferenceProxyImpl myThreadProxy;
private final DebugProcessImpl myDebugProcess;
+ private final NodeManagerImpl myNodeManager;
private volatile JavaStackFrame myTopFrame;
private boolean myTopFrameReady = false;
private final MethodsTracker myTracker = new MethodsTracker();
@@ -51,6 +53,7 @@ public class JavaExecutionStack extends XExecutionStack {
super(calcRepresentation(threadProxy), calcIcon(threadProxy, current));
myThreadProxy = threadProxy;
myDebugProcess = debugProcess;
+ myNodeManager = myDebugProcess.getXdebugProcess().getNodeManager();
if (current) {
myTopFrame = calcTopFrame();
}
@@ -81,7 +84,7 @@ public class JavaExecutionStack extends XExecutionStack {
try {
StackFrameProxyImpl frame = myThreadProxy.frame(0);
if (frame != null) {
- return new JavaStackFrame(frame, myDebugProcess, myTracker);
+ return new JavaStackFrame(frame, myDebugProcess, myTracker, myNodeManager);
}
}
catch (EvaluateException e) {
@@ -180,7 +183,7 @@ public class JavaExecutionStack extends XExecutionStack {
@Override
public void contextAction() throws Exception {
if (myStackFramesIterator.hasNext()) {
- JavaStackFrame frame = new JavaStackFrame(myStackFramesIterator.next(), myDebugProcess, myTracker);
+ JavaStackFrame frame = new JavaStackFrame(myStackFramesIterator.next(), myDebugProcess, myTracker, myNodeManager);
if (DebuggerSettings.getInstance().SHOW_LIBRARY_STACKFRAMES || (!frame.getDescriptor().isSynthetic() && !frame.getDescriptor().isInLibraryContent())) {
if (++myAdded > mySkip) {
myContainer.addStackFrames(Arrays.asList(frame), false);
diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/JavaStackFrame.java b/java/debugger/impl/src/com/intellij/debugger/engine/JavaStackFrame.java
index bcd8257736c2..db28c4bf34a7 100644
--- a/java/debugger/impl/src/com/intellij/debugger/engine/JavaStackFrame.java
+++ b/java/debugger/impl/src/com/intellij/debugger/engine/JavaStackFrame.java
@@ -71,9 +71,12 @@ public class JavaStackFrame extends XStackFrame {
private static final JavaFramesListRenderer FRAME_RENDERER = new JavaFramesListRenderer();
private JavaDebuggerEvaluator myEvaluator = null;
- public JavaStackFrame(@NotNull StackFrameProxyImpl stackFrameProxy, @NotNull DebugProcessImpl debugProcess, MethodsTracker tracker) {
+ public JavaStackFrame(@NotNull StackFrameProxyImpl stackFrameProxy,
+ @NotNull DebugProcessImpl debugProcess,
+ @NotNull MethodsTracker tracker,
+ @NotNull NodeManagerImpl nodeManager) {
myDebugProcess = debugProcess;
- myNodeManager = debugProcess.getXdebugProcess().getNodeManager();
+ myNodeManager = nodeManager;
myDescriptor = new StackFrameDescriptorImpl(stackFrameProxy, tracker);
myDescriptor.setContext(null);
myDescriptor.updateRepresentation(null, DescriptorLabelListener.DUMMY_LISTENER);
@@ -311,8 +314,7 @@ public class JavaStackFrame extends XStackFrame {
final Collection<Value> argValues = frame.getArgumentValues();
int index = 0;
for (Value argValue : argValues) {
- final ArgumentValueDescriptorImpl descriptor = myNodeManager.getArgumentValueDescriptor(null, index++, argValue, null);
- children.add(JavaValue.create(descriptor, evaluationContext, myNodeManager));
+ children.add(createArgumentValue(index++, argValue, null, evaluationContext));
}
node.setMessage(MessageDescriptor.LOCAL_VARIABLES_INFO_UNAVAILABLE.getLabel(), XDebuggerUIConstants.INFORMATION_MESSAGE_ICON, SimpleTextAttributes.REGULAR_ATTRIBUTES, null);
//myChildren.add(myNodeManager.createMessageNode(MessageDescriptor.LOCAL_VARIABLES_INFO_UNAVAILABLE));
@@ -323,9 +325,7 @@ public class JavaStackFrame extends XStackFrame {
try {
final Map<DecompiledLocalVariable, Value> values = LocalVariablesUtil.fetchValues(frame.getStackFrame(), decompiled);
for (DecompiledLocalVariable var : decompiled) {
- final Value value = values.get(var);
- final ArgumentValueDescriptorImpl descriptor = myNodeManager.getArgumentValueDescriptor(null, var.getSlot(), value, var.getName());
- children.add(JavaValue.create(descriptor, evaluationContext, myNodeManager));
+ children.add(createArgumentValue(var.getSlot(), values.get(var), var.getName(), evaluationContext));
}
}
catch (Exception ex) {
@@ -339,6 +339,13 @@ public class JavaStackFrame extends XStackFrame {
}
}
+ private JavaValue createArgumentValue(int index, Value value, String name, EvaluationContextImpl evaluationContext) {
+ ArgumentValueDescriptorImpl descriptor = myNodeManager.getArgumentValueDescriptor(null, index, value, name);
+ // setContext is required to calculate correct name
+ descriptor.setContext(evaluationContext);
+ return JavaValue.create(descriptor, evaluationContext, myNodeManager);
+ }
+
protected void superBuildVariables(final EvaluationContextImpl evaluationContext, XValueChildrenList children) throws EvaluateException {
final StackFrameProxyImpl frame = getStackFrameProxy();
for (final LocalVariableProxyImpl local : frame.visibleVariables()) {
@@ -354,6 +361,6 @@ public class JavaStackFrame extends XStackFrame {
@Nullable
@Override
public Object getEqualityObject() {
- return getStackFrameProxy().hashCode();
+ return myDescriptor.getMethod();
}
}
diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/JavaValueMarker.java b/java/debugger/impl/src/com/intellij/debugger/engine/JavaValueMarker.java
index be1b8fae60b9..6a555a87063a 100644
--- a/java/debugger/impl/src/com/intellij/debugger/engine/JavaValueMarker.java
+++ b/java/debugger/impl/src/com/intellij/debugger/engine/JavaValueMarker.java
@@ -30,8 +30,7 @@ public class JavaValueMarker extends XValueMarkerProvider<JavaValue, ObjectRefer
@Override
public boolean canMark(@NotNull JavaValue value) {
- Value obj = value.getDescriptor().getValue();
- return obj instanceof ObjectReference;
+ return value.getDescriptor().canMark();
}
@Override
diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/SuspendManagerImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/SuspendManagerImpl.java
index 576f781dc368..c1f1f87db1a9 100644
--- a/java/debugger/impl/src/com/intellij/debugger/engine/SuspendManagerImpl.java
+++ b/java/debugger/impl/src/com/intellij/debugger/engine/SuspendManagerImpl.java
@@ -15,6 +15,7 @@
*/
package com.intellij.debugger.engine;
+import com.intellij.debugger.engine.events.DebuggerCommandImpl;
import com.intellij.debugger.jdi.ThreadReferenceProxyImpl;
import com.intellij.openapi.diagnostic.Logger;
import com.sun.jdi.InternalException;
@@ -296,7 +297,7 @@ public class SuspendManagerImpl implements SuspendManager {
}
}
- private void processVote(SuspendContextImpl suspendContext) {
+ private void processVote(final SuspendContextImpl suspendContext) {
LOG.assertTrue(suspendContext.myVotesToVote > 0);
suspendContext.myVotesToVote--;
@@ -305,7 +306,18 @@ public class SuspendManagerImpl implements SuspendManager {
}
if(suspendContext.myVotesToVote == 0) {
if(suspendContext.myIsVotedForResume) {
- resume(suspendContext);
+ // resume in a separate request to allow other requests be processed (e.g. dependent bpts enable)
+ myDebugProcess.getManagerThread().schedule(new DebuggerCommandImpl() {
+ @Override
+ protected void action() throws Exception {
+ resume(suspendContext);
+ }
+
+ @Override
+ public Priority getPriority() {
+ return Priority.HIGH;
+ }
+ });
}
else {
if (LOG.isDebugEnabled()) {
diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/MethodEvaluator.java b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/MethodEvaluator.java
index 69cbb140be86..2569559d2d11 100644
--- a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/MethodEvaluator.java
+++ b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/MethodEvaluator.java
@@ -30,7 +30,10 @@ import com.intellij.debugger.engine.evaluation.EvaluateRuntimeException;
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
import com.intellij.debugger.impl.DebuggerUtilsEx;
import com.intellij.openapi.diagnostic.Logger;
-import com.sun.jdi.*;
+import com.sun.jdi.ClassType;
+import com.sun.jdi.Method;
+import com.sun.jdi.ObjectReference;
+import com.sun.jdi.ReferenceType;
import java.util.ArrayList;
import java.util.List;
@@ -127,14 +130,16 @@ public class MethodEvaluator implements Evaluator {
_refType = ((ClassType)referenceType).superclass();
}
Method jdiMethod = DebuggerUtils.findMethod(_refType, myMethodName, signature);
- if (jdiMethod == null || jdiMethod.argumentTypes().size() != args.size()) {
+ if (signature == null) {
+ // we know nothing about expected method's signature, so trying to match my method name and parameter count
// dummy matching, may be improved with types matching later
- List<Method> methods = _refType.methodsByName(myMethodName);
- for (Method method : methods) {
- List<Type> types = method.argumentTypes();
- if (types.size() == args.size()) {
- jdiMethod = method;
- break;
+ // IMPORTANT! using argumentTypeNames() instead of argumentTypes() to avoid type resolution inside JDI, which may be time-consuming
+ if (jdiMethod == null || jdiMethod.argumentTypeNames().size() != args.size()) {
+ for (Method method : _refType.methodsByName(myMethodName)) {
+ if (method.argumentTypeNames().size() == args.size()) {
+ jdiMethod = method;
+ break;
+ }
}
}
}
diff --git a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerManagerImpl.java b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerManagerImpl.java
index f5404cd65023..79c1db31db3c 100644
--- a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerManagerImpl.java
+++ b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerManagerImpl.java
@@ -28,6 +28,7 @@ import com.intellij.execution.configurations.JavaParameters;
import com.intellij.execution.configurations.ModuleRunProfile;
import com.intellij.execution.configurations.RemoteConnection;
import com.intellij.execution.configurations.RunProfileState;
+import com.intellij.execution.process.KillableColoredProcessHandler;
import com.intellij.execution.process.ProcessAdapter;
import com.intellij.execution.process.ProcessEvent;
import com.intellij.execution.process.ProcessHandler;
@@ -286,7 +287,8 @@ public class DebuggerManagerImpl extends DebuggerManagerEx implements Persistent
final DebugProcessImpl debugProcess = getDebugProcess(event.getProcessHandler());
if (debugProcess != null) {
// if current thread is a "debugger manager thread", stop will execute synchronously
- debugProcess.stop(willBeDestroyed);
+ // it is KillableColoredProcessHandler responsibility to terminate VM
+ debugProcess.stop(willBeDestroyed && !(event.getProcessHandler() instanceof KillableColoredProcessHandler));
// wait at most 10 seconds: the problem is that debugProcess.stop() can hang if there are troubles in the debuggee
// if processWillTerminate() is called from AWT thread debugProcess.waitFor() will block it and the whole app will hang
diff --git a/java/debugger/impl/src/com/intellij/debugger/impl/JavaEditorTextProviderImpl.java b/java/debugger/impl/src/com/intellij/debugger/impl/JavaEditorTextProviderImpl.java
index 7b76b9738843..02f4ee44fd53 100644
--- a/java/debugger/impl/src/com/intellij/debugger/impl/JavaEditorTextProviderImpl.java
+++ b/java/debugger/impl/src/com/intellij/debugger/impl/JavaEditorTextProviderImpl.java
@@ -110,7 +110,9 @@ public class JavaEditorTextProviderImpl implements EditorTextProvider {
else if (parent instanceof PsiInstanceOfExpression
|| parent instanceof PsiBinaryExpression
|| parent instanceof PsiPolyadicExpression
- || parent instanceof PsiPrefixExpression) {
+ || parent instanceof PsiPrefixExpression
+ || parent instanceof PsiConditionalExpression
+ ) {
if (allowMethodCalls || !DebuggerUtils.hasSideEffects(parent)) {
expression = parent;
}
diff --git a/java/debugger/impl/src/com/intellij/debugger/settings/CompoundRendererConfigurable.java b/java/debugger/impl/src/com/intellij/debugger/settings/CompoundRendererConfigurable.java
index e570b642b2bd..a4484cccc1fe 100644
--- a/java/debugger/impl/src/com/intellij/debugger/settings/CompoundRendererConfigurable.java
+++ b/java/debugger/impl/src/com/intellij/debugger/settings/CompoundRendererConfigurable.java
@@ -25,14 +25,10 @@ import com.intellij.debugger.impl.DebuggerUtilsEx;
import com.intellij.debugger.ui.DebuggerExpressionTextField;
import com.intellij.debugger.ui.JavaDebuggerSupport;
import com.intellij.debugger.ui.tree.render.*;
-import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.options.ConfigurationException;
-import com.intellij.openapi.options.UnnamedConfigurable;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
@@ -41,7 +37,7 @@ import com.intellij.ui.table.JBTable;
import com.intellij.util.Function;
import com.intellij.util.ui.AbstractTableCellEditor;
import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.table.AbstractTableModel;
@@ -52,57 +48,33 @@ import java.awt.event.*;
import java.util.ArrayList;
import java.util.List;
-/**
- * @author Eugene Zhuravlev
- * Date: Feb 24, 2005
- */
-public class CompoundRendererConfigurable implements UnnamedConfigurable {
+class CompoundRendererConfigurable extends JPanel {
private CompoundReferenceRenderer myRenderer;
private CompoundReferenceRenderer myOriginalRenderer;
private Project myProject;
- private ClassNameEditorWithBrowseButton myClassNameField;
- private JRadioButton myRbDefaultLabel;
- private JRadioButton myRbExpressionLabel;
- private JRadioButton myRbDefaultChildrenRenderer;
- private JRadioButton myRbExpressionChildrenRenderer;
- private JRadioButton myRbListChildrenRenderer;
- private DebuggerExpressionTextField myLabelEditor;
- private DebuggerExpressionTextField myChildrenEditor;
- private DebuggerExpressionTextField myChildrenExpandedEditor;
+ private final ClassNameEditorWithBrowseButton myClassNameField;
+ private final JRadioButton myRbDefaultLabel;
+ private final JRadioButton myRbExpressionLabel;
+ private final JRadioButton myRbDefaultChildrenRenderer;
+ private final JRadioButton myRbExpressionChildrenRenderer;
+ private final JRadioButton myRbListChildrenRenderer;
+ private final DebuggerExpressionTextField myLabelEditor;
+ private final DebuggerExpressionTextField myChildrenEditor;
+ private final DebuggerExpressionTextField myChildrenExpandedEditor;
private DebuggerExpressionTextField myListChildrenEditor;
- private JComponent myChildrenListEditor;
- private JLabel myExpandedLabel;
- private JPanel myMainPanel;
+ private final JLabel myExpandedLabel;
private JBTable myTable;
@NonNls private static final String EMPTY_PANEL_ID = "EMPTY";
@NonNls private static final String DATA_PANEL_ID = "DATA";
private static final int NAME_TABLE_COLUMN = 0;
private static final int EXPRESSION_TABLE_COLUMN = 1;
- public CompoundRendererConfigurable(@Nullable Project project) {
- myProject = project;
- }
-
- public void setRenderer(NodeRenderer renderer) {
- if (renderer instanceof CompoundReferenceRenderer) {
- myRenderer = (CompoundReferenceRenderer)renderer;
- myOriginalRenderer = (CompoundReferenceRenderer)renderer.clone();
- }
- else {
- myRenderer = myOriginalRenderer = null;
- }
- reset();
- }
-
- public CompoundReferenceRenderer getRenderer() {
- return myRenderer;
- }
+ public CompoundRendererConfigurable() {
+ super(new CardLayout());
- public JComponent createComponent() {
if (myProject == null) {
myProject = JavaDebuggerSupport.getContextProjectForEditorFieldsInDebuggerConfigurables();
}
- final JPanel panel = new JPanel(new GridBagLayout());
myRbDefaultLabel = new JRadioButton(DebuggerBundle.message("label.compound.renderer.configurable.use.default.renderer"));
myRbExpressionLabel = new JRadioButton(DebuggerBundle.message("label.compound.renderer.configurable.use.expression"));
@@ -121,10 +93,11 @@ public class CompoundRendererConfigurable implements UnnamedConfigurable {
myLabelEditor = new DebuggerExpressionTextField(myProject, null, "ClassLabelExpression");
myChildrenEditor = new DebuggerExpressionTextField(myProject, null, "ClassChildrenExpression");
myChildrenExpandedEditor = new DebuggerExpressionTextField(myProject, null, "ClassChildrenExpression");
- myChildrenListEditor = createChildrenListEditor();
+ JComponent myChildrenListEditor = createChildrenListEditor();
final ItemListener updateListener = new ItemListener() {
- public void itemStateChanged(ItemEvent e) {
+ @Override
+ public void itemStateChanged(@NotNull ItemEvent e) {
updateEnabledState();
}
};
@@ -133,7 +106,8 @@ public class CompoundRendererConfigurable implements UnnamedConfigurable {
myRbExpressionChildrenRenderer.addItemListener(updateListener);
myClassNameField = new ClassNameEditorWithBrowseButton(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
+ @Override
+ public void actionPerformed(@NotNull ActionEvent e) {
PsiClass psiClass = DebuggerUtils.getInstance()
.chooseClassDialog(DebuggerBundle.message("title.compound.renderer.configurable.choose.renderer.reference.type"), myProject);
if (psiClass != null) {
@@ -143,20 +117,14 @@ public class CompoundRendererConfigurable implements UnnamedConfigurable {
}
}
}, myProject);
- final EditorTextField textField = myClassNameField.getEditorTextField();
- final FocusAdapter updateContextListener = new FocusAdapter() {
- public void focusLost(FocusEvent e) {
- updateContext(myClassNameField.getText());
- }
- };
- textField.addFocusListener(updateContextListener);
- Disposer.register(myClassNameField, new Disposable() {
+ myClassNameField.getEditorTextField().addFocusListener(new FocusAdapter() {
@Override
- public void dispose() {
- textField.removeFocusListener(updateContextListener);
+ public void focusLost(@NotNull FocusEvent e) {
+ updateContext(myClassNameField.getText());
}
});
+ JPanel panel = new JPanel(new GridBagLayout());
panel.add(new JLabel(DebuggerBundle.message("label.compound.renderer.configurable.apply.to")),
new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE,
new Insets(0, 0, 0, 0), 0, 0));
@@ -197,15 +165,28 @@ public class CompoundRendererConfigurable implements UnnamedConfigurable {
panel.add(myChildrenListEditor,
new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH,
new Insets(4, 30, 0, 0), 0, 0));
+ add(new JPanel(), EMPTY_PANEL_ID);
+ add(panel, DATA_PANEL_ID);
+ }
- myMainPanel = new JPanel(new CardLayout());
- myMainPanel.add(new JPanel(), EMPTY_PANEL_ID);
- myMainPanel.add(panel, DATA_PANEL_ID);
- return myMainPanel;
+ public void setRenderer(NodeRenderer renderer) {
+ if (renderer instanceof CompoundReferenceRenderer) {
+ myRenderer = (CompoundReferenceRenderer)renderer;
+ myOriginalRenderer = (CompoundReferenceRenderer)renderer.clone();
+ }
+ else {
+ myRenderer = myOriginalRenderer = null;
+ }
+ reset();
+ }
+
+ public CompoundReferenceRenderer getRenderer() {
+ return myRenderer;
}
private void updateContext(final String qName) {
ApplicationManager.getApplication().runReadAction(new Runnable() {
+ @Override
public void run() {
final Project project = myProject;
final PsiClass psiClass = project != null ? DebuggerUtils.findClass(qName, project, GlobalSearchScope.allScope(project)) : null;
@@ -214,6 +195,7 @@ public class CompoundRendererConfigurable implements UnnamedConfigurable {
myChildrenExpandedEditor.setContext(psiClass);
myListChildrenEditor.setContext(psiClass);
+ assert project != null;
PsiType type = DebuggerUtils.getType(qName, project);
myLabelEditor.setThisType(type);
myChildrenEditor.setThisType(type);
@@ -251,17 +233,21 @@ public class CompoundRendererConfigurable implements UnnamedConfigurable {
final TableColumn exprColumn = myTable.getColumnModel().getColumn(EXPRESSION_TABLE_COLUMN);
exprColumn.setCellEditor(new AbstractTableCellEditor() {
+ @Override
public Object getCellEditorValue() {
return myListChildrenEditor.getText();
}
+ @Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
myListChildrenEditor.setText((TextWithImports)value);
return myListChildrenEditor;
}
});
exprColumn.setCellRenderer(new DefaultTableCellRenderer() {
- public Component getTableCellRendererComponent(JTable table,
+ @NotNull
+ @Override
+ public Component getTableCellRendererComponent(@NotNull JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
@@ -309,7 +295,7 @@ public class CompoundRendererConfigurable implements UnnamedConfigurable {
return !DebuggerUtilsEx.externalizableEqual(cloned, myOriginalRenderer);
}
- public void apply() throws ConfigurationException {
+ public void apply() {
if (myRenderer == null) {
return;
}
@@ -342,7 +328,7 @@ public class CompoundRendererConfigurable implements UnnamedConfigurable {
public void reset() {
final TextWithImports emptyExpressionFragment = new TextWithImportsImpl(CodeFragmentKind.EXPRESSION, "");
- ((CardLayout)myMainPanel.getLayout()).show(myMainPanel, myRenderer == null ? EMPTY_PANEL_ID : DATA_PANEL_ID);
+ ((CardLayout)getLayout()).show(this, myRenderer == null ? EMPTY_PANEL_ID : DATA_PANEL_ID);
if (myRenderer == null) {
return;
}
@@ -390,27 +376,11 @@ public class CompoundRendererConfigurable implements UnnamedConfigurable {
updateContext(className);
}
- public void disposeUIResources() {
- myRenderer = null;
- myOriginalRenderer = null;
- myLabelEditor.dispose();
- myChildrenEditor.dispose();
- myChildrenExpandedEditor.dispose();
- myListChildrenEditor.dispose();
- Disposer.dispose(myClassNameField);
- myLabelEditor = null;
- myChildrenEditor = null;
- myChildrenExpandedEditor = null;
- myListChildrenEditor = null;
- myClassNameField = null;
- myProject = null;
- }
-
private MyTableModel getTableModel() {
return (MyTableModel)myTable.getModel();
}
- private final class MyTableModel extends AbstractTableModel {
+ private static final class MyTableModel extends AbstractTableModel {
private final List<Row> myData = new ArrayList<Row>();
public MyTableModel() {
@@ -423,18 +393,23 @@ public class CompoundRendererConfigurable implements UnnamedConfigurable {
}
}
+ @Override
public int getColumnCount() {
return 2;
}
+ @Override
public int getRowCount() {
return myData.size();
}
+ @Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return true;
}
+ @NotNull
+ @Override
public Class getColumnClass(int columnIndex) {
switch (columnIndex) {
case NAME_TABLE_COLUMN:
@@ -446,6 +421,7 @@ public class CompoundRendererConfigurable implements UnnamedConfigurable {
}
}
+ @Override
public Object getValueAt(int rowIndex, int columnIndex) {
if (rowIndex >= getRowCount()) {
return null;
@@ -461,6 +437,7 @@ public class CompoundRendererConfigurable implements UnnamedConfigurable {
}
}
+ @Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
if (rowIndex >= getRowCount()) {
return;
@@ -476,6 +453,8 @@ public class CompoundRendererConfigurable implements UnnamedConfigurable {
}
}
+ @NotNull
+ @Override
public String getColumnName(int columnIndex) {
switch (columnIndex) {
case NAME_TABLE_COLUMN:
@@ -513,7 +492,7 @@ public class CompoundRendererConfigurable implements UnnamedConfigurable {
return pairs;
}
- private final class Row {
+ private static final class Row {
public String name;
public TextWithImports value;
diff --git a/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerLaunchingConfigurable.java b/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerLaunchingConfigurable.java
index 490f99bb5461..b0748cfd336d 100644
--- a/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerLaunchingConfigurable.java
+++ b/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerLaunchingConfigurable.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,24 +16,23 @@
package com.intellij.debugger.settings;
import com.intellij.debugger.DebuggerBundle;
-import com.intellij.openapi.options.Configurable;
-import com.intellij.openapi.options.OptionsBundle;
+import com.intellij.openapi.options.ConfigurableUi;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.ui.StateRestoringCheckBox;
import com.intellij.ui.components.panels.VerticalBox;
+import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
-public class DebuggerLaunchingConfigurable implements Configurable {
+class DebuggerLaunchingConfigurable implements ConfigurableUi<DebuggerSettings> {
private JRadioButton myRbSocket;
private JRadioButton myRbShmem;
private StateRestoringCheckBox myCbForceClassicVM;
private JCheckBox myCbDisableJIT;
@Override
- public void reset() {
- final DebuggerSettings settings = DebuggerSettings.getInstance();
+ public void reset(@NotNull DebuggerSettings settings) {
if (!SystemInfo.isWindows) {
myRbSocket.setSelected(true);
myRbShmem.setEnabled(false);
@@ -52,8 +51,8 @@ public class DebuggerLaunchingConfigurable implements Configurable {
}
@Override
- public void apply() {
- getSettingsTo(DebuggerSettings.getInstance());
+ public void apply(@NotNull DebuggerSettings settings) {
+ getSettingsTo(settings);
}
private void getSettingsTo(DebuggerSettings settings) {
@@ -68,25 +67,15 @@ public class DebuggerLaunchingConfigurable implements Configurable {
}
@Override
- public boolean isModified() {
- final DebuggerSettings currentSettings = DebuggerSettings.getInstance();
- final DebuggerSettings debuggerSettings = currentSettings.clone();
+ public boolean isModified(@NotNull DebuggerSettings currentSettings) {
+ DebuggerSettings debuggerSettings = currentSettings.clone();
getSettingsTo(debuggerSettings);
return !debuggerSettings.equals(currentSettings);
}
+ @NotNull
@Override
- public String getDisplayName() {
- return OptionsBundle.message("options.java.display.name");
- }
-
- @Override
- public String getHelpTopic() {
- return "reference.idesettings.debugger.launching";
- }
-
- @Override
- public JComponent createComponent() {
+ public JComponent getComponent() {
myCbForceClassicVM = new StateRestoringCheckBox(DebuggerBundle.message("label.debugger.launching.configurable.force.classic.vm"));
myCbDisableJIT = new JCheckBox(DebuggerBundle.message("label.debugger.launching.configurable.disable.jit"));
myRbSocket = new JRadioButton(DebuggerBundle.message("label.debugger.launching.configurable.socket"));
@@ -110,12 +99,6 @@ public class DebuggerLaunchingConfigurable implements Configurable {
JPanel result = new JPanel(new BorderLayout());
result.add(panel, BorderLayout.NORTH);
-
return result;
}
-
-
- @Override
- public void disposeUIResources() {
- }
} \ No newline at end of file
diff --git a/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerSteppingConfigurable.java b/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerSteppingConfigurable.java
index cec458ccbb70..cf7e367f1ce8 100644
--- a/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerSteppingConfigurable.java
+++ b/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerSteppingConfigurable.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,10 +17,7 @@ package com.intellij.debugger.settings;
import com.intellij.debugger.DebuggerBundle;
import com.intellij.debugger.ui.JavaDebuggerSupport;
-import com.intellij.openapi.options.Configurable;
-import com.intellij.openapi.options.OptionsBundle;
-import com.intellij.openapi.options.SearchableConfigurable;
-import com.intellij.openapi.project.Project;
+import com.intellij.openapi.options.ConfigurableUi;
import com.intellij.ui.classFilter.ClassFilterEditor;
import org.jetbrains.annotations.NotNull;
@@ -29,18 +26,16 @@ import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
-public class DebuggerSteppingConfigurable implements SearchableConfigurable, Configurable.NoScroll {
+class DebuggerSteppingConfigurable implements ConfigurableUi<DebuggerSettings> {
private JCheckBox myCbStepInfoFiltersEnabled;
private JCheckBox myCbSkipSyntheticMethods;
private JCheckBox myCbSkipConstructors;
private JCheckBox myCbSkipClassLoaders;
private ClassFilterEditor mySteppingFilterEditor;
private JCheckBox myCbSkipSimpleGetters;
- private Project myProject;
@Override
- public void reset() {
- final DebuggerSettings settings = DebuggerSettings.getInstance();
+ public void reset(@NotNull DebuggerSettings settings) {
myCbSkipSimpleGetters.setSelected(settings.SKIP_GETTERS);
myCbSkipSyntheticMethods.setSelected(settings.SKIP_SYNTHETIC_METHODS);
myCbSkipConstructors.setSelected(settings.SKIP_CONSTRUCTORS);
@@ -50,13 +45,11 @@ public class DebuggerSteppingConfigurable implements SearchableConfigurable, Con
mySteppingFilterEditor.setFilters(settings.getSteppingFilters());
mySteppingFilterEditor.setEnabled(settings.TRACING_FILTERS_ENABLED);
-
-
}
@Override
- public void apply() {
- getSettingsTo(DebuggerSettings.getInstance());
+ public void apply(@NotNull DebuggerSettings settings) {
+ getSettingsTo(settings);
}
private void getSettingsTo(DebuggerSettings settings) {
@@ -71,39 +64,16 @@ public class DebuggerSteppingConfigurable implements SearchableConfigurable, Con
}
@Override
- public boolean isModified() {
- final DebuggerSettings currentSettings = DebuggerSettings.getInstance();
- final DebuggerSettings debuggerSettings = currentSettings.clone();
+ public boolean isModified(@NotNull DebuggerSettings currentSettings) {
+ DebuggerSettings debuggerSettings = currentSettings.clone();
getSettingsTo(debuggerSettings);
return !debuggerSettings.equals(currentSettings);
}
@Override
- public String getDisplayName() {
- return OptionsBundle.message("options.java.display.name");
- }
-
- @Override
@NotNull
- public String getHelpTopic() {
- return "reference.idesettings.debugger.stepping";
- }
-
- @Override
- @NotNull
- public String getId() {
- return getHelpTopic();
- }
-
- @Override
- public Runnable enableSearch(String option) {
- return null;
- }
-
- @Override
- public JComponent createComponent() {
+ public JComponent getComponent() {
final JPanel panel = new JPanel(new GridBagLayout());
- myProject = JavaDebuggerSupport.getContextProjectForEditorFieldsInDebuggerConfigurables();
myCbSkipSyntheticMethods = new JCheckBox(DebuggerBundle.message("label.debugger.general.configurable.skip.synthetic.methods"));
myCbSkipConstructors = new JCheckBox(DebuggerBundle.message("label.debugger.general.configurable.skip.constructors"));
myCbSkipClassLoaders = new JCheckBox(DebuggerBundle.message("label.debugger.general.configurable.skip.classLoaders"));
@@ -115,7 +85,7 @@ public class DebuggerSteppingConfigurable implements SearchableConfigurable, Con
panel.add(myCbSkipSimpleGetters, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0),0, 0));
panel.add(myCbStepInfoFiltersEnabled, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(8, 0, 0, 0),0, 0));
- mySteppingFilterEditor = new ClassFilterEditor(myProject, null, "reference.viewBreakpoints.classFilters.newPattern");
+ mySteppingFilterEditor = new ClassFilterEditor(JavaDebuggerSupport.getContextProjectForEditorFieldsInDebuggerConfigurables(), null, "reference.viewBreakpoints.classFilters.newPattern");
panel.add(mySteppingFilterEditor, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 5, 0, 0),0, 0));
myCbStepInfoFiltersEnabled.addActionListener(new ActionListener() {
@@ -126,11 +96,4 @@ public class DebuggerSteppingConfigurable implements SearchableConfigurable, Con
});
return panel;
}
-
- @Override
- public void disposeUIResources() {
- mySteppingFilterEditor = null;
- myProject = null;
- }
-
-}
+} \ No newline at end of file
diff --git a/java/debugger/impl/src/com/intellij/debugger/settings/JavaDebuggerSettings.java b/java/debugger/impl/src/com/intellij/debugger/settings/JavaDebuggerSettings.java
index 7151cb9f650e..e6f271b3981a 100644
--- a/java/debugger/impl/src/com/intellij/debugger/settings/JavaDebuggerSettings.java
+++ b/java/debugger/impl/src/com/intellij/debugger/settings/JavaDebuggerSettings.java
@@ -15,41 +15,78 @@
*/
package com.intellij.debugger.settings;
+import com.intellij.debugger.DebuggerBundle;
import com.intellij.openapi.options.Configurable;
+import com.intellij.openapi.options.OptionsBundle;
+import com.intellij.openapi.options.SimpleConfigurable;
+import com.intellij.openapi.util.Getter;
+import com.intellij.xdebugger.settings.DebuggerSettingsCategory;
import com.intellij.xdebugger.settings.XDebuggerSettings;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import static java.util.Collections.singletonList;
+
/**
* We cannot now transform DebuggerSettings to XDebuggerSettings: getState/loadState is not called for EP,
* but we cannot use standard implementation to save our state, due to backward compatibility we must use own state spec.
- *
+ * <p/>
* But we must implement createConfigurable as part of XDebuggerSettings otherwise java general settings will be before xdebugger general setting,
* because JavaDebuggerSettingsPanelProvider has higher priority than XDebuggerSettingsPanelProviderImpl.
*/
-class JavaDebuggerSettings extends XDebuggerSettings<Element> {
+public class JavaDebuggerSettings extends XDebuggerSettings<Element> {
protected JavaDebuggerSettings() {
super("java");
}
- @Nullable
+ @NotNull
@Override
- public Configurable createConfigurable(@NotNull Category category) {
+ public Collection<? extends Configurable> createConfigurables(@NotNull DebuggerSettingsCategory category) {
+ Getter<DebuggerSettings> settingsGetter = new Getter<DebuggerSettings>() {
+ @Override
+ public DebuggerSettings get() {
+ return DebuggerSettings.getInstance();
+ }
+ };
+
switch (category) {
- case ROOT:
- return new DebuggerLaunchingConfigurable();
+ case GENERAL:
+ return singletonList(SimpleConfigurable.create("reference.idesettings.debugger.launching", OptionsBundle.message("options.java.display.name"),
+ DebuggerLaunchingConfigurable.class, settingsGetter));
case DATA_VIEWS:
- return new DebuggerDataViewsConfigurable(null);
+ return createDataViewsConfigurable();
case STEPPING:
- return new DebuggerSteppingConfigurable();
+ return singletonList(SimpleConfigurable.create("reference.idesettings.debugger.stepping", OptionsBundle.message("options.java.display.name"),
+ DebuggerSteppingConfigurable.class, settingsGetter));
+ case HOTSWAP:
+ return singletonList(SimpleConfigurable.create("reference.idesettings.debugger.hotswap", OptionsBundle.message("options.java.display.name"),
+ JavaHotSwapConfigurableUi.class, settingsGetter));
}
- return null;
+ return Collections.emptyList();
+ }
+
+ @SuppressWarnings("SpellCheckingInspection")
+ @NotNull
+ public static List<Configurable> createDataViewsConfigurable() {
+ return Arrays.<Configurable>asList(new DebuggerDataViewsConfigurable(null),
+ SimpleConfigurable.create("reference.idesettings.debugger.typerenderers", DebuggerBundle.message("user.renderers.configurable.display.name"),
+ UserRenderersConfigurable.class, new Getter<NodeRendererSettings>() {
+ @Override
+ public NodeRendererSettings get() {
+ return NodeRendererSettings.getInstance();
+ }
+ }));
}
@Override
- public void generalApplied(@NotNull XDebuggerSettings.Category category) {
- if (category == XDebuggerSettings.Category.DATA_VIEWS) {
+ public void generalApplied(@NotNull DebuggerSettingsCategory category) {
+ if (category == DebuggerSettingsCategory.DATA_VIEWS) {
NodeRendererSettings.getInstance().fireRenderersChanged();
}
}
diff --git a/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerHotswapConfigurable.java b/java/debugger/impl/src/com/intellij/debugger/settings/JavaHotSwapConfigurableUi.java
index a70be30556e2..82a33a895fcb 100644
--- a/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerHotswapConfigurable.java
+++ b/java/debugger/impl/src/com/intellij/debugger/settings/JavaHotSwapConfigurableUi.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,14 +16,14 @@
package com.intellij.debugger.settings;
import com.intellij.debugger.DebuggerBundle;
-import com.intellij.openapi.options.SearchableConfigurable;
+import com.intellij.openapi.options.ConfigurableUi;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.border.Border;
import java.awt.*;
-public class DebuggerHotswapConfigurable implements SearchableConfigurable {
+class JavaHotSwapConfigurableUi implements ConfigurableUi<DebuggerSettings> {
private JCheckBox myHotswapInBackground;
private JCheckBox myCbCompileBeforeHotswap;
private JCheckBox myCbHangWarningEnabled;
@@ -31,8 +31,8 @@ public class DebuggerHotswapConfigurable implements SearchableConfigurable {
private JRadioButton myRbNever;
private JRadioButton myRbAsk;
- public void reset() {
- final DebuggerSettings settings = DebuggerSettings.getInstance();
+ @Override
+ public void reset(@NotNull DebuggerSettings settings) {
myHotswapInBackground.setSelected(settings.HOTSWAP_IN_BACKGROUND);
myCbCompileBeforeHotswap.setSelected(settings.COMPILE_BEFORE_HOTSWAP);
myCbHangWarningEnabled.setSelected(settings.HOTSWAP_HANG_WARNING_ENABLED);
@@ -48,8 +48,9 @@ public class DebuggerHotswapConfigurable implements SearchableConfigurable {
}
}
- public void apply() {
- getSettingsTo(DebuggerSettings.getInstance());
+ @Override
+ public void apply(@NotNull DebuggerSettings settings) {
+ getSettingsTo(settings);
}
private void getSettingsTo(DebuggerSettings settings) {
@@ -68,31 +69,16 @@ public class DebuggerHotswapConfigurable implements SearchableConfigurable {
}
}
- public boolean isModified() {
- final DebuggerSettings currentSettings = DebuggerSettings.getInstance();
+ @Override
+ public boolean isModified(@NotNull DebuggerSettings currentSettings) {
final DebuggerSettings debuggerSettings = currentSettings.clone();
getSettingsTo(debuggerSettings);
return !debuggerSettings.equals(currentSettings);
}
- public String getDisplayName() {
- return DebuggerBundle.message("debugger.hotswap.configurable.display.name");
- }
-
- public String getHelpTopic() {
- return "reference.idesettings.debugger.hotswap";
- }
-
@NotNull
- public String getId() {
- return getHelpTopic();
- }
-
- public Runnable enableSearch(String option) {
- return null;
- }
-
- public JComponent createComponent() {
+ @Override
+ public JComponent getComponent() {
final JPanel panel = new JPanel(new GridBagLayout());
myCbCompileBeforeHotswap = new JCheckBox(DebuggerBundle.message("label.debugger.hotswap.configurable.compile.before.hotswap"));
@@ -130,9 +116,4 @@ public class DebuggerHotswapConfigurable implements SearchableConfigurable {
return panel;
}
-
-
- public void disposeUIResources() {
- }
-
-}
+} \ No newline at end of file
diff --git a/java/debugger/impl/src/com/intellij/debugger/settings/UserRenderersConfigurable.java b/java/debugger/impl/src/com/intellij/debugger/settings/UserRenderersConfigurable.java
index 3ab2028d5813..3a8505c7dfe8 100644
--- a/java/debugger/impl/src/com/intellij/debugger/settings/UserRenderersConfigurable.java
+++ b/java/debugger/impl/src/com/intellij/debugger/settings/UserRenderersConfigurable.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,17 +20,12 @@ import com.intellij.debugger.ui.tree.render.CompoundNodeRenderer;
import com.intellij.debugger.ui.tree.render.NodeRenderer;
import com.intellij.ide.util.ElementsChooser;
import com.intellij.openapi.actionSystem.*;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.options.Configurable;
-import com.intellij.openapi.options.ConfigurationException;
-import com.intellij.openapi.options.SearchableConfigurable;
-import com.intellij.openapi.project.Project;
+import com.intellij.openapi.options.ConfigurableUi;
import com.intellij.ui.DocumentAdapter;
import com.intellij.util.IconUtil;
import com.intellij.util.PlatformIcons;
import com.intellij.util.containers.InternalIterator;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
@@ -40,56 +35,25 @@ import java.awt.*;
import java.util.ArrayList;
import java.util.List;
-/**
- * @author Eugene Zhuravlev
- * Date: Feb 19, 2005
- */
-public class UserRenderersConfigurable implements SearchableConfigurable, Configurable.NoScroll {
- private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.settings.UserRenderersConfigurable");
+public final class UserRenderersConfigurable extends JPanel implements ConfigurableUi<NodeRendererSettings> {
private static final Icon ADD_ICON = IconUtil.getAddIcon();
private static final Icon REMOVE_ICON = IconUtil.getRemoveIcon();
private static final Icon COPY_ICON = PlatformIcons.COPY_ICON;
private static final Icon UP_ICON = IconUtil.getMoveUpIcon();
private static final Icon DOWN_ICON = IconUtil.getMoveDownIcon();
- private JPanel myNameFieldPanel;
- private JTextField myNameField;
+ private final JPanel myNameFieldPanel;
+ private final JTextField myNameField;
private ElementsChooser<NodeRenderer> myRendererChooser;
private NodeRenderer myCurrentRenderer = null;
- private final CompoundRendererConfigurable myRendererDataConfigurable;
-
- public UserRenderersConfigurable(@Nullable Project project) {
- myRendererDataConfigurable = new CompoundRendererConfigurable(project);
- }
-
- public String getDisplayName() {
- return DebuggerBundle.message("user.renderers.configurable.display.name");
- }
-
- public String getHelpTopic() {
- return "reference.idesettings.debugger.typerenderers";
- }
-
- @NotNull
- public String getId() {
- return getHelpTopic();
- }
-
- public Runnable enableSearch(String option) {
- return null;
- }
-
- public JComponent createComponent() {
- final JPanel panel = new JPanel(new BorderLayout(4, 0));
+ private final CompoundRendererConfigurable myRendererDataConfigurable = new CompoundRendererConfigurable();
- final JComponent renderersList = createRenderersList();
- final JComponent toolbar = createToolbar();
- final JComponent rendererDataPanel = myRendererDataConfigurable.createComponent();
+ public UserRenderersConfigurable() {
+ super(new BorderLayout(4, 0));
- final JPanel left = new JPanel(new BorderLayout());
-
- left.add(toolbar, BorderLayout.NORTH);
- left.add(renderersList, BorderLayout.CENTER);
+ JPanel left = new JPanel(new BorderLayout());
+ left.add(createToolbar(), BorderLayout.NORTH);
+ left.add(createRenderersList(), BorderLayout.CENTER);
myNameField = new JTextField();
myNameFieldPanel = new JPanel(new BorderLayout());
@@ -98,11 +62,11 @@ public class UserRenderersConfigurable implements SearchableConfigurable, Config
myNameFieldPanel.setVisible(false);
final JPanel center = new JPanel(new BorderLayout(0, 4));
-
center.add(myNameFieldPanel, BorderLayout.NORTH);
- center.add(rendererDataPanel, BorderLayout.CENTER);
+ center.add(myRendererDataConfigurable, BorderLayout.CENTER);
myNameField.getDocument().addDocumentListener(new DocumentAdapter() {
+ @Override
protected void textChanged(DocumentEvent e) {
if (myCurrentRenderer != null) {
myCurrentRenderer.setName(myNameField.getText());
@@ -111,10 +75,14 @@ public class UserRenderersConfigurable implements SearchableConfigurable, Config
}
});
- panel.add(left, BorderLayout.WEST);
- panel.add(center, BorderLayout.CENTER);
+ add(left, BorderLayout.WEST);
+ add(center, BorderLayout.CENTER);
+ }
- return panel;
+ @Override
+ @NotNull
+ public JComponent getComponent() {
+ return this;
}
private JComponent createRenderersList() {
@@ -122,12 +90,14 @@ public class UserRenderersConfigurable implements SearchableConfigurable, Config
myRendererChooser.getEmptyText().setText(DebuggerBundle.message("text.user.renderers.configurable.no.renderers"));
myRendererChooser.addElementsMarkListener(new ElementsChooser.ElementsMarkListener<NodeRenderer>() {
+ @Override
public void elementMarkChanged(final NodeRenderer element, final boolean isMarked) {
element.setEnabled(isMarked);
}
});
myRendererChooser.addListSelectionListener(new ListSelectionListener() {
- public void valueChanged(ListSelectionEvent e) {
+ @Override
+ public void valueChanged(@NotNull ListSelectionEvent e) {
if (!e.getValueIsAdjusting()) {
updateCurrentRenderer(myRendererChooser.getSelectedElements());
}
@@ -138,7 +108,7 @@ public class UserRenderersConfigurable implements SearchableConfigurable, Config
private void updateCurrentRenderer(List<NodeRenderer> selectedElements) {
if (selectedElements.size() != 1) {
- // multiselection
+ // multi selection
setCurrentRenderer(null);
}
else {
@@ -150,13 +120,8 @@ public class UserRenderersConfigurable implements SearchableConfigurable, Config
if (myCurrentRenderer == renderer) {
return;
}
- try {
- if (myRendererDataConfigurable.isModified()) {
- myRendererDataConfigurable.apply();
- }
- }
- catch (ConfigurationException e) {
- LOG.error(e);
+ if (myRendererDataConfigurable.isModified()) {
+ myRendererDataConfigurable.apply();
}
myCurrentRenderer = renderer;
if (renderer != null) {
@@ -181,11 +146,12 @@ public class UserRenderersConfigurable implements SearchableConfigurable, Config
return toolbar.getComponent();
}
- public void apply() throws ConfigurationException {
+ @Override
+ public void apply(@NotNull NodeRendererSettings settings) {
myRendererDataConfigurable.apply();
- flushTo(NodeRendererSettings.getInstance().getCustomRenderers());
+ flushTo(settings.getCustomRenderers());
- NodeRendererSettings.getInstance().fireRenderersChanged();
+ settings.fireRenderersChanged();
}
private void flushTo(final RendererConfiguration rendererConfiguration) {
@@ -197,11 +163,11 @@ public class UserRenderersConfigurable implements SearchableConfigurable, Config
rendererConfiguration.setRenderers(renderers);
}
- public boolean isModified() {
+ @Override
+ public boolean isModified(@NotNull NodeRendererSettings settings) {
if (myRendererDataConfigurable.isModified()) {
return true;
}
- final NodeRendererSettings settings = NodeRendererSettings.getInstance();
final RendererConfiguration rendererConfiguration = settings.getCustomRenderers();
if (myRendererChooser.getElementCount() != rendererConfiguration.getRendererCount()) {
return true;
@@ -211,11 +177,13 @@ public class UserRenderersConfigurable implements SearchableConfigurable, Config
return !uiConfiguration.equals(rendererConfiguration);
}
- public void reset() {
+ @Override
+ public void reset(@NotNull NodeRendererSettings settings) {
myRendererChooser.removeAllElements();
- final RendererConfiguration rendererConfiguration = NodeRendererSettings.getInstance().getCustomRenderers();
+ final RendererConfiguration rendererConfiguration = settings.getCustomRenderers();
final ArrayList<NodeRenderer> elementsToSelect = new ArrayList<NodeRenderer>(1);
rendererConfiguration.iterateRenderers(new InternalIterator<NodeRenderer>() {
+ @Override
public boolean visit(final NodeRenderer renderer) {
final NodeRenderer clonedRenderer = (NodeRenderer)renderer.clone();
myRendererChooser.addElement(clonedRenderer, clonedRenderer.isEnabled());
@@ -230,21 +198,18 @@ public class UserRenderersConfigurable implements SearchableConfigurable, Config
myRendererDataConfigurable.reset();
}
- public void disposeUIResources() {
- myRendererChooser.removeAllElements();
- myRendererDataConfigurable.disposeUIResources();
- }
-
private class AddAction extends AnAction {
public AddAction() {
super(DebuggerBundle.message("button.add"), DebuggerBundle.message("user.renderers.configurable.button.description.add"), ADD_ICON);
}
+ @Override
public void actionPerformed(AnActionEvent e) {
final NodeRenderer renderer = (NodeRenderer)NodeRendererSettings.getInstance().createRenderer(CompoundNodeRenderer.UNIQUE_ID);
renderer.setEnabled(true);
myRendererChooser.addElement(renderer, renderer.isEnabled());
SwingUtilities.invokeLater(new Runnable() {
+ @Override
public void run() {
myNameField.requestFocus();
}
@@ -257,16 +222,18 @@ public class UserRenderersConfigurable implements SearchableConfigurable, Config
super(DebuggerBundle.message("button.remove"), DebuggerBundle.message("user.renderers.configurable.button.description.remove"), REMOVE_ICON);
}
+ @Override
public void actionPerformed(AnActionEvent e) {
for (NodeRenderer selectedElement : myRendererChooser.getSelectedElements()) {
myRendererChooser.removeElement(selectedElement);
}
}
+ @Override
public void update(AnActionEvent e) {
super.update(e);
- final Presentation presentation = e.getPresentation();
- presentation.setEnabled(myRendererChooser.getSelectedElement() != null);
+
+ e.getPresentation().setEnabled(myRendererChooser.getSelectedElement() != null);
}
}
@@ -275,18 +242,18 @@ public class UserRenderersConfigurable implements SearchableConfigurable, Config
super(DebuggerBundle.message("button.copy"), DebuggerBundle.message("user.renderers.configurable.button.description.copy"), COPY_ICON);
}
+ @Override
public void actionPerformed(AnActionEvent e) {
final NodeRenderer selectedElement = myRendererChooser.getSelectedElement();
if (selectedElement != null) {
- final NodeRenderer cloned = (NodeRenderer)selectedElement.clone();
- myRendererChooser.addElement(cloned, true);
+ myRendererChooser.addElement((NodeRenderer)selectedElement.clone(), true);
}
}
+ @Override
public void update(AnActionEvent e) {
super.update(e);
- final Presentation presentation = e.getPresentation();
- presentation.setEnabled(myRendererChooser.getSelectedElement() != null);
+ e.getPresentation().setEnabled(myRendererChooser.getSelectedElement() != null);
}
}
@@ -300,6 +267,7 @@ public class UserRenderersConfigurable implements SearchableConfigurable, Config
myMoveUp = up;
}
+ @Override
public void actionPerformed(AnActionEvent e) {
final int selectedRow = myRendererChooser.getSelectedElementRow();
if (selectedRow < 0) {
@@ -315,10 +283,10 @@ public class UserRenderersConfigurable implements SearchableConfigurable, Config
myRendererChooser.moveElement(myRendererChooser.getElementAt(selectedRow), newRow);
}
+ @Override
public void update(AnActionEvent e) {
super.update(e);
- final Presentation presentation = e.getPresentation();
- presentation.setEnabled(myRendererChooser.getSelectedElement() != null);
+ e.getPresentation().setEnabled(myRendererChooser.getSelectedElement() != null);
}
}
}
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerPanelsManager.java b/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerPanelsManager.java
index 3809431c21f8..13336358620b 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerPanelsManager.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerPanelsManager.java
@@ -214,7 +214,7 @@ public class DebuggerPanelsManager implements ProjectComponent {
public void toFront(DebuggerSession session) {
DebuggerSessionTab sessionTab = getSessionTab(session);
if (sessionTab != null) {
- sessionTab.toFront();
+ sessionTab.toFront(true);
}
}
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/JavaDebuggerSupport.java b/java/debugger/impl/src/com/intellij/debugger/ui/JavaDebuggerSupport.java
index 27f63e032314..20d95f8fff3d 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/JavaDebuggerSupport.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/JavaDebuggerSupport.java
@@ -18,9 +18,6 @@ package com.intellij.debugger.ui;
import com.intellij.debugger.DebuggerManagerEx;
import com.intellij.debugger.actions.*;
import com.intellij.debugger.impl.DebuggerContextImpl;
-import com.intellij.debugger.settings.DebuggerHotswapConfigurable;
-import com.intellij.debugger.settings.NodeRendererSettings;
-import com.intellij.debugger.settings.UserRenderersConfigurable;
import com.intellij.debugger.ui.breakpoints.Breakpoint;
import com.intellij.ide.DataManager;
import com.intellij.openapi.Disposable;
@@ -28,7 +25,6 @@ import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.markup.GutterIconRenderer;
-import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.xdebugger.AbstractDebuggerSession;
@@ -42,13 +38,11 @@ import com.intellij.xdebugger.impl.actions.MarkObjectActionHandler;
import com.intellij.xdebugger.impl.breakpoints.ui.BreakpointItem;
import com.intellij.xdebugger.impl.breakpoints.ui.BreakpointPanelProvider;
import com.intellij.xdebugger.impl.evaluate.quick.common.QuickEvaluateHandler;
-import com.intellij.xdebugger.impl.settings.DebuggerSettingsPanelProvider;
import com.intellij.xdebugger.impl.ui.DebuggerUIUtil;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
-import java.util.ArrayList;
import java.util.Collection;
/**
@@ -68,7 +62,6 @@ public class JavaDebuggerSupport extends DebuggerSupport {
private final ShowExecutionPointActionHandler myShowExecutionPointActionHandler = new ShowExecutionPointActionHandler();
//private final EvaluateActionHandler myEvaluateActionHandler = new EvaluateActionHandler();
private final QuickEvaluateActionHandler myQuickEvaluateHandler = new QuickEvaluateActionHandler();
- private final JavaDebuggerSettingsPanelProvider myDebuggerSettingsPanelProvider = new JavaDebuggerSettingsPanelProvider();
private final DebuggerActionHandler mySmartStepIntoHandler = new JvmSmartStepIntoActionHandler();
private final DebuggerActionHandler myAddToWatchedActionHandler = new AddToWatchActionHandler();
private final JavaMarkObjectActionHandler myMarkObjectActionHandler = new JavaMarkObjectActionHandler();
@@ -118,13 +111,13 @@ public class JavaDebuggerSupport extends DebuggerSupport {
@Override
@NotNull
public DebuggerActionHandler getRunToCursorHandler() {
- return myRunToCursorActionHandler;
+ return DISABLED;
}
@Override
@NotNull
public DebuggerActionHandler getForceRunToCursorHandler() {
- return myForceRunToCursorActionHandler;
+ return DISABLED;
}
@Override
@@ -216,12 +209,6 @@ public class JavaDebuggerSupport extends DebuggerSupport {
return X_EDIT;
}
- @Override
- @NotNull
- public DebuggerSettingsPanelProvider getSettingsPanelProvider() {
- return myDebuggerSettingsPanelProvider;
- }
-
private static class JavaBreakpointPanelProvider extends BreakpointPanelProvider<Breakpoint> {
//private final List<MyBreakpointManagerListener> myListeners = ContainerUtil.createLockFreeCopyOnWriteList();
@@ -335,27 +322,6 @@ public class JavaDebuggerSupport extends DebuggerSupport {
//}
}
- final static class JavaDebuggerSettingsPanelProvider extends DebuggerSettingsPanelProvider {
- @Override
- public int getPriority() {
- return 1;
- }
-
- @NotNull
- @Override
- public Collection<? extends Configurable> getConfigurables() {
- final ArrayList<Configurable> configurables = new ArrayList<Configurable>();
- configurables.add(new UserRenderersConfigurable(null));
- configurables.add(new DebuggerHotswapConfigurable());
- return configurables;
- }
-
- @Override
- public void apply() {
- NodeRendererSettings.getInstance().fireRenderersChanged();
- }
- }
-
public static Project getContextProjectForEditorFieldsInDebuggerConfigurables() {
//todo[nik] improve
Project project = CommonDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext());
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/XBreakpointGroupingByPackageRule.java b/java/debugger/impl/src/com/intellij/debugger/ui/XBreakpointGroupingByPackageRule.java
index f06574569db8..98c772d75044 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/XBreakpointGroupingByPackageRule.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/XBreakpointGroupingByPackageRule.java
@@ -63,6 +63,6 @@ public class XBreakpointGroupingByPackageRule<B> extends XBreakpointGroupingRule
@Nullable
@Override
public Icon getIcon() {
- return AllIcons.Nodes.Package;
+ return AllIcons.Actions.GroupByPackage;
}
}
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/AnyExceptionBreakpoint.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/AnyExceptionBreakpoint.java
index ebbef2c2ec44..414960b1980a 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/AnyExceptionBreakpoint.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/AnyExceptionBreakpoint.java
@@ -51,7 +51,7 @@ public class AnyExceptionBreakpoint extends ExceptionBreakpoint {
public void createRequest(DebugProcessImpl debugProcess) {
DebuggerManagerThreadImpl.assertIsManagerThread();
- if (!isEnabled() || !debugProcess.isAttached() || debugProcess.areBreakpointsMuted() || !debugProcess.getRequestsManager().findRequests(this).isEmpty()) {
+ if (!shouldCreateRequest(debugProcess)) {
return;
}
super.processClassPrepare(debugProcess, null);
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/Breakpoint.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/Breakpoint.java
index 6879407b3c9a..328dc5f2cd77 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/Breakpoint.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/Breakpoint.java
@@ -33,6 +33,7 @@ import com.intellij.debugger.requests.ClassPrepareRequestor;
import com.intellij.debugger.settings.DebuggerSettings;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.JDOMExternalizerUtil;
import com.intellij.openapi.util.Key;
@@ -46,6 +47,7 @@ import com.intellij.xdebugger.XExpression;
import com.intellij.xdebugger.breakpoints.SuspendPolicy;
import com.intellij.xdebugger.breakpoints.XBreakpoint;
import com.intellij.xdebugger.breakpoints.XLineBreakpoint;
+import com.intellij.xdebugger.impl.XDebugSessionImpl;
import com.intellij.xdebugger.impl.XDebuggerHistoryManager;
import com.intellij.xdebugger.impl.XDebuggerUtilImpl;
import com.intellij.xdebugger.impl.breakpoints.XBreakpointBase;
@@ -95,7 +97,20 @@ public abstract class Breakpoint<P extends JavaBreakpointProperties> implements
* Request for creating all needed JPDA requests in the specified VM
* @param debuggerProcess the requesting process
*/
- public abstract void createRequest(DebugProcessImpl debuggerProcess);
+ public abstract void createRequest(DebugProcessImpl debugProcess);
+
+ protected boolean shouldCreateRequest(final DebugProcessImpl debugProcess) {
+ return ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
+ @Override
+ public Boolean compute() {
+ JavaDebugProcess process = debugProcess.getXdebugProcess();
+ return process != null
+ && debugProcess.isAttached()
+ && ((XDebugSessionImpl)process.getSession()).isBreakpointActive(myXBreakpoint)
+ && debugProcess.getRequestsManager().findRequests(Breakpoint.this).isEmpty();
+ }
+ });
+ }
/**
* Request for creating all needed JPDA requests in the specified VM
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointWithHighlighter.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointWithHighlighter.java
index d6cbf1487ab9..cc373743736d 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointWithHighlighter.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointWithHighlighter.java
@@ -17,10 +17,7 @@ package com.intellij.debugger.ui.breakpoints;
import com.intellij.CommonBundle;
import com.intellij.debugger.*;
-import com.intellij.debugger.engine.DebugProcess;
-import com.intellij.debugger.engine.DebugProcessImpl;
-import com.intellij.debugger.engine.DebuggerManagerThreadImpl;
-import com.intellij.debugger.engine.JVMNameUtil;
+import com.intellij.debugger.engine.*;
import com.intellij.debugger.engine.events.DebuggerCommandImpl;
import com.intellij.debugger.engine.requests.RequestManagerImpl;
import com.intellij.debugger.impl.DebuggerContextImpl;
@@ -300,10 +297,7 @@ public abstract class BreakpointWithHighlighter<P extends JavaBreakpointProperti
public void createRequest(@NotNull DebugProcessImpl debugProcess) {
DebuggerManagerThreadImpl.assertIsManagerThread();
// check is this breakpoint is enabled, vm reference is valid and there're no requests created yet
- if (!isEnabled() ||
- !debugProcess.isAttached() ||
- isMuted(debugProcess) ||
- !debugProcess.getRequestsManager().findRequests(this).isEmpty()) {
+ if (!shouldCreateRequest(debugProcess)) {
return;
}
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/ExceptionBreakpoint.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/ExceptionBreakpoint.java
index 88ddf4882733..e4f404e909c7 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/ExceptionBreakpoint.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/ExceptionBreakpoint.java
@@ -118,7 +118,7 @@ public class ExceptionBreakpoint extends Breakpoint<JavaExceptionBreakpointPrope
public void createRequest(final DebugProcessImpl debugProcess) {
DebuggerManagerThreadImpl.assertIsManagerThread();
- if (!isEnabled() || !debugProcess.isAttached() || debugProcess.areBreakpointsMuted() || !debugProcess.getRequestsManager().findRequests(this).isEmpty()) {
+ if (!shouldCreateRequest(debugProcess)) {
return;
}
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointTypeBase.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointTypeBase.java
index a537db14b2e8..4e1d3e2adb3f 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointTypeBase.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointTypeBase.java
@@ -63,7 +63,7 @@ public abstract class JavaBreakpointTypeBase<T extends JavaBreakpointProperties>
Breakpoint javaBreakpoint = BreakpointManager.getJavaBreakpoint(breakpoint);
if (javaBreakpoint != null) {
PsiClass aClass = javaBreakpoint.getPsiClass();
- if (aClass != null && aClass.getContainingFile() != null) {
+ if (aClass != null && aClass.getContainingFile() != null && aClass.getTextOffset() >= 0) {
return XDebuggerUtil.getInstance().createPositionByOffset(aClass.getContainingFile().getVirtualFile(), aClass.getTextOffset());
}
}
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/RunToCursorBreakpoint.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/RunToCursorBreakpoint.java
index 5b5233a92157..4d43a2b0d557 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/RunToCursorBreakpoint.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/RunToCursorBreakpoint.java
@@ -123,4 +123,9 @@ public class RunToCursorBreakpoint extends LineBreakpoint {
return new RunToCursorBreakpoint(project, pos, restoreBreakpoints);
}
+
+ @Override
+ protected boolean shouldCreateRequest(DebugProcessImpl debugProcess) {
+ return debugProcess.isAttached() && debugProcess.getRequestsManager().findRequests(this).isEmpty();
+ }
}
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/WildcardMethodBreakpoint.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/WildcardMethodBreakpoint.java
index c106f65cab81..e8b947c0e865 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/WildcardMethodBreakpoint.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/WildcardMethodBreakpoint.java
@@ -129,7 +129,7 @@ public class WildcardMethodBreakpoint extends Breakpoint<JavaMethodBreakpointPro
public void createRequest(DebugProcessImpl debugProcess) {
DebuggerManagerThreadImpl.assertIsManagerThread();
- if (!isEnabled() || !debugProcess.isAttached() || debugProcess.areBreakpointsMuted() || !debugProcess.getRequestsManager().findRequests(this).isEmpty()) {
+ if (!shouldCreateRequest(debugProcess)) {
return;
}
try {
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ValueDescriptorImpl.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ValueDescriptorImpl.java
index abda6968def4..f4da39f318a7 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ValueDescriptorImpl.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ValueDescriptorImpl.java
@@ -484,7 +484,7 @@ public abstract class ValueDescriptorImpl extends NodeDescriptorImpl implements
}
public boolean canSetValue() {
- return !myIsSynthetic && isLvalue();
+ return myValueReady && !myIsSynthetic && isLvalue();
}
public String getValueLabel() {
@@ -534,4 +534,10 @@ public abstract class ValueDescriptorImpl extends NodeDescriptorImpl implements
}
}
+ public boolean canMark() {
+ if (!myValueReady) {
+ return false;
+ }
+ return getValue() instanceof ObjectReference;
+ }
}
diff --git a/java/execution/impl/src/com/intellij/execution/application/ApplicationConfigurable.java b/java/execution/impl/src/com/intellij/execution/application/ApplicationConfigurable.java
index 04af179638cd..27958a922d2c 100644
--- a/java/execution/impl/src/com/intellij/execution/application/ApplicationConfigurable.java
+++ b/java/execution/impl/src/com/intellij/execution/application/ApplicationConfigurable.java
@@ -85,7 +85,7 @@ public class ApplicationConfigurable extends SettingsEditor<ApplicationConfigura
public void resetEditorFrom(final ApplicationConfiguration configuration) {
myCommonProgramParameters.reset(configuration);
myModuleSelector.reset(configuration);
- getMainClassField().setText(configuration.MAIN_CLASS_NAME.replaceAll("\\$", "\\."));
+ getMainClassField().setText(configuration.MAIN_CLASS_NAME != null ? configuration.MAIN_CLASS_NAME.replaceAll("\\$", "\\.") : "");
myAlternativeJREPanel.init(configuration.ALTERNATIVE_JRE_PATH, configuration.ALTERNATIVE_JRE_PATH_ENABLED);
updateShowSwingInspector(configuration);
diff --git a/java/execution/impl/src/com/intellij/execution/application/ApplicationConfiguration.java b/java/execution/impl/src/com/intellij/execution/application/ApplicationConfiguration.java
index 2370ad3bda71..578d5fbba6ea 100644
--- a/java/execution/impl/src/com/intellij/execution/application/ApplicationConfiguration.java
+++ b/java/execution/impl/src/com/intellij/execution/application/ApplicationConfiguration.java
@@ -21,6 +21,7 @@ import com.intellij.execution.configuration.EnvironmentVariablesComponent;
import com.intellij.execution.configurations.*;
import com.intellij.execution.filters.TextConsoleBuilderFactory;
import com.intellij.execution.junit.RefactoringListeners;
+import com.intellij.execution.process.KillableColoredProcessHandler;
import com.intellij.execution.process.OSProcessHandler;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.util.JavaParametersUtil;
@@ -33,6 +34,7 @@ import com.intellij.openapi.options.SettingsEditorGroup;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.DefaultJDOMExternalizer;
import com.intellij.openapi.util.InvalidDataException;
+import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
@@ -285,12 +287,17 @@ public class ApplicationConfiguration extends ModuleBasedConfiguration<JavaRunCo
@NotNull
@Override
protected OSProcessHandler startProcess() throws ExecutionException {
- final OSProcessHandler handler = super.startProcess();
+ OSProcessHandler handler = SystemInfo.isWindows ? super.startProcess() : KillableColoredProcessHandler.create(createCommandLine());
RunnerSettings runnerSettings = getRunnerSettings();
JavaRunConfigurationExtensionManager.getInstance().attachExtensionsToProcess(myConfiguration, handler, runnerSettings);
return handler;
}
+ @Override
+ protected boolean ansiColoringEnabled() {
+ return true;
+ }
+
protected ApplicationConfiguration getConfiguration() {
return myConfiguration;
}
diff --git a/java/execution/impl/src/com/intellij/execution/impl/DefaultJavaProgramRunner.java b/java/execution/impl/src/com/intellij/execution/impl/DefaultJavaProgramRunner.java
index d472761b017e..3190e19dcee4 100644
--- a/java/execution/impl/src/com/intellij/execution/impl/DefaultJavaProgramRunner.java
+++ b/java/execution/impl/src/com/intellij/execution/impl/DefaultJavaProgramRunner.java
@@ -224,9 +224,10 @@ public class DefaultJavaProgramRunner extends JavaPatchableProgramRunner {
threadStates = ThreadDumpParser.parse(stdout);
if (threadStates == null || threadStates.isEmpty()) {
try {
+ //noinspection BusyWait
Thread.sleep(50);
}
- catch (InterruptedException e1) {
+ catch (InterruptedException ignored) {
//
}
threadStates = null;
diff --git a/java/idea-ui/src/com/intellij/ide/projectWizard/NewProjectWizard.java b/java/idea-ui/src/com/intellij/ide/projectWizard/NewProjectWizard.java
index fbe8636ee360..7627d9396fc5 100644
--- a/java/idea-ui/src/com/intellij/ide/projectWizard/NewProjectWizard.java
+++ b/java/idea-ui/src/com/intellij/ide/projectWizard/NewProjectWizard.java
@@ -46,6 +46,7 @@ public class NewProjectWizard extends AbstractProjectWizard {
protected void init(@NotNull ModulesProvider modulesProvider) {
myWizardContext.setNewWizard(true);
+ myWizardContext.setModulesProvider(modulesProvider);
ProjectTypeStep projectTypeStep = new ProjectTypeStep(myWizardContext, this, modulesProvider);
Disposer.register(getDisposable(), projectTypeStep);
mySequence.addCommonStep(projectTypeStep);
diff --git a/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypeStep.java b/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypeStep.java
index 2ed47fd7cb13..8fca04c7aa69 100644
--- a/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypeStep.java
+++ b/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypeStep.java
@@ -126,6 +126,7 @@ public class ProjectTypeStep extends ModuleWizardStep implements SettingsStep, D
private final Map<String, ModuleWizardStep> myCustomSteps = new HashMap<String, ModuleWizardStep>();
private final MultiMap<TemplatesGroup,ProjectTemplate> myTemplatesMap;
private String myCurrentCard;
+ private TemplatesGroup myLastSelectedGroup;
public ProjectTypeStep(WizardContext context, NewProjectWizard wizard, ModulesProvider modulesProvider) {
myContext = context;
@@ -369,7 +370,8 @@ public class ProjectTypeStep extends ModuleWizardStep implements SettingsStep, D
// new TemplatesGroup selected
public void projectTypeChanged() {
TemplatesGroup group = getSelectedGroup();
- if (group == null) return;
+ if (group == null || group == myLastSelectedGroup) return;
+ myLastSelectedGroup = group;
PropertiesComponent.getInstance().setValue(PROJECT_WIZARD_GROUP, group.getId() );
ModuleBuilder groupModuleBuilder = group.getModuleBuilder();
diff --git a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/impl/FrameworkSupportModelBase.java b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/impl/FrameworkSupportModelBase.java
index 036675179e6f..6c281b0def27 100644
--- a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/impl/FrameworkSupportModelBase.java
+++ b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/impl/FrameworkSupportModelBase.java
@@ -107,6 +107,8 @@ public abstract class FrameworkSupportModelBase extends UserDataHolderBase imple
final FrameworkSupportNode node = mySettingsMap.get(providerId);
if (node != null && enable != node.isChecked()) {
node.setChecked(enable);
+ // ensure configurable to be created and registered to disposer
+ node.getConfigurable();
}
}
diff --git a/java/idea-ui/src/com/intellij/ide/util/projectWizard/NamePathComponent.java b/java/idea-ui/src/com/intellij/ide/util/projectWizard/NamePathComponent.java
index d76fa7437167..da18f37c2290 100644
--- a/java/idea-ui/src/com/intellij/ide/util/projectWizard/NamePathComponent.java
+++ b/java/idea-ui/src/com/intellij/ide/util/projectWizard/NamePathComponent.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,12 +19,12 @@ import com.intellij.ide.IdeBundle;
import com.intellij.ide.highlighter.ProjectFileType;
import com.intellij.ide.util.BrowseFilesListener;
import com.intellij.openapi.application.ApplicationInfo;
-import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.DocumentAdapter;
import com.intellij.ui.FieldPanel;
@@ -138,52 +138,40 @@ public class NamePathComponent extends JPanel{
return component;
}
- private String getProjectFilePath(boolean isDefault) {
- if (isDefault) {
- return getPath() + "/" + getNameValue() + ProjectFileType.DOT_DEFAULT_EXTENSION;
- }
- else {
- return getPath() + "/" + Project.DIRECTORY_STORE_FOLDER;
- }
- }
-
- public boolean validateNameAndPath(WizardContext context, boolean defaultFormat) throws
- ConfigurationException {
- final String name = getNameValue();
- if (name.length() == 0) {
- final ApplicationInfo info = ApplicationManager.getApplication().getComponent(ApplicationInfo.class);
- throw new ConfigurationException(
- IdeBundle.message("prompt.new.project.file.name", info.getVersionName(), context.getPresentationName()));
+ public boolean validateNameAndPath(WizardContext context, boolean defaultFormat) throws ConfigurationException {
+ String name = getNameValue();
+ if (StringUtil.isEmptyOrSpaces(name)) {
+ ApplicationInfo info = ApplicationInfo.getInstance();
+ throw new ConfigurationException(IdeBundle.message("prompt.new.project.file.name", info.getVersionName(), context.getPresentationName()));
}
- final String projectFileDirectory = getPath();
- if (projectFileDirectory.length() == 0) {
+ String projectDirectory = getPath();
+ if (StringUtil.isEmptyOrSpaces(projectDirectory)) {
throw new ConfigurationException(IdeBundle.message("prompt.enter.project.file.location", context.getPresentationName()));
}
- if (myShouldBeAbsolute && !new File(projectFileDirectory).isAbsolute()) {
+ if (myShouldBeAbsolute && !new File(projectDirectory).isAbsolute()) {
throw new ConfigurationException(StringUtil.capitalize(IdeBundle.message("file.location.should.be.absolute", context.getPresentationName())));
}
- final boolean shouldPromptCreation = isPathChangedByUser();
- if (!ProjectWizardUtil
- .createDirectoryIfNotExists(IdeBundle.message("directory.project.file.directory", context.getPresentationName()),
- projectFileDirectory, shouldPromptCreation)) {
+
+ boolean shouldPromptCreation = isPathChangedByUser();
+ String message = IdeBundle.message("directory.project.file.directory", context.getPresentationName());
+ if (!ProjectWizardUtil.createDirectoryIfNotExists(message, projectDirectory, shouldPromptCreation)) {
return false;
}
- final File file = new File(projectFileDirectory);
+ File file = new File(projectDirectory);
if (file.exists() && !file.canWrite()) {
- throw new ConfigurationException(String.format("Directory '%s' is not writable!\nPlease choose another project location.", projectFileDirectory));
+ throw new ConfigurationException(String.format("Directory '%s' is not writable!\nPlease choose another project location.", projectDirectory));
}
boolean shouldContinue = true;
- final File projectFile = new File(getProjectFilePath(defaultFormat));
+ String fileName = defaultFormat ? name + ProjectFileType.DOT_DEFAULT_EXTENSION : Project.DIRECTORY_STORE_FOLDER;
+ File projectFile = new File(file, fileName);
if (projectFile.exists()) {
- int answer = Messages.showYesNoDialog(
- IdeBundle.message("prompt.overwrite.project.file", projectFile.getAbsolutePath(), context.getPresentationName()),
- IdeBundle.message("title.file.already.exists"), Messages.getQuestionIcon());
+ message = IdeBundle.message("prompt.overwrite.project.file", projectFile.getAbsolutePath(), context.getPresentationName());
+ int answer = Messages.showYesNoDialog(message, IdeBundle.message("title.file.already.exists"), Messages.getQuestionIcon());
shouldContinue = (answer == Messages.YES);
}
-
return shouldContinue;
}
@@ -204,14 +192,15 @@ public class NamePathComponent extends JPanel{
}
public String getPath() {
- return myTfPath.getText().trim().replace(File.separatorChar, '/');
+ String text = myTfPath.getText().trim();
+ return FileUtil.expandUserHome(FileUtil.toSystemIndependentName(text));
}
public void setPath(String path) {
final boolean isPathChangedByUser = myIsPathChangedByUser;
setPathNameSyncEnabled(false);
try {
- myTfPath.setText(path);
+ myTfPath.setText(FileUtil.getLocationRelativeToUserHome(FileUtil.toSystemDependentName(path)));
}
finally {
myIsPathChangedByUser = isPathChangedByUser;
diff --git a/java/idea-ui/src/com/intellij/openapi/projectRoots/ui/SdkEditor.java b/java/idea-ui/src/com/intellij/openapi/projectRoots/ui/SdkEditor.java
index 68e174159e1a..0c41048c0db8 100644
--- a/java/idea-ui/src/com/intellij/openapi/projectRoots/ui/SdkEditor.java
+++ b/java/idea-ui/src/com/intellij/openapi/projectRoots/ui/SdkEditor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -32,6 +32,7 @@ import com.intellij.openapi.util.ActionCallback;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.TabbedPaneWrapper;
import com.intellij.ui.navigation.History;
@@ -151,11 +152,13 @@ public class SdkEditor implements Configurable, Place.Navigator {
myHomeComponent.getTextField().setEditable(false);
myHomeFieldLabel = new JLabel(getHomeFieldLabelValue());
- myMainPanel.add(myHomeFieldLabel, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(2, 0, 2, 2), 0, 0));
- myMainPanel.add(myHomeComponent, new GridBagConstraints(1, GridBagConstraints.RELATIVE, 1, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(2, 2, 2, 0), 0, 0));
+ final int leftInset = Registry.is("ide.new.project.settings") ? 10 : 0;
+ final int rightInset = Registry.is("ide.new.project.settings") ? 10 : 0;
+ myMainPanel.add(myHomeFieldLabel, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(2, leftInset, 2, 2), 0, 0));
+ myMainPanel.add(myHomeComponent, new GridBagConstraints(1, GridBagConstraints.RELATIVE, 1, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(2, 2, 2, rightInset), 0, 0));
myAdditionalDataPanel = new JPanel(new BorderLayout());
- myMainPanel.add(myAdditionalDataPanel, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 2, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(2, 0, 0, 0), 0, 0));
+ myMainPanel.add(myAdditionalDataPanel, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 2, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(2, leftInset, 0, rightInset), 0, 0));
myMainPanel.add(myTabbedPane.getComponent(), new GridBagConstraints(0, GridBagConstraints.RELATIVE, 2, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(2, 0, 0, 0), 0, 0));
}
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/JavaContentEntriesEditor.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/JavaContentEntriesEditor.java
index cbfd826d8462..73f9f7f39807 100644
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/JavaContentEntriesEditor.java
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/JavaContentEntriesEditor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,6 +26,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectBundle;
import com.intellij.openapi.roots.ContentEntry;
import com.intellij.openapi.roots.ModifiableRootModel;
+import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
@@ -140,6 +141,7 @@ public class JavaContentEntriesEditor extends CommonContentEntriesEditor {
@Override
protected JPanel createBottomControl(Module module) {
+ if (Registry.is("ide.new.project.settings")) return null;
final JPanel innerPanel = new JPanel(new GridBagLayout());
innerPanel.setBorder(BorderFactory.createEmptyBorder(6, 0, 0, 6));
return innerPanel;
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModulesConfigurator.form b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModulesConfigurator.form
index 292c1f6c81c6..576d5146ff89 100644
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModulesConfigurator.form
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModulesConfigurator.form
@@ -1,12 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.openapi.roots.ui.configuration.ProjectConfigurable">
<grid id="27dc6" binding="myWholePanel" layout-manager="GridLayoutManager" row-count="5" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="10">
- <margin top="14" left="4" bottom="4" right="4"/>
+ <margin top="0" left="0" bottom="0" right="0"/>
<constraints>
- <xy x="20" y="20" width="907" height="282"/>
+ <xy x="20" y="20" width="907" height="288"/>
</constraints>
<properties/>
- <border type="none"/>
+ <border type="none">
+ <size top="14" left="10" bottom="14" right="10"/>
+ </border>
<children>
<vspacer id="2fb9d">
<constraints>
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectConfigurable.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectConfigurable.java
index 9c46d56ce21e..2bc8499e6c01 100644
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectConfigurable.java
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectConfigurable.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -39,6 +39,7 @@ import com.intellij.openapi.ui.DetailsComponent;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.EmptyRunnable;
import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.pom.java.LanguageLevel;
@@ -49,6 +50,7 @@ import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
+import javax.swing.border.EmptyBorder;
import javax.swing.event.DocumentEvent;
import java.awt.*;
import java.io.IOException;
@@ -108,7 +110,7 @@ public class ProjectConfigurable extends ProjectStructureElementConfigurable<Pro
@Override
public JComponent createOptionsPanel() {
- myDetailsComponent = new DetailsComponent();
+ myDetailsComponent = new DetailsComponent(!Registry.is("ide.new.project.settings"), !Registry.is("ide.new.project.settings"));
myDetailsComponent.setContent(myPanel);
myDetailsComponent.setText(getBannerSlogan());
@@ -152,7 +154,7 @@ public class ProjectConfigurable extends ProjectStructureElementConfigurable<Pro
myPanel.add(myWholePanel, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST,
GridBagConstraints.NONE, new Insets(4, 0, 0, 0), 0, 0));
-
+ myPanel.setBorder(new EmptyBorder(0, 10, 0, 10));
myProjectCompilerOutput.getTextField().getDocument().addDocumentListener(new DocumentAdapter() {
@Override
protected void textChanged(DocumentEvent e) {
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectJdksConfigurable.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectJdksConfigurable.java
index d78731b0a3c8..f24153739031 100644
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectJdksConfigurable.java
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectJdksConfigurable.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -161,6 +161,9 @@ public class ProjectJdksConfigurable extends MasterDetailsComponent {
@Override
@Nullable
protected ArrayList<AnAction> createActions(final boolean fromPopup) {
+ if (myProjectJdksModel == null) {
+ return null;
+ }
final ArrayList<AnAction> actions = new ArrayList<AnAction>();
DefaultActionGroup group = new DefaultActionGroup(ProjectBundle.message("add.new.jdk.text"), true);
group.getTemplatePresentation().setIcon(IconUtil.getAddIcon());
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectStructureConfigurable.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectStructureConfigurable.java
index bf083f92c66c..a5867d66d176 100644
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectStructureConfigurable.java
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectStructureConfigurable.java
@@ -44,6 +44,7 @@ import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.wm.ex.IdeFocusTraversalPolicy;
import com.intellij.packaging.artifacts.Artifact;
import com.intellij.ui.JBSplitter;
+import com.intellij.ui.OnePixelSplitter;
import com.intellij.ui.components.panels.Wrapper;
import com.intellij.ui.navigation.BackAction;
import com.intellij.ui.navigation.ForwardAction;
@@ -174,12 +175,9 @@ public class ProjectStructureConfigurable extends BaseConfigurable implements Se
public JComponent createComponent() {
myComponent = new MyPanel();
- mySplitter = new JBSplitter(false, .15f);
+ mySplitter = Registry.is("ide.new.project.settings") ? new OnePixelSplitter(false, .15f) : new JBSplitter(false, .15f);
mySplitter.setSplitterProportionKey("ProjectStructure.TopLevelElements");
mySplitter.setHonorComponentsMinimumSize(true);
- if (Registry.is("ide.new.project.settings")) {
- mySplitter.setOnePixelMode();
- }
initSidePanel();
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/SidePanel.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/SidePanel.java
index 290f35e561b5..355888b02a42 100644
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/SidePanel.java
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/SidePanel.java
@@ -20,7 +20,10 @@ import com.intellij.openapi.ui.GraphicsConfig;
import com.intellij.openapi.ui.popup.ListItemDescriptor;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.ui.*;
+import com.intellij.ui.Gray;
+import com.intellij.ui.JBColor;
+import com.intellij.ui.ScrollPaneFactory;
+import com.intellij.ui.SeparatorWithText;
import com.intellij.ui.components.JBList;
import com.intellij.ui.components.panels.NonOpaquePanel;
import com.intellij.ui.navigation.History;
@@ -172,16 +175,14 @@ public class SidePanel extends JPanel {
protected JComponent createItemComponent() {
myExtraPanel = new NonOpaquePanel(new BorderLayout());
myCountLabel = new CountLabel();
-
+ final JComponent component = super.createItemComponent();
if (Registry.is("ide.new.project.settings")) {
- myTextLabel = new EngravedLabel();
- myTextLabel.setFont(myTextLabel.getFont().deriveFont(Font.BOLD));
myTextLabel.setForeground(Gray._240);
myTextLabel.setOpaque(true);
- return layoutComponent(myTextLabel);
}
- return super.createItemComponent();
+
+ return component;
}
@Override
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactEditorImpl.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactEditorImpl.java
index 69b490828f0b..618f085f00bb 100644
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactEditorImpl.java
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactEditorImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,12 +34,12 @@ import com.intellij.openapi.roots.ui.configuration.artifacts.sourceItems.Library
import com.intellij.openapi.roots.ui.configuration.artifacts.sourceItems.ModuleOutputSourceItem;
import com.intellij.openapi.roots.ui.configuration.artifacts.sourceItems.SourceItemsTree;
import com.intellij.openapi.ui.FixedSizeButton;
-import com.intellij.openapi.ui.Splitter;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.io.FileUtilRt;
+import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.packaging.artifacts.Artifact;
@@ -83,6 +83,7 @@ public class ArtifactEditorImpl implements ArtifactEditorEx {
private JPanel myErrorPanelPlace;
private ThreeStateCheckBox myShowContentCheckBox;
private FixedSizeButton myShowSpecificContentOptionsButton;
+ private JPanel myTopPanel;
private final ActionGroup myShowSpecificContentOptionsGroup;
private final Project myProject;
private final ComplexElementSubstitutionParameters mySubstitutionParameters = new ComplexElementSubstitutionParameters();
@@ -106,6 +107,9 @@ public class ArtifactEditorImpl implements ArtifactEditorEx {
myPropertiesEditors = new ArtifactPropertiesEditors(myContext, myOriginalArtifact, myOriginalArtifact);
Disposer.register(this, mySourceItemsTree);
Disposer.register(this, myLayoutTreeComponent);
+ if (Registry.is("ide.new.project.settings")) {
+ myTopPanel.setBorder(new EmptyBorder(0, 10, 0, 10));
+ }
myBuildOnMakeCheckBox.setSelected(artifact.isBuildOnMake());
final String outputPath = artifact.getOutputPath();
myOutputDirectoryField.addBrowseFolderListener(CompilerBundle.message("dialog.title.output.directory.for.artifact"),
@@ -202,7 +206,7 @@ public class ArtifactEditorImpl implements ArtifactEditorEx {
myErrorPanelPlace.add(myValidationManager.getMainErrorPanel(), BorderLayout.CENTER);
- Splitter splitter = new Splitter(false);
+ final JBSplitter splitter = Registry.is("ide.new.project.settings") ? new OnePixelSplitter(false) : new JBSplitter(false);
final JPanel leftPanel = new JPanel(new BorderLayout());
JPanel treePanel = myLayoutTreeComponent.getTreePanel();
if (UIUtil.isUnderDarcula()) {
@@ -213,7 +217,7 @@ public class ArtifactEditorImpl implements ArtifactEditorEx {
leftPanel.add(treePanel, BorderLayout.CENTER);
if (UIUtil.isUnderDarcula()) {
CompoundBorder border =
- new CompoundBorder(new CustomLineBorder(UIUtil.getBorderColor(), 0, 0, 0, 1), BorderFactory.createEmptyBorder(0, 0, 0, 0));
+ new CompoundBorder(new CustomLineBorder(0, 0, 0, 1), BorderFactory.createEmptyBorder(0, 0, 0, 0));
leftPanel.setBorder(border);
} else {
leftPanel.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 0));
@@ -241,7 +245,7 @@ public class ArtifactEditorImpl implements ArtifactEditorEx {
labelPanel.add(link);
rightTopPanel.add(labelPanel, BorderLayout.CENTER);
rightPanel.add(rightTopPanel, BorderLayout.NORTH);
- JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(mySourceItemsTree, UIUtil.isUnderDarcula());
+ JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(mySourceItemsTree, UIUtil.isUnderDarcula() || Registry.is("ide.new.project.settings"));
JPanel scrollPaneWrap = new JPanel(new BorderLayout());
scrollPaneWrap.add(scrollPane, BorderLayout.CENTER);
if (UIUtil.isUnderDarcula()) {
@@ -257,6 +261,13 @@ public class ArtifactEditorImpl implements ArtifactEditorEx {
rightPanel.setBorder(BorderFactory.createEmptyBorder(3, 0, 3, 3));
}
splitter.setSecondComponent(rightPanel);
+ if (Registry.is("ide.new.project.settings")) {
+ splitter.getDivider().setBackground(UIUtil.getPanelBackground());
+ treePanel.setBorder(new EmptyBorder(0, 0, 0, 0));
+ rightPanel.setBorder(new EmptyBorder(0, 0, 0, 0));
+ scrollPaneWrap.setBorder(new EmptyBorder(0,0,0,0));
+ leftPanel.setBorder(new EmptyBorder(0,0,0,0));
+ }
myShowContentCheckBox.addActionListener(new ActionListener() {
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactsEditorImpl.form b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactsEditorImpl.form
index d3edac73dcf3..17c98953e52a 100644
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactsEditorImpl.form
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactsEditorImpl.form
@@ -8,7 +8,7 @@
<properties/>
<border type="none"/>
<children>
- <grid id="6e544" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <grid id="6e544" binding="myTopPanel" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="1" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactsStructureConfigurable.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactsStructureConfigurable.java
index 52b601e4d9fe..5deea9c75f74 100644
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactsStructureConfigurable.java
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactsStructureConfigurable.java
@@ -286,25 +286,7 @@ public class ArtifactsStructureConfigurable extends BaseStructureConfigurable {
}
private void addArtifact(@NotNull ArtifactType type, @NotNull ArtifactTemplate artifactTemplate) {
- final ArtifactTemplate.NewArtifactConfiguration configuration = artifactTemplate.createArtifact();
- if (configuration == null) {
- return;
- }
-
- final String baseName = configuration.getArtifactName();
- String name = baseName;
- int i = 2;
- while (myPackagingEditorContext.getArtifactModel().findArtifact(name) != null) {
- name = baseName + i;
- i++;
- }
-
- ArtifactType actualType = configuration.getArtifactType();
- if (actualType == null) {
- actualType = type;
- }
- final ModifiableArtifact artifact = myPackagingEditorContext.getOrCreateModifiableArtifactModel().addArtifact(name, actualType, configuration.getRootElement());
- artifactTemplate.setUpArtifact(artifact, configuration);
+ Artifact artifact = ArtifactUtil.addArtifact(myPackagingEditorContext.getOrCreateModifiableArtifactModel(), type, artifactTemplate);
selectNodeInTree(findNodeByObject(myRoot, artifact));
}
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/LayoutTreeComponent.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/LayoutTreeComponent.java
index ff1fdd393961..d8392ea73e63 100644
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/LayoutTreeComponent.java
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/LayoutTreeComponent.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -47,7 +47,6 @@ import com.intellij.ui.treeStructure.SimpleTreeStructure;
import com.intellij.ui.treeStructure.WeightBasedComparator;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.ContainerUtil;
-import com.intellij.util.ui.UIUtil;
import com.intellij.util.ui.tree.TreeUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -132,7 +131,7 @@ public class LayoutTreeComponent implements DnDTarget, Disposable {
emptyPanel.setPreferredSize(new Dimension(0, 0));
myPropertiesPanelWrapper = new JPanel(new CardLayout());
- myPropertiesPanel.setBorder(new CustomLineBorder(UIUtil.getBorderColor(), 1, 0, 0, 0));
+ myPropertiesPanel.setBorder(new CustomLineBorder(1, 0, 0, 0));
myPropertiesPanelWrapper.add(EMPTY_CARD, emptyPanel);
myPropertiesPanelWrapper.add(PROPERTIES_CARD, myPropertiesPanel);
}
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/LibraryRootsComponent.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/LibraryRootsComponent.java
index 5d884a6f9bc8..e47e955fff24 100644
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/LibraryRootsComponent.java
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/LibraryRootsComponent.java
@@ -41,6 +41,7 @@ import com.intellij.openapi.ui.ex.MultiLineLabel;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Disposer;
+import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.vfs.JarFileSystem;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
@@ -48,6 +49,7 @@ import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.ui.AnActionButton;
import com.intellij.ui.AnActionButtonRunnable;
import com.intellij.ui.ToolbarDecorator;
+import com.intellij.ui.border.CustomLineBorder;
import com.intellij.ui.treeStructure.Tree;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IconUtil;
@@ -157,7 +159,9 @@ public class LibraryRootsComponent implements Disposable, LibraryEditorComponent
ToolbarDecorator toolbarDecorator = ToolbarDecorator.createDecorator(myTree).disableUpDownActions()
.setRemoveActionName(ProjectBundle.message("library.remove.action"))
.disableRemoveAction();
-
+ if (Registry.is("ide.new.project.settings")) {
+ toolbarDecorator.setPanelBorder(new CustomLineBorder(1, 0, 0, 0));
+ }
final List<AttachRootButtonDescriptor> popupItems = new ArrayList<AttachRootButtonDescriptor>();
for (AttachRootButtonDescriptor descriptor : myDescriptor.createAttachButtons()) {
Icon icon = descriptor.getToolbarIcon();
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/BaseStructureConfigurable.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/BaseStructureConfigurable.java
index b88f92474fcf..a3b1db0dcf24 100644
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/BaseStructureConfigurable.java
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/BaseStructureConfigurable.java
@@ -38,7 +38,6 @@ import com.intellij.openapi.ui.NamedConfigurable;
import com.intellij.openapi.util.ActionCallback;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Disposer;
-import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.packaging.artifacts.Artifact;
import com.intellij.ui.TreeSpeedSearch;
@@ -302,7 +301,7 @@ public abstract class BaseStructureConfigurable extends MasterDetailsComponent i
result.addAll(copyActions);
result.add(Separator.getInstance());
- if (fromPopup || !(SystemInfo.isMac && Registry.is("ide.new.project.settings"))) {
+ if (fromPopup || !Registry.is("ide.new.project.settings")) {
result.add(new MyFindUsagesAction(myTree));
}
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/FacetStructureConfigurable.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/FacetStructureConfigurable.java
index e5a008d3dcbb..d5248a55e7ad 100644
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/FacetStructureConfigurable.java
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/FacetStructureConfigurable.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,6 +35,7 @@ import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.FacetProje
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureElement;
import com.intellij.openapi.ui.DetailsComponent;
import com.intellij.openapi.ui.NamedConfigurable;
+import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.treeStructure.filtered.FilteringTreeBuilder;
import com.intellij.util.ui.tree.TreeUtil;
@@ -277,8 +278,10 @@ public class FacetStructureConfigurable extends BaseStructureConfigurable {
actions.add(new MyNavigateAction());
}
actions.add(new MyRemoveAction());
- actions.add(Separator.getInstance());
- addCollapseExpandActions(actions);
+ if (fromPopup || !(Registry.is("ide.new.project.settings"))) {
+ actions.add(Separator.getInstance());
+ addCollapseExpandActions(actions);
+ }
return actions;
}
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/FacetsTreeCellRenderer.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/FacetsTreeCellRenderer.java
index d89fe3797478..216ad982bbd3 100644
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/FacetsTreeCellRenderer.java
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/FacetsTreeCellRenderer.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -54,15 +54,7 @@ public class FacetsTreeCellRenderer extends GroupedElementsRenderer.Tree {
if (configurable != null) {
final Icon icon = configurable.getIcon(expanded);
final boolean showSeparator = configurable instanceof FrameworkDetectionConfigurable;
- int width = -1;
- if (showSeparator && tree.isVisible()) {
- final int treeWidth = tree.getVisibleRect().width;
- if (treeWidth > 0) {
- width = treeWidth;
- }
- }
- final JComponent component = configureComponent(node.getDisplayName(), null, icon, icon, selected, showSeparator, null,
- width);
+ final JComponent component = configureComponent(node.getDisplayName(), null, icon, icon, selected, showSeparator, null, -1);
myTextLabel.setOpaque(selected);
return component;
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ModuleStructureConfigurable.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ModuleStructureConfigurable.java
index 1c313c1077ee..a2a7e6b5c76f 100644
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ModuleStructureConfigurable.java
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ModuleStructureConfigurable.java
@@ -53,7 +53,6 @@ import com.intellij.openapi.ui.*;
import com.intellij.openapi.util.ActionCallback;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.NullableComputable;
-import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
@@ -149,9 +148,9 @@ public class ModuleStructureConfigurable extends BaseStructureConfigurable imple
@NotNull
protected ArrayList<AnAction> createActions(final boolean fromPopup) {
final ArrayList<AnAction> result = super.createActions(fromPopup);
- result.add(Separator.getInstance());
- result.add(new MyGroupAction());
- if (fromPopup || !(SystemInfo.isMac && Registry.is("ide.new.project.settings"))) {
+ if (fromPopup || !Registry.is("ide.new.project.settings")) {
+ result.add(Separator.getInstance());
+ result.add(new MyGroupAction());
addCollapseExpandActions(result);
}
return result;
diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java
index 7f8d01382b09..c23ebdd00855 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java
@@ -1292,5 +1292,31 @@ public class GenericsHighlightUtil {
}
}
}
+
+ public static HighlightInfo checkInferredIntersections(PsiSubstitutor substitutor, TextRange ref) {
+ for (Map.Entry<PsiTypeParameter, PsiType> typeEntry : substitutor.getSubstitutionMap().entrySet()) {
+ final PsiType type = typeEntry.getValue();
+ if (type instanceof PsiIntersectionType) {
+ final PsiType[] conjuncts = ((PsiIntersectionType)type).getConjuncts();
+ for (int i = 0; i < conjuncts.length; i++) {
+ PsiClass conjunct = PsiUtil.resolveClassInClassTypeOnly(conjuncts[i]);
+ if (conjunct != null && !conjunct.isInterface()) {
+ for (int i1 = i + 1; i1 < conjuncts.length; i1++) {
+ PsiClass oppositeConjunct = PsiUtil.resolveClassInClassTypeOnly(conjuncts[i1]);
+ if (oppositeConjunct != null && !oppositeConjunct.isInterface()) {
+ if (!conjunct.isInheritor(oppositeConjunct, true) && !oppositeConjunct.isInheritor(conjunct, true)) {
+ return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR)
+ .descriptionAndTooltip("Type parameter " + typeEntry.getKey().getName() + " has incompatible upper bounds: " +
+ conjunct.getName() + " and " + oppositeConjunct.getName())
+ .range(ref).create();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return null;
+ }
}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java
index 602e3fea2cc2..a4ea7087af5a 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java
@@ -696,14 +696,17 @@ public class HighlightControlFlowUtil {
return true;
}
- if (ControlFlowUtil.isVariableDefinitelyAssigned(variable, controlFlow)) {
- final Collection<ControlFlowUtil.VariableInfo> initializedTwice = ControlFlowUtil.getInitializedTwice(controlFlow);
- effectivelyFinal = !initializedTwice.contains(new ControlFlowUtil.VariableInfo(variable, null));
- if (effectivelyFinal) {
- effectivelyFinal = notAccessedForWriting(variable, new LocalSearchScope(scope));
+ final List<PsiReferenceExpression> readBeforeWriteLocals = ControlFlowUtil.getReadBeforeWriteLocals(controlFlow);
+ for (PsiReferenceExpression expression : readBeforeWriteLocals) {
+ if (expression.resolve() == variable) {
+ return PsiUtil.isAccessedForReading(expression);
}
- } else {
- effectivelyFinal = false;
+ }
+
+ final Collection<ControlFlowUtil.VariableInfo> initializedTwice = ControlFlowUtil.getInitializedTwice(controlFlow);
+ effectivelyFinal = !initializedTwice.contains(new ControlFlowUtil.VariableInfo(variable, null));
+ if (effectivelyFinal) {
+ effectivelyFinal = notAccessedForWriting(variable, new LocalSearchScope(scope));
}
}
return effectivelyFinal;
diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java
index b567ce41325a..118c98efc9d2 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java
@@ -344,8 +344,12 @@ public class HighlightMethodUtil {
if (resolved instanceof PsiMethod && resolveResult.isValidResult()) {
TextRange fixRange = getFixRange(methodCall);
highlightInfo = HighlightUtil.checkUnhandledExceptions(methodCall, fixRange);
- if (highlightInfo == null && !LambdaUtil.isValidQualifier4InterfaceStaticMethodCall((PsiMethod)resolved, methodCall.getMethodExpression(), resolveResult.getCurrentFileResolveScope(), languageLevel)) {
- highlightInfo = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).descriptionAndTooltip("Static method may be invoked on containing interface class only").range(fixRange).create();
+ if (highlightInfo == null) {
+ if (!LambdaUtil.isValidQualifier4InterfaceStaticMethodCall((PsiMethod)resolved, methodCall.getMethodExpression(), resolveResult.getCurrentFileResolveScope(), languageLevel)) {
+ highlightInfo = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).descriptionAndTooltip("Static method may be invoked on containing interface class only").range(fixRange).create();
+ } else {
+ highlightInfo = GenericsHighlightUtil.checkInferredIntersections(substitutor, fixRange);
+ }
}
}
else {
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeLambdaInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeLambdaInspection.java
index c1f127d3a1df..621ce3fce2af 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeLambdaInspection.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeLambdaInspection.java
@@ -141,7 +141,19 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection
.inferTypeArguments(method.getTypeParameters(), parameters, expressions,
((MethodCandidateInfo)result).getSiteSubstitutor(), callExpr.getParent(),
DefaultParameterTypeInferencePolicy.INSTANCE);
- return substitutor.substitute(parameters[i].getType());
+ PsiType paramType;
+ if (i < parameters.length) {
+ paramType = parameters[i].getType();
+ }
+ else {
+ paramType = parameters[parameters.length - 1].getType();
+ if (!(paramType instanceof PsiEllipsisType)) {
+ return null;
+ }
+ paramType = ((PsiEllipsisType)paramType).getComponentType();
+ }
+
+ return substitutor.substitute(paramType);
}
}
}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/Analysis.java b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/Analysis.java
index 44e493c63f0a..47ef448c7484 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/Analysis.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/Analysis.java
@@ -208,7 +208,8 @@ class MakeResult<Res> implements PendingAction<Res> {
}
abstract class Analysis<Res> {
- private static final int STEPS_LIMIT = 30000;
+ public static final int STEPS_LIMIT = 30000;
+ public static final int EQUATION_SIZE_LIMIT = 30;
final RichControlFlow richControlFlow;
final Direction direction;
final ControlFlowGraph controlFlow;
@@ -225,7 +226,7 @@ abstract class Analysis<Res> {
Res earlyResult = null;
abstract Res identity();
- abstract Res combineResults(Res delta, List<Res> subResults);
+ abstract Res combineResults(Res delta, List<Res> subResults) throws AnalyzerException;
abstract boolean isEarlyResult(Res res);
abstract Equation<Key, Value> mkEquation(Res result);
abstract void processState(State state) throws AnalyzerException;
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisConverter.java b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisConverter.java
index f29dd7f6cf0c..0239a661c4ee 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisConverter.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisConverter.java
@@ -15,112 +15,68 @@
*/
package com.intellij.codeInspection.bytecodeAnalysis;
-import com.intellij.ide.util.PropertiesComponent;
import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.components.ApplicationComponent;
import com.intellij.openapi.progress.ProgressManager;
-import com.intellij.openapi.util.ThrowableComputable;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.TypeConversionUtil;
-import com.intellij.util.io.*;
-import gnu.trove.TIntHashSet;
-import gnu.trove.TIntObjectHashMap;
-import gnu.trove.TIntObjectIterator;
+import gnu.trove.TLongArrayList;
+import gnu.trove.TLongHashSet;
+import gnu.trove.TLongObjectHashMap;
+import gnu.trove.TLongObjectIterator;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
import org.jetbrains.org.objectweb.asm.Type;
-import java.io.DataInput;
-import java.io.DataOutput;
-import java.io.File;
import java.io.IOException;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
import static com.intellij.codeInspection.bytecodeAnalysis.ProjectBytecodeAnalysis.LOG;
/**
* @author lambdamix
*/
-public class BytecodeAnalysisConverter implements ApplicationComponent {
+public abstract class BytecodeAnalysisConverter implements ApplicationComponent {
- private static final String VERSION = "BytecodeAnalysisConverter.Enumerators";
+ public static final int SHIFT = 4096;
public static BytecodeAnalysisConverter getInstance() {
return ApplicationManager.getApplication().getComponent(BytecodeAnalysisConverter.class);
}
- private PersistentStringEnumerator myNamesEnumerator;
- private PersistentEnumeratorDelegate<int[]> myCompoundKeyEnumerator;
- private int version;
-
- @Override
- public void initComponent() {
- version = PropertiesComponent.getInstance().getOrInitInt(VERSION, 0);
- final File keysDir = new File(PathManager.getIndexRoot(), "bytecodekeys");
- final File namesFile = new File(keysDir, "names");
- final File compoundKeysFile = new File(keysDir, "compound");
-
- try {
- IOUtil.openCleanOrResetBroken(new ThrowableComputable<Void, IOException>() {
- @Override
- public Void compute() throws IOException {
- myNamesEnumerator = new PersistentStringEnumerator(namesFile, true);
- myCompoundKeyEnumerator = new IntArrayPersistentEnumerator(compoundKeysFile, new IntArrayKeyDescriptor());
- return null;
- }
- }, new Runnable() {
- @Override
- public void run() {
- LOG.info("Error during initialization of enumerators in bytecode analysis. Re-initializing.");
- IOUtil.deleteAllFilesStartingWith(keysDir);
- version ++;
- }
- });
- }
- catch (IOException e) {
- LOG.error("Re-initialization of enumerators in bytecode analysis failed.", e);
- }
- // TODO: is it enough for rebuilding indices?
- PropertiesComponent.getInstance().setValue(VERSION, String.valueOf(version));
- }
-
- @Override
- public void disposeComponent() {
- try {
- myNamesEnumerator.close();
- myCompoundKeyEnumerator.close();
- }
- catch (IOException e) {
- LOG.debug(e);
- }
- }
-
@NotNull
@Override
public String getComponentName() {
return "BytecodeAnalysisConverter";
}
- IntIdEquation convert(Equation<Key, Value> equation) throws IOException {
+ public abstract int getVersion();
+
+ protected abstract int enumerateString(@NotNull String s) throws IOException;
+
+ protected abstract int enumerateCompoundKey(@NotNull int[] key) throws IOException;
+
+ IdEquation convert(Equation<Key, Value> equation) throws IOException {
ProgressManager.checkCanceled();
Result<Key, Value> rhs = equation.rhs;
- IntIdResult result;
+ IdResult result;
if (rhs instanceof Final) {
- result = new IntIdFinal(((Final<Key, Value>)rhs).value);
+ result = new IdFinal(((Final<Key, Value>)rhs).value);
} else {
Pending<Key, Value> pending = (Pending<Key, Value>)rhs;
Set<Product<Key, Value>> sumOrigin = pending.sum;
IntIdComponent[] components = new IntIdComponent[sumOrigin.size()];
int componentI = 0;
for (Product<Key, Value> prod : sumOrigin) {
- int[] intProd = new int[prod.ids.size()];
+ long[] intProd = new long[prod.ids.size()];
int idI = 0;
for (Key id : prod.ids) {
- int rawId = mkAsmKey(id);
+ long rawId = mkAsmKey(id);
if (rawId <= 0) {
LOG.error("raw key should be positive. rawId = " + rawId);
}
@@ -131,24 +87,51 @@ public class BytecodeAnalysisConverter implements ApplicationComponent {
components[componentI] = intIdComponent;
componentI++;
}
- result = new IntIdPending(components);
+ result = new IdPending(components);
}
- int rawKey = mkAsmKey(equation.id);
+ long rawKey = mkAsmKey(equation.id);
if (rawKey <= 0) {
LOG.error("raw key should be positive. rawKey = " + rawKey);
}
- int key = equation.id.stable ? rawKey : -rawKey;
- return new IntIdEquation(key, result);
+ long key = equation.id.stable ? rawKey : -rawKey;
+ return new IdEquation(key, result);
}
- public int mkAsmKey(@NotNull Key key) throws IOException {
- return myCompoundKeyEnumerator.enumerate(new int[]{mkDirectionKey(key.direction), mkAsmSignatureKey(key.method)});
+ public long mkAsmKey(@NotNull Key key) throws IOException {
+ long baseKey = mkAsmSignatureKey(key.method);
+ long directionKey = mkDirectionKey(key.direction);
+ return baseKey * SHIFT + directionKey;
}
- private int mkDirectionKey(Direction dir) throws IOException {
- return myCompoundKeyEnumerator.enumerate(new int[]{dir.directionId(), dir.paramId(), dir.valueId()});
+ private static int mkDirectionKey(Direction dir) throws IOException {
+ if (dir instanceof Out) {
+ return 0;
+ } else if (dir instanceof In) {
+ In in = (In)dir;
+ return 8 * in.paramId() + 1;
+ } else {
+ InOut inOut = (InOut)dir;
+ return 8 * inOut.paramId() + 2 + inOut.valueId();
+ }
+ }
+
+ @NotNull
+ private static Direction extractDirection(int directionKey) {
+ if (directionKey == 0) {
+ return new Out();
+ }
+ else {
+ int paramId = directionKey / 8;
+ int subDirection = directionKey % 8;
+ if (subDirection == 1) {
+ return new In(paramId);
+ }
+ else {
+ return new InOut(paramId, Value.values()[subDirection - 2]);
+ }
+ }
}
// class + short signature
@@ -156,33 +139,19 @@ public class BytecodeAnalysisConverter implements ApplicationComponent {
int[] sigKey = new int[2];
sigKey[0] = mkAsmTypeKey(Type.getObjectType(method.internalClassName));
sigKey[1] = mkAsmShortSignatureKey(method);
- return myCompoundKeyEnumerator.enumerate(sigKey);
+ return enumerateCompoundKey(sigKey);
}
private int mkAsmShortSignatureKey(@NotNull Method method) throws IOException {
Type[] argTypes = Type.getArgumentTypes(method.methodDesc);
int arity = argTypes.length;
- int[] sigKey = new int[3 + arity];
+ int[] sigKey = new int[2 + arity];
sigKey[0] = mkAsmTypeKey(Type.getReturnType(method.methodDesc));
- sigKey[1] = myNamesEnumerator.enumerate(method.methodName);
- sigKey[2] = argTypes.length;
+ sigKey[1] = enumerateString(method.methodName);
for (int i = 0; i < argTypes.length; i++) {
- sigKey[3 + i] = mkAsmTypeKey(argTypes[i]);
+ sigKey[2 + i] = mkAsmTypeKey(argTypes[i]);
}
- return myCompoundKeyEnumerator.enumerate(sigKey);
- }
-
- @Nullable
- private static Direction extractDirection(int[] directionKey) {
- switch (directionKey[0]) {
- case Direction.OUT_DIRECTION:
- return new Out();
- case Direction.IN_DIRECTION:
- return new In(directionKey[1]);
- case Direction.INOUT_DIRECTION:
- return new InOut(directionKey[1], Value.values()[directionKey[2]]);
- }
- return null;
+ return enumerateCompoundKey(sigKey);
}
private int mkAsmTypeKey(Type type) throws IOException {
@@ -197,22 +166,22 @@ public class BytecodeAnalysisConverter implements ApplicationComponent {
packageName = "";
simpleName = className;
}
- int[] classKey = new int[]{myNamesEnumerator.enumerate(packageName), myNamesEnumerator.enumerate(simpleName)};
- return myCompoundKeyEnumerator.enumerate(classKey);
+ int[] classKey = new int[]{enumerateString(packageName), enumerateString(simpleName)};
+ return enumerateCompoundKey(classKey);
}
- public int mkPsiKey(@NotNull PsiMethod psiMethod, Direction direction) throws IOException {
+ public long mkPsiKey(@NotNull PsiMethod psiMethod, Direction direction) throws IOException {
final PsiClass psiClass = PsiTreeUtil.getParentOfType(psiMethod, PsiClass.class, false);
if (psiClass == null) {
LOG.debug("PsiClass was null for " + psiMethod.getName());
return -1;
}
- int sigKey = mkPsiSignatureKey(psiMethod);
+ long sigKey = mkPsiSignatureKey(psiMethod);
if (sigKey == -1) {
return -1;
}
- return myCompoundKeyEnumerator.enumerate(new int[]{mkDirectionKey(direction), sigKey});
-
+ long directionKey = mkDirectionKey(direction);
+ return sigKey * SHIFT + directionKey;
}
private int mkPsiSignatureKey(@NotNull PsiMethod psiMethod) throws IOException {
@@ -228,21 +197,20 @@ public class BytecodeAnalysisConverter implements ApplicationComponent {
final int shift = isInnerClassConstructor ? 1 : 0;
final int arity = parameters.length + shift;
- int[] shortSigKey = new int[3 + arity];
+ int[] shortSigKey = new int[2 + arity];
if (returnType == null) {
shortSigKey[0] = mkPsiTypeKey(PsiType.VOID);
- shortSigKey[1] = myNamesEnumerator.enumerate("<init>");
+ shortSigKey[1] = enumerateString("<init>");
} else {
shortSigKey[0] = mkPsiTypeKey(returnType);
- shortSigKey[1] = myNamesEnumerator.enumerate(psiMethod.getName());
+ shortSigKey[1] = enumerateString(psiMethod.getName());
}
- shortSigKey[2] = arity;
if (isInnerClassConstructor) {
- shortSigKey[3] = mkPsiClassKey(outerClass, 0);
+ shortSigKey[2] = mkPsiClassKey(outerClass, 0);
}
for (int i = 0; i < parameters.length; i++) {
PsiParameter parameter = parameters[i];
- shortSigKey[3 + i + shift] = mkPsiTypeKey(parameter.getType());
+ shortSigKey[2 + i + shift] = mkPsiTypeKey(parameter.getType());
}
for (int aShortSigKey : shortSigKey) {
if (aShortSigKey == -1) {
@@ -256,9 +224,28 @@ public class BytecodeAnalysisConverter implements ApplicationComponent {
return -1;
}
sigKey[0] = classKey;
- sigKey[1] = myCompoundKeyEnumerator.enumerate(shortSigKey);
+ sigKey[1] = enumerateCompoundKey(shortSigKey);
- return myCompoundKeyEnumerator.enumerate(sigKey);
+ return enumerateCompoundKey(sigKey);
+ }
+
+ public TLongArrayList mkInOutKeys(@NotNull PsiMethod psiMethod, long primaryKey) throws IOException {
+ PsiParameter[] parameters = psiMethod.getParameterList().getParameters();
+ TLongArrayList keys = new TLongArrayList(parameters.length * 2 + 1);
+ for (int i = 0; i < parameters.length; i++) {
+ PsiParameter parameter = parameters[i];
+ PsiType parameterType = parameter.getType();
+ if (parameterType instanceof PsiPrimitiveType) {
+ if (PsiType.BOOLEAN.equals(parameterType)) {
+ keys.add(primaryKey + mkDirectionKey(new InOut(i, Value.False)));
+ keys.add(primaryKey + mkDirectionKey(new InOut(i, Value.True)));
+ }
+ } else {
+ keys.add(primaryKey + mkDirectionKey(new InOut(i, Value.NotNull)));
+ keys.add(primaryKey + mkDirectionKey(new InOut(i, Value.Null)));
+ }
+ }
+ return keys;
}
@@ -279,17 +266,17 @@ public class BytecodeAnalysisConverter implements ApplicationComponent {
className = qname.substring(packageName.length() + 1).replace('.', '$');
}
int[] classKey = new int[2];
- classKey[0] = myNamesEnumerator.enumerate(packageName);
+ classKey[0] = enumerateString(packageName);
if (dimensions == 0) {
- classKey[1] = myNamesEnumerator.enumerate(className);
+ classKey[1] = enumerateString(className);
} else {
StringBuilder sb = new StringBuilder(className);
for (int j = 0; j < dimensions; j++) {
sb.append("[]");
}
- classKey[1] = myNamesEnumerator.enumerate(sb.toString());
+ classKey[1] = enumerateString(sb.toString());
}
- return myCompoundKeyEnumerator.enumerate(classKey);
+ return enumerateCompoundKey(classKey);
}
private int mkPsiTypeKey(PsiType psiType) throws IOException {
@@ -316,77 +303,69 @@ public class BytecodeAnalysisConverter implements ApplicationComponent {
String packageName = "";
String className = psiType.getPresentableText();
int[] classKey = new int[2];
- classKey[0] = myNamesEnumerator.enumerate(packageName);
+ classKey[0] = enumerateString(packageName);
if (dimensions == 0) {
- classKey[1] = myNamesEnumerator.enumerate(className);
+ classKey[1] = enumerateString(className);
} else {
StringBuilder sb = new StringBuilder(className);
for (int j = 0; j < dimensions; j++) {
sb.append("[]");
}
- classKey[1] = myNamesEnumerator.enumerate(sb.toString());
+ classKey[1] = enumerateString(sb.toString());
}
- return myCompoundKeyEnumerator.enumerate(classKey);
+ return enumerateCompoundKey(classKey);
}
return -1;
}
- public void addAnnotations(TIntObjectHashMap<Value> internalIdSolutions, Annotations annotations) {
-
- TIntObjectHashMap<List<String>> contractClauses = new TIntObjectHashMap<List<String>>();
- TIntObjectIterator<Value> solutionsIterator = internalIdSolutions.iterator();
+ public void addMethodAnnotations(TLongObjectHashMap<Value> internalIdSolutions, Annotations annotations, long methodKey, int arity) {
- TIntHashSet notNulls = annotations.notNulls;
- TIntObjectHashMap<String> contracts = annotations.contracts;
+ List<String> clauses = new ArrayList<String>();
+ TLongObjectIterator<Value> solutionsIterator = internalIdSolutions.iterator();
+ TLongHashSet notNulls = annotations.notNulls;
+ TLongObjectHashMap<String> contracts = annotations.contracts;
for (int i = internalIdSolutions.size(); i-- > 0;) {
solutionsIterator.advance();
- int key = Math.abs(solutionsIterator.key());
+ long key = Math.abs(solutionsIterator.key());
Value value = solutionsIterator.value();
if (value == Value.Top || value == Value.Bot) {
continue;
}
- try {
- int[] compoundKey = myCompoundKeyEnumerator.valueOf(key);
- Direction direction = extractDirection(myCompoundKeyEnumerator.valueOf(compoundKey[0]));
- if (value == Value.NotNull && (direction instanceof In || direction instanceof Out)) {
- notNulls.add(key);
- }
- else if (direction instanceof InOut) {
- compoundKey = new int[]{mkDirectionKey(new Out()), compoundKey[1]};
- try {
- int baseKey = myCompoundKeyEnumerator.enumerate(compoundKey);
- List<String> clauses = contractClauses.get(baseKey);
- if (clauses == null) {
- clauses = new ArrayList<String>();
- contractClauses.put(baseKey, clauses);
- }
- int[] sig = myCompoundKeyEnumerator.valueOf(compoundKey[1]);
- int[] shortSig = myCompoundKeyEnumerator.valueOf(sig[1]);
- int arity = shortSig[2];
- clauses.add(contractElement(arity, (InOut)direction, value));
- }
- catch (IOException e) {
- LOG.debug(e);
- }
- }
+ Direction direction = extractDirection((int)(key % SHIFT));
+ if (value == Value.NotNull && direction instanceof Out && key == methodKey) {
+ notNulls.add(key);
}
- catch (IOException e) {
- LOG.debug(e);
+ else if (direction instanceof InOut) {
+ long baseKey = key - (key % SHIFT);
+ if (baseKey == methodKey) {
+ clauses.add(contractElement(arity, (InOut)direction, value));
+ }
}
}
- TIntObjectIterator<List<String>> buildersIterator = contractClauses.iterator();
- for (int i = contractClauses.size(); i-- > 0;) {
- buildersIterator.advance();
- int key = buildersIterator.key();
- if (!notNulls.contains(key)) {
- List<String> clauses = buildersIterator.value();
- Collections.sort(clauses);
- StringBuilder sb = new StringBuilder("\"");
- StringUtil.join(clauses, ";", sb);
- sb.append('"');
- contracts.put(key, sb.toString().intern());
+ if (!notNulls.contains(methodKey) && !clauses.isEmpty()) {
+ Collections.sort(clauses);
+ StringBuilder sb = new StringBuilder("\"");
+ StringUtil.join(clauses, ";", sb);
+ sb.append('"');
+ contracts.put(methodKey, sb.toString().intern());
+ }
+ }
+
+ public void addParameterAnnotations(TLongObjectHashMap<Value> internalIdSolutions, Annotations annotations) {
+ TLongObjectIterator<Value> solutionsIterator = internalIdSolutions.iterator();
+ TLongHashSet notNulls = annotations.notNulls;
+ for (int i = internalIdSolutions.size(); i-- > 0;) {
+ solutionsIterator.advance();
+ long key = Math.abs(solutionsIterator.key());
+ Value value = solutionsIterator.value();
+ if (value == Value.Top || value == Value.Bot) {
+ continue;
+ }
+ Direction direction = extractDirection((int)(key % SHIFT));
+ if (value == Value.NotNull && (direction instanceof In || direction instanceof Out)) {
+ notNulls.add(key);
}
}
}
@@ -418,68 +397,4 @@ public class BytecodeAnalysisConverter implements ApplicationComponent {
return sb.toString();
}
- public int getVersion() {
- return version;
- }
-
- private static class IntArrayKeyDescriptor implements KeyDescriptor<int[]> {
-
- @Override
- public void save(@NotNull DataOutput out, int[] value) throws IOException {
- DataInputOutputUtil.writeINT(out, value.length);
- for (int i : value) {
- DataInputOutputUtil.writeINT(out, i);
- }
- }
-
- @Override
- public int[] read(@NotNull DataInput in) throws IOException {
- int[] value = new int[DataInputOutputUtil.readINT(in)];
- for (int i = 0; i < value.length; i++) {
- value[i] = DataInputOutputUtil.readINT(in);
- }
- return value;
- }
-
- @Override
- public int getHashCode(int[] value) {
- return Arrays.hashCode(value);
- }
-
- @Override
- public boolean isEqual(int[] val1, int[] val2) {
- return Arrays.equals(val1, val2);
- }
- }
-
- private static class IntArrayPersistentEnumerator extends PersistentEnumeratorDelegate<int[]> {
- private final CachingEnumerator<int[]> myCache;
-
- public IntArrayPersistentEnumerator(File compoundKeysFile, IntArrayKeyDescriptor descriptor) throws IOException {
- super(compoundKeysFile, descriptor, 1024 * 4);
- myCache = new CachingEnumerator<int[]>(new DataEnumerator<int[]>() {
- @Override
- public int enumerate(@Nullable int[] value) throws IOException {
- return IntArrayPersistentEnumerator.super.enumerate(value);
- }
-
- @Nullable
- @Override
- public int[] valueOf(int idx) throws IOException {
- return IntArrayPersistentEnumerator.super.valueOf(idx);
- }
- }, descriptor);
- }
-
- @Override
- public int enumerate(@Nullable int[] value) throws IOException {
- return myCache.enumerate(value);
- }
-
- @Nullable
- @Override
- public int[] valueOf(int idx) throws IOException {
- return myCache.valueOf(idx);
- }
- }
}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisConverterImpl.java b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisConverterImpl.java
new file mode 100644
index 000000000000..067cc743679e
--- /dev/null
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisConverterImpl.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInspection.bytecodeAnalysis;
+
+import com.intellij.ide.util.PropertiesComponent;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.PathManager;
+import com.intellij.openapi.util.ThrowableComputable;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.util.io.*;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.*;
+import java.io.DataOutputStream;
+import java.util.Arrays;
+
+import static com.intellij.codeInspection.bytecodeAnalysis.ProjectBytecodeAnalysis.LOG;
+
+/**
+ * @author lambdamix
+ */
+public class BytecodeAnalysisConverterImpl extends BytecodeAnalysisConverter {
+ private static final int LOGIC_VERSION = 1;
+ private static final String ENUMERATORS_VERSION_KEY = "BytecodeAnalysisConverter.Enumerators";
+
+ private File myVersionFile;
+ private PersistentStringEnumerator myNamesEnumerator;
+ private PersistentEnumeratorDelegate<int[]> myCompoundKeyEnumerator;
+ private int version;
+
+ @Override
+ public void initComponent() {
+
+ // suffix as an indicator of version
+ final File keysDir = new File(PathManager.getIndexRoot(), "bytecodekeys");
+ final File namesFile = new File(keysDir, "names" + LOGIC_VERSION);
+ final File compoundKeysFile = new File(keysDir, "compound" + LOGIC_VERSION);
+ myVersionFile = new File(keysDir, "version" + LOGIC_VERSION);
+
+ version = PropertiesComponent.getInstance().getOrInitInt(ENUMERATORS_VERSION_KEY, 0);
+ if (ApplicationManager.getApplication().isUnitTestMode()) {
+ version = _readVersion();
+ }
+
+ if (!namesFile.exists() || !compoundKeysFile.exists() || !myVersionFile.exists()) {
+ LOG.info("No enumerators detected, re-initialization of enumerators.");
+ IOUtil.deleteAllFilesStartingWith(keysDir);
+ version++;
+ }
+
+ try {
+ IOUtil.openCleanOrResetBroken(new ThrowableComputable<Void, IOException>() {
+ @Override
+ public Void compute() throws IOException {
+ myNamesEnumerator = new PersistentStringEnumerator(namesFile, true);
+ myCompoundKeyEnumerator = new IntArrayPersistentEnumerator(compoundKeysFile, new IntArrayKeyDescriptor());
+ return null;
+ }
+ }, new Runnable() {
+ @Override
+ public void run() {
+ LOG.info("Error during initialization of enumerators in bytecode analysis. Re-initializing.");
+ IOUtil.deleteAllFilesStartingWith(keysDir);
+ version++;
+ }
+ });
+ }
+ catch (IOException e) {
+ LOG.error("Re-initialization of enumerators in bytecode analysis failed.", e);
+ }
+ PropertiesComponent.getInstance().setValue(ENUMERATORS_VERSION_KEY, String.valueOf(version));
+ _saveVersion();
+ }
+
+ @Override
+ public void disposeComponent() {
+ try {
+ myNamesEnumerator.close();
+ myCompoundKeyEnumerator.close();
+ }
+ catch (IOException e) {
+ LOG.debug(e);
+ }
+ }
+
+ public int _readVersion() {
+ try {
+ final DataInputStream is = new DataInputStream(new FileInputStream(myVersionFile));
+ try {
+ return is.readInt();
+ }
+ finally {
+ is.close();
+ }
+ }
+ catch (FileNotFoundException ignored) {
+ }
+ catch (IOException ignored) {
+ }
+ return 0;
+ }
+
+ private void _saveVersion() {
+ try {
+ FileUtil.createIfDoesntExist(myVersionFile);
+ final DataOutputStream os = new DataOutputStream(new FileOutputStream(myVersionFile));
+ try {
+ os.writeInt(version);
+ }
+ finally {
+ os.close();
+ }
+ }
+ catch (IOException ignored) {
+ }
+ }
+
+ public int getVersion() {
+ return version;
+ }
+
+ @Override
+ protected int enumerateString(@NotNull String s) throws IOException {
+ return myNamesEnumerator.enumerate(s);
+ }
+
+ @Override
+ protected int enumerateCompoundKey(@NotNull int[] key) throws IOException {
+ return myCompoundKeyEnumerator.enumerate(key);
+ }
+
+ private static class IntArrayKeyDescriptor implements KeyDescriptor<int[]>, DifferentSerializableBytesImplyNonEqualityPolicy {
+
+ @Override
+ public void save(@NotNull DataOutput out, int[] value) throws IOException {
+ DataInputOutputUtil.writeINT(out, value.length);
+ for (int i : value) {
+ DataInputOutputUtil.writeINT(out, i);
+ }
+ }
+
+ @Override
+ public int[] read(@NotNull DataInput in) throws IOException {
+ int[] value = new int[DataInputOutputUtil.readINT(in)];
+ for (int i = 0; i < value.length; i++) {
+ value[i] = DataInputOutputUtil.readINT(in);
+ }
+ return value;
+ }
+
+ @Override
+ public int getHashCode(int[] value) {
+ return Arrays.hashCode(value);
+ }
+
+ @Override
+ public boolean isEqual(int[] val1, int[] val2) {
+ return Arrays.equals(val1, val2);
+ }
+ }
+
+ private static class IntArrayPersistentEnumerator extends PersistentEnumeratorDelegate<int[]> {
+ private final CachingEnumerator<int[]> myCache;
+
+ public IntArrayPersistentEnumerator(File compoundKeysFile, IntArrayKeyDescriptor descriptor) throws IOException {
+ super(compoundKeysFile, descriptor, 1024 * 4);
+ myCache = new CachingEnumerator<int[]>(new DataEnumerator<int[]>() {
+ @Override
+ public int enumerate(@Nullable int[] value) throws IOException {
+ return IntArrayPersistentEnumerator.super.enumerate(value);
+ }
+
+ @Nullable
+ @Override
+ public int[] valueOf(int idx) throws IOException {
+ return IntArrayPersistentEnumerator.super.valueOf(idx);
+ }
+ }, descriptor);
+ }
+
+ @Override
+ public int enumerate(@Nullable int[] value) throws IOException {
+ return myCache.enumerate(value);
+ }
+
+ @Nullable
+ @Override
+ public int[] valueOf(int idx) throws IOException {
+ return myCache.valueOf(idx);
+ }
+ }
+}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisIndex.java b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisIndex.java
index 6a4b32783c95..297b2b694c62 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisIndex.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisIndex.java
@@ -19,31 +19,29 @@ import com.intellij.ide.highlighter.JavaClassFileType;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.openapi.vfs.VirtualFileWithId;
import com.intellij.util.SystemProperties;
import com.intellij.util.indexing.*;
import com.intellij.util.io.DataExternalizer;
import com.intellij.util.io.DataInputOutputUtil;
-import com.intellij.util.io.EnumeratorIntegerDescriptor;
+import com.intellij.util.io.DifferentSerializableBytesImplyNonEqualityPolicy;
import com.intellij.util.io.KeyDescriptor;
import org.jetbrains.annotations.NotNull;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
/**
* @author lambdamix
*/
-public class BytecodeAnalysisIndex extends FileBasedIndexExtension<Integer, Collection<IntIdEquation>> {
- public static final ID<Integer, Collection<IntIdEquation>> NAME = ID.create("bytecodeAnalysis");
+public class BytecodeAnalysisIndex extends FileBasedIndexExtension<Long, IdEquation> {
+ public static final ID<Long, IdEquation> NAME = ID.create("bytecodeAnalysis");
private final EquationExternalizer myExternalizer = new EquationExternalizer();
- private static final DataIndexer<Integer, Collection<IntIdEquation>, FileContent> INDEXER =
+ private static final DataIndexer<Long, IdEquation, FileContent> INDEXER =
new ClassDataIndexer(BytecodeAnalysisConverter.getInstance());
+ private static final SmartLongKeyDescriptor KEY_DESCRIPTOR = new SmartLongKeyDescriptor();
- private static final int ourInternalVersion = 2;
+ private static final int ourInternalVersion = 3;
private static boolean ourEnabled = SystemProperties.getBooleanProperty("idea.enable.bytecode.contract.inference", isEnabledByDefault());
private static boolean isEnabledByDefault() {
@@ -51,31 +49,27 @@ public class BytecodeAnalysisIndex extends FileBasedIndexExtension<Integer, Coll
return application.isInternal() || application.isUnitTestMode();
}
- public static int indexKey(VirtualFile file, boolean parameters) {
- return (file instanceof VirtualFileWithId ? ((VirtualFileWithId)file).getId() * 2 : -2) + (parameters ? 1 : 0);
- }
-
@NotNull
@Override
- public ID<Integer, Collection<IntIdEquation>> getName() {
+ public ID<Long, IdEquation> getName() {
return NAME;
}
@NotNull
@Override
- public DataIndexer<Integer, Collection<IntIdEquation>, FileContent> getIndexer() {
+ public DataIndexer<Long, IdEquation, FileContent> getIndexer() {
return INDEXER;
}
@NotNull
@Override
- public KeyDescriptor<Integer> getKeyDescriptor() {
- return EnumeratorIntegerDescriptor.INSTANCE;
+ public KeyDescriptor<Long> getKeyDescriptor() {
+ return KEY_DESCRIPTOR;
}
@NotNull
@Override
- public DataExternalizer<Collection<IntIdEquation>> getValueExternalizer() {
+ public DataExternalizer<IdEquation> getValueExternalizer() {
return myExternalizer;
}
@@ -100,68 +94,108 @@ public class BytecodeAnalysisIndex extends FileBasedIndexExtension<Integer, Coll
return ourInternalVersion + BytecodeAnalysisConverter.getInstance().getVersion() + (ourEnabled ? 0xFF : 0);
}
- public static class EquationExternalizer implements DataExternalizer<Collection<IntIdEquation>> {
+ public static class EquationExternalizer implements DataExternalizer<IdEquation>, DifferentSerializableBytesImplyNonEqualityPolicy {
@Override
- public void save(@NotNull DataOutput out, Collection<IntIdEquation> equations) throws IOException {
- DataInputOutputUtil.writeINT(out, equations.size());
-
- for (IntIdEquation equation : equations) {
- out.writeInt(equation.id);
- IntIdResult rhs = equation.rhs;
- if (rhs instanceof IntIdFinal) {
- IntIdFinal finalResult = (IntIdFinal)rhs;
- out.writeBoolean(true); // final flag
- DataInputOutputUtil.writeINT(out, finalResult.value.ordinal());
- } else {
- IntIdPending pendResult = (IntIdPending)rhs;
- out.writeBoolean(false); // pending flag
- DataInputOutputUtil.writeINT(out, pendResult.delta.length);
-
- for (IntIdComponent component : pendResult.delta) {
- DataInputOutputUtil.writeINT(out, component.value.ordinal());
- int[] ids = component.ids;
- DataInputOutputUtil.writeINT(out, ids.length);
- for (int id : ids) {
- out.writeInt(id);
- }
+ public void save(@NotNull DataOutput out, IdEquation equation) throws IOException {
+ long id = equation.id;
+ int sign = id > 0 ? 1 : -1;
+ id = Math.abs(id);
+ int primaryId = (int)(id / BytecodeAnalysisConverter.SHIFT);
+ int secondaryId = (int)(id % BytecodeAnalysisConverter.SHIFT);
+ out.writeInt(sign * primaryId);
+ DataInputOutputUtil.writeINT(out, secondaryId);
+ IdResult rhs = equation.rhs;
+ if (rhs instanceof IdFinal) {
+ IdFinal finalResult = (IdFinal)rhs;
+ out.writeBoolean(true); // final flag
+ DataInputOutputUtil.writeINT(out, finalResult.value.ordinal());
+ } else {
+ IdPending pendResult = (IdPending)rhs;
+ out.writeBoolean(false); // pending flag
+ DataInputOutputUtil.writeINT(out, pendResult.delta.length);
+
+ for (IntIdComponent component : pendResult.delta) {
+ DataInputOutputUtil.writeINT(out, component.value.ordinal());
+ long[] ids = component.ids;
+ DataInputOutputUtil.writeINT(out, ids.length);
+ for (long id1 : ids) {
+ sign = id1 > 0 ? 1 : -1;
+ id = Math.abs(id1);
+ primaryId = (int)(id / BytecodeAnalysisConverter.SHIFT);
+ secondaryId = (int)(id % BytecodeAnalysisConverter.SHIFT);
+ out.writeInt(sign * primaryId);
+ DataInputOutputUtil.writeINT(out, secondaryId);
}
}
}
}
@Override
- public Collection<IntIdEquation> read(@NotNull DataInput in) throws IOException {
-
- int size = DataInputOutputUtil.readINT(in);
- ArrayList<IntIdEquation> result = new ArrayList<IntIdEquation>(size);
-
- for (int x = 0; x < size; x++) {
- int equationId = in.readInt();
- boolean isFinal = in.readBoolean(); // flag
- if (isFinal) {
+ public IdEquation read(@NotNull DataInput in) throws IOException {
+ long primaryId = in.readInt();
+ int sign = primaryId > 0 ? 1 : -1;
+ primaryId = Math.abs(primaryId);
+ int secondaryId = DataInputOutputUtil.readINT(in);
+ long equationId = sign * (primaryId * BytecodeAnalysisConverter.SHIFT + secondaryId);
+ boolean isFinal = in.readBoolean(); // flag
+ if (isFinal) {
+ int ordinal = DataInputOutputUtil.readINT(in);
+ Value value = Value.values()[ordinal];
+ return new IdEquation(equationId, new IdFinal(value));
+ } else {
+
+ int sumLength = DataInputOutputUtil.readINT(in);
+ IntIdComponent[] components = new IntIdComponent[sumLength];
+
+ for (int i = 0; i < sumLength; i++) {
int ordinal = DataInputOutputUtil.readINT(in);
Value value = Value.values()[ordinal];
- result.add(new IntIdEquation(equationId, new IntIdFinal(value)));
- } else {
-
- int sumLength = DataInputOutputUtil.readINT(in);
- IntIdComponent[] components = new IntIdComponent[sumLength];
-
- for (int i = 0; i < sumLength; i++) {
- int ordinal = DataInputOutputUtil.readINT(in);
- Value value = Value.values()[ordinal];
- int componentSize = DataInputOutputUtil.readINT(in);
- int[] ids = new int[componentSize];
- for (int j = 0; j < componentSize; j++) {
- ids[j] = in.readInt();
- }
- components[i] = new IntIdComponent(value, ids);
+ int componentSize = DataInputOutputUtil.readINT(in);
+ long[] ids = new long[componentSize];
+ for (int j = 0; j < componentSize; j++) {
+ primaryId = in.readInt();
+ sign = primaryId > 0 ? 1 : -1;
+ primaryId = Math.abs(primaryId);
+ secondaryId = DataInputOutputUtil.readINT(in);
+ long id = sign * (primaryId * BytecodeAnalysisConverter.SHIFT + secondaryId);
+ ids[j] = id;
}
- result.add(new IntIdEquation(equationId, new IntIdPending(components)));
+ components[i] = new IntIdComponent(value, ids);
}
+ return new IdEquation(equationId, new IdPending(components));
}
+ }
+ }
+
+ private static class SmartLongKeyDescriptor implements KeyDescriptor<Long>, DifferentSerializableBytesImplyNonEqualityPolicy {
+ @Override
+ public void save(@NotNull DataOutput out, Long value) throws IOException {
+ long id = value.longValue();
+ int sign = id > 0 ? 1 : -1;
+ id = Math.abs(id);
+ int primaryId = (int)(id / BytecodeAnalysisConverter.SHIFT);
+ int secondaryId = (int)(id % BytecodeAnalysisConverter.SHIFT);
+ out.writeInt(primaryId * sign);
+ DataInputOutputUtil.writeINT(out, secondaryId);
+ }
+
+ @Override
+ public Long read(@NotNull DataInput in) throws IOException {
+ long primaryId = in.readInt();
+ int sign = primaryId > 0 ? 1 : -1;
+ primaryId = Math.abs(primaryId);
+ int secondaryId = DataInputOutputUtil.readINT(in);
+ return sign * (primaryId * BytecodeAnalysisConverter.SHIFT + secondaryId);
+ }
- return result;
+ @Override
+ public int getHashCode(Long value) {
+ return value.hashCode();
+ }
+
+ @Override
+ public boolean isEqual(Long val1, Long val2) {
+ return val1.longValue() == val2.longValue();
}
}
}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/ClassDataIndexer.java b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/ClassDataIndexer.java
index 5e74a8b5dbb3..9e656b98a7fb 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/ClassDataIndexer.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/ClassDataIndexer.java
@@ -33,7 +33,7 @@ import static com.intellij.codeInspection.bytecodeAnalysis.ProjectBytecodeAnalys
/**
* @author lambdamix
*/
-public class ClassDataIndexer implements DataIndexer<Integer, Collection<IntIdEquation>, FileContent> {
+public class ClassDataIndexer implements DataIndexer<Long, IdEquation, FileContent> {
final BytecodeAnalysisConverter myConverter;
public ClassDataIndexer(BytecodeAnalysisConverter converter) {
@@ -42,25 +42,20 @@ public class ClassDataIndexer implements DataIndexer<Integer, Collection<IntIdEq
@NotNull
@Override
- public Map<Integer, Collection<IntIdEquation>> map(@NotNull FileContent inputData) {
- HashMap<Integer, Collection<IntIdEquation>> map = new HashMap<Integer, Collection<IntIdEquation>>(2);
+ public Map<Long, IdEquation> map(@NotNull FileContent inputData) {
+ HashMap<Long, IdEquation> map = new HashMap<Long, IdEquation>();
try {
ClassEquations rawEquations = processClass(new ClassReader(inputData.getContent()));
List<Equation<Key, Value>> rawParameterEquations = rawEquations.parameterEquations;
List<Equation<Key, Value>> rawContractEquations = rawEquations.contractEquations;
- Collection<IntIdEquation> idParameterEquations = new ArrayList<IntIdEquation>(rawParameterEquations.size());
- Collection<IntIdEquation> idContractEquations = new ArrayList<IntIdEquation>(rawContractEquations.size());
-
- map.put(BytecodeAnalysisIndex.indexKey(inputData.getFile(), true), idParameterEquations);
- map.put(BytecodeAnalysisIndex.indexKey(inputData.getFile(), false), idContractEquations);
-
-
for (Equation<Key, Value> rawParameterEquation: rawParameterEquations) {
- idParameterEquations.add(myConverter.convert(rawParameterEquation));
+ IdEquation equation = myConverter.convert(rawParameterEquation);
+ map.put(equation.id, equation);
}
for (Equation<Key, Value> rawContractEquation: rawContractEquations) {
- idContractEquations.add(myConverter.convert(rawContractEquation));
+ IdEquation equation = myConverter.convert(rawContractEquation);
+ map.put(equation.id, equation);
}
}
catch (ProcessCanceledException e) {
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/Contracts.java b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/Contracts.java
index c837b127b74b..7b6c52e75a63 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/Contracts.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/Contracts.java
@@ -49,7 +49,7 @@ class InOutAnalysis extends Analysis<Result<Key, Value>> {
}
@Override
- Result<Key, Value> combineResults(Result<Key, Value> delta, List<Result<Key, Value>> subResults) {
+ Result<Key, Value> combineResults(Result<Key, Value> delta, List<Result<Key, Value>> subResults) throws AnalyzerException {
Result<Key, Value> result = null;
for (Result<Key, Value> subResult : subResults) {
if (result == null) {
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/Parameters.java b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/Parameters.java
index 08c52c4d49b0..625eb8eed977 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/Parameters.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/Parameters.java
@@ -78,8 +78,9 @@ abstract class PResults {
};
static final class ConditionalNPE implements PResult {
final Set<Set<Key>> sop;
- public ConditionalNPE(Set<Set<Key>> sop) {
+ public ConditionalNPE(Set<Set<Key>> sop) throws AnalyzerException {
this.sop = sop;
+ checkLimit(sop);
}
public ConditionalNPE(Key key) {
@@ -88,9 +89,19 @@ abstract class PResults {
prod.add(key);
sop.add(prod);
}
+
+ static void checkLimit(Set<Set<Key>> sop) throws AnalyzerException {
+ int size = 0;
+ for (Set<Key> keys : sop) {
+ size += keys.size();
+ }
+ if (size > Analysis.EQUATION_SIZE_LIMIT) {
+ throw new AnalyzerException(null, "Equation size is too big");
+ }
+ }
}
- static PResult join(PResult r1, PResult r2) {
+ static PResult join(PResult r1, PResult r2) throws AnalyzerException {
if (Identity == r1) return r2;
if (Identity == r2) return r1;
if (Return == r1) return Return;
@@ -102,7 +113,7 @@ abstract class PResults {
return new ConditionalNPE(join(cnpe1.sop, cnpe2.sop));
}
- static PResult meet(PResult r1, PResult r2) {
+ static PResult meet(PResult r1, PResult r2) throws AnalyzerException {
if (Identity == r1) return r2;
if (Return == r1) return r2;
if (Return == r2) return r1;
@@ -130,7 +141,7 @@ class NonNullInAnalysis extends Analysis<PResult> {
}
@Override
- PResult combineResults(PResult delta, List<PResult> subResults) {
+ PResult combineResults(PResult delta, List<PResult> subResults) throws AnalyzerException {
PResult subResult = Identity;
for (PResult sr : subResults) {
subResult = join(subResult, sr);
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/ProjectBytecodeAnalysis.java b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/ProjectBytecodeAnalysis.java
index 86b9dd101fd9..23d9d5a9e1c5 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/ProjectBytecodeAnalysis.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/ProjectBytecodeAnalysis.java
@@ -15,34 +15,31 @@
*/
package com.intellij.codeInspection.bytecodeAnalysis;
-import com.intellij.ProjectTopics;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInspection.dataFlow.ControlFlowAnalyzer;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.roots.ContentIterator;
-import com.intellij.openapi.roots.ModuleRootAdapter;
-import com.intellij.openapi.roots.ModuleRootEvent;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.ModificationTracker;
-import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.ProjectScope;
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.psi.util.CachedValuesManager;
+import com.intellij.psi.util.PsiFormatUtil;
import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.containers.LongStack;
import com.intellij.util.indexing.FileBasedIndex;
-import com.intellij.util.messages.MessageBusConnection;
-import gnu.trove.TIntHashSet;
-import gnu.trove.TIntObjectHashMap;
+import gnu.trove.TLongArrayList;
+import gnu.trove.TLongHashSet;
+import gnu.trove.TLongObjectHashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
-import java.util.Collection;
+import java.util.List;
/**
* @author lambdamix
@@ -50,93 +47,15 @@ import java.util.Collection;
public class ProjectBytecodeAnalysis {
public static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.bytecodeAnalysis");
public static final Key<Boolean> INFERRED_ANNOTATION = Key.create("INFERRED_ANNOTATION");
+ public static final int EQUATIONS_LIMIT = 1000;
private final Project myProject;
- private volatile Annotations myAnnotations = null;
-
public static ProjectBytecodeAnalysis getInstance(@NotNull Project project) {
return ServiceManager.getService(project, ProjectBytecodeAnalysis.class);
}
public ProjectBytecodeAnalysis(Project project) {
myProject = project;
- final MessageBusConnection connection = myProject.getMessageBus().connect();
- connection.subscribe(ProjectTopics.PROJECT_ROOTS, new ModuleRootAdapter() {
- @Override
- public void rootsChanged(ModuleRootEvent event) {
- unloadAnnotations();
- }
- });
- }
-
- private void loadAnnotations() {
- Annotations annotations = new Annotations();
- loadParameterAnnotations(annotations);
- loadContractAnnotations(annotations);
- myAnnotations = annotations;
- LOG.debug("NotNull annotations: " + myAnnotations.notNulls.size());
- LOG.debug("Contract annotations: " + myAnnotations.contracts.size());
- }
-
- private void unloadAnnotations() {
- myAnnotations = null;
- LOG.debug("unloaded");
- }
-
- private void loadParameterAnnotations(Annotations annotations) {
- LOG.debug("initializing parameter annotations");
- final IntIdSolver solver = new IntIdSolver(new ELattice<Value>(Value.NotNull, Value.Top));
-
- processValues(true, new FileBasedIndex.ValueProcessor<Collection<IntIdEquation>>() {
- @Override
- public boolean process(VirtualFile file, Collection<IntIdEquation> value) {
- for (IntIdEquation intIdEquation : value) {
- solver.addEquation(intIdEquation);
- }
- return true;
- }
- });
-
- LOG.debug("parameter equations are constructed");
- LOG.debug("equations: " + solver.getSize());
- TIntObjectHashMap<Value> solutions = solver.solve();
- LOG.debug("parameter equations are solved");
- BytecodeAnalysisConverter.getInstance().addAnnotations(solutions, annotations);
- }
-
- private void processValues(final boolean parameters, final FileBasedIndex.ValueProcessor<Collection<IntIdEquation>> processor) {
- final GlobalSearchScope libScope = ProjectScope.getLibrariesScope(myProject);
- final FileBasedIndex index = FileBasedIndex.getInstance();
- index.iterateIndexableFiles(new ContentIterator() {
- @Override
- public boolean processFile(VirtualFile fileOrDir) {
- ProgressManager.checkCanceled();
- if (!fileOrDir.isDirectory() && libScope.contains(fileOrDir)) {
- index.processValues(BytecodeAnalysisIndex.NAME, BytecodeAnalysisIndex.indexKey(fileOrDir, parameters),
- fileOrDir, processor, GlobalSearchScope.fileScope(myProject, fileOrDir));
- }
- return false;
- }
- }, myProject, null);
- }
-
- private void loadContractAnnotations(Annotations annotations) {
- LOG.debug("initializing contract annotations");
- final IntIdSolver solver = new IntIdSolver(new ELattice<Value>(Value.Bot, Value.Top));
- processValues(false, new FileBasedIndex.ValueProcessor<Collection<IntIdEquation>>() {
- @Override
- public boolean process(VirtualFile file, Collection<IntIdEquation> value) {
- for (IntIdEquation intIdEquation : value) {
- solver.addEquation(intIdEquation);
- }
- return true;
- }
- });
- LOG.debug("contract equations are constructed");
- LOG.debug("equations: " + solver.getSize());
- TIntObjectHashMap<Value> solutions = solver.solve();
- LOG.debug("contract equations are solved");
- BytecodeAnalysisConverter.getInstance().addAnnotations(solutions, annotations);
}
@Nullable
@@ -144,11 +63,14 @@ public class ProjectBytecodeAnalysis {
if (!(listOwner instanceof PsiCompiledElement)) {
return null;
}
- if (annotationFQN.equals("org.jetbrains.annotations.NotNull")) {
- return findNotNullAnnotation(listOwner);
- }
- else if (annotationFQN.equals("org.jetbrains.annotations.Contract")) {
- return findContractAnnotation(listOwner);
+ if (annotationFQN.equals(AnnotationUtil.NOT_NULL) || annotationFQN.equals(ControlFlowAnalyzer.ORG_JETBRAINS_ANNOTATIONS_CONTRACT)) {
+ PsiAnnotation[] annotations = findInferredAnnotations(listOwner);
+ for (PsiAnnotation annotation : annotations) {
+ if (annotationFQN.equals(annotation.getQualifiedName())) {
+ return annotation;
+ }
+ }
+ return null;
}
else {
return null;
@@ -156,26 +78,30 @@ public class ProjectBytecodeAnalysis {
}
@NotNull
- public PsiAnnotation[] findInferredAnnotations(@NotNull PsiModifierListOwner listOwner) {
+ public PsiAnnotation[] findInferredAnnotations(@NotNull final PsiModifierListOwner listOwner) {
if (!(listOwner instanceof PsiCompiledElement)) {
return PsiAnnotation.EMPTY_ARRAY;
}
- return collectInferredAnnotations(listOwner);
+ return CachedValuesManager.getCachedValue(listOwner, new CachedValueProvider<PsiAnnotation[]>() {
+ @Nullable
+ @Override
+ public Result<PsiAnnotation[]> compute() {
+ return Result.create(collectInferredAnnotations(listOwner), listOwner);
+ }
+ });
}
- // TODO the best way to synchronize?
@NotNull
- private synchronized PsiAnnotation[] collectInferredAnnotations(PsiModifierListOwner listOwner) {
- if (myAnnotations == null) {
- loadAnnotations();
- }
+ private PsiAnnotation[] collectInferredAnnotations(PsiModifierListOwner listOwner) {
try {
- int key = getKey(listOwner);
- if (key == -1) {
+ long ownerKey = getKey(listOwner);
+ if (ownerKey == -1) {
return PsiAnnotation.EMPTY_ARRAY;
}
- boolean notNull = myAnnotations.notNulls.contains(key);
- String contractValue = myAnnotations.contracts.get(key);
+ TLongArrayList allKeys = contractKeys(listOwner, ownerKey);
+ Annotations annotations = loadAnnotations(listOwner, ownerKey, allKeys);
+ boolean notNull = annotations.notNulls.contains(ownerKey);
+ String contractValue = annotations.contracts.get(ownerKey);
if (notNull && contractValue != null) {
return new PsiAnnotation[]{
@@ -201,6 +127,11 @@ public class ProjectBytecodeAnalysis {
LOG.debug(e);
return PsiAnnotation.EMPTY_ARRAY;
}
+ catch (EquationsLimitException e) {
+ String externalName = PsiFormatUtil.getExternalName(listOwner, false, Integer.MAX_VALUE);
+ LOG.info("Too many equations for " + externalName);
+ return PsiAnnotation.EMPTY_ARRAY;
+ }
}
private PsiAnnotation getNotNullAnnotation() {
@@ -213,54 +144,15 @@ public class ProjectBytecodeAnalysis {
});
}
- @Nullable
- private synchronized PsiAnnotation findNotNullAnnotation(PsiModifierListOwner listOwner) {
- if (myAnnotations == null) {
- loadAnnotations();
- }
- try {
- int key = getKey(listOwner);
- if (key == -1) {
- return null;
- }
- return myAnnotations.notNulls.contains(key) ? getNotNullAnnotation() : null;
- }
- catch (IOException e) {
- LOG.debug(e);
- return null;
- }
- }
-
- @Nullable
- private synchronized PsiAnnotation findContractAnnotation(PsiModifierListOwner listOwner) {
- if (myAnnotations == null) {
- loadAnnotations();
- }
- try {
- int key = getKey(listOwner);
- if (key == -1) {
- return null;
- }
- String contractValue = myAnnotations.contracts.get(key);
- return contractValue != null ? createContractAnnotation(contractValue) : null;
- }
- catch (IOException e) {
- LOG.debug(e);
- return null;
- }
- }
-
public PsiAnnotation createContractAnnotation(String contractValue) {
return createAnnotationFromText("@org.jetbrains.annotations.Contract(" + contractValue + ")");
}
- public static int getKey(@NotNull PsiModifierListOwner owner) throws IOException {
+ public static long getKey(@NotNull PsiModifierListOwner owner) throws IOException {
LOG.assertTrue(owner instanceof PsiCompiledElement, owner);
-
if (owner instanceof PsiMethod) {
return BytecodeAnalysisConverter.getInstance().mkPsiKey((PsiMethod)owner, new Out());
}
-
if (owner instanceof PsiParameter) {
PsiElement parent = owner.getParent();
if (parent instanceof PsiParameterList) {
@@ -275,6 +167,80 @@ public class ProjectBytecodeAnalysis {
return -1;
}
+ public static TLongArrayList contractKeys(@NotNull PsiModifierListOwner owner, long primaryKey) throws IOException {
+ if (owner instanceof PsiMethod) {
+ TLongArrayList result = BytecodeAnalysisConverter.getInstance().mkInOutKeys((PsiMethod)owner, primaryKey);
+ result.add(primaryKey);
+ return result;
+ }
+ TLongArrayList result = new TLongArrayList(1);
+ result.add(primaryKey);
+ return result;
+ }
+
+ private Annotations loadAnnotations(@NotNull PsiModifierListOwner owner, long key, TLongArrayList allKeys)
+ throws IOException, EquationsLimitException {
+ Annotations result = new Annotations();
+ if (owner instanceof PsiParameter) {
+ final Solver solver = new Solver(new ELattice<Value>(Value.NotNull, Value.Top));
+ collectEquations(allKeys, solver);
+ TLongObjectHashMap<Value> solutions = solver.solve();
+ BytecodeAnalysisConverter.getInstance().addParameterAnnotations(solutions, result);
+ } else if (owner instanceof PsiMethod) {
+ final Solver solver = new Solver(new ELattice<Value>(Value.Bot, Value.Top));
+ collectEquations(allKeys, solver);
+ TLongObjectHashMap<Value> solutions = solver.solve();
+ BytecodeAnalysisConverter.getInstance().addMethodAnnotations(solutions, result, key,
+ ((PsiMethod)owner).getParameterList().getParameters().length);
+ }
+ return result;
+ }
+
+ private void collectEquations(TLongArrayList keys, Solver solver) throws EquationsLimitException {
+ GlobalSearchScope librariesScope = ProjectScope.getLibrariesScope(myProject);
+ TLongHashSet queued = new TLongHashSet();
+ LongStack queue = new LongStack();
+
+ for (int i = 0; i < keys.size(); i++) {
+ long key = keys.get(i);
+ queue.push(key);
+ queued.add(key);
+ // stable/unstable
+ queue.push(-key);
+ queued.add(-key);
+ }
+
+ FileBasedIndex index = FileBasedIndex.getInstance();
+ while (!queue.empty()) {
+ if (queued.size() > EQUATIONS_LIMIT) {
+ throw new EquationsLimitException();
+ }
+ ProgressManager.checkCanceled();
+ List<IdEquation> equations = index.getValues(BytecodeAnalysisIndex.NAME, queue.pop(), librariesScope);
+ for (IdEquation equation : equations) {
+ IdResult rhs = equation.rhs;
+ solver.addEquation(equation);
+ if (rhs instanceof IdPending) {
+ IdPending intIdPending = (IdPending)rhs;
+ for (IntIdComponent component : intIdPending.delta) {
+ for (long depKey : component.ids) {
+ if (!queued.contains(depKey)) {
+ queue.push(depKey);
+ queued.add(depKey);
+ }
+ // stable/unstable
+ long swapped = -depKey;
+ if (!queued.contains(swapped)) {
+ queue.push(swapped);
+ queued.add(swapped);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
@NotNull
private PsiAnnotation createAnnotationFromText(@NotNull final String text) throws IncorrectOperationException {
PsiAnnotation annotation = JavaPsiFacade.getElementFactory(myProject).createAnnotationFromText(text, null);
@@ -285,7 +251,9 @@ public class ProjectBytecodeAnalysis {
class Annotations {
// @NotNull keys
- final TIntHashSet notNulls = new TIntHashSet();
+ final TLongHashSet notNulls = new TLongHashSet();
// @Contracts
- final TIntObjectHashMap<String> contracts = new TIntObjectHashMap<String>();
+ final TLongObjectHashMap<String> contracts = new TLongObjectHashMap<String>();
}
+
+class EquationsLimitException extends Exception {}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/Solver.java b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/Solver.java
index 47c97790d102..1dec1de8a606 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/Solver.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/Solver.java
@@ -15,10 +15,12 @@
*/
package com.intellij.codeInspection.bytecodeAnalysis;
-import com.intellij.util.containers.IntStack;
-import com.intellij.util.containers.IntToIntSetMap;
-import gnu.trove.TIntObjectHashMap;
+import com.intellij.util.containers.LongStack;
+import gnu.trove.TLongHashSet;
+import gnu.trove.TLongIterator;
+import gnu.trove.TLongObjectHashMap;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.org.objectweb.asm.tree.analysis.AnalyzerException;
import java.util.*;
@@ -49,9 +51,9 @@ final class ELattice<T extends Enum<T>> {
// component specialized for ints
final class IntIdComponent {
Value value;
- final int[] ids;
+ final long[] ids;
- IntIdComponent(Value value, int[] ids) {
+ IntIdComponent(Value value, long[] ids) {
this.value = value;
this.ids = ids;
}
@@ -74,7 +76,7 @@ final class IntIdComponent {
return value.ordinal() + Arrays.hashCode(ids);
}
- public boolean remove(int id) {
+ public boolean remove(long id) {
return IdUtils.remove(ids, id);
}
@@ -89,18 +91,18 @@ final class IntIdComponent {
class IdUtils {
// removed value
- static final int nullId = 0;
+ static final long nullId = 0;
- static boolean contains(int[] ids, int id) {
- for (int id1 : ids) {
+ static boolean contains(long[] ids, int id) {
+ for (long id1 : ids) {
if (id1 == id) return true;
}
return false;
}
- static boolean isEmpty(int[] ids) {
- for (int id : ids) {
+ static boolean isEmpty(long[] ids) {
+ for (long id : ids) {
if (id != nullId) return false;
}
return true;
@@ -117,7 +119,7 @@ class IdUtils {
return result;
}
- static boolean remove(int[] ids, int id) {
+ static boolean remove(long[] ids, long id) {
boolean removed = false;
for (int i = 0; i < ids.length; i++) {
if (ids[i] == id) {
@@ -137,7 +139,7 @@ class ResultUtil<Id, T extends Enum<T>> {
top = lattice.top;
}
- Result<Id, T> join(Result<Id, T> r1, Result<Id, T> r2) {
+ Result<Id, T> join(Result<Id, T> r1, Result<Id, T> r2) throws AnalyzerException {
if (r1 instanceof Final && ((Final) r1).value == top) {
return r1;
}
@@ -166,8 +168,19 @@ class ResultUtil<Id, T extends Enum<T>> {
Set<Product<Id, T>> sum = new HashSet<Product<Id, T>>();
sum.addAll(pending1.sum);
sum.addAll(pending2.sum);
+ checkLimit(sum);
return new Pending<Id, T>(sum);
}
+
+ private void checkLimit(Set<Product<Id, T>> sum) throws AnalyzerException {
+ int size = 0;
+ for (Product<Id, T> prod : sum) {
+ size += prod.ids.size();
+ }
+ if (size > Analysis.EQUATION_SIZE_LIMIT) {
+ throw new AnalyzerException(null, "Equation size is too big");
+ }
+ }
}
final class Product<K, V> {
@@ -222,11 +235,11 @@ final class Pending<Id, T> implements Result<Id, T> {
}
-interface IntIdResult {}
+interface IdResult {}
// this just wrapper, no need for this really
-final class IntIdFinal implements IntIdResult {
+final class IdFinal implements IdResult {
final Value value;
- public IntIdFinal(Value value) {
+ public IdFinal(Value value) {
this.value = value;
}
@@ -235,7 +248,7 @@ final class IntIdFinal implements IntIdResult {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
- IntIdFinal that = (IntIdFinal)o;
+ IdFinal that = (IdFinal)o;
if (value != that.value) return false;
@@ -253,19 +266,19 @@ final class IntIdFinal implements IntIdResult {
}
}
-final class IntIdPending implements IntIdResult {
+final class IdPending implements IdResult {
final IntIdComponent[] delta;
- IntIdPending(IntIdComponent[] delta) {
+ IdPending(IntIdComponent[] delta) {
this.delta = delta;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
- if (!(o instanceof IntIdPending)) return false;
- IntIdPending pending = (IntIdPending)o;
- return !Arrays.equals(delta, pending.delta);
+ if (!(o instanceof IdPending)) return false;
+ IdPending pending = (IdPending)o;
+ return Arrays.equals(delta, pending.delta);
}
@Override
@@ -273,20 +286,20 @@ final class IntIdPending implements IntIdResult {
return Arrays.hashCode(delta);
}
- IntIdPending copy() {
+ IdPending copy() {
IntIdComponent[] delta1 = new IntIdComponent[delta.length];
for (int i = 0; i < delta.length; i++) {
delta1[i] = delta[i].copy();
}
- return new IntIdPending(delta1);
+ return new IdPending(delta1);
}
}
-final class IntIdEquation {
- final int id;
- final IntIdResult rhs;
+final class IdEquation {
+ final long id;
+ final IdResult rhs;
- IntIdEquation(int id, IntIdResult rhs) {
+ IdEquation(long id, IdResult rhs) {
this.id = id;
this.rhs = rhs;
}
@@ -294,9 +307,9 @@ final class IntIdEquation {
@Override
public boolean equals(Object o) {
if (this == o) return true;
- if (!(o instanceof IntIdEquation)) return false;
+ if (!(o instanceof IdEquation)) return false;
- IntIdEquation equation = (IntIdEquation)o;
+ IdEquation equation = (IdEquation)o;
if (id != equation.id) return false;
if (!rhs.equals(equation.rhs)) return false;
@@ -306,9 +319,7 @@ final class IntIdEquation {
@Override
public int hashCode() {
- int result = id;
- result = 31 * result + rhs.hashCode();
- return result;
+ return 31 * ((int)(id ^ (id >>> 32))) + rhs.hashCode();
}
}
@@ -337,41 +348,46 @@ final class Equation<Id, T> {
}
}
-final class IntIdSolver {
+final class Solver {
private int size = 0;
private final ELattice<Value> lattice;
- private final IntToIntSetMap dependencies = new IntToIntSetMap(10000, 0.5f);
- private final TIntObjectHashMap<IntIdPending> pending = new TIntObjectHashMap<IntIdPending>();
- private final TIntObjectHashMap<Value> solved = new TIntObjectHashMap<Value>();
- private final IntStack moving = new IntStack();
+ private final TLongObjectHashMap<TLongHashSet> dependencies = new TLongObjectHashMap<TLongHashSet>();
+ private final TLongObjectHashMap<IdPending> pending = new TLongObjectHashMap<IdPending>();
+ private final TLongObjectHashMap<Value> solved = new TLongObjectHashMap<Value>();
+ private final LongStack moving = new LongStack();
int getSize() {
return size;
}
- IntIdSolver(ELattice<Value> lattice) {
+ Solver(ELattice<Value> lattice) {
this.lattice = lattice;
}
- void addEquation(IntIdEquation equation) {
+ void addEquation(IdEquation equation) {
size ++;
- IntIdResult rhs = equation.rhs;
- if (rhs instanceof IntIdFinal) {
- solved.put(equation.id, ((IntIdFinal) rhs).value);
+ IdResult rhs = equation.rhs;
+ if (rhs instanceof IdFinal) {
+ solved.put(equation.id, ((IdFinal) rhs).value);
moving.push(equation.id);
- } else if (rhs instanceof IntIdPending) {
- IntIdPending pendResult = ((IntIdPending)rhs).copy();
- IntIdResult norm = normalize(pendResult.delta);
- if (norm instanceof IntIdFinal) {
- solved.put(equation.id, ((IntIdFinal) norm).value);
+ } else if (rhs instanceof IdPending) {
+ IdPending pendResult = ((IdPending)rhs).copy();
+ IdResult norm = normalize(pendResult.delta);
+ if (norm instanceof IdFinal) {
+ solved.put(equation.id, ((IdFinal) norm).value);
moving.push(equation.id);
}
else {
- IntIdPending pendResult1 = ((IntIdPending)rhs).copy();
+ IdPending pendResult1 = ((IdPending)rhs).copy();
for (IntIdComponent component : pendResult1.delta) {
- for (int trigger : component.ids) {
- dependencies.addOccurence(trigger, equation.id);
+ for (long trigger : component.ids) {
+ TLongHashSet set = dependencies.get(trigger);
+ if (set == null) {
+ set = new TLongHashSet();
+ dependencies.put(trigger, set);
+ }
+ set.add(equation.id);
}
pending.put(equation.id, pendResult1);
}
@@ -379,31 +395,35 @@ final class IntIdSolver {
}
}
- TIntObjectHashMap<Value> solve() {
+ TLongObjectHashMap<Value> solve() {
while (!moving.empty()) {
- int id = moving.pop();
+ long id = moving.pop();
Value value = solved.get(id);
boolean stable = id > 0;
- int[] pIds = stable ? new int[]{id, -id} : new int[]{-id, id};
+ long[] pIds = stable ? new long[]{id, -id} : new long[]{-id, id};
Value[] pVals = stable ? new Value[]{value, value} : new Value[]{value, lattice.top};
for (int i = 0; i < pIds.length; i++) {
- int pId = pIds[i];
+ long pId = pIds[i];
Value pVal = pVals[i];
- // todo - remove
- int[] dIds = dependencies.get(pId);
- for (int dId : dIds) {
- IntIdPending pend = pending.remove(dId);
+ TLongHashSet dIds = dependencies.get(pId);
+ if (dIds == null) {
+ continue;
+ }
+ TLongIterator dIdsIterator = dIds.iterator();
+ while (dIdsIterator.hasNext()) {
+ long dId = dIdsIterator.next();
+ IdPending pend = pending.remove(dId);
if (pend != null) {
- IntIdResult pend1 = substitute(pend, pId, pVal);
- if (pend1 instanceof IntIdFinal) {
- IntIdFinal fi = (IntIdFinal)pend1;
+ IdResult pend1 = substitute(pend, pId, pVal);
+ if (pend1 instanceof IdFinal) {
+ IdFinal fi = (IdFinal)pend1;
solved.put(dId, fi.value);
moving.push(dId);
}
else {
- pending.put(dId, (IntIdPending)pend1);
+ pending.put(dId, (IdPending)pend1);
}
}
}
@@ -414,7 +434,7 @@ final class IntIdSolver {
}
// substitute id -> value into pending
- IntIdResult substitute(IntIdPending pending, int id, Value value) {
+ IdResult substitute(IdPending pending, long id, Value value) {
IntIdComponent[] sum = pending.delta;
for (IntIdComponent intIdComponent : sum) {
if (intIdComponent.remove(id)) {
@@ -424,7 +444,7 @@ final class IntIdSolver {
return normalize(sum);
}
- IntIdResult normalize(IntIdComponent[] sum) {
+ IdResult normalize(IntIdComponent[] sum) {
Value acc = lattice.bot;
boolean computableNow = true;
for (IntIdComponent prod : sum) {
@@ -434,7 +454,7 @@ final class IntIdSolver {
computableNow = false;
}
}
- return (acc == lattice.top || computableNow) ? new IntIdFinal(acc) : new IntIdPending(sum);
+ return (acc == lattice.top || computableNow) ? new IdFinal(acc) : new IdPending(sum);
}
}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractInference.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractInference.java
index a1c908837ad0..bd207e58a0fe 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractInference.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractInference.java
@@ -71,7 +71,23 @@ class ContractInferenceInterpreter {
if (statements.length == 1) {
if (statements[0] instanceof PsiReturnStatement) {
List<MethodContract> result = handleDelegation(((PsiReturnStatement)statements[0]).getReturnValue(), false);
- if (result != null) return result;
+ if (result != null) {
+ PsiTypeElement typeElement = myMethod.getReturnTypeElement();
+ final boolean returningObject = typeElement == null || !(typeElement.getType() instanceof PsiClassType);
+ return ContainerUtil.findAll(result, new Condition<MethodContract>() {
+ @Override
+ public boolean value(MethodContract contract) {
+ if ((contract.returnValue == NULL_VALUE || contract.returnValue == NOT_NULL_VALUE) && returningObject) {
+ return false;
+ }
+ if ((contract.returnValue == TRUE_VALUE || contract.returnValue == FALSE_VALUE) && !returningObject) {
+ return false;
+ }
+
+ return true;
+ }
+ });
+ }
}
else if (statements[0] instanceof PsiExpressionStatement && ((PsiExpressionStatement)statements[0]).getExpression() instanceof PsiMethodCallExpression) {
List<MethodContract> result = handleDelegation(((PsiExpressionStatement)statements[0]).getExpression(), false);
@@ -132,6 +148,9 @@ class ContractInferenceInterpreter {
}
else {
answer = withConstraint(answer, paramIndex, argConstraint);
+ if (answer == null) {
+ return null;
+ }
}
}
}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/MethodContract.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/MethodContract.java
index 691c2f00d985..1167210f917e 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/MethodContract.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/MethodContract.java
@@ -89,10 +89,16 @@ public class MethodContract {
throw new ParseException("A contract clause must be in form arg1, ..., argN -> return-value");
}
- String[] argStrings = clause.substring(0, arrowIndex).split(",");
- ValueConstraint[] args = new ValueConstraint[argStrings.length];
- for (int i = 0; i < args.length; i++) {
- args[i] = parseConstraint(argStrings[i]);
+ String beforeArrow = clause.substring(0, arrowIndex);
+ ValueConstraint[] args;
+ if (StringUtil.isNotEmpty(beforeArrow)) {
+ String[] argStrings = beforeArrow.split(",");
+ args = new ValueConstraint[argStrings.length];
+ for (int i = 0; i < args.length; i++) {
+ args[i] = parseConstraint(argStrings[i]);
+ }
+ } else {
+ args = new ValueConstraint[0];
}
result.add(new MethodContract(args, parseConstraint(clause.substring(arrowIndex + arrow.length()))));
}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java
index 013e24cbe07a..36449128b494 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java
@@ -500,21 +500,19 @@ public class StandardInstructionVisitor extends InstructionVisitor {
PsiType varType = var.getVariableType();
if (!(varType instanceof PsiPrimitiveType)) return null;
+
+ if (varType == PsiType.FLOAT || varType == PsiType.DOUBLE) return null;
double minValue = varType == PsiType.BYTE ? Byte.MIN_VALUE :
varType == PsiType.SHORT ? Short.MIN_VALUE :
varType == PsiType.INT ? Integer.MIN_VALUE :
varType == PsiType.CHAR ? Character.MIN_VALUE :
- varType == PsiType.LONG ? Long.MIN_VALUE :
- varType == PsiType.FLOAT ? Float.MIN_VALUE :
- Double.MIN_VALUE;
+ Long.MIN_VALUE;
double maxValue = varType == PsiType.BYTE ? Byte.MAX_VALUE :
varType == PsiType.SHORT ? Short.MAX_VALUE :
varType == PsiType.INT ? Integer.MAX_VALUE :
varType == PsiType.CHAR ? Character.MAX_VALUE :
- varType == PsiType.LONG ? Long.MAX_VALUE :
- varType == PsiType.FLOAT ? Float.MAX_VALUE :
- Double.MAX_VALUE;
+ Long.MAX_VALUE;
return checkComparisonWithKnownRange(instruction, runner, memState, opSign, comparedWith, minValue, maxValue);
}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/xml/DeprecatedClassUsageInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/xml/DeprecatedClassUsageInspection.java
index 0a914c0d4477..8c9e4a72dfef 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/xml/DeprecatedClassUsageInspection.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/xml/DeprecatedClassUsageInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,7 +20,6 @@ import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.codeInspection.XmlSuppressableInspectionTool;
import com.intellij.codeInspection.deprecation.DeprecationInspection;
import com.intellij.psi.*;
-import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlAttributeValue;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.ArrayUtil;
@@ -46,11 +45,6 @@ public class DeprecatedClassUsageInspection extends XmlSuppressableInspectionToo
}
@Override
- public void visitXmlAttribute(XmlAttribute attribute) {
- checkReferences(attribute, holder);
- }
-
- @Override
public void visitXmlAttributeValue(XmlAttributeValue value) {
checkReferences(value, holder);
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java b/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java
index b60094ffbd6f..ad53d9484959 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java
@@ -138,8 +138,8 @@ public class PreferByKindWeigher extends LookupElementWeigher {
qualifiedWithField,
qualifiedWithGetter,
superMethodParameters,
- expectedTypeConstant,
field,
+ expectedTypeConstant,
getter,
normal,
collectionFactory,
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddMethodQualifierFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddMethodQualifierFix.java
index ff851372e208..4ab9d43fbc1d 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddMethodQualifierFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddMethodQualifierFix.java
@@ -69,10 +69,14 @@ public class AddMethodQualifierFix implements IntentionAction {
if (element == null || !element.isValid()) {
return false;
}
+ return getOrFindCandidates().size() != 0;
+ }
+
+ private synchronized List<PsiVariable> getOrFindCandidates() {
if (myCandidates == null) {
findCandidates();
}
- return myCandidates.size() != 0;
+ return myCandidates;
}
private void findCandidates() {
@@ -84,6 +88,9 @@ public class AddMethodQualifierFix implements IntentionAction {
}
for (final PsiVariable var : CreateFromUsageUtils.guessMatchingVariables(methodCallElement)) {
+ if (var.getName() == null) {
+ continue;
+ }
final PsiType type = var.getType();
if (!(type instanceof PsiClassType)) {
continue;
@@ -132,7 +139,7 @@ public class AddMethodQualifierFix implements IntentionAction {
@NotNull
@Override
public String getTextFor(final PsiVariable value) {
- return ObjectUtils.assertNotNull(value.getName());
+ return value.getName();
}
@Override
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AnonymousTargetClassPreselectionUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AnonymousTargetClassPreselectionUtil.java
new file mode 100644
index 000000000000..421c43cabe88
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AnonymousTargetClassPreselectionUtil.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.daemon.impl.quickfix;
+
+import com.intellij.ide.util.PropertiesComponent;
+import com.intellij.psi.PsiAnonymousClass;
+import com.intellij.psi.PsiClass;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collection;
+
+public class AnonymousTargetClassPreselectionUtil {
+ private static final String PRESELECT_ANONYMOUS = "create.member.preselect.anonymous";
+
+ public static void rememberSelection(PsiClass aClass, PsiClass firstClass) {
+ if (firstClass instanceof PsiAnonymousClass) {
+ PropertiesComponent.getInstance().setValue(PRESELECT_ANONYMOUS, String.valueOf(aClass == firstClass));
+ }
+ }
+
+ @Nullable
+ public static PsiClass getPreselection(Collection<PsiClass> classes, PsiClass firstClass) {
+ if (firstClass instanceof PsiAnonymousClass && !PropertiesComponent.getInstance().getBoolean(PRESELECT_ANONYMOUS, true)) {
+ for (PsiClass aClass : classes) {
+ if (!(aClass instanceof PsiAnonymousClass)) {
+ return aClass;
+ }
+ }
+ }
+ return null;
+ }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageBaseFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageBaseFix.java
index 09b83e2a489f..abe9368374e8 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageBaseFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageBaseFix.java
@@ -119,7 +119,8 @@ public abstract class CreateFromUsageBaseFix extends BaseIntentionAction {
protected abstract PsiElement getElement();
private void chooseTargetClass(List<PsiClass> classes, final Editor editor) {
- final Project project = classes.get(0).getProject();
+ final PsiClass firstClass = classes.get(0);
+ final Project project = firstClass.getProject();
final JList list = new JBList(classes);
PsiElementListCellRenderer renderer = new PsiClassListCellRenderer();
@@ -128,12 +129,18 @@ public abstract class CreateFromUsageBaseFix extends BaseIntentionAction {
final PopupChooserBuilder builder = new PopupChooserBuilder(list);
renderer.installSpeedSearch(builder);
+ final PsiClass preselection = AnonymousTargetClassPreselectionUtil.getPreselection(classes, firstClass);
+ if (preselection != null) {
+ list.setSelectedValue(preselection, true);
+ }
+
Runnable runnable = new Runnable() {
@Override
public void run() {
int index = list.getSelectedIndex();
if (index < 0) return;
final PsiClass aClass = (PsiClass) list.getSelectedValue();
+ AnonymousTargetClassPreselectionUtil.rememberSelection(aClass, firstClass);
CommandProcessor.getInstance().executeCommand(project, new Runnable() {
@Override
public void run() {
diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/CopyPasteReferenceProcessor.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/CopyPasteReferenceProcessor.java
index 906dfa6258de..e6991736c0e3 100644
--- a/java/java-impl/src/com/intellij/codeInsight/editorActions/CopyPasteReferenceProcessor.java
+++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/CopyPasteReferenceProcessor.java
@@ -144,6 +144,17 @@ public abstract class CopyPasteReferenceProcessor<TRef extends PsiElement> exten
RangeMarker bounds,
ReferenceData[] referenceData);
+ protected PsiElement resolveReferenceIgnoreOverriding(PsiPolyVariantReference reference) {
+ PsiElement referent = reference.resolve();
+ if (referent == null) {
+ final ResolveResult[] results = reference.multiResolve(true);
+ if (results.length > 0) {
+ referent = results[0].getElement();
+ }
+ }
+ return referent;
+ }
+
protected abstract void restoreReferences(ReferenceData[] referenceData,
TRef[] refs);
diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/JavaCopyPasteReferenceProcessor.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/JavaCopyPasteReferenceProcessor.java
index 51edddd250aa..76be78b7932d 100644
--- a/java/java-impl/src/com/intellij/codeInsight/editorActions/JavaCopyPasteReferenceProcessor.java
+++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/JavaCopyPasteReferenceProcessor.java
@@ -88,7 +88,8 @@ public class JavaCopyPasteReferenceProcessor extends CopyPasteReferenceProcessor
}
else {
if (reference instanceof PsiReferenceExpression) {
- PsiElement referent = reference.resolve();
+ PsiElement referent = resolveReferenceIgnoreOverriding(reference);
+
if (!(referent instanceof PsiNamedElement)
|| !data.staticMemberName.equals(((PsiNamedElement)referent).getName())
|| !(referent instanceof PsiMember)
diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/MissingCatchBodyFixer.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/MissingCatchBodyFixer.java
index 1d4d281aea68..08e06283d4a5 100644
--- a/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/MissingCatchBodyFixer.java
+++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/MissingCatchBodyFixer.java
@@ -36,7 +36,7 @@ public class MissingCatchBodyFixer implements Fixer {
final Document doc = editor.getDocument();
PsiCodeBlock body = catchSection.getCatchBlock();
- if (body != null && startLine(doc, body) == startLine(doc, catchSection)) return;
+ if (body != null && body.getLBrace() != null && body.getRBrace() != null) return;
final PsiJavaToken rParenth = catchSection.getRParenth();
if (rParenth == null) return;
@@ -44,7 +44,4 @@ public class MissingCatchBodyFixer implements Fixer {
doc.insertString(rParenth.getTextRange().getEndOffset(), "{}");
}
- private static int startLine(Document doc, PsiElement psiElement) {
- return doc.getLineNumber(psiElement.getTextRange().getStartOffset());
- }
} \ No newline at end of file
diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/PlainEnterProcessor.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/PlainEnterProcessor.java
index 6bafcc00d983..884442c778cc 100644
--- a/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/PlainEnterProcessor.java
+++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/PlainEnterProcessor.java
@@ -83,6 +83,22 @@ public class PlainEnterProcessor implements EnterProcessor {
@Nullable
private static PsiCodeBlock getControlStatementBlock(int caret, PsiElement element) {
+ if (element instanceof PsiTryStatement) {
+ PsiCodeBlock tryBlock = ((PsiTryStatement)element).getTryBlock();
+ if (tryBlock != null && caret < tryBlock.getTextRange().getEndOffset()) return tryBlock;
+
+ for (PsiCodeBlock catchBlock : ((PsiTryStatement)element).getCatchBlocks()) {
+ if (catchBlock != null && caret < catchBlock.getTextRange().getEndOffset()) return catchBlock;
+ }
+
+ return ((PsiTryStatement)element).getFinallyBlock();
+ }
+
+ if (element instanceof PsiMethod) {
+ PsiCodeBlock methodBody = ((PsiMethod)element).getBody();
+ if (methodBody != null) return methodBody;
+ }
+
PsiStatement body = null;
if (element instanceof PsiIfStatement) {
body = ((PsiIfStatement)element).getThenBranch();
@@ -102,10 +118,6 @@ public class PlainEnterProcessor implements EnterProcessor {
else if (element instanceof PsiDoWhileStatement) {
body = ((PsiDoWhileStatement)element).getBody();
}
- else if (element instanceof PsiMethod) {
- PsiCodeBlock methodBody = ((PsiMethod)element).getBody();
- if (methodBody != null) return methodBody;
- }
return body instanceof PsiBlockStatement ? ((PsiBlockStatement)body).getCodeBlock() : null;
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/hint/api/impls/MethodParameterInfoHandler.java b/java/java-impl/src/com/intellij/codeInsight/hint/api/impls/MethodParameterInfoHandler.java
index fd85d1124171..daf2e3002dd2 100644
--- a/java/java-impl/src/com/intellij/codeInsight/hint/api/impls/MethodParameterInfoHandler.java
+++ b/java/java-impl/src/com/intellij/codeInsight/hint/api/impls/MethodParameterInfoHandler.java
@@ -450,18 +450,24 @@ public class MethodParameterInfoHandler implements ParameterInfoHandlerWithTabAc
final PsiJavaCodeReferenceElement element = annotation.getNameReferenceElement();
if (element != null) {
final PsiElement resolved = element.resolve();
- if (resolved instanceof PsiClass && !AnnotationUtil.isAnnotated((PsiClass)resolved, "java.lang.annotation.Documented", false)) continue;
+ if (resolved instanceof PsiClass && !AnnotationUtil.isAnnotated((PsiClass)resolved, "java.lang.annotation.Documented", false, true)) {
+ continue;
+ }
String referenceName = element.getReferenceName();
- if (!shownAnnotations.add(referenceName)) continue;
-
- if (lastSize != buffer.length()) buffer.append(" ");
- buffer.append("@").append(referenceName);
+ if (shownAnnotations.add(referenceName) || isRepeatableAnnotation(resolved)) {
+ if (lastSize != buffer.length()) buffer.append(" ");
+ buffer.append("@").append(referenceName);
+ }
}
}
if (lastSize != buffer.length()) buffer.append(" ");
}
+ private static boolean isRepeatableAnnotation(PsiElement resolved) {
+ return resolved instanceof PsiClass && !AnnotationUtil.isAnnotated((PsiModifierListOwner)resolved, CommonClassNames.JAVA_LANG_ANNOTATION_REPEATABLE, false, true);
+ }
+
@Override
public void updateUI(final Object p, @NotNull final ParameterInfoUIContext context) {
if (p instanceof CandidateInfo) {
diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/FieldFromParameterUtils.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/FieldFromParameterUtils.java
index ccec3c3cab07..37fb882e5e66 100644
--- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/FieldFromParameterUtils.java
+++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/FieldFromParameterUtils.java
@@ -187,14 +187,14 @@ public final class FieldFromParameterUtils {
modifierList.setModifierProperty(PsiModifier.FINAL, isFinal);
final NullableNotNullManager manager = NullableNotNullManager.getInstance(project);
- final String nullable = manager.getNullable(parameter);
- if (nullable != null) {
- modifierList.addAfter(factory.createAnnotationFromText("@" + nullable, field), null);
+ final PsiAnnotation nullable = manager.getNullableAnnotation(parameter, false);
+ if (nullable != null && !manager.isContainerAnnotation(nullable)) {
+ modifierList.addAfter(factory.createAnnotationFromText("@" + nullable.getQualifiedName(), field), null);
}
else if (isFinal) {
- final String notNull = manager.getNotNull(parameter);
- if (notNull != null) {
- modifierList.addAfter(factory.createAnnotationFromText("@" + notNull, field), null);
+ final PsiAnnotation notNull = manager.getNotNullAnnotation(parameter, false);
+ if (notNull != null && !manager.isContainerAnnotation(notNull)) {
+ modifierList.addAfter(factory.createAnnotationFromText("@" + notNull.getQualifiedName(), field), null);
}
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/CastExpressionPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/CastExpressionPostfixTemplate.java
index 952987a72c19..14059174cc16 100644
--- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/CastExpressionPostfixTemplate.java
+++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/CastExpressionPostfixTemplate.java
@@ -20,13 +20,17 @@ import com.intellij.openapi.editor.Editor;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
-public class CastExpressionPostfixTemplate extends JavaPostfixTemplateWithChooser {
+import static com.intellij.codeInsight.template.postfix.templates.PostfixTemplatesUtils.selectorWithChooser;
+import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.IS_NON_VOID;
+import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.JAVA_PSI_INFO;
+
+public class CastExpressionPostfixTemplate extends PostfixTemplateWithExpressionSelector {
public CastExpressionPostfixTemplate() {
- super("cast", "((SomeType) expr)");
+ super("cast", "((SomeType) expr)", JAVA_PSI_INFO, selectorWithChooser(IS_NON_VOID));
}
@Override
- protected void doIt(@NotNull final Editor editor, @NotNull final PsiElement expression) {
+ protected void expandForChooseExpression(@NotNull PsiElement expression, @NotNull Editor editor) {
PostfixTemplatesUtils.surround(new JavaWithCastSurrounder(), editor, expression);
}
} \ No newline at end of file
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IntroduceFieldPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IntroduceFieldPostfixTemplate.java
index 40da7fd94b88..2bac79d890bd 100644
--- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IntroduceFieldPostfixTemplate.java
+++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IntroduceFieldPostfixTemplate.java
@@ -23,13 +23,17 @@ import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.refactoring.introduceField.IntroduceFieldHandler;
import org.jetbrains.annotations.NotNull;
-public class IntroduceFieldPostfixTemplate extends JavaPostfixTemplateWithChooser {
+import static com.intellij.codeInsight.template.postfix.templates.PostfixTemplatesUtils.selectorWithChooser;
+import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.IS_NON_VOID;
+import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.JAVA_PSI_INFO;
+
+public class IntroduceFieldPostfixTemplate extends PostfixTemplateWithExpressionSelector {
public IntroduceFieldPostfixTemplate() {
- super("field", "myField = expr");
+ super("field", "myField = expr", JAVA_PSI_INFO, selectorWithChooser(IS_NON_VOID));
}
@Override
- protected void doIt(@NotNull Editor editor, @NotNull PsiElement expression) {
+ protected void expandForChooseExpression(@NotNull PsiElement expression, @NotNull Editor editor) {
IntroduceFieldHandler handler =
ApplicationManager.getApplication().isUnitTestMode() ? getMockHandler(expression) : new IntroduceFieldHandler();
handler.invoke(expression.getProject(), new PsiElement[]{expression}, null);
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IntroduceVariablePostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IntroduceVariablePostfixTemplate.java
index 57c03f9501fa..be2dc23850e7 100644
--- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IntroduceVariablePostfixTemplate.java
+++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IntroduceVariablePostfixTemplate.java
@@ -28,14 +28,18 @@ import com.intellij.refactoring.introduceVariable.IntroduceVariableSettings;
import com.intellij.refactoring.ui.TypeSelectorManagerImpl;
import org.jetbrains.annotations.NotNull;
+import static com.intellij.codeInsight.template.postfix.templates.PostfixTemplatesUtils.selectorWithChooser;
+import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.IS_NON_VOID;
+import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.JAVA_PSI_INFO;
+
// todo: support for int[].var (parses as .class access!)
-public class IntroduceVariablePostfixTemplate extends JavaPostfixTemplateWithChooser {
+public class IntroduceVariablePostfixTemplate extends PostfixTemplateWithExpressionSelector {
public IntroduceVariablePostfixTemplate() {
- super("var", "T name = expr");
+ super("var", "T name = expr", JAVA_PSI_INFO, selectorWithChooser(IS_NON_VOID));
}
@Override
- protected void doIt(@NotNull Editor editor, @NotNull PsiElement expression) {
+ protected void expandForChooseExpression(@NotNull PsiElement expression, @NotNull Editor editor) {
// for advanced stuff use ((PsiJavaCodeReferenceElement)expression).advancedResolve(true).getElement();
IntroduceVariableHandler handler =
ApplicationManager.getApplication().isUnitTestMode() ? getMockHandler() : new IntroduceVariableHandler();
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/JavaPostfixTemplateProvider.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/JavaPostfixTemplateProvider.java
index 148f4bb187db..629d4dd02115 100644
--- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/JavaPostfixTemplateProvider.java
+++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/JavaPostfixTemplateProvider.java
@@ -144,6 +144,6 @@ public class JavaPostfixTemplateProvider implements PostfixTemplateProvider {
}
private static boolean isSemicolonNeeded(@NotNull PsiFile file, @NotNull Editor editor) {
- return JavaCompletionContributor.semicolonNeeded(editor, file, CompletionInitializationContext.calcStartOffset(editor));
+ return JavaCompletionContributor.semicolonNeeded(editor, file, CompletionInitializationContext.calcStartOffset(editor.getCaretModel().getCurrentCaret()));
}
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/JavaPostfixTemplateWithChooser.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/JavaPostfixTemplateWithChooser.java
deleted file mode 100644
index 72de706f4858..000000000000
--- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/JavaPostfixTemplateWithChooser.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 2000-2014 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.codeInsight.template.postfix.templates;
-
-
-import com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils;
-import com.intellij.openapi.util.Condition;
-import com.intellij.psi.PsiElement;
-import org.jetbrains.annotations.NotNull;
-
-import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.JAVA_PSI_INFO;
-
-public abstract class JavaPostfixTemplateWithChooser extends ExpressionPostfixTemplateWithChooser {
-
-
- protected JavaPostfixTemplateWithChooser(@NotNull String name, @NotNull String example) {
- super(name, example, JAVA_PSI_INFO);
- }
-
- protected JavaPostfixTemplateWithChooser(@NotNull String name, @NotNull String key, @NotNull String example) {
- super(name, key, example, JAVA_PSI_INFO);
- }
-
- @NotNull
- @Override
- protected Condition<PsiElement> getTypeCondition() {
- return JavaPostfixTemplatesUtils.IS_NON_VOID;
- }
-}
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NotExpressionPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NotExpressionPostfixTemplate.java
index ac6f22c5092f..6160433cefe3 100644
--- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NotExpressionPostfixTemplate.java
+++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NotExpressionPostfixTemplate.java
@@ -15,26 +15,16 @@
*/
package com.intellij.codeInsight.template.postfix.templates;
-import com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils;
-import com.intellij.openapi.util.Condition;
-import com.intellij.psi.PsiElement;
-import org.jetbrains.annotations.NotNull;
-
+import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.IS_BOOLEAN;
import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.JAVA_PSI_INFO;
public class NotExpressionPostfixTemplate extends NotPostfixTemplate {
public NotExpressionPostfixTemplate() {
- super(JAVA_PSI_INFO);
+ super(JAVA_PSI_INFO, IS_BOOLEAN);
}
public NotExpressionPostfixTemplate(String alias) {
- super(alias, alias, "!expr", JAVA_PSI_INFO);
- }
-
- @NotNull
- @Override
- protected Condition<PsiElement> getTypeCondition() {
- return JavaPostfixTemplatesUtils.IS_BOOLEAN;
+ super(alias, alias, "!expr", JAVA_PSI_INFO, IS_BOOLEAN);
}
} \ No newline at end of file
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ParenthesizedExpressionPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ParenthesizedExpressionPostfixTemplate.java
index 68b5c48fcd15..46c0c30b24f5 100644
--- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ParenthesizedExpressionPostfixTemplate.java
+++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ParenthesizedExpressionPostfixTemplate.java
@@ -15,21 +15,11 @@
*/
package com.intellij.codeInsight.template.postfix.templates;
-import com.intellij.openapi.util.Condition;
-import com.intellij.psi.PsiElement;
-import org.jetbrains.annotations.NotNull;
-
import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.IS_NON_VOID;
import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.JAVA_PSI_INFO;
public class ParenthesizedExpressionPostfixTemplate extends ParenthesizedPostfixTemplate {
public ParenthesizedExpressionPostfixTemplate() {
- super(JAVA_PSI_INFO);
- }
-
- @NotNull
- @Override
- protected Condition<PsiElement> getTypeCondition() {
- return IS_NON_VOID;
+ super(JAVA_PSI_INFO, IS_NON_VOID);
}
} \ No newline at end of file
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/util/JavaPostfixTemplatesUtils.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/util/JavaPostfixTemplatesUtils.java
index e217175cdab9..2142c8fd33da 100644
--- a/java/java-impl/src/com/intellij/codeInsight/template/postfix/util/JavaPostfixTemplatesUtils.java
+++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/util/JavaPostfixTemplatesUtils.java
@@ -16,7 +16,7 @@
package com.intellij.codeInsight.template.postfix.util;
import com.intellij.codeInsight.CodeInsightServicesUtil;
-import com.intellij.codeInsight.template.postfix.templates.PostfixTemplatePsiInfoBase;
+import com.intellij.codeInsight.template.postfix.templates.PostfixTemplatePsiInfo;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.util.Condition;
import com.intellij.psi.*;
@@ -36,7 +36,7 @@ public abstract class JavaPostfixTemplatesUtils {
private JavaPostfixTemplatesUtils() {
}
- public static final PostfixTemplatePsiInfoBase JAVA_PSI_INFO = new PostfixTemplatePsiInfoBase() {
+ public static final PostfixTemplatePsiInfo JAVA_PSI_INFO = new PostfixTemplatePsiInfo() {
@NotNull
@Override
@@ -136,7 +136,11 @@ public abstract class JavaPostfixTemplatesUtils {
@Contract("null -> false")
public static boolean isNotPrimitiveTypeExpression(@Nullable PsiExpression expression) {
- return expression != null && !(expression.getType() instanceof PsiPrimitiveType);
+ if (expression == null) {
+ return false;
+ }
+ PsiType type = expression.getType();
+ return type != null && !(type instanceof PsiPrimitiveType);
}
@Contract("null -> false")
diff --git a/java/java-impl/src/com/intellij/codeInspection/ex/GlobalJavaInspectionContextImpl.java b/java/java-impl/src/com/intellij/codeInspection/ex/GlobalJavaInspectionContextImpl.java
index aff69ec85da9..b3aed0603150 100644
--- a/java/java-impl/src/com/intellij/codeInspection/ex/GlobalJavaInspectionContextImpl.java
+++ b/java/java-impl/src/com/intellij/codeInspection/ex/GlobalJavaInspectionContextImpl.java
@@ -194,7 +194,7 @@ public class GlobalJavaInspectionContextImpl extends GlobalJavaInspectionContext
final SearchScope searchScope = new GlobalSearchScope(refManager.getProject()) {
@Override
public boolean contains(@NotNull VirtualFile file) {
- return !scope.contains(file) || file.getFileType() != StdFileTypes.JAVA;
+ return scope != null && !scope.contains(file) || file.getFileType() != StdFileTypes.JAVA;
}
@Override
@@ -394,7 +394,7 @@ public class GlobalJavaInspectionContextImpl extends GlobalJavaInspectionContext
@Override
public boolean execute(PsiReference reference) {
AnalysisScope scope = context.getRefManager().getScope();
- if (scope.contains(reference.getElement()) && reference.getElement().getLanguage() == StdLanguages.JAVA ||
+ if (scope != null && scope.contains(reference.getElement()) && reference.getElement().getLanguage() == StdLanguages.JAVA ||
PsiTreeUtil.getParentOfType(reference.getElement(), PsiDocComment.class) != null) {
return true;
}
diff --git a/java/java-impl/src/com/intellij/codeInspection/sameParameterValue/SameParameterValueInspection.java b/java/java-impl/src/com/intellij/codeInspection/sameParameterValue/SameParameterValueInspection.java
index baab93de8d25..bcfea46a569c 100644
--- a/java/java-impl/src/com/intellij/codeInspection/sameParameterValue/SameParameterValueInspection.java
+++ b/java/java-impl/src/com/intellij/codeInspection/sameParameterValue/SameParameterValueInspection.java
@@ -76,7 +76,7 @@ public class SameParameterValueInspection extends SameParameterValueInspectionBa
public void applyFix(@NotNull final Project project, @NotNull ProblemDescriptor descriptor) {
final PsiElement element = descriptor.getPsiElement();
final PsiMethod method = PsiTreeUtil.getParentOfType(element, PsiMethod.class);
- LOG.assertTrue(method != null);
+ if (method == null) return;
PsiParameter parameter = PsiTreeUtil.getParentOfType(element, PsiParameter.class, false);
if (parameter == null) {
final PsiParameter[] parameters = method.getParameterList().getParameters();
diff --git a/java/java-impl/src/com/intellij/codeInspection/unusedParameters/UnusedParametersInspection.java b/java/java-impl/src/com/intellij/codeInspection/unusedParameters/UnusedParametersInspection.java
index c33d0d68b8cb..bb97f5cd78d5 100644
--- a/java/java-impl/src/com/intellij/codeInspection/unusedParameters/UnusedParametersInspection.java
+++ b/java/java-impl/src/com/intellij/codeInspection/unusedParameters/UnusedParametersInspection.java
@@ -132,7 +132,7 @@ public class UnusedParametersInspection extends GlobalJavaBatchInspectionTool {
int idx = refParameter.getIndex();
final boolean[] found = {false};
for (int i = 0; i < derived.length && !found[0]; i++) {
- if (!scope.contains(derived[i])) {
+ if (scope == null || !scope.contains(derived[i])) {
final PsiParameter[] parameters = derived[i].getParameterList().getParameters();
if (parameters.length >= idx) continue;
PsiParameter psiParameter = parameters[idx];
diff --git a/java/java-impl/src/com/intellij/codeInspection/varScopeCanBeNarrowed/FieldCanBeLocalInspection.java b/java/java-impl/src/com/intellij/codeInspection/varScopeCanBeNarrowed/FieldCanBeLocalInspection.java
index 38ee7449994a..51beb4239fc3 100644
--- a/java/java-impl/src/com/intellij/codeInspection/varScopeCanBeNarrowed/FieldCanBeLocalInspection.java
+++ b/java/java-impl/src/com/intellij/codeInspection/varScopeCanBeNarrowed/FieldCanBeLocalInspection.java
@@ -63,7 +63,7 @@ public class FieldCanBeLocalInspection extends FieldCanBeLocalInspectionBase {
@Override
protected PsiElement moveDeclaration(@NotNull final Project project, @NotNull final PsiField variable) {
final Map<PsiCodeBlock, Collection<PsiReference>> refs = new HashMap<PsiCodeBlock, Collection<PsiReference>>();
- groupByCodeBlocks(ReferencesSearch.search(variable).findAll(), refs);
+ if (!groupByCodeBlocks(ReferencesSearch.search(variable).findAll(), refs)) return null;
PsiElement element = null;
for (Collection<PsiReference> psiReferences : refs.values()) {
element = super.moveDeclaration(project, variable, psiReferences, false);
@@ -82,11 +82,14 @@ public class FieldCanBeLocalInspection extends FieldCanBeLocalInspectionBase {
return element;
}
- private static void groupByCodeBlocks(final Collection<PsiReference> allReferences, Map<PsiCodeBlock, Collection<PsiReference>> refs) {
+ private static boolean groupByCodeBlocks(final Collection<PsiReference> allReferences, Map<PsiCodeBlock, Collection<PsiReference>> refs) {
for (PsiReference psiReference : allReferences) {
final PsiElement element = psiReference.getElement();
final PsiCodeBlock block = PsiTreeUtil.getTopmostParentOfType(element, PsiCodeBlock.class);
- LOG.assertTrue(block != null);
+ if (block == null) {
+ return false;
+ }
+
Collection<PsiReference> references = refs.get(block);
if (references == null) {
references = new ArrayList<PsiReference>();
@@ -95,6 +98,7 @@ public class FieldCanBeLocalInspection extends FieldCanBeLocalInspectionBase {
}
references.add(psiReference);
}
+ return true;
}
private static boolean findExistentBlock(Map<PsiCodeBlock, Collection<PsiReference>> refs,
diff --git a/java/java-impl/src/com/intellij/ide/projectView/impl/PackageViewPane.java b/java/java-impl/src/com/intellij/ide/projectView/impl/PackageViewPane.java
index 98f1fbeddfca..73fcc83df646 100644
--- a/java/java-impl/src/com/intellij/ide/projectView/impl/PackageViewPane.java
+++ b/java/java-impl/src/com/intellij/ide/projectView/impl/PackageViewPane.java
@@ -28,9 +28,7 @@ import com.intellij.ide.SelectInTarget;
import com.intellij.ide.impl.PackagesPaneSelectInTarget;
import com.intellij.ide.projectView.ProjectView;
import com.intellij.ide.projectView.ViewSettings;
-import com.intellij.ide.projectView.impl.nodes.PackageElement;
-import com.intellij.ide.projectView.impl.nodes.PackageUtil;
-import com.intellij.ide.projectView.impl.nodes.PackageViewProjectNode;
+import com.intellij.ide.projectView.impl.nodes.*;
import com.intellij.ide.util.DeleteHandler;
import com.intellij.ide.util.treeView.AbstractTreeBuilder;
import com.intellij.ide.util.treeView.AbstractTreeNode;
@@ -48,8 +46,8 @@ import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiPackage;
import com.intellij.psi.search.GlobalSearchScope;
-import com.intellij.psi.util.PsiUtilBase;
import com.intellij.psi.util.PsiUtilCore;
+import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -140,14 +138,30 @@ public final class PackageViewPane extends AbstractProjectViewPSIPane {
@Override
public PsiDirectory[] getSelectedDirectories() {
- final PackageElement packageElement = getSelectedPackageElement();
- if (packageElement != null) {
- final Module module = packageElement.getModule();
- final PsiPackage aPackage = packageElement.getPackage();
- if (module != null && aPackage != null) {
- return aPackage.getDirectories(GlobalSearchScope.moduleScope(module));
+ List<PsiDirectory> directories = ContainerUtil.newArrayList();
+ for (PackageElementNode node : getSelectedNodes(PackageElementNode.class)) {
+ PackageElement packageElement = node.getValue();
+ PsiPackage aPackage = packageElement != null ? packageElement.getPackage() : null;
+ final Module module = packageElement != null ? packageElement.getModule() : null;
+ if (aPackage != null && module != null) {
+ GlobalSearchScope scope = GlobalSearchScope.moduleScope(module);
+ Collections.addAll(directories, aPackage.getDirectories(scope));
+
+ Object parentValue = node.getParent().getValue();
+ PsiPackage parentNodePackage = parentValue instanceof PackageElement ? ((PackageElement)parentValue).getPackage() : null;
+ while (true) {
+ aPackage = aPackage.getParentPackage();
+ if (aPackage == null || aPackage.getQualifiedName().isEmpty() || aPackage.equals(parentNodePackage)) {
+ break;
+ }
+ Collections.addAll(directories, aPackage.getDirectories(scope));
+ }
}
}
+ if (!directories.isEmpty()) {
+ return directories.toArray(new PsiDirectory[directories.size()]);
+ }
+
return super.getSelectedDirectories();
}
diff --git a/java/java-impl/src/com/intellij/ide/util/gotoByName/DefaultClassNavigationContributor.java b/java/java-impl/src/com/intellij/ide/util/gotoByName/DefaultClassNavigationContributor.java
index b0cbc06d048e..2f5418631dae 100644
--- a/java/java-impl/src/com/intellij/ide/util/gotoByName/DefaultClassNavigationContributor.java
+++ b/java/java-impl/src/com/intellij/ide/util/gotoByName/DefaultClassNavigationContributor.java
@@ -19,10 +19,14 @@ 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.codeStyle.MinusculeMatcher;
+import com.intellij.psi.codeStyle.NameUtil;
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.CommonProcessors;
import com.intellij.util.Processor;
@@ -32,6 +36,8 @@ import com.intellij.util.indexing.IdFilter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.util.regex.Matcher;
+
public class DefaultClassNavigationContributor implements ChooseByNameContributorEx, GotoClassContributor {
@Override
@NotNull
@@ -74,7 +80,7 @@ public class DefaultClassNavigationContributor implements ChooseByNameContributo
@Override
public String getQualifiedNameSeparator() {
- return ".";
+ return "$";
}
@Override
@@ -86,12 +92,28 @@ public class DefaultClassNavigationContributor implements ChooseByNameContributo
public void processElementsWithName(@NotNull String name,
@NotNull final Processor<NavigationItem> processor,
@NotNull final FindSymbolParameters parameters) {
+ String namePattern = StringUtil.getShortName(parameters.getCompletePattern());
+ boolean hasDollar = namePattern.contains("$");
+ if (hasDollar) {
+ Matcher matcher = ChooseByNamePopup.patternToDetectAnonymousClasses.matcher(namePattern);
+ if (matcher.matches()) {
+ namePattern = matcher.group(1);
+ hasDollar = namePattern.contains("$");
+ }
+ }
+ final MinusculeMatcher innerMatcher = hasDollar ? new MinusculeMatcher("*" + namePattern, NameUtil.MatchingCaseSensitivity.NONE) : null;
PsiShortNamesCache.getInstance(parameters.getProject()).processClassesWithName(name, new Processor<PsiClass>() {
final boolean isAnnotation = parameters.getLocalPatternName().startsWith("@");
+
@Override
public boolean process(PsiClass aClass) {
if (aClass.getContainingFile().getVirtualFile() == null || !aClass.isPhysical()) return true;
if (isAnnotation && !aClass.isAnnotationType()) return true;
+ if (innerMatcher != null) {
+ if (aClass.getContainingClass() == null) return true;
+ String jvmQName = ClassUtil.getJVMClassName(aClass);
+ if (jvmQName == null || !innerMatcher.matches(StringUtil.getShortName(jvmQName))) return true;
+ }
return processor.process(aClass);
}
}, parameters.getSearchScope(), parameters.getIdFilter());
diff --git a/java/java-impl/src/com/intellij/openapi/roots/impl/ExcludeCompilerOutputPolicy.java b/java/java-impl/src/com/intellij/openapi/roots/impl/ExcludeCompilerOutputPolicy.java
index adbacfcd38ce..c825d8318edc 100644
--- a/java/java-impl/src/com/intellij/openapi/roots/impl/ExcludeCompilerOutputPolicy.java
+++ b/java/java-impl/src/com/intellij/openapi/roots/impl/ExcludeCompilerOutputPolicy.java
@@ -15,16 +15,12 @@
*/
package com.intellij.openapi.roots.impl;
-import com.intellij.openapi.module.Module;
-import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.CompilerModuleExtension;
import com.intellij.openapi.roots.CompilerProjectExtension;
import com.intellij.openapi.roots.ModuleRootModel;
-import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.pointers.VirtualFilePointer;
-import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
@@ -40,26 +36,6 @@ public class ExcludeCompilerOutputPolicy implements DirectoryIndexExcludePolicy
myProject = project;
}
- @Override
- public boolean isExcludeRoot(final VirtualFile file) {
- CompilerProjectExtension compilerProjectExtension = CompilerProjectExtension.getInstance(myProject);
- if (isEqualWithFileOrUrl(file, compilerProjectExtension.getCompilerOutput(), compilerProjectExtension.getCompilerOutputUrl())) return true;
-
- for (Module m : ModuleManager.getInstance(myProject).getModules()) {
- CompilerModuleExtension rm = CompilerModuleExtension.getInstance(m);
- if (isEqualWithFileOrUrl(file, rm.getCompilerOutputPath(), rm.getCompilerOutputUrl())) return true;
- if (isEqualWithFileOrUrl(file, rm.getCompilerOutputPathForTests(), rm.getCompilerOutputUrlForTests())) return true;
- }
- return false;
- }
-
- @Override
- public boolean isExcludeRootForModule(@NotNull final Module module, final VirtualFile excludeRoot) {
- final CompilerModuleExtension compilerModuleExtension = CompilerModuleExtension.getInstance(module);
- return Comparing.equal(compilerModuleExtension.getCompilerOutputPath(), excludeRoot) ||
- Comparing.equal(compilerModuleExtension.getCompilerOutputPathForTests(), excludeRoot);
- }
-
@NotNull
@Override
public VirtualFile[] getExcludeRootsForProject() {
@@ -88,14 +64,4 @@ public class ExcludeCompilerOutputPolicy implements DirectoryIndexExcludePolicy
}
return result.isEmpty() ? VirtualFilePointer.EMPTY_ARRAY : result.toArray(new VirtualFilePointer[result.size()]);
}
-
- private static boolean isEqualWithFileOrUrl(VirtualFile file, VirtualFile fileToCompareWith, String url) {
- if (fileToCompareWith != null) {
- if (Comparing.equal(fileToCompareWith, file)) return true;
- }
- else if (url != null) {
- if (FileUtil.pathsEqual(url, file.getUrl())) return true;
- }
- return false;
- }
}
diff --git a/java/java-impl/src/com/intellij/psi/codeStyle/arrangement/JavaArrangementVisitor.java b/java/java-impl/src/com/intellij/psi/codeStyle/arrangement/JavaArrangementVisitor.java
index 3651fa1afe3a..ff1170b64bef 100644
--- a/java/java-impl/src/com/intellij/psi/codeStyle/arrangement/JavaArrangementVisitor.java
+++ b/java/java-impl/src/com/intellij/psi/codeStyle/arrangement/JavaArrangementVisitor.java
@@ -280,6 +280,7 @@ public class JavaArrangementVisitor extends JavaRecursiveElementVisitor {
if (ref instanceof PsiField && containingClassFields.contains(ref)) {
referencedElements.add((PsiField)ref);
}
+ super.visitReferenceExpression(expression);
}
});
diff --git a/java/java-impl/src/com/intellij/psi/impl/search/JspIndexPatternBuilder.java b/java/java-impl/src/com/intellij/psi/impl/search/JspIndexPatternBuilder.java
index a8316f8dc0ee..eaa93875ba15 100644
--- a/java/java-impl/src/com/intellij/psi/impl/search/JspIndexPatternBuilder.java
+++ b/java/java-impl/src/com/intellij/psi/impl/search/JspIndexPatternBuilder.java
@@ -18,6 +18,7 @@ package com.intellij.psi.impl.search;
import com.intellij.lang.LanguageParserDefinitions;
import com.intellij.lang.ParserDefinition;
import com.intellij.lexer.Lexer;
+import com.intellij.openapi.editor.impl.EditorHighlighterCache;
import com.intellij.psi.JspPsiUtil;
import com.intellij.psi.PsiFile;
import com.intellij.psi.impl.source.tree.StdTokenSets;
@@ -34,7 +35,7 @@ public class JspIndexPatternBuilder implements IndexPatternBuilder {
@Override
public Lexer getIndexingLexer(@NotNull final PsiFile file) {
if (JspPsiUtil.isInJspFile(file)) {
- return LexerEditorHighlighterLexer.getLexerBasedOnLexerHighlighter(file.getText(), file.getVirtualFile(), file.getProject());
+ return EditorHighlighterCache.getLexerBasedOnLexerHighlighter(file.getText(), file.getVirtualFile(), file.getProject());
}
return null;
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FilePathReferenceProvider.java b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FilePathReferenceProvider.java
index 827a3d128a24..5380043307c7 100644
--- a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FilePathReferenceProvider.java
+++ b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FilePathReferenceProvider.java
@@ -142,9 +142,7 @@ public class FilePathReferenceProvider extends PsiReferenceProvider {
@NotNull
public static Collection<PsiFileSystemItem> getRoots(final Module thisModule, boolean includingClasses) {
if (thisModule == null) return Collections.emptyList();
- Set<Module> modules = new com.intellij.util.containers.HashSet<Module>();
ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(thisModule);
- ModuleUtilCore.getDependencies(thisModule, modules);
List<PsiFileSystemItem> result = new ArrayList<PsiFileSystemItem>();
final PsiManager psiManager = PsiManager.getInstance(thisModule.getProject());
if (includingClasses) {
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/MethodPropertyReference.java b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/MethodPropertyReference.java
index f7dc89ce5b80..307d608ddbd8 100644
--- a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/MethodPropertyReference.java
+++ b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/MethodPropertyReference.java
@@ -16,7 +16,6 @@
package com.intellij.psi.impl.source.resolve.reference.impl.providers;
import com.intellij.psi.*;
-import com.intellij.psi.jsp.JspImplicitVariable;
import com.intellij.psi.jsp.JspSpiUtil;
import com.intellij.psi.util.PropertyUtil;
import com.intellij.psi.xml.XmlAttribute;
@@ -62,8 +61,8 @@ public class MethodPropertyReference extends BasicAttributeValueReference {
}
} else if (psiElement instanceof PsiClass) {
return (PsiClass)psiElement;
- } else if (psiElement instanceof JspImplicitVariable) {
- final PsiType type=((JspImplicitVariable)psiElement).getType();
+ } else if (psiElement instanceof PsiVariable) {
+ final PsiType type=((PsiVariable)psiElement).getType();
if (type instanceof PsiClassType) {
return ((PsiClassType)type).resolve();
}
diff --git a/java/java-impl/src/com/intellij/refactoring/anonymousToInner/AnonymousToInnerDialog.java b/java/java-impl/src/com/intellij/refactoring/anonymousToInner/AnonymousToInnerDialog.java
index 7bca3c07b4c0..80201559ef34 100644
--- a/java/java-impl/src/com/intellij/refactoring/anonymousToInner/AnonymousToInnerDialog.java
+++ b/java/java-impl/src/com/intellij/refactoring/anonymousToInner/AnonymousToInnerDialog.java
@@ -86,20 +86,23 @@ class AnonymousToInnerDialog extends DialogWrapper{
final String[] names;
String name = myAnonClass.getBaseClassReference().getReferenceName();
PsiType[] typeParameters = myAnonClass.getBaseClassReference().getTypeParameters();
- if (typeParameters.length > 0) {
- names = new String[]{StringUtil.join(typeParameters, new Function<PsiType, String>() {
- public String fun(PsiType psiType) {
- PsiType type = psiType;
- if (psiType instanceof PsiClassType) {
- type = TypeConversionUtil.erasure(psiType);
- }
- if (type == null || type.equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) return "";
- if (type instanceof PsiArrayType) {
- type = type.getDeepComponentType();
- }
- return StringUtil.getShortName(type.getPresentableText());
+
+ final String typeParamsList = StringUtil.join(typeParameters, new Function<PsiType, String>() {
+ public String fun(PsiType psiType) {
+ PsiType type = psiType;
+ if (psiType instanceof PsiClassType) {
+ type = TypeConversionUtil.erasure(psiType);
}
- }, "") + name, "My" + name};
+ if (type == null || type.equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) return "";
+ if (type instanceof PsiArrayType) {
+ type = type.getDeepComponentType();
+ }
+ return StringUtil.getShortName(type.getPresentableText());
+ }
+ }, "") + name;
+
+ if (!typeParamsList.equals(name)) {
+ names = new String[]{typeParamsList, "My" + name};
} else {
names = new String[]{"My" + name};
}
diff --git a/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java b/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java
index 75544f9d8ab9..ce52274140bb 100644
--- a/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java
+++ b/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java
@@ -19,6 +19,7 @@ import com.intellij.codeInsight.ChangeContextUtil;
import com.intellij.codeInsight.ExceptionUtil;
import com.intellij.codeInsight.NullableNotNullManager;
import com.intellij.codeInsight.daemon.impl.analysis.JavaHighlightUtil;
+import com.intellij.codeInsight.daemon.impl.quickfix.AnonymousTargetClassPreselectionUtil;
import com.intellij.codeInsight.highlighting.HighlightManager;
import com.intellij.codeInsight.intention.impl.AddNullableAnnotationFix;
import com.intellij.codeInsight.navigation.NavigationUtil;
@@ -1133,6 +1134,7 @@ public class ExtractMethodProcessor implements MatchProvider {
final PsiElementProcessor<PsiClass> processor = new PsiElementProcessor<PsiClass>() {
@Override
public boolean execute(@NotNull PsiClass selectedClass) {
+ AnonymousTargetClassPreselectionUtil.rememberSelection(selectedClass, myTargetClass);
final List<PsiVariable> array = classes.get(selectedClass);
myNeedChangeContext = myTargetClass != selectedClass;
myTargetClass = selectedClass;
@@ -1184,7 +1186,9 @@ public class ExtractMethodProcessor implements MatchProvider {
if (classes.size() > 1) {
final PsiClass[] psiClasses = classes.keySet().toArray(new PsiClass[classes.size()]);
- NavigationUtil.getPsiElementPopup(psiClasses, new PsiClassListCellRenderer(), "Choose Destination Class", processor).showInBestPositionFor(myEditor);
+ final PsiClass preselection = AnonymousTargetClassPreselectionUtil.getPreselection(classes.keySet(), psiClasses[0]);
+ NavigationUtil.getPsiElementPopup(psiClasses, new PsiClassListCellRenderer(), "Choose Destination Class", processor, preselection)
+ .showInBestPositionFor(myEditor);
return true;
}
}
diff --git a/java/java-impl/src/com/intellij/refactoring/introduceField/BaseExpressionToFieldHandler.java b/java/java-impl/src/com/intellij/refactoring/introduceField/BaseExpressionToFieldHandler.java
index a751acea42df..75473959ddcc 100644
--- a/java/java-impl/src/com/intellij/refactoring/introduceField/BaseExpressionToFieldHandler.java
+++ b/java/java-impl/src/com/intellij/refactoring/introduceField/BaseExpressionToFieldHandler.java
@@ -27,6 +27,7 @@ package com.intellij.refactoring.introduceField;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInsight.ChangeContextUtil;
import com.intellij.codeInsight.TestFrameworks;
+import com.intellij.codeInsight.daemon.impl.quickfix.AnonymousTargetClassPreselectionUtil;
import com.intellij.codeInsight.highlighting.HighlightManager;
import com.intellij.codeInsight.lookup.LookupManager;
import com.intellij.codeInsight.navigation.NavigationUtil;
@@ -129,18 +130,13 @@ public abstract class BaseExpressionToFieldHandler extends IntroduceHandlerBase
return !convertExpressionToField(selectedExpr, editor, file, project, tempType);
}
else {
- PsiClass selection = null;
- for (PsiClass psiClass : classes) {
- if (!(psiClass instanceof PsiAnonymousClass)) {
- selection = psiClass;
- break;
- }
- }
+ PsiClass selection = AnonymousTargetClassPreselectionUtil.getPreselection(classes, myParentClass);
NavigationUtil.getPsiElementPopup(classes.toArray(new PsiClass[classes.size()]), new PsiClassListCellRenderer(),
"Choose class to introduce " + (myIsConstant ? "constant" : "field"),
new PsiElementProcessor<PsiClass>() {
@Override
public boolean execute(@NotNull PsiClass aClass) {
+ AnonymousTargetClassPreselectionUtil.rememberSelection(aClass, myParentClass);
myParentClass = aClass;
convertExpressionToField(selectedExpr, editor, file, project, tempType);
return false;
diff --git a/java/java-impl/src/com/intellij/refactoring/introduceField/LocalToFieldHandler.java b/java/java-impl/src/com/intellij/refactoring/introduceField/LocalToFieldHandler.java
index 5b5c39fb10a8..0b31eedf8be0 100644
--- a/java/java-impl/src/com/intellij/refactoring/introduceField/LocalToFieldHandler.java
+++ b/java/java-impl/src/com/intellij/refactoring/introduceField/LocalToFieldHandler.java
@@ -18,6 +18,7 @@ package com.intellij.refactoring.introduceField;
import com.intellij.codeInsight.ChangeContextUtil;
import com.intellij.codeInsight.CodeInsightUtil;
import com.intellij.codeInsight.TestFrameworks;
+import com.intellij.codeInsight.daemon.impl.quickfix.AnonymousTargetClassPreselectionUtil;
import com.intellij.codeInsight.navigation.NavigationUtil;
import com.intellij.ide.util.PsiClassListCellRenderer;
import com.intellij.openapi.application.ApplicationManager;
@@ -66,7 +67,7 @@ public abstract class LocalToFieldHandler {
public boolean convertLocalToField(final PsiLocalVariable local, final Editor editor) {
boolean tempIsStatic = myIsConstant;
PsiElement parent = local.getParent();
- List<PsiClass> classes = new ArrayList<PsiClass>();
+ final List<PsiClass> classes = new ArrayList<PsiClass>();
while (parent != null && parent.getContainingFile() != null) {
if (parent instanceof PsiClass && !(myIsConstant && parent instanceof PsiAnonymousClass)) {
classes.add((PsiClass)parent);
@@ -90,13 +91,16 @@ public abstract class LocalToFieldHandler {
if (convertLocalToField(local, classes.get(getChosenClassIndex(classes)), editor, tempIsStatic)) return false;
} else {
final boolean isStatic = tempIsStatic;
+ final PsiClass firstClass = classes.get(0);
+ final PsiClass preselection = AnonymousTargetClassPreselectionUtil.getPreselection(classes, firstClass);
NavigationUtil.getPsiElementPopup(classes.toArray(new PsiClass[classes.size()]), new PsiClassListCellRenderer(), "Choose class to introduce " + (myIsConstant ? "constant" : "field"), new PsiElementProcessor<PsiClass>() {
@Override
public boolean execute(@NotNull PsiClass aClass) {
+ AnonymousTargetClassPreselectionUtil.rememberSelection(aClass, aClass);
convertLocalToField(local, aClass, editor, isStatic);
return false;
}
- }).showInBestPositionFor(editor);
+ }, preselection).showInBestPositionFor(editor);
}
return true;
diff --git a/java/java-impl/src/com/intellij/refactoring/rename/RenameJavaMethodProcessor.java b/java/java-impl/src/com/intellij/refactoring/rename/RenameJavaMethodProcessor.java
index c410d763dac1..f09da834c348 100644
--- a/java/java-impl/src/com/intellij/refactoring/rename/RenameJavaMethodProcessor.java
+++ b/java/java-impl/src/com/intellij/refactoring/rename/RenameJavaMethodProcessor.java
@@ -210,10 +210,16 @@ public class RenameJavaMethodProcessor extends RenameJavaMemberProcessor {
if (element instanceof PsiReferenceExpression) {
if (((PsiReferenceExpression)element).resolve() == methodToRename) {
final PsiElement parent = element.getParent();
- LOG.assertTrue(parent instanceof PsiMethodCallExpression, parent.getText());
- final PsiMethodCallExpression copy = (PsiMethodCallExpression)JavaPsiFacade.getElementFactory(element.getProject())
- .createExpressionFromText(parent.getText(), element);
- final PsiReferenceExpression expression = (PsiReferenceExpression)processRef(copy.getMethodExpression(), newName);
+ final PsiReferenceExpression copyRef;
+ if (parent instanceof PsiMethodCallExpression) {
+ final PsiMethodCallExpression copy = (PsiMethodCallExpression)JavaPsiFacade.getElementFactory(element.getProject())
+ .createExpressionFromText(parent.getText(), element);
+ copyRef = copy.getMethodExpression();
+ } else {
+ LOG.assertTrue(element instanceof PsiMethodReferenceExpression, element.getText());
+ copyRef = (PsiReferenceExpression)element.copy();
+ }
+ final PsiReferenceExpression expression = (PsiReferenceExpression)processRef(copyRef, newName);
if (expression == null) continue;
final JavaResolveResult resolveResult = expression.advancedResolve(true);
final PsiMember resolveResultElement = (PsiMember)resolveResult.getElement();
diff --git a/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java b/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java
index f2ac34e8aed0..ca01331d3e94 100644
--- a/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java
+++ b/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java
@@ -617,7 +617,7 @@ public class RefactoringUtil {
Project project = expr.getProject();
String[] suggestedNames =
JavaCodeStyleManager.getInstance(project).suggestVariableName(VariableKind.LOCAL_VARIABLE, null, expr, null).names;
- final String prefix = suggestedNames[0];
+ final String prefix = suggestedNames.length > 0 ? suggestedNames[0] : "var";
final String id = JavaCodeStyleManager.getInstance(project).suggestUniqueVariableName(prefix, context, true);
PsiElementFactory factory = JavaPsiFacade.getInstance(expr.getProject()).getElementFactory();
diff --git a/java/java-impl/src/com/intellij/testIntegration/createTest/MissedTestsDialog.java b/java/java-impl/src/com/intellij/testIntegration/createTest/MissedTestsDialog.java
index b34d28e3f6f4..ee8bcf0d1c1c 100644
--- a/java/java-impl/src/com/intellij/testIntegration/createTest/MissedTestsDialog.java
+++ b/java/java-impl/src/com/intellij/testIntegration/createTest/MissedTestsDialog.java
@@ -20,19 +20,15 @@ import com.intellij.codeInsight.template.Template;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.psi.JavaPsiFacade;
-import com.intellij.psi.PsiClass;
-import com.intellij.psi.PsiMember;
-import com.intellij.psi.PsiMethod;
-import com.intellij.refactoring.ui.MemberSelectionPanel;
+import com.intellij.psi.*;
import com.intellij.refactoring.ui.MemberSelectionTable;
import com.intellij.refactoring.util.classMembers.MemberInfo;
import com.intellij.testIntegration.TestFramework;
import com.intellij.testIntegration.TestIntegrationUtils;
import com.intellij.ui.ScrollPaneFactory;
-import com.intellij.ui.SeparatorFactory;
import com.intellij.ui.components.JBCheckBox;
import com.intellij.util.Function;
+import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.Nullable;
@@ -40,8 +36,10 @@ import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
-import java.util.*;
+import java.util.Collection;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
public class MissedTestsDialog extends DialogWrapper {
private final PsiClass mySourceClass;
@@ -85,9 +83,7 @@ public class MissedTestsDialog extends DialogWrapper {
private void disableMethodsWithTests(List<MemberInfo> info) {
final Set<String> existingNames = new HashSet<String>();
- final Template template = TestIntegrationUtils
- .createTestMethodTemplate(TestIntegrationUtils.MethodKind.TEST, myDescriptor, myTestClass, null, true, existingNames);
- final String prefix = JavaPsiFacade.getElementFactory(myTestClass.getProject()).createMethodFromText(template.getTemplateText(), myTestClass).getName();
+ final String prefix = getTestPrefix(existingNames);
existingNames.addAll(ContainerUtil.map(myTestClass.getMethods(), new Function<PsiMethod, String>() {
@Override
@@ -103,6 +99,16 @@ public class MissedTestsDialog extends DialogWrapper {
}
}
+ private String getTestPrefix(Set<String> existingNames) {
+ final Template template = TestIntegrationUtils.createTestMethodTemplate(TestIntegrationUtils.MethodKind.TEST, myDescriptor, myTestClass, null, true, existingNames);
+ try {
+ return JavaPsiFacade.getElementFactory(myTestClass.getProject()).createMethodFromText(template.getTemplateText(), myTestClass).getName();
+ }
+ catch (IncorrectOperationException e) {
+ return "";
+ }
+ }
+
private void updateMethodsTable() {
List<MemberInfo> infos = TestIntegrationUtils.extractClassMethods(mySourceClass, myIncludeInheritedCb.isSelected());
diff --git a/java/java-impl/src/com/intellij/usages/impl/rules/JavaUsageTypeProvider.java b/java/java-impl/src/com/intellij/usages/impl/rules/JavaUsageTypeProvider.java
index 445a8aab14a2..93b9737bdfe3 100644
--- a/java/java-impl/src/com/intellij/usages/impl/rules/JavaUsageTypeProvider.java
+++ b/java/java-impl/src/com/intellij/usages/impl/rules/JavaUsageTypeProvider.java
@@ -70,7 +70,8 @@ public class JavaUsageTypeProvider implements UsageTypeProviderEx {
return UsageType.RECURSION;
}
if (qualifier != null && !(qualifier instanceof PsiThisExpression) && calledMethod != null) {
- if (haveCommonSuperMethod(containerMethod, calledMethod)) {
+ if (Comparing.equal(containerMethod.getName(), calledMethod.getName()) &&
+ haveCommonSuperMethod(containerMethod, calledMethod)) {
boolean parametersDelegated = parametersDelegated(containerMethod, callExpression);
if (qualifier instanceof PsiSuperExpression) {
diff --git a/java/java-psi-api/src/com/intellij/codeInsight/AnnotationTargetUtil.java b/java/java-psi-api/src/com/intellij/codeInsight/AnnotationTargetUtil.java
new file mode 100644
index 000000000000..c7d9e303aae3
--- /dev/null
+++ b/java/java-psi-api/src/com/intellij/codeInsight/AnnotationTargetUtil.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.psi.*;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collections;
+import java.util.Set;
+
+/**
+ * @author peter
+ */
+public class AnnotationTargetUtil {
+ public static final Set<PsiAnnotation.TargetType> DEFAULT_TARGETS = Collections.unmodifiableSet(ContainerUtil.newHashSet(
+ PsiAnnotation.TargetType.PACKAGE, PsiAnnotation.TargetType.TYPE, PsiAnnotation.TargetType.ANNOTATION_TYPE,
+ PsiAnnotation.TargetType.FIELD, PsiAnnotation.TargetType.METHOD, PsiAnnotation.TargetType.CONSTRUCTOR,
+ PsiAnnotation.TargetType.PARAMETER, PsiAnnotation.TargetType.LOCAL_VARIABLE));
+ private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.AnnotationUtil");
+ private static final PsiAnnotation.TargetType[] PACKAGE_TARGETS = {PsiAnnotation.TargetType.PACKAGE};
+ private static final PsiAnnotation.TargetType[] TYPE_USE_TARGETS = {PsiAnnotation.TargetType.TYPE_USE};
+ private static final PsiAnnotation.TargetType[] ANNOTATION_TARGETS = {PsiAnnotation.TargetType.ANNOTATION_TYPE, PsiAnnotation.TargetType.TYPE, PsiAnnotation.TargetType.TYPE_USE};
+ private static final PsiAnnotation.TargetType[] TYPE_TARGETS = {PsiAnnotation.TargetType.TYPE, PsiAnnotation.TargetType.TYPE_USE};
+ private static final PsiAnnotation.TargetType[] TYPE_PARAMETER_TARGETS = {
+ PsiAnnotation.TargetType.TYPE_PARAMETER, PsiAnnotation.TargetType.TYPE_USE};
+ private static final PsiAnnotation.TargetType[] CONSTRUCTOR_TARGETS = {PsiAnnotation.TargetType.CONSTRUCTOR, PsiAnnotation.TargetType.TYPE_USE};
+ private static final PsiAnnotation.TargetType[] METHOD_TARGETS = {PsiAnnotation.TargetType.METHOD, PsiAnnotation.TargetType.TYPE_USE};
+ private static final PsiAnnotation.TargetType[] FIELD_TARGETS = {PsiAnnotation.TargetType.FIELD, PsiAnnotation.TargetType.TYPE_USE};
+ private static final PsiAnnotation.TargetType[] PARAMETER_TARGETS = {PsiAnnotation.TargetType.PARAMETER, PsiAnnotation.TargetType.TYPE_USE};
+ private static final PsiAnnotation.TargetType[] LOCAL_VARIABLE_TARGETS ={
+ PsiAnnotation.TargetType.LOCAL_VARIABLE, PsiAnnotation.TargetType.TYPE_USE};
+
+ @NotNull
+ public static PsiAnnotation.TargetType[] getTargetsForLocation(@Nullable PsiAnnotationOwner owner) {
+ if (owner == null) {
+ return PsiAnnotation.TargetType.EMPTY_ARRAY;
+ }
+
+ if (owner instanceof PsiType || owner instanceof PsiTypeElement) {
+ return TYPE_USE_TARGETS;
+ }
+
+ if (owner instanceof PsiTypeParameter) {
+ return TYPE_PARAMETER_TARGETS;
+ }
+
+ if (owner instanceof PsiModifierList) {
+ PsiElement element = ((PsiModifierList)owner).getParent();
+ if (element instanceof PsiPackageStatement) {
+ return PACKAGE_TARGETS;
+ }
+ if (element instanceof PsiClass) {
+ if (((PsiClass)element).isAnnotationType()) {
+ return ANNOTATION_TARGETS;
+ }
+ else {
+ return TYPE_TARGETS;
+ }
+ }
+ if (element instanceof PsiMethod) {
+ if (((PsiMethod)element).isConstructor()) {
+ return CONSTRUCTOR_TARGETS;
+ }
+ else {
+ return METHOD_TARGETS;
+ }
+ }
+ if (element instanceof PsiField) {
+ return FIELD_TARGETS;
+ }
+ if (element instanceof PsiParameter) {
+ return PARAMETER_TARGETS;
+ }
+ if (element instanceof PsiLocalVariable) {
+ return LOCAL_VARIABLE_TARGETS;
+ }
+ }
+
+ return PsiAnnotation.TargetType.EMPTY_ARRAY;
+ }
+
+ @Nullable
+ public static Set<PsiAnnotation.TargetType> extractRequiredAnnotationTargets(@Nullable PsiAnnotationMemberValue value) {
+ if (value instanceof PsiReference) {
+ PsiAnnotation.TargetType targetType = translateTargetRef((PsiReference)value);
+ if (targetType != null) {
+ return Collections.singleton(targetType);
+ }
+ }
+ else if (value instanceof PsiArrayInitializerMemberValue) {
+ Set <PsiAnnotation.TargetType> targets = ContainerUtil.newHashSet();
+ for (PsiAnnotationMemberValue initializer : ((PsiArrayInitializerMemberValue)value).getInitializers()) {
+ if (initializer instanceof PsiReference) {
+ PsiAnnotation.TargetType targetType = translateTargetRef((PsiReference)initializer);
+ if (targetType != null) {
+ targets.add(targetType);
+ }
+ }
+ }
+ return targets;
+ }
+
+ return null;
+ }
+
+ @Nullable
+ private static PsiAnnotation.TargetType translateTargetRef(@NotNull PsiReference reference) {
+ PsiElement field = reference.resolve();
+ if (field instanceof PsiEnumConstant) {
+ String name = ((PsiEnumConstant)field).getName();
+ try {
+ return PsiAnnotation.TargetType.valueOf(name);
+ }
+ catch (IllegalArgumentException e) {
+ LOG.warn("Unknown target: " + name);
+ }
+ }
+ return null;
+ }
+}
diff --git a/java/java-psi-api/src/com/intellij/codeInsight/AnnotationUtil.java b/java/java-psi-api/src/com/intellij/codeInsight/AnnotationUtil.java
index c2c79a9d9d8a..25034e9ab7ba 100644
--- a/java/java-psi-api/src/com/intellij/codeInsight/AnnotationUtil.java
+++ b/java/java-psi-api/src/com/intellij/codeInsight/AnnotationUtil.java
@@ -379,14 +379,14 @@ public class AnnotationUtil {
@NotNull
public static PsiAnnotation[] getAllAnnotations(@NotNull PsiModifierListOwner owner,
boolean inHierarchy,
- Set<PsiModifierListOwner> visited) {
+ @Nullable Set<PsiModifierListOwner> visited) {
return getAllAnnotations(owner, inHierarchy, visited, true);
}
@NotNull
public static PsiAnnotation[] getAllAnnotations(@NotNull PsiModifierListOwner owner,
boolean inHierarchy,
- Set<PsiModifierListOwner> visited, boolean withInferred) {
+ @Nullable Set<PsiModifierListOwner> visited, boolean withInferred) {
final PsiModifierList list = owner.getModifierList();
PsiAnnotation[] annotations = PsiAnnotation.EMPTY_ARRAY;
if (list != null) {
diff --git a/java/java-psi-api/src/com/intellij/codeInsight/NullableNotNullManager.java b/java/java-psi-api/src/com/intellij/codeInsight/NullableNotNullManager.java
index 21e014e4aca3..2210e02a080a 100644
--- a/java/java-psi-api/src/com/intellij/codeInsight/NullableNotNullManager.java
+++ b/java/java-psi-api/src/com/intellij/codeInsight/NullableNotNullManager.java
@@ -44,10 +44,13 @@ public class NullableNotNullManager implements PersistentStateComponent<Element>
public final JDOMExternalizableStringList myNullables = new JDOMExternalizableStringList();
public final JDOMExternalizableStringList myNotNulls = new JDOMExternalizableStringList();
- public static final String[] DEFAULT_NULLABLES = {AnnotationUtil.NULLABLE, "javax.annotation.Nullable",
+ private static final String JAVAX_ANNOTATION_NULLABLE = "javax.annotation.Nullable";
+ private static final String JAVAX_ANNOTATION_NONNULL = "javax.annotation.Nonnull";
+
+ public static final String[] DEFAULT_NULLABLES = {AnnotationUtil.NULLABLE, JAVAX_ANNOTATION_NULLABLE,
"edu.umd.cs.findbugs.annotations.Nullable", "android.support.annotation.Nullable"
};
- public static final String[] DEFAULT_NOT_NULLS = {AnnotationUtil.NOT_NULL, "javax.annotation.Nonnull",
+ public static final String[] DEFAULT_NOT_NULLS = {AnnotationUtil.NOT_NULL, JAVAX_ANNOTATION_NONNULL,
"edu.umd.cs.findbugs.annotations.NonNull", "android.support.annotation.NonNull"
};
@@ -103,6 +106,11 @@ public class NullableNotNullManager implements PersistentStateComponent<Element>
return findNullabilityAnnotation(owner, checkBases, true);
}
+ public boolean isContainerAnnotation(@NotNull PsiAnnotation anno) {
+ PsiAnnotation.TargetType[] acceptAnyTarget = PsiAnnotation.TargetType.values();
+ return isNullabilityDefault(anno, true, acceptAnyTarget) || isNullabilityDefault(anno, false, acceptAnyTarget);
+ }
+
public void setDefaultNullable(@NotNull String defaultNullable) {
LOG.assertTrue(getNullables().contains(defaultNullable));
myDefaultNullable = defaultNullable;
@@ -138,15 +146,20 @@ public class NullableNotNullManager implements PersistentStateComponent<Element>
return annotation;
}
- if (owner instanceof PsiParameter && !TypeConversionUtil.isPrimitiveAndNotNull(((PsiParameter)owner).getType())) {
- // even if javax.annotation.Nullable is not configured, it should still take precedence over ByDefault annotations
- if (AnnotationUtil.isAnnotated(owner, nullable ? Arrays.asList(DEFAULT_NOT_NULLS) : Arrays.asList(DEFAULT_NULLABLES), checkBases, false)) {
- return null;
- }
- return findContainerAnnotation(owner, nullable
- ? "javax.annotation.ParametersAreNullableByDefault"
- : "javax.annotation.ParametersAreNonnullByDefault");
+ PsiType type = getOwnerType(owner);
+ if (type == null || TypeConversionUtil.isPrimitiveAndNotNull(type)) return null;
+
+ // even if javax.annotation.Nullable is not configured, it should still take precedence over ByDefault annotations
+ if (AnnotationUtil.isAnnotated(owner, nullable ? Arrays.asList(DEFAULT_NOT_NULLS) : Arrays.asList(DEFAULT_NULLABLES), checkBases, false)) {
+ return null;
}
+ return findNullabilityDefaultInHierarchy(owner, nullable);
+ }
+
+ @Nullable
+ private static PsiType getOwnerType(PsiModifierListOwner owner) {
+ if (owner instanceof PsiVariable) return ((PsiVariable)owner).getType();
+ if (owner instanceof PsiMethod) return ((PsiMethod)owner).getReturnType();
return null;
}
@@ -159,11 +172,13 @@ public class NullableNotNullManager implements PersistentStateComponent<Element>
}
@Nullable
- private static PsiAnnotation findContainerAnnotation(PsiModifierListOwner owner, String annotationFQN) {
+ private static PsiAnnotation findNullabilityDefaultInHierarchy(PsiModifierListOwner owner, boolean nullable) {
+ PsiAnnotation.TargetType[] placeTargetTypes = AnnotationTargetUtil.getTargetsForLocation(owner.getModifierList());
+
PsiElement element = owner.getParent();
while (element != null) {
if (element instanceof PsiModifierListOwner) {
- PsiAnnotation annotation = AnnotationUtil.findAnnotation((PsiModifierListOwner)element, annotationFQN);
+ PsiAnnotation annotation = getNullabilityDefault((PsiModifierListOwner)element, nullable, placeTargetTypes);
if (annotation != null) {
return annotation;
}
@@ -172,7 +187,7 @@ public class NullableNotNullManager implements PersistentStateComponent<Element>
if (element instanceof PsiClassOwner) {
String packageName = ((PsiClassOwner)element).getPackageName();
PsiPackage psiPackage = JavaPsiFacade.getInstance(element.getProject()).findPackage(packageName);
- return AnnotationUtil.findAnnotation(psiPackage, annotationFQN);
+ return psiPackage == null ? null : getNullabilityDefault(psiPackage, nullable, placeTargetTypes);
}
element = element.getContext();
@@ -180,6 +195,37 @@ public class NullableNotNullManager implements PersistentStateComponent<Element>
return null;
}
+ private static PsiAnnotation getNullabilityDefault(@NotNull PsiModifierListOwner container, boolean nullable, PsiAnnotation.TargetType[] placeTargetTypes) {
+ PsiModifierList modifierList = container.getModifierList();
+ if (modifierList == null) return null;
+ for (PsiAnnotation annotation : modifierList.getAnnotations()) {
+ if (isNullabilityDefault(annotation, nullable, placeTargetTypes)) {
+ return annotation;
+ }
+ }
+ return null;
+ }
+
+ private static boolean isNullabilityDefault(@NotNull PsiAnnotation annotation, boolean nullable, PsiAnnotation.TargetType[] placeTargetTypes) {
+ PsiJavaCodeReferenceElement element = annotation.getNameReferenceElement();
+ PsiElement declaration = element == null ? null : element.resolve();
+ if (!(declaration instanceof PsiClass)) return false;
+
+ if (!AnnotationUtil.isAnnotated((PsiClass)declaration,
+ nullable ? JAVAX_ANNOTATION_NULLABLE : JAVAX_ANNOTATION_NONNULL,
+ false,
+ true)) {
+ return false;
+ }
+
+ PsiAnnotation tqDefault = AnnotationUtil.findAnnotation((PsiClass)declaration, true, "javax.annotation.meta.TypeQualifierDefault");
+ if (tqDefault == null) return false;
+
+ Set<PsiAnnotation.TargetType> required = AnnotationTargetUtil.extractRequiredAnnotationTargets(tqDefault.findAttributeValue(null));
+ if (required == null) return false;
+ return required.isEmpty() || ContainerUtil.intersects(required, Arrays.asList(placeTargetTypes));
+ }
+
public List<String> getNullables() {
return myNullables;
}
diff --git a/java/java-psi-api/src/com/intellij/psi/GenericsUtil.java b/java/java-psi-api/src/com/intellij/psi/GenericsUtil.java
index 7cabc118fc6c..52888f123215 100644
--- a/java/java-psi-api/src/com/intellij/psi/GenericsUtil.java
+++ b/java/java-psi-api/src/com/intellij/psi/GenericsUtil.java
@@ -476,6 +476,9 @@ public class GenericsUtil {
PsiType substituted = resolveResult.getSubstitutor().substitute(typeParam);
if (substituted instanceof PsiWildcardType) {
substituted = ((PsiWildcardType)substituted).getBound();
+ if (substituted instanceof PsiCapturedWildcardType) {
+ substituted = ((PsiCapturedWildcardType)substituted).getWildcard().getBound();
+ }
if (substituted == null) substituted = TypeConversionUtil.typeParameterErasure(typeParam);
}
map.put(typeParam, substituted);
diff --git a/java/java-psi-api/src/com/intellij/psi/infos/MethodCandidateInfo.java b/java/java-psi-api/src/com/intellij/psi/infos/MethodCandidateInfo.java
index e7506ebd92fd..f43358007eab 100644
--- a/java/java-psi-api/src/com/intellij/psi/infos/MethodCandidateInfo.java
+++ b/java/java-psi-api/src/com/intellij/psi/infos/MethodCandidateInfo.java
@@ -180,7 +180,7 @@ public class MethodCandidateInfo extends CandidateInfo{
@NotNull
public PsiSubstitutor getSubstitutor(boolean includeReturnConstraint) {
PsiSubstitutor substitutor = myCalcedSubstitutor;
- if (substitutor == null || !includeReturnConstraint && myLanguageLevel.isAtLeast(LanguageLevel.JDK_1_8)) {
+ if (substitutor == null || !includeReturnConstraint && myLanguageLevel.isAtLeast(LanguageLevel.JDK_1_8) || isOverloadCheck()) {
PsiSubstitutor incompleteSubstitutor = super.getSubstitutor();
PsiMethod method = getElement();
if (myTypeArguments == null) {
@@ -189,7 +189,7 @@ public class MethodCandidateInfo extends CandidateInfo{
final PsiSubstitutor inferredSubstitutor = inferTypeArguments(DefaultParameterTypeInferencePolicy.INSTANCE, includeReturnConstraint);
if (!stackStamp.mayCacheNow() ||
- !ourOverloadGuard.currentStack().isEmpty() ||
+ isOverloadCheck() ||
!includeReturnConstraint && myLanguageLevel.isAtLeast(LanguageLevel.JDK_1_8) ||
getMarkerList() != null && PsiResolveHelper.ourGraphGuard.currentStack().contains(getMarkerList().getParent())) {
return inferredSubstitutor;
@@ -209,6 +209,10 @@ public class MethodCandidateInfo extends CandidateInfo{
return substitutor;
}
+ public static boolean isOverloadCheck() {
+ return !ourOverloadGuard.currentStack().isEmpty();
+ }
+
public boolean isTypeArgumentsApplicable() {
return isTypeArgumentsApplicable(false);
diff --git a/java/java-psi-api/src/com/intellij/psi/util/MethodSignatureUtil.java b/java/java-psi-api/src/com/intellij/psi/util/MethodSignatureUtil.java
index 622714c6dd61..22591801e32e 100644
--- a/java/java-psi-api/src/com/intellij/psi/util/MethodSignatureUtil.java
+++ b/java/java-psi-api/src/com/intellij/psi/util/MethodSignatureUtil.java
@@ -114,7 +114,7 @@ public class MethodSignatureUtil {
}
public static boolean areSignaturesEqual(@NotNull PsiMethod method1, @NotNull PsiMethod method2) {
- return method1.getSignature(PsiSubstitutor.EMPTY).equals(method2.getSignature(PsiSubstitutor.EMPTY));
+ return areSignaturesEqual(method1.getSignature(PsiSubstitutor.EMPTY), method2.getSignature(PsiSubstitutor.EMPTY));
}
public static boolean areSignaturesEqual(@NotNull MethodSignature method1, @NotNull MethodSignature method2) {
@@ -172,10 +172,10 @@ public class MethodSignatureUtil {
public static boolean isSuperMethod(@NotNull PsiMethod superMethodCandidate, @NotNull PsiMethod derivedMethod) {
PsiClass superClassCandidate = superMethodCandidate.getContainingClass();
PsiClass derivedClass = derivedMethod.getContainingClass();
- if (derivedClass == null || superClassCandidate == null) return false;
- if (!derivedClass.isInheritor(superClassCandidate, true)) return false;
- final PsiSubstitutor superSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(superClassCandidate, derivedClass,
- PsiSubstitutor.EMPTY);
+ if (derivedClass == null || superClassCandidate == null || derivedClass == superClassCandidate) return false;
+ final PsiSubstitutor superSubstitutor = TypeConversionUtil.getMaybeSuperClassSubstitutor(superClassCandidate, derivedClass,
+ PsiSubstitutor.EMPTY, null);
+ if (superSubstitutor == null) return false;
final MethodSignature superSignature = superMethodCandidate.getSignature(superSubstitutor);
final MethodSignature derivedSignature = derivedMethod.getSignature(PsiSubstitutor.EMPTY);
return isSubsignature(superSignature, derivedSignature);
diff --git a/java/java-psi-api/src/com/intellij/psi/util/PsiUtil.java b/java/java-psi-api/src/com/intellij/psi/util/PsiUtil.java
index e5493711b7c2..a69e11a9d3cc 100644
--- a/java/java-psi-api/src/com/intellij/psi/util/PsiUtil.java
+++ b/java/java-psi-api/src/com/intellij/psi/util/PsiUtil.java
@@ -1099,6 +1099,11 @@ public final class PsiUtil extends PsiUtilCore {
return true;
}
}
+ else if (parent instanceof PsiConditionalExpression) {
+ if (checkSameExpression(expr, ((PsiConditionalExpression)parent).getCondition())) {
+ return true;
+ }
+ }
return false;
}
diff --git a/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java b/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java
index 477a74e64b2e..42f1494bad2e 100644
--- a/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java
+++ b/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java
@@ -128,6 +128,9 @@ public class TypeConversionUtil {
return boxedType != null && areTypesConvertible(boxedType, toType);
}
if (!fromIsPrimitive) {
+ // 5.5. Casting Contexts
+ if ((fromTypeRank == SHORT_RANK || fromTypeRank == BYTE_RANK) && toTypeRank == CHAR_RANK) return false;
+
if (fromType instanceof PsiClassType) {
if (languageLevel == null) {
languageLevel = ((PsiClassType)fromType).getLanguageLevel();
@@ -162,7 +165,7 @@ public class TypeConversionUtil {
/**
* see JLS 5.1.5, JLS3 5.1.6
*/
- private static boolean isNarrowingReferenceConversionAllowed(PsiType fromType, PsiType toType) {
+ private static boolean isNarrowingReferenceConversionAllowed(@NotNull PsiType fromType, @NotNull PsiType toType) {
if (toType instanceof PsiPrimitiveType || fromType instanceof PsiPrimitiveType) return fromType.equals(toType);
//Done with primitives
if (toType instanceof PsiDiamondType || fromType instanceof PsiDiamondType) return false;
@@ -280,60 +283,56 @@ public class TypeConversionUtil {
return false;
}
}
- else {
- if (!toClass.isInterface()) {
- if (!toClass.hasModifierProperty(PsiModifier.FINAL)) {
- return checkSuperTypesWithDifferentTypeArguments(fromResult, toClass, manager, toResult.getSubstitutor(), null, languageLevel);
- }
- else {
- if (!toClass.isInheritor(fromClass, true)) return false;
- PsiSubstitutor toSubstitutor = getSuperClassSubstitutor(fromClass, toClass, toResult.getSubstitutor());
- return areSameArgumentTypes(fromClass, fromResult.getSubstitutor(), toSubstitutor);
- }
+ else if (!toClass.isInterface()) {
+ if (!toClass.hasModifierProperty(PsiModifier.FINAL)) {
+ return checkSuperTypesWithDifferentTypeArguments(fromResult, toClass, manager, toResult.getSubstitutor(), null, languageLevel);
}
else {
- if (languageLevel.compareTo(LanguageLevel.JDK_1_5) < 0) {
- //In jls2 check for method in both interfaces with the same signature but different return types.
- Collection<HierarchicalMethodSignature> fromClassMethodSignatures = fromClass.getVisibleSignatures();
- Collection<HierarchicalMethodSignature> toClassMethodSignatures = toClass.getVisibleSignatures();
-
- for (HierarchicalMethodSignature fromMethodSignature : fromClassMethodSignatures) {
- for (HierarchicalMethodSignature toMethodSignature : toClassMethodSignatures) {
- if (fromMethodSignature.equals(toMethodSignature)) {
- final PsiType fromClassReturnType = fromMethodSignature.getMethod().getReturnType();
- final PsiType toClassReturnType = toMethodSignature.getMethod().getReturnType();
- if (fromClassReturnType != null
- && toClassReturnType != null
- && !fromClassReturnType.equals(toClassReturnType)) {
- return false;
- }
- }
+ PsiSubstitutor toSubstitutor = getMaybeSuperClassSubstitutor(fromClass, toClass, toResult.getSubstitutor(), null);
+ return toSubstitutor != null && areSameArgumentTypes(fromClass, fromResult.getSubstitutor(), toSubstitutor);
+ }
+ }
+ else if (languageLevel.compareTo(LanguageLevel.JDK_1_5) < 0) {
+ //In jls2 check for method in both interfaces with the same signature but different return types.
+ Collection<HierarchicalMethodSignature> fromClassMethodSignatures = fromClass.getVisibleSignatures();
+ Collection<HierarchicalMethodSignature> toClassMethodSignatures = toClass.getVisibleSignatures();
+
+ for (HierarchicalMethodSignature fromMethodSignature : fromClassMethodSignatures) {
+ for (HierarchicalMethodSignature toMethodSignature : toClassMethodSignatures) {
+ if (fromMethodSignature.equals(toMethodSignature)) {
+ final PsiType fromClassReturnType = fromMethodSignature.getMethod().getReturnType();
+ final PsiType toClassReturnType = toMethodSignature.getMethod().getReturnType();
+ if (fromClassReturnType != null
+ && toClassReturnType != null
+ && !fromClassReturnType.equals(toClassReturnType)) {
+ return false;
}
}
- return true;
- }
- else {
- //In jls3 check for super interface with distinct type arguments
- PsiClassType.ClassResolveResult baseResult;
- PsiClass derived;
- PsiSubstitutor derivedSubstitutor;
- if (toClass.isInheritor(fromClass, true)) {
- baseResult = fromResult;
- derived = toClass;
- derivedSubstitutor = toResult.getSubstitutor();
- }
- else {
- baseResult = toResult;
- derived = fromClass;
- derivedSubstitutor = fromResult.getSubstitutor();
- }
- return checkSuperTypesWithDifferentTypeArguments(baseResult, derived, manager, derivedSubstitutor, null, languageLevel);
}
}
+ return true;
+ }
+ else {
+ //In jls3 check for super interface with distinct type arguments
+ PsiClassType.ClassResolveResult baseResult;
+ PsiClass derived;
+ PsiSubstitutor derivedSubstitutor;
+ if (toClass.isInheritor(fromClass, true)) {
+ baseResult = fromResult;
+ derived = toClass;
+ derivedSubstitutor = toResult.getSubstitutor();
+ }
+ else {
+ baseResult = toResult;
+ derived = fromClass;
+ derivedSubstitutor = fromResult.getSubstitutor();
+ }
+ return checkSuperTypesWithDifferentTypeArguments(baseResult, derived, manager, derivedSubstitutor, null, languageLevel);
}
}
- private static PsiClassType obtainSafeSuperType(final PsiTypeParameter typeParameter) {
+ @NotNull
+ private static PsiClassType obtainSafeSuperType(@NotNull PsiTypeParameter typeParameter) {
final PsiClassType superType = typeParameter.getSuperTypes()[0];
final PsiClassType.ClassResolveResult result = superType.resolveGenerics();
final PsiClass superClass = result.getElement();
@@ -344,12 +343,12 @@ public class TypeConversionUtil {
return superType;
}
- private static boolean checkSuperTypesWithDifferentTypeArguments(PsiClassType.ClassResolveResult baseResult,
- PsiClass derived,
- PsiManager manager,
- PsiSubstitutor derivedSubstitutor,
+ private static boolean checkSuperTypesWithDifferentTypeArguments(@NotNull PsiClassType.ClassResolveResult baseResult,
+ @NotNull PsiClass derived,
+ @NotNull PsiManager manager,
+ @NotNull PsiSubstitutor derivedSubstitutor,
Set<PsiClass> visited,
- final LanguageLevel languageLevel) {
+ @NotNull LanguageLevel languageLevel) {
if (visited != null && visited.contains(derived)) return true;
if (languageLevel.compareTo(LanguageLevel.JDK_1_5) < 0) return true;
@@ -359,10 +358,12 @@ public class TypeConversionUtil {
derivedSubstitutor = getSuperClassSubstitutor(derived, derived, derivedSubstitutor);
return areSameArgumentTypes(derived, baseResult.getSubstitutor(), derivedSubstitutor, 1);
}
- else if (base.isInheritor(derived, true)) {
- derivedSubstitutor = getSuperClassSubstitutor(derived, derived, derivedSubstitutor);
- PsiSubstitutor baseSubstitutor = getSuperClassSubstitutor(derived, base, baseResult.getSubstitutor());
- if (!areSameArgumentTypes(derived, baseSubstitutor, derivedSubstitutor)) return false;
+ else {
+ PsiSubstitutor baseSubstitutor = getMaybeSuperClassSubstitutor(derived, base, baseResult.getSubstitutor(), null);
+ if (baseSubstitutor != null) {
+ derivedSubstitutor = getSuperClassSubstitutor(derived, derived, derivedSubstitutor);
+ if (!areSameArgumentTypes(derived, baseSubstitutor, derivedSubstitutor)) return false;
+ }
}
if (visited == null) visited = new THashSet<PsiClass>();
@@ -375,7 +376,7 @@ public class TypeConversionUtil {
return true;
}
- private static boolean areSameParameterTypes(PsiClassType type1, PsiClassType type2) {
+ private static boolean areSameParameterTypes(@NotNull PsiClassType type1, @NotNull PsiClassType type2) {
PsiClassType.ClassResolveResult resolveResult1 = type1.resolveGenerics();
PsiClassType.ClassResolveResult resolveResult2 = type2.resolveGenerics();
final PsiClass aClass = resolveResult1.getElement();
@@ -386,13 +387,13 @@ public class TypeConversionUtil {
areSameArgumentTypes(aClass, resolveResult1.getSubstitutor(), resolveResult2.getSubstitutor());
}
- private static boolean areSameArgumentTypes(PsiClass aClass, PsiSubstitutor substitutor1, PsiSubstitutor substitutor2) {
+ private static boolean areSameArgumentTypes(@NotNull PsiClass aClass, @NotNull PsiSubstitutor substitutor1, @NotNull PsiSubstitutor substitutor2) {
return areSameArgumentTypes(aClass, substitutor1, substitutor2, 0);
}
- private static boolean areSameArgumentTypes(PsiClass aClass,
- PsiSubstitutor substitutor1,
- PsiSubstitutor substitutor2,
+ private static boolean areSameArgumentTypes(@NotNull PsiClass aClass,
+ @NotNull PsiSubstitutor substitutor1,
+ @NotNull PsiSubstitutor substitutor2,
int level) {
for (PsiTypeParameter typeParameter : PsiUtil.typeParametersIterable(aClass)) {
PsiType typeArg1 = substitutor1.substitute(typeParameter);
@@ -463,7 +464,7 @@ public class TypeConversionUtil {
* STRING_TYPE for String,
* Integer.MAX_VALUE for others
*/
- public static int getTypeRank(PsiType type) {
+ public static int getTypeRank(@NotNull PsiType type) {
PsiPrimitiveType unboxedType = PsiPrimitiveType.getUnboxedType(type);
if (unboxedType != null) {
type = unboxedType;
@@ -597,13 +598,13 @@ public class TypeConversionUtil {
return isPrimitiveAndNotNull(type);
}
- public static boolean isUnaryOperatorApplicable(PsiJavaToken token, PsiExpression operand) {
+ public static boolean isUnaryOperatorApplicable(@NotNull PsiJavaToken token, PsiExpression operand) {
if (operand == null) return false;
PsiType type = operand.getType();
return type != null && isUnaryOperatorApplicable(token, type);
}
- public static boolean isUnaryOperatorApplicable(final PsiJavaToken token, final PsiType type) {
+ public static boolean isUnaryOperatorApplicable(@NotNull PsiJavaToken token, @NotNull PsiType type) {
IElementType i = token.getTokenType();
int typeRank = getTypeRank(type);
if (i == JavaTokenType.MINUSMINUS || i == JavaTokenType.PLUSPLUS) {
@@ -672,7 +673,7 @@ public class TypeConversionUtil {
value = ((Number)rValue).longValue();
}
else if (rValue instanceof Character) {
- value = ((Character)rValue).charValue();
+ value = (Character)rValue;
}
else {
return false;
@@ -832,7 +833,7 @@ public class TypeConversionUtil {
return isClassAssignable(leftResult, rightResult, allowUncheckedConversion);
}
- private static boolean isAssignableFromWildcard(PsiType left, PsiWildcardType rightWildcardType) {
+ private static boolean isAssignableFromWildcard(@NotNull PsiType left, @NotNull PsiWildcardType rightWildcardType) {
if (rightWildcardType.isSuper()) {
final PsiClass aClass = PsiUtil.resolveClassInType(rightWildcardType.getSuperBound());
if (aClass instanceof PsiTypeParameter) {
@@ -845,14 +846,14 @@ public class TypeConversionUtil {
return isAssignable(left, rightWildcardType.getExtendsBound());
}
- private static boolean isAssignableToWildcard(PsiWildcardType wildcardType, PsiType right) {
+ private static boolean isAssignableToWildcard(@NotNull PsiWildcardType wildcardType, @NotNull PsiType right) {
if (wildcardType.isSuper()) {
return isAssignable(wildcardType.getSuperBound(), right);
}
return isAssignable(wildcardType.getExtendsBound(), right);
}
- private static boolean isUnboxable(final PsiPrimitiveType left, final PsiClassType right) {
+ private static boolean isUnboxable(@NotNull PsiPrimitiveType left, @NotNull PsiClassType right) {
final PsiPrimitiveType rightUnboxedType = PsiPrimitiveType.getUnboxedType(right);
return rightUnboxedType != null && isAssignable(left, rightUnboxedType);
}
@@ -869,7 +870,7 @@ public class TypeConversionUtil {
private static final Key<CachedValue<Set<String>>> POSSIBLE_BOXED_HOLDER_TYPES = Key.create("Types that may be possibly assigned from primitive ones");
- private static boolean isBoxable(final PsiClassType left, final PsiPrimitiveType right) {
+ private static boolean isBoxable(@NotNull PsiClassType left, @NotNull PsiPrimitiveType right) {
if (!left.getLanguageLevel().isAtLeast(LanguageLevel.JDK_1_5)) return false;
final PsiClass psiClass = left.resolve();
if (psiClass == null) return false;
@@ -883,7 +884,8 @@ public class TypeConversionUtil {
return rightBoxed != null && isAssignable(left, rightBoxed);
}
- private static Set<String> getAllBoxedTypeSupers(PsiClass psiClass) {
+ @NotNull
+ private static Set<String> getAllBoxedTypeSupers(@NotNull PsiClass psiClass) {
PsiManager manager = psiClass.getManager();
final Project project = psiClass.getProject();
CachedValue<Set<String>> boxedHolderTypes = project.getUserData(POSSIBLE_BOXED_HOLDER_TYPES);
@@ -908,12 +910,11 @@ public class TypeConversionUtil {
}, false));
}
- final Set<String> boxedHolders = boxedHolderTypes.getValue();
- return boxedHolders;
+ return boxedHolderTypes.getValue();
}
- private static boolean isClassAssignable(PsiClassType.ClassResolveResult leftResult,
- PsiClassType.ClassResolveResult rightResult,
+ private static boolean isClassAssignable(@NotNull PsiClassType.ClassResolveResult leftResult,
+ @NotNull PsiClassType.ClassResolveResult rightResult,
boolean allowUncheckedConversion) {
final PsiClass leftClass = leftResult.getElement();
final PsiClass rightClass = rightResult.getElement();
@@ -923,8 +924,8 @@ public class TypeConversionUtil {
&& typeParametersAgree(leftResult, rightResult, allowUncheckedConversion);
}
- private static boolean typeParametersAgree(PsiClassType.ClassResolveResult leftResult,
- PsiClassType.ClassResolveResult rightResult,
+ private static boolean typeParametersAgree(@NotNull PsiClassType.ClassResolveResult leftResult,
+ @NotNull PsiClassType.ClassResolveResult rightResult,
boolean allowUncheckedConversion) {
PsiSubstitutor rightSubstitutor = rightResult.getSubstitutor();
PsiClass leftClass = leftResult.getElement();
@@ -962,7 +963,7 @@ public class TypeConversionUtil {
private static final RecursionGuard ourGuard = RecursionManager.createGuard("isAssignable");
- public static boolean typesAgree(PsiType typeLeft, PsiType typeRight, final boolean allowUncheckedConversion) {
+ public static boolean typesAgree(@NotNull PsiType typeLeft, @NotNull PsiType typeRight, final boolean allowUncheckedConversion) {
if (typeLeft instanceof PsiWildcardType) {
final PsiWildcardType leftWildcard = (PsiWildcardType)typeLeft;
final PsiType leftBound = leftWildcard.getBound();
@@ -986,7 +987,7 @@ public class TypeConversionUtil {
return isAssignable(rightWildcard.getBound(), leftBound, allowUncheckedConversion);
}
});
- if (assignable != null && assignable.booleanValue()) {
+ if (assignable != null && assignable) {
return true;
}
}
@@ -1022,7 +1023,7 @@ public class TypeConversionUtil {
@Nullable
public static PsiSubstitutor getClassSubstitutor(@NotNull PsiClass superClassCandidate,
@NotNull PsiClass derivedClassCandidate,
- PsiSubstitutor derivedSubstitutor) {
+ @NotNull PsiSubstitutor derivedSubstitutor) {
if (superClassCandidate.getManager().areElementsEquivalent(superClassCandidate, derivedClassCandidate)) {
PsiTypeParameter[] baseParams = superClassCandidate.getTypeParameters();
PsiTypeParameter[] derivedParams = derivedClassCandidate.getTypeParameters();
@@ -1031,8 +1032,7 @@ public class TypeConversionUtil {
}
return derivedSubstitutor;
}
- if (!derivedClassCandidate.isInheritor(superClassCandidate, true)) return null;
- return getSuperClassSubstitutor(superClassCandidate, derivedClassCandidate, derivedSubstitutor);
+ return getMaybeSuperClassSubstitutor(superClassCandidate, derivedClassCandidate, derivedSubstitutor, null);
}
private static final Set<String> ourReportedSuperClassSubstitutorExceptions = new ConcurrentHashSet<String>();
@@ -1042,52 +1042,61 @@ public class TypeConversionUtil {
* values that they have in <code>derivedClass</code>, given that type parameters in
* <code>derivedClass</code> are bound by <code>derivedSubstitutor</code>.
* <code>superClass</code> must be a super class/interface of <code>derivedClass</code> (as in
- * <code>InheritanceUtil.isInheritor(derivedClass, superClass, true)</code>
+ * <code>InheritanceUtil.isInheritorOrSelf(derivedClass, superClass, true)</code>
*
* @return substitutor (never returns <code>null</code>)
* @see PsiClass#isInheritor(PsiClass, boolean)
+ * @see InheritanceUtil#isInheritorOrSelf(com.intellij.psi.PsiClass, com.intellij.psi.PsiClass, boolean)
*/
@NotNull
public static PsiSubstitutor getSuperClassSubstitutor(@NotNull PsiClass superClass,
@NotNull PsiClass derivedClass,
@NotNull PsiSubstitutor derivedSubstitutor) {
- // [dsl] assertion commented out since we no longer cache isInheritor
- //LOG.assertTrue(derivedClass.isInheritor(superClass, true), "Not inheritor: " + derivedClass + " super: " + superClass);
+ if (!superClass.hasTypeParameters() && superClass.getContainingClass() == null) return PsiSubstitutor.EMPTY; //optimization and protection against EJB queer hierarchy
+
+ Set<PsiClass> visited = new THashSet<PsiClass>();
+ PsiSubstitutor substitutor = getMaybeSuperClassSubstitutor(superClass, derivedClass, derivedSubstitutor, visited);
+
+ if (substitutor == null) {
+ if (ourReportedSuperClassSubstitutorExceptions.add(derivedClass.getQualifiedName() + "/" + superClass.getQualifiedName())) {
+ reportHierarchyInconsistency(superClass, derivedClass, visited);
+ }
+ return PsiSubstitutor.EMPTY;
+ }
+ return substitutor;
+ }
- if (!superClass.hasTypeParameters() && superClass.getContainingClass() == null) return PsiSubstitutor.EMPTY; //optimization
+ // the same as getSuperClassSubstitutor() but can return null, which means that classes were not inheritors
+ @Nullable
+ public static PsiSubstitutor getMaybeSuperClassSubstitutor(@NotNull PsiClass superClass,
+ @NotNull PsiClass derivedClass,
+ @NotNull PsiSubstitutor derivedSubstitutor,
+ @Nullable Set<PsiClass> visited) {
+ if (!superClass.hasTypeParameters() && superClass.getContainingClass() == null) {
+ return InheritanceUtil.isInheritorOrSelf(derivedClass, superClass, true) ? PsiSubstitutor.EMPTY : null; //optimization
+ }
final PsiManager manager = superClass.getManager();
if (PsiUtil.isRawSubstitutor(derivedClass, derivedSubstitutor)) {
- return JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createRawSubstitutor(superClass);
+ return InheritanceUtil.isInheritorOrSelf(derivedClass, superClass, true) ? JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createRawSubstitutor(superClass) : null;
}
- final PsiClass objectClass = JavaPsiFacade.getInstance(manager.getProject()).findClass(CommonClassNames.JAVA_LANG_OBJECT, superClass.getResolveScope());
- if (manager.areElementsEquivalent(superClass, objectClass)) {
+ if (CommonClassNames.JAVA_LANG_OBJECT_SHORT.equals(superClass.getName()) &&
+ manager.areElementsEquivalent(superClass, JavaPsiFacade.getInstance(manager.getProject()).findClass(CommonClassNames.JAVA_LANG_OBJECT, superClass.getResolveScope()))) {
return PsiSubstitutor.EMPTY;
}
- PsiSubstitutor substitutor;
- final Set<PsiClass> visited = new THashSet<PsiClass>();
if (derivedClass instanceof PsiAnonymousClass) {
final PsiClassType baseType = ((PsiAnonymousClass)derivedClass).getBaseClassType();
final JavaResolveResult result = baseType.resolveGenerics();
if (result.getElement() == null) return PsiSubstitutor.UNKNOWN;
- substitutor = getSuperClassSubstitutorInner(superClass, (PsiClass)result.getElement(),
- derivedSubstitutor.putAll(result.getSubstitutor()), visited, manager);
- }
- else {
- substitutor = getSuperClassSubstitutorInner(superClass, derivedClass, derivedSubstitutor, visited, manager);
+ derivedClass = (PsiClass)result.getElement();
+ derivedSubstitutor = derivedSubstitutor.putAll(result.getSubstitutor());
}
- if (substitutor == null) {
- if (ourReportedSuperClassSubstitutorExceptions.add(derivedClass.getQualifiedName() + "/" + superClass.getQualifiedName())) {
- reportHierarchyInconsistency(superClass, derivedClass, visited);
- }
- return PsiSubstitutor.EMPTY;
- }
- return substitutor;
+ return getSuperClassSubstitutorInner(superClass, derivedClass, derivedSubstitutor, visited == null ? new THashSet<PsiClass>() : visited, manager);
}
- private static void reportHierarchyInconsistency(PsiClass superClass, PsiClass derivedClass, Set<PsiClass> visited) {
+ private static void reportHierarchyInconsistency(@NotNull PsiClass superClass, @NotNull PsiClass derivedClass, @NotNull Set<PsiClass> visited) {
final StringBuilder msg = new StringBuilder("Super: " + classInfo(superClass));
msg.append("visited:\n");
for (PsiClass aClass : visited) {
@@ -1105,7 +1114,8 @@ public class TypeConversionUtil {
LOG.error(msg.toString());
}
- private static String classInfo(PsiClass aClass) {
+ @NotNull
+ private static String classInfo(@NotNull PsiClass aClass) {
String s = aClass.getQualifiedName() + "(" + aClass.getClass().getName() + "; " + PsiUtilCore.getVirtualFile(aClass) + ");\n";
s += "extends: ";
for (PsiClassType type : aClass.getExtendsListTypes()) {
@@ -1124,12 +1134,14 @@ public class TypeConversionUtil {
return getSuperClassSubstitutor(superClass, classResolveResult.getElement(), classResolveResult.getSubstitutor());
}
- private static PsiSubstitutor getSuperClassSubstitutorInner(PsiClass base,
- PsiClass candidate,
- PsiSubstitutor candidateSubstitutor,
- Set<PsiClass> visited,
- PsiManager manager) {
+ @Nullable
+ private static PsiSubstitutor getSuperClassSubstitutorInner(@NotNull PsiClass base,
+ @NotNull PsiClass candidate,
+ @NotNull PsiSubstitutor candidateSubstitutor,
+ @NotNull Set<PsiClass> visited,
+ @NotNull PsiManager manager) {
if (!visited.add(candidate)) return null;
+ assert candidateSubstitutor.isValid();
if (base == candidate) return candidateSubstitutor;
if (manager.areElementsEquivalent(base, candidate)) {
@@ -1148,19 +1160,18 @@ public class TypeConversionUtil {
}
}
- PsiSubstitutor substitutor = checkReferenceList(candidate.getExtendsListTypes(), candidateSubstitutor, base, visited,
- manager);
+ PsiSubstitutor substitutor = checkReferenceList(candidate.getExtendsListTypes(), candidateSubstitutor, base, visited, manager);
if (substitutor == null) {
substitutor = checkReferenceList(candidate.getImplementsListTypes(), candidateSubstitutor, base, visited, manager);
}
return substitutor;
}
- private static PsiSubstitutor checkReferenceList(final PsiClassType[] types, PsiSubstitutor candidateSubstitutor,
- PsiClass base,
- Set<PsiClass> set,
- PsiManager manager) {
- assert candidateSubstitutor.isValid();
+ private static PsiSubstitutor checkReferenceList(@NotNull PsiClassType[] types,
+ @NotNull PsiSubstitutor candidateSubstitutor,
+ @NotNull PsiClass base,
+ @NotNull Set<PsiClass> set,
+ @NotNull PsiManager manager) {
for (final PsiClassType type : types) {
final PsiType substitutedType = candidateSubstitutor.substitute(type);
//if (!(substitutedType instanceof PsiClassType)) return null;
@@ -1170,8 +1181,7 @@ public class TypeConversionUtil {
final PsiElement newCandidate = result.getElement();
if (newCandidate != null) {
final PsiSubstitutor substitutor = result.getSubstitutor();
- final PsiSubstitutor newSubstitutor = getSuperClassSubstitutorInner(base, (PsiClass)newCandidate,
- substitutor, set, manager);
+ final PsiSubstitutor newSubstitutor = getSuperClassSubstitutorInner(base, (PsiClass)newCandidate, substitutor, set, manager);
if (newSubstitutor != null) {
return type.isRaw() ? JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createRawSubstitutor(base) : newSubstitutor;
}
@@ -1183,6 +1193,7 @@ public class TypeConversionUtil {
/**
* see JLS 5.6.2
*/
+ @NotNull
public static PsiType binaryNumericPromotion(PsiType type1, PsiType type2) {
if (isDoubleType(type1)) return unbox(type1);
if (isDoubleType(type2)) return unbox(type2);
@@ -1194,7 +1205,8 @@ public class TypeConversionUtil {
return PsiType.INT;
}
- private static PsiType unbox(PsiType type) {
+ @NotNull
+ private static PsiType unbox(@NotNull PsiType type) {
if (type instanceof PsiPrimitiveType) return type;
if (type instanceof PsiClassType) {
type = PsiPrimitiveType.getUnboxedType(type);
@@ -1393,6 +1405,7 @@ public class TypeConversionUtil {
return value;
}
+ @NotNull
public static PsiType unboxAndBalanceTypes(PsiType type1, PsiType type2) {
if (type1 instanceof PsiClassType) type1 = PsiPrimitiveType.getUnboxedType(type1);
if (type2 instanceof PsiClassType) type2 = PsiPrimitiveType.getUnboxedType(type2);
@@ -1442,7 +1455,7 @@ public class TypeConversionUtil {
}
@Nullable
- public static PsiType calcTypeForBinaryExpression(PsiType lType, PsiType rType, IElementType sign, boolean accessLType) {
+ public static PsiType calcTypeForBinaryExpression(PsiType lType, PsiType rType, @NotNull IElementType sign, boolean accessLType) {
if (sign == JavaTokenType.PLUS) {
// evaluate right argument first, since '+-/*%' is left associative and left operand tends to be bigger
if (rType == null) return null;
@@ -1512,321 +1525,371 @@ public class TypeConversionUtil {
}
private interface Caster {
- Object cast(Object operand);
+ @NotNull
+ Object cast(@NotNull Object operand);
}
private static final Caster[][] caster = {
{
new Caster() {
+ @NotNull
@Override
- public Object cast(Object operand) {
+ public Object cast(@NotNull Object operand) {
return operand;
}
}
, new Caster() {
+ @NotNull
@Override
- public Object cast(Object operand) {
- return Short.valueOf((short)((Number)operand).intValue());
+ public Object cast(@NotNull Object operand) {
+ return (short)((Number)operand).intValue();
}
}
, new Caster() {
+ @NotNull
@Override
- public Object cast(Object operand) {
- return new Character((char) ((Number) operand).intValue());
+ public Object cast(@NotNull Object operand) {
+ return (char)((Number)operand).intValue();
}
}
, new Caster() {
+ @NotNull
@Override
- public Object cast(Object operand) {
- return Integer.valueOf(((Number)operand).intValue());
+ public Object cast(@NotNull Object operand) {
+ return ((Number)operand).intValue();
}
}
, new Caster() {
+ @NotNull
@Override
- public Object cast(Object operand) {
- return Long.valueOf(((Number)operand).intValue());
+ public Object cast(@NotNull Object operand) {
+ return (long)((Number)operand).intValue();
}
}
, new Caster() {
+ @NotNull
@Override
- public Object cast(Object operand) {
- return new Float(((Number) operand).intValue());
+ public Object cast(@NotNull Object operand) {
+ return (float)((Number)operand).intValue();
}
}
, new Caster() {
+ @NotNull
@Override
- public Object cast(Object operand) {
- return new Double(((Number) operand).intValue());
+ public Object cast(@NotNull Object operand) {
+ return (double)((Number)operand).intValue();
}
}
}
,
{
new Caster() {
+ @NotNull
@Override
- public Object cast(Object operand) {
- return Byte.valueOf((byte)((Short)operand).shortValue());
+ public Object cast(@NotNull Object operand) {
+ return (byte)((Short)operand).shortValue();
}
}
, new Caster() {
+ @NotNull
@Override
- public Object cast(Object operand) {
- return Short.valueOf(((Short)operand).shortValue());
+ public Object cast(@NotNull Object operand) {
+ return operand;
}
}
, new Caster() {
+ @NotNull
@Override
- public Object cast(Object operand) {
- return new Character((char) ((Short) operand).shortValue());
+ public Object cast(@NotNull Object operand) {
+ return (char)((Short)operand).shortValue();
}
}
, new Caster() {
+ @NotNull
@Override
- public Object cast(Object operand) {
- return Integer.valueOf(((Short)operand).shortValue());
+ public Object cast(@NotNull Object operand) {
+ return (int)(Short)operand;
}
}
, new Caster() {
+ @NotNull
@Override
- public Object cast(Object operand) {
- return Long.valueOf(((Short)operand).shortValue());
+ public Object cast(@NotNull Object operand) {
+ return (long)(Short)operand;
}
}
, new Caster() {
+ @NotNull
@Override
- public Object cast(Object operand) {
- return new Float(((Short) operand).shortValue());
+ public Object cast(@NotNull Object operand) {
+ return (float)(Short)operand;
}
}
, new Caster() {
+ @NotNull
@Override
- public Object cast(Object operand) {
- return new Double(((Short) operand).shortValue());
+ public Object cast(@NotNull Object operand) {
+ return (double)(Short)operand;
}
}
}
,
{
new Caster() {
+ @NotNull
@Override
- public Object cast(Object operand) {
- return Byte.valueOf((byte)((Character)operand).charValue());
+ public Object cast(@NotNull Object operand) {
+ return (byte)((Character)operand).charValue();
}
}
, new Caster() {
+ @NotNull
@Override
- public Object cast(Object operand) {
- return Short.valueOf((short)((Character)operand).charValue());
+ public Object cast(@NotNull Object operand) {
+ return (short)((Character)operand).charValue();
}
}
, new Caster() {
+ @NotNull
@Override
- public Object cast(Object operand) {
- return new Character(((Character) operand).charValue());
+ public Object cast(@NotNull Object operand) {
+ return operand;
}
}
, new Caster() {
+ @NotNull
@Override
- public Object cast(Object operand) {
- return Integer.valueOf(((Character)operand).charValue());
+ public Object cast(@NotNull Object operand) {
+ return (int)(Character)operand;
}
}
, new Caster() {
+ @NotNull
@Override
- public Object cast(Object operand) {
- return Long.valueOf(((Character)operand).charValue());
+ public Object cast(@NotNull Object operand) {
+ return (long)(Character)operand;
}
}
, new Caster() {
+ @NotNull
@Override
- public Object cast(Object operand) {
- return new Float(((Character) operand).charValue());
+ public Object cast(@NotNull Object operand) {
+ return (float)(Character)operand;
}
}
, new Caster() {
+ @NotNull
@Override
- public Object cast(Object operand) {
- return new Double(((Character) operand).charValue());
+ public Object cast(@NotNull Object operand) {
+ return (double)(Character)operand;
}
}
}
,
{
new Caster() {
+ @NotNull
@Override
- public Object cast(Object operand) {
- return Byte.valueOf((byte)((Integer)operand).intValue());
+ public Object cast(@NotNull Object operand) {
+ return (byte)((Integer)operand).intValue();
}
}
, new Caster() {
+ @NotNull
@Override
- public Object cast(Object operand) {
- return Short.valueOf((short)((Integer)operand).intValue());
+ public Object cast(@NotNull Object operand) {
+ return (short)((Integer)operand).intValue();
}
}
, new Caster() {
+ @NotNull
@Override
- public Object cast(Object operand) {
- return new Character((char) ((Integer) operand).intValue());
+ public Object cast(@NotNull Object operand) {
+ return (char)((Integer)operand).intValue();
}
}
, new Caster() {
+ @NotNull
@Override
- public Object cast(Object operand) {
- return Integer.valueOf(((Integer)operand).intValue());
+ public Object cast(@NotNull Object operand) {
+ return operand;
}
}
, new Caster() {
+ @NotNull
@Override
- public Object cast(Object operand) {
- return Long.valueOf(((Integer)operand).intValue());
+ public Object cast(@NotNull Object operand) {
+ return (long)(Integer)operand;
}
}
, new Caster() {
+ @NotNull
@Override
- public Object cast(Object operand) {
- return new Float(((Integer) operand).intValue());
+ public Object cast(@NotNull Object operand) {
+ return (float)(Integer)operand;
}
}
, new Caster() {
+ @NotNull
@Override
- public Object cast(Object operand) {
- return new Double(((Integer) operand).intValue());
+ public Object cast(@NotNull Object operand) {
+ return (double)(Integer)operand;
}
}
}
,
{
new Caster() {
+ @NotNull
@Override
- public Object cast(Object operand) {
- return Byte.valueOf((byte)((Long)operand).longValue());
+ public Object cast(@NotNull Object operand) {
+ return (byte)((Long)operand).longValue();
}
}
, new Caster() {
+ @NotNull
@Override
- public Object cast(Object operand) {
- return Short.valueOf((short)((Long)operand).longValue());
+ public Object cast(@NotNull Object operand) {
+ return (short)((Long)operand).longValue();
}
}
, new Caster() {
+ @NotNull
@Override
- public Object cast(Object operand) {
- return new Character((char) ((Long) operand).longValue());
+ public Object cast(@NotNull Object operand) {
+ return (char)((Long)operand).longValue();
}
}
, new Caster() {
+ @NotNull
@Override
- public Object cast(Object operand) {
- return Integer.valueOf((int)((Long)operand).longValue());
+ public Object cast(@NotNull Object operand) {
+ return (int)((Long)operand).longValue();
}
}
, new Caster() {
+ @NotNull
@Override
- public Object cast(Object operand) {
- return Long.valueOf(((Long)operand).longValue());
+ public Object cast(@NotNull Object operand) {
+ return operand;
}
}
, new Caster() {
+ @NotNull
@Override
- public Object cast(Object operand) {
- return new Float(((Long) operand).longValue());
+ public Object cast(@NotNull Object operand) {
+ return (float)(Long)operand;
}
}
, new Caster() {
+ @NotNull
@Override
- public Object cast(Object operand) {
- return new Double(((Long) operand).longValue());
+ public Object cast(@NotNull Object operand) {
+ return (double)(Long)operand;
}
}
}
,
{
new Caster() {
+ @NotNull
@Override
- public Object cast(Object operand) {
- return Byte.valueOf((byte)((Float)operand).floatValue());
+ public Object cast(@NotNull Object operand) {
+ return (byte)((Float)operand).floatValue();
}
}
, new Caster() {
+ @NotNull
@Override
- public Object cast(Object operand) {
- return Short.valueOf((short)((Float)operand).floatValue());
+ public Object cast(@NotNull Object operand) {
+ return (short)((Float)operand).floatValue();
}
}
, new Caster() {
+ @NotNull
@Override
- public Object cast(Object operand) {
- return new Character((char) ((Float) operand).floatValue());
+ public Object cast(@NotNull Object operand) {
+ return (char)((Float)operand).floatValue();
}
}
, new Caster() {
+ @NotNull
@Override
- public Object cast(Object operand) {
- return Integer.valueOf((int)((Float)operand).floatValue());
+ public Object cast(@NotNull Object operand) {
+ return (int)((Float)operand).floatValue();
}
}
, new Caster() {
+ @NotNull
@Override
- public Object cast(Object operand) {
- return Long.valueOf((long)((Float)operand).floatValue());
+ public Object cast(@NotNull Object operand) {
+ return (long)((Float)operand).floatValue();
}
}
, new Caster() {
+ @NotNull
@Override
- public Object cast(Object operand) {
- return new Float(((Float) operand).floatValue());
+ public Object cast(@NotNull Object operand) {
+ return operand;
}
}
, new Caster() {
+ @NotNull
@Override
- public Object cast(Object operand) {
- return new Double(((Float) operand).floatValue());
+ public Object cast(@NotNull Object operand) {
+ return (double)(Float)operand;
}
}
}
,
{
new Caster() {
+ @NotNull
@Override
- public Object cast(Object operand) {
- return Byte.valueOf((byte)((Double)operand).doubleValue());
+ public Object cast(@NotNull Object operand) {
+ return (byte)((Double)operand).doubleValue();
}
}
, new Caster() {
+ @NotNull
@Override
- public Object cast(Object operand) {
- return Short.valueOf((short)((Double)operand).doubleValue());
+ public Object cast(@NotNull Object operand) {
+ return (short)((Double)operand).doubleValue();
}
}
, new Caster() {
+ @NotNull
@Override
- public Object cast(Object operand) {
- return new Character((char) ((Double) operand).doubleValue());
+ public Object cast(@NotNull Object operand) {
+ return (char)((Double)operand).doubleValue();
}
}
, new Caster() {
+ @NotNull
@Override
- public Object cast(Object operand) {
- return Integer.valueOf((int)((Double)operand).doubleValue());
+ public Object cast(@NotNull Object operand) {
+ return (int)((Double)operand).doubleValue();
}
}
, new Caster() {
+ @NotNull
@Override
- public Object cast(Object operand) {
- return Long.valueOf((long)((Double)operand).doubleValue());
+ public Object cast(@NotNull Object operand) {
+ return (long)((Double)operand).doubleValue();
}
}
, new Caster() {
+ @NotNull
@Override
- public Object cast(Object operand) {
- return new Float(((Double) operand).doubleValue());
+ public Object cast(@NotNull Object operand) {
+ return new Float((Double)operand);
}
}
, new Caster() {
+ @NotNull
@Override
- public Object cast(Object operand) {
- return new Double(((Double) operand).doubleValue());
+ public Object cast(@NotNull Object operand) {
+ return operand;
}
}
}
@@ -1844,7 +1907,7 @@ public class TypeConversionUtil {
WRAPPER_TO_PRIMITIVE.put(Double.class, PsiType.DOUBLE);
}
- private static PsiType wrapperToPrimitive(Object o) {
+ private static PsiType wrapperToPrimitive(@NotNull Object o) {
return WRAPPER_TO_PRIMITIVE.get(o.getClass());
}
diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/CustomExceptionHandler.java b/java/java-psi-impl/src/com/intellij/codeInsight/CustomExceptionHandler.java
new file mode 100644
index 000000000000..7678390d0356
--- /dev/null
+++ b/java/java-psi-impl/src/com/intellij/codeInsight/CustomExceptionHandler.java
@@ -0,0 +1,13 @@
+package com.intellij.codeInsight;
+
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.psi.PsiClassType;
+import com.intellij.psi.PsiElement;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public abstract class CustomExceptionHandler {
+ public static final ExtensionPointName<CustomExceptionHandler> KEY = ExtensionPointName.create("com.intellij.custom.exception.handler");
+
+ public abstract boolean isHandled(@Nullable PsiElement element, @NotNull PsiClassType exceptionType, PsiElement topElement);
+}
diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/ExceptionUtil.java b/java/java-psi-impl/src/com/intellij/codeInsight/ExceptionUtil.java
index 552c7e2d9ff5..bb4e322a2eec 100644
--- a/java/java-psi-impl/src/com/intellij/codeInsight/ExceptionUtil.java
+++ b/java/java-psi-impl/src/com/intellij/codeInsight/ExceptionUtil.java
@@ -15,6 +15,7 @@
*/
package com.intellij.codeInsight;
+import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.*;
import com.intellij.psi.controlFlow.*;
@@ -675,6 +676,10 @@ public class ExceptionUtil {
// exceptions thrown in field initializers should be thrown in all class constructors
return areAllConstructorsThrow(aClass, exceptionType);
}
+ } else {
+ for (CustomExceptionHandler exceptionHandler : Extensions.getExtensions(CustomExceptionHandler.KEY)) {
+ if (exceptionHandler.isHandled(element, exceptionType, topElement)) return true;
+ }
}
return isHandled(parent, exceptionType, topElement);
}
diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilderBase.java b/java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilderBase.java
index 5e008afb4797..e2de5a55e0b3 100644
--- a/java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilderBase.java
+++ b/java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilderBase.java
@@ -598,9 +598,15 @@ public abstract class JavaFoldingBuilderBase extends CustomFoldingBuilder implem
Document document = method.getContainingFile().getViewProvider().getDocument();
PsiCodeBlock body = method.getBody();
- if (body == null || document == null) {
+ PsiIdentifier nameIdentifier = method.getNameIdentifier();
+ if (body == null || document == null || nameIdentifier == null) {
return false;
}
+ if (document.getLineNumber(nameIdentifier.getTextRange().getStartOffset()) !=
+ document.getLineNumber(method.getParameterList().getTextRange().getEndOffset())) {
+ return false;
+ }
+
PsiJavaToken lBrace = body.getLBrace();
PsiJavaToken rBrace = body.getRBrace();
PsiStatement[] statements = body.getStatements();
diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/ParameterNameFoldingManager.java b/java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/ParameterNameFoldingManager.java
index aca4357f7e49..a8b2b40111ba 100644
--- a/java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/ParameterNameFoldingManager.java
+++ b/java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/ParameterNameFoldingManager.java
@@ -39,7 +39,8 @@ public class ParameterNameFoldingManager {
Couple.of("first", "last"),
Couple.of("first", "second"),
Couple.of("from", "to"),
- Couple.of("key", "value")
+ Couple.of("key", "value"),
+ Couple.of("min", "max")
);
private final PsiCallExpression myCallExpression;
@@ -58,7 +59,8 @@ public class ParameterNameFoldingManager {
if (callArgument instanceof PsiPrefixExpression) {
PsiPrefixExpression expr = (PsiPrefixExpression)callArgument;
IElementType tokenType = expr.getOperationTokenType();
- return JavaTokenType.MINUS.equals(tokenType) && expr.getOperand() instanceof PsiLiteralExpression;
+ return (JavaTokenType.MINUS.equals(tokenType)
+ || JavaTokenType.PLUS.equals(tokenType)) && expr.getOperand() instanceof PsiLiteralExpression;
}
return false;
diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/ColorUtil.java b/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/ColorUtil.java
index f7094421b980..ac2fe33d0e43 100644
--- a/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/ColorUtil.java
+++ b/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/ColorUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,10 +17,10 @@ package com.intellij.codeInsight.javadoc;
import com.intellij.psi.*;
import com.intellij.util.ArrayUtil;
+import com.intellij.util.ReflectionUtil;
import org.jetbrains.annotations.NotNull;
import java.awt.*;
-import java.lang.reflect.Field;
/**
* @author spleaner
@@ -98,14 +98,12 @@ public class ColorUtil {
if (reference != null) {
final PsiElement psiElement = reference.resolve();
if (psiElement instanceof PsiField) {
- final PsiClass psiClass = ((PsiField) psiElement).getContainingClass();
+ PsiField psiField = (PsiField)psiElement;
+ final PsiClass psiClass = psiField.getContainingClass();
if (psiClass != null && "java.awt.Color".equals(psiClass.getQualifiedName())) {
- try {
- Field field = Class.forName("java.awt.Color").getField(((PsiField)psiElement).getName());
- final Color c = (Color) field.get(null);
+ Color c = ReflectionUtil.getField(Color.class, null, Color.class, psiField.getName());
+ if (c != null) {
buffer.append(generatePreviewHtml(c));
- } catch (Exception e) {
- // nothing
}
}
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/PsiDiamondTypeImpl.java b/java/java-psi-impl/src/com/intellij/psi/PsiDiamondTypeImpl.java
index e1116894f14f..5f3eee5c6be3 100644
--- a/java/java-psi-impl/src/com/intellij/psi/PsiDiamondTypeImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/PsiDiamondTypeImpl.java
@@ -34,6 +34,7 @@ import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.Function;
import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.VisibilityUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -253,8 +254,9 @@ public class PsiDiamondTypeImpl extends PsiDiamondType {
PsiTypeParameter[] params,
PsiJavaCodeReferenceElement reference) {
final StringBuilder buf = new StringBuilder();
- buf.append(constructor != null ? constructor.getModifierList().getText() : containingClass.getModifierList().getText());
- if (buf.length() > 0) {
+ final String modifier = VisibilityUtil.getVisibilityModifier(constructor != null ? constructor.getModifierList() : containingClass.getModifierList());
+ if (!PsiModifier.PACKAGE_LOCAL.equals(modifier)) {
+ buf.append(modifier);
buf.append(" ");
}
buf.append("static ");
@@ -262,8 +264,20 @@ public class PsiDiamondTypeImpl extends PsiDiamondType {
buf.append(StringUtil.join(params, new Function<PsiTypeParameter, String>() {
@Override
public String fun(PsiTypeParameter psiTypeParameter) {
- final String extendsList = psiTypeParameter.getLanguage().isKindOf(JavaLanguage.INSTANCE) ? psiTypeParameter.getExtendsList().getText() : null;
- return psiTypeParameter.getName() + (StringUtil.isEmpty(extendsList) ? "" : " " + extendsList);
+ String extendsList = "";
+ if (psiTypeParameter.getLanguage().isKindOf(JavaLanguage.INSTANCE)) {
+ final PsiClassType[] extendsListTypes = psiTypeParameter.getExtendsListTypes();
+ if (extendsListTypes.length > 0) {
+ final Function<PsiClassType, String> canonicalTypePresentationFun = new Function<PsiClassType, String>() {
+ @Override
+ public String fun(PsiClassType type) {
+ return type.getCanonicalText();
+ }
+ };
+ extendsList = " extends " + StringUtil.join(extendsListTypes, canonicalTypePresentationFun, "&");
+ }
+ }
+ return psiTypeParameter.getName() + extendsList;
}
}, ", "));
buf.append(">");
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/InheritanceImplUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/InheritanceImplUtil.java
index f958555a3c45..9427551aacf8 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/InheritanceImplUtil.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/InheritanceImplUtil.java
@@ -25,9 +25,7 @@ import com.intellij.psi.util.CachedValuesManager;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiModificationTracker;
import com.intellij.util.containers.ConcurrentWeakHashMap;
-import com.intellij.util.containers.HashSet;
import gnu.trove.THashSet;
-import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -39,10 +37,12 @@ public class InheritanceImplUtil {
public static boolean isInheritor(@NotNull final PsiClass candidateClass, @NotNull PsiClass baseClass, final boolean checkDeep) {
if (baseClass instanceof PsiAnonymousClass) return false;
- if (!checkDeep) return isInheritor(candidateClass, baseClass, false, null);
+ if (!checkDeep) {
+ return isInheritor(candidateClass.getManager(), candidateClass, baseClass, false, null);
+ }
- if (CommonClassNames.JAVA_LANG_OBJECT_SHORT.equals(candidateClass.getName()) && CommonClassNames.JAVA_LANG_OBJECT.equals(candidateClass.getQualifiedName())) return false;
- if (CommonClassNames.JAVA_LANG_OBJECT_SHORT.equals(baseClass.getName()) && CommonClassNames.JAVA_LANG_OBJECT.equals(baseClass.getQualifiedName())) return true;
+ if (hasObjectQualifiedName(candidateClass)) return false;
+ if (hasObjectQualifiedName(baseClass)) return true;
Map<PsiClass, Boolean> map = CachedValuesManager.
getCachedValue(candidateClass, new CachedValueProvider<Map<PsiClass, Boolean>>() {
@Nullable
@@ -55,18 +55,29 @@ public class InheritanceImplUtil {
Boolean computed = map.get(baseClass);
if (computed == null) {
- computed = isInheritor(candidateClass, baseClass, true, null);
+ computed = isInheritor(candidateClass.getManager(), candidateClass, baseClass, true, null);
map.put(baseClass, computed);
}
return computed;
}
- private static boolean isInheritor(@NotNull PsiClass candidateClass, @NotNull PsiClass baseClass, boolean checkDeep, Set<PsiClass> checkedClasses) {
+ public static boolean hasObjectQualifiedName(@NotNull PsiClass candidateClass) {
+ if (!CommonClassNames.JAVA_LANG_OBJECT_SHORT.equals(candidateClass.getName())) {
+ return false;
+ }
+ PsiElement parent = candidateClass.getParent();
+ return parent instanceof PsiJavaFile && CommonClassNames.DEFAULT_PACKAGE.equals(((PsiJavaFile)parent).getPackageName());
+ }
+
+ private static boolean isInheritor(@NotNull PsiManager manager,
+ @NotNull PsiClass candidateClass,
+ @NotNull PsiClass baseClass,
+ boolean checkDeep,
+ @Nullable Set<PsiClass> checkedClasses) {
if (candidateClass instanceof PsiAnonymousClass) {
final PsiClass baseCandidateClass = ((PsiAnonymousClass)candidateClass).getBaseClassType().resolve();
return baseCandidateClass != null && InheritanceUtil.isInheritorOrSelf(baseCandidateClass, baseClass, checkDeep);
}
- PsiManager manager = candidateClass.getManager();
/* //TODO fix classhashprovider so it doesn't use class qnames only
final ClassHashProvider provider = getHashProvider((PsiManagerImpl) manager);
if (checkDeep && provider != null) {
@@ -81,8 +92,7 @@ public class InheritanceImplUtil {
LOG.debug("Using uncached version for " + candidateClass.getQualifiedName() + " and " + baseClass);
}
- @NonNls final String baseName = baseClass.getName();
- if (CommonClassNames.JAVA_LANG_OBJECT_SHORT.equals(baseName)) {
+ if (hasObjectQualifiedName(baseClass)) {
PsiClass objectClass = JavaPsiFacade.getInstance(manager.getProject()).findClass(CommonClassNames.JAVA_LANG_OBJECT, candidateClass.getResolveScope());
if (manager.areElementsEquivalent(baseClass, objectClass)) {
if (manager.areElementsEquivalent(candidateClass, objectClass)) return false;
@@ -103,6 +113,7 @@ public class InheritanceImplUtil {
if (cInt == bInt && checkReferenceListWithQualifiedNames(baseQName, candidateClass.getExtendsList(), manager, scope)) return true;
return bInt && !cInt && checkReferenceListWithQualifiedNames(baseQName, candidateClass.getImplementsList(), manager, scope);
}
+ String baseName = baseClass.getName();
if (cInt == bInt) {
for (PsiClassType type : candidateClass.getExtendsListTypes()) {
if (Comparing.equal(type.getClassName(), baseName)) {
@@ -125,7 +136,7 @@ public class InheritanceImplUtil {
return false;
}
- return isInheritorWithoutCaching(candidateClass, baseClass, checkDeep, checkedClasses);
+ return isInheritorWithoutCaching(manager, candidateClass, baseClass, checkedClasses);
}
private static boolean checkReferenceListWithQualifiedNames(final String baseQName, final PsiReferenceList extList, final PsiManager manager,
@@ -141,63 +152,50 @@ public class InheritanceImplUtil {
return false;
}
- private static boolean isInheritorWithoutCaching(PsiClass aClass, PsiClass baseClass, boolean checkDeep, Set<PsiClass> checkedClasses) {
- PsiManager manager = aClass.getManager();
+ private static boolean isInheritorWithoutCaching(@NotNull PsiManager manager,
+ @NotNull PsiClass aClass,
+ @NotNull PsiClass baseClass,
+ @Nullable Set<PsiClass> checkedClasses) {
if (manager.areElementsEquivalent(aClass, baseClass)) return false;
if (aClass.isInterface() && !baseClass.isInterface()) {
return false;
}
- //if (PsiUtil.hasModifierProperty(baseClass, PsiModifier.FINAL)) {
- // return false;
- //}
-
- if (checkDeep) {
- if (checkedClasses == null) {
- checkedClasses = new THashSet<PsiClass>();
- }
- checkedClasses.add(aClass);
+ if (checkedClasses == null) {
+ checkedClasses = new THashSet<PsiClass>();
}
+ checkedClasses.add(aClass);
- if (!aClass.isInterface() && baseClass.isInterface()) {
- if (checkDeep && checkInheritor(aClass.getSuperClass(), baseClass, checkDeep, checkedClasses)) {
- return true;
- }
- return checkInheritor(aClass.getInterfaces(), baseClass, checkDeep, checkedClasses);
-
- }
- else {
- return checkInheritor(aClass.getSupers(), baseClass, checkDeep, checkedClasses);
- }
+ return checkInheritor(manager, aClass.getExtendsListTypes(), baseClass, checkedClasses) ||
+ checkInheritor(manager, aClass.getImplementsListTypes(), baseClass, checkedClasses);
}
- private static boolean checkInheritor(PsiClass[] supers, PsiClass baseClass, boolean checkDeep, Set<PsiClass> checkedClasses) {
- for (PsiClass aSuper : supers) {
- if (checkInheritor(aSuper, baseClass, checkDeep, checkedClasses)) {
+ private static boolean checkInheritor(@NotNull PsiManager manager,
+ @NotNull PsiClassType[] supers,
+ @NotNull PsiClass baseClass,
+ @NotNull Set<PsiClass> checkedClasses) {
+ for (PsiClassType aSuper : supers) {
+ PsiClass aClass = aSuper.resolve();
+ if (aClass != null && checkInheritor(manager, aClass, baseClass, checkedClasses)) {
return true;
}
}
return false;
}
- private static boolean checkInheritor(PsiClass aClass, PsiClass baseClass, boolean checkDeep, Set<PsiClass> checkedClasses) {
+ private static boolean checkInheritor(@NotNull PsiManager manager,
+ @NotNull PsiClass aClass,
+ @NotNull PsiClass baseClass,
+ @NotNull Set<PsiClass> checkedClasses) {
ProgressIndicatorProvider.checkCanceled();
- if (aClass != null) {
- PsiManager manager = baseClass.getManager();
- if (manager.areElementsEquivalent(baseClass, aClass)) {
- return true;
- }
- if (checkedClasses != null && checkedClasses.contains(aClass)) { // to prevent infinite recursion
- return false;
- }
- if (checkDeep) {
- if (isInheritor(aClass, baseClass, checkDeep, checkedClasses)) {
- return true;
- }
- }
+ if (manager.areElementsEquivalent(baseClass, aClass)) {
+ return true;
}
- return false;
+ if (checkedClasses.contains(aClass)) { // to prevent infinite recursion
+ return false;
+ }
+ return isInheritor(manager, aClass, baseClass, true, checkedClasses);
}
public static boolean isInheritorDeep(@NotNull PsiClass candidateClass, @NotNull PsiClass baseClass, @Nullable final PsiClass classToByPass) {
@@ -207,9 +205,9 @@ public class InheritanceImplUtil {
Set<PsiClass> checkedClasses = null;
if (classToByPass != null) {
- checkedClasses = new HashSet<PsiClass>();
+ checkedClasses = new THashSet<PsiClass>();
checkedClasses.add(classToByPass);
}
- return isInheritor(candidateClass, baseClass, true, checkedClasses);
+ return isInheritor(candidateClass.getManager(), candidateClass, baseClass, true, checkedClasses);
}
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java
index 514087492300..938b40f51bb8 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java
@@ -15,6 +15,7 @@
*/
package com.intellij.psi.impl;
+import com.intellij.codeInsight.AnnotationTargetUtil;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
@@ -51,7 +52,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
-import java.util.Collections;
import java.util.List;
import java.util.Set;
@@ -60,22 +60,6 @@ import static com.intellij.psi.PsiAnnotation.TargetType;
public class PsiImplUtil {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.PsiImplUtil");
- private static final Set<TargetType> DEFAULT_TARGETS = Collections.unmodifiableSet(ContainerUtil.newHashSet(
- TargetType.PACKAGE, TargetType.TYPE, TargetType.ANNOTATION_TYPE,
- TargetType.FIELD, TargetType.METHOD, TargetType.CONSTRUCTOR,
- TargetType.PARAMETER, TargetType.LOCAL_VARIABLE));
-
- private static final TargetType[] PACKAGE_TARGETS = {TargetType.PACKAGE};
- private static final TargetType[] TYPE_USE_TARGETS = {TargetType.TYPE_USE};
- private static final TargetType[] ANNOTATION_TARGETS = {TargetType.ANNOTATION_TYPE, TargetType.TYPE, TargetType.TYPE_USE};
- private static final TargetType[] TYPE_TARGETS = {TargetType.TYPE, TargetType.TYPE_USE};
- private static final TargetType[] TYPE_PARAMETER_TARGETS = {TargetType.TYPE_PARAMETER, TargetType.TYPE_USE};
- private static final TargetType[] CONSTRUCTOR_TARGETS = {TargetType.CONSTRUCTOR, TargetType.TYPE_USE};
- private static final TargetType[] METHOD_TARGETS = {TargetType.METHOD, TargetType.TYPE_USE};
- private static final TargetType[] FIELD_TARGETS = {TargetType.FIELD, TargetType.TYPE_USE};
- private static final TargetType[] PARAMETER_TARGETS = {TargetType.PARAMETER, TargetType.TYPE_USE};
- private static final TargetType[] LOCAL_VARIABLE_TARGETS ={TargetType.LOCAL_VARIABLE, TargetType.TYPE_USE};
-
private PsiImplUtil() { }
@NotNull
@@ -376,93 +360,14 @@ public class PsiImplUtil {
PsiModifierList modifierList = annotationType.getModifierList();
if (modifierList == null) return null;
PsiAnnotation target = modifierList.findAnnotation(CommonClassNames.JAVA_LANG_ANNOTATION_TARGET);
- if (target == null) return DEFAULT_TARGETS; // if omitted it is applicable to all but Java 8 TYPE_USE/TYPE_PARAMETERS targets
-
- PsiAnnotationMemberValue value = target.findAttributeValue(null);
- if (value instanceof PsiReference) {
- TargetType targetType = translateTargetRef((PsiReference)value);
- if (targetType != null) {
- return Collections.singleton(targetType);
- }
- }
- else if (value instanceof PsiArrayInitializerMemberValue) {
- Set <TargetType> targets = ContainerUtil.newHashSet();
- for (PsiAnnotationMemberValue initializer : ((PsiArrayInitializerMemberValue)value).getInitializers()) {
- if (initializer instanceof PsiReference) {
- TargetType targetType = translateTargetRef((PsiReference)initializer);
- if (targetType != null) {
- targets.add(targetType);
- }
- }
- }
- return targets;
- }
+ if (target == null) return AnnotationTargetUtil.DEFAULT_TARGETS; // if omitted it is applicable to all but Java 8 TYPE_USE/TYPE_PARAMETERS targets
- return null;
- }
-
- @Nullable
- private static TargetType translateTargetRef(PsiReference reference) {
- PsiElement field = reference.resolve();
- if (field instanceof PsiEnumConstant) {
- String name = ((PsiEnumConstant)field).getName();
- try {
- return TargetType.valueOf(name);
- }
- catch (IllegalArgumentException e) {
- LOG.warn("Unknown target: " + name);
- }
- }
- return null;
+ return AnnotationTargetUtil.extractRequiredAnnotationTargets(target.findAttributeValue(null));
}
@NotNull
public static TargetType[] getTargetsForLocation(@Nullable PsiAnnotationOwner owner) {
- if (owner == null) {
- return TargetType.EMPTY_ARRAY;
- }
-
- if (owner instanceof PsiType || owner instanceof PsiTypeElement) {
- return TYPE_USE_TARGETS;
- }
-
- if (owner instanceof PsiTypeParameter) {
- return TYPE_PARAMETER_TARGETS;
- }
-
- if (owner instanceof PsiModifierList) {
- PsiElement element = ((PsiModifierList)owner).getParent();
- if (element instanceof PsiPackageStatement) {
- return PACKAGE_TARGETS;
- }
- if (element instanceof PsiClass) {
- if (((PsiClass)element).isAnnotationType()) {
- return ANNOTATION_TARGETS;
- }
- else {
- return TYPE_TARGETS;
- }
- }
- if (element instanceof PsiMethod) {
- if (((PsiMethod)element).isConstructor()) {
- return CONSTRUCTOR_TARGETS;
- }
- else {
- return METHOD_TARGETS;
- }
- }
- if (element instanceof PsiField) {
- return FIELD_TARGETS;
- }
- if (element instanceof PsiParameter) {
- return PARAMETER_TARGETS;
- }
- if (element instanceof PsiLocalVariable) {
- return LOCAL_VARIABLE_TARGETS;
- }
- }
-
- return TargetType.EMPTY_ARRAY;
+ return AnnotationTargetUtil.getTargetsForLocation(owner);
}
@Nullable
@@ -782,4 +687,33 @@ public class PsiImplUtil {
return element instanceof LeafElement && tokenSet.contains(((LeafElement)element).getElementType());
}
+ public static PsiType buildTypeFromTypeString(@NotNull final String typeName, @NotNull final PsiElement context, @NotNull final PsiFile psiFile) {
+ PsiType resultType;
+ final PsiManager psiManager = psiFile.getManager();
+
+ if (typeName.indexOf('<') != -1 || typeName.indexOf('[') != -1 || typeName.indexOf('.') == -1) {
+ try {
+ return JavaPsiFacade.getInstance(psiManager.getProject()).getElementFactory().createTypeFromText(typeName, context);
+ } catch(Exception ex) {} // invalid syntax will produce unresolved class type
+ }
+
+ PsiClass aClass = JavaPsiFacade.getInstance(psiManager.getProject()).findClass(typeName, context.getResolveScope());
+
+ if (aClass == null) {
+ final LightClassReference ref = new LightClassReference(
+ psiManager,
+ PsiNameHelper.getShortClassName(typeName),
+ typeName,
+ PsiSubstitutor.EMPTY,
+ psiFile
+ );
+ resultType = new PsiClassReferenceType(ref, null);
+ } else {
+ PsiElementFactory factory = JavaPsiFacade.getInstance(psiManager.getProject()).getElementFactory();
+ PsiSubstitutor substitutor = factory.createRawSubstitutor(aClass);
+ resultType = factory.createType(aClass, substitutor);
+ }
+
+ return resultType;
+ }
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java
index f1d847cb24c2..e0db7701574d 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java
@@ -18,6 +18,7 @@ package com.intellij.psi.impl;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.ProjectRootModificationTracker;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.*;
@@ -370,7 +371,12 @@ public class PsiSuperMethodImplUtil {
if (result == null) {
result = new HierarchicalMethodSignatureImpl((MethodSignatureBackedByPsiMethod)method.getSignature(PsiSubstitutor.EMPTY));
}
- return CachedValueProvider.Result.create(result, PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT);
+
+ Project project = aClass == null ? method.getProject() : aClass.getProject();
+ // cache Cls method hierarchy until root changed
+ Object dependency = method instanceof PsiCompiledElement ? ProjectRootModificationTracker.getInstance(project) :
+ PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT;
+ return CachedValueProvider.Result.create(result, dependency);
}
};
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/StubBuildingVisitor.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/StubBuildingVisitor.java
index d2a66271353d..b356698428d8 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/StubBuildingVisitor.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/StubBuildingVisitor.java
@@ -84,7 +84,8 @@ public class StubBuildingVisitor<T> extends ClassVisitor {
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
- String fqn, shortName;
+ String fqn;
+ String shortName;
if (myShortName != null && name.endsWith(myShortName)) {
shortName = myShortName;
fqn = name.length() == shortName.length()
@@ -338,7 +339,8 @@ public class StubBuildingVisitor<T> extends ClassVisitor {
if (fqn == null) return true; // impossible case, just ignore
if (fqn.length() != signature.length()) return false;
- int p = 0, dot;
+ int p = 0;
+ int dot;
while ((dot = fqn.indexOf('.', p)) >= 0) {
if (!signature.regionMatches(p, fqn, p, dot - p)) {
return false;
@@ -428,24 +430,10 @@ public class StubBuildingVisitor<T> extends ClassVisitor {
List<String> args = new ArrayList<String>();
List<String> throwables = exceptions != null ? new ArrayList<String>() : null;
- final PsiMethodStubImpl stub = new PsiMethodStubImpl(myResult, StringRef.fromString(canonicalMethodName), flags, null);
+ int modifiersMask = packMethodFlags(access, myResult.isInterface());
+ final PsiMethodStubImpl stub = new PsiMethodStubImpl(myResult, StringRef.fromString(canonicalMethodName), flags, signature, args, throwables, desc, modifiersMask);
- final PsiModifierListStub modList = new PsiModifierListStubImpl(stub, packMethodFlags(access, myResult.isInterface()));
-
- String returnType = null;
- boolean parsedViaGenericSignature = false;
- if (signature != null) {
- try {
- returnType = parseMethodViaGenericSignature(signature, stub, args, throwables);
- parsedViaGenericSignature = true;
- }
- catch (ClsFormatException ignored) { }
- }
- if (returnType == null) {
- returnType = parseMethodViaDescription(desc, stub, args);
- }
-
- stub.setReturnType(TypeInfo.fromString(returnType));
+ PsiModifierListStub modList = (PsiModifierListStub)stub.findChildStubByType(JavaStubElementTypes.MODIFIER_LIST);
if (isEnum && isConstructor && signature == null && args.size() >= 2 && JAVA_LANG_STRING.equals(args.get(0)) && "int".equals(args.get(1))) {
// exclude synthetic enum constructor parameters
@@ -454,6 +442,7 @@ public class StubBuildingVisitor<T> extends ClassVisitor {
final boolean isNonStaticInnerClassConstructor =
isConstructor && !(myParent instanceof PsiFileStub) && (myModList.getModifiersMask() & Opcodes.ACC_STATIC) == 0;
+ boolean parsedViaGenericSignature = stub.isParsedViaGenericSignature();
final boolean shouldSkipFirstParamForNonStaticInnerClassConstructor = !parsedViaGenericSignature && isNonStaticInnerClassConstructor;
final PsiParameterListStubImpl parameterList = new PsiParameterListStubImpl(stub);
@@ -502,7 +491,8 @@ public class StubBuildingVisitor<T> extends ClassVisitor {
}
}
- private static String parseMethodViaDescription(final String desc, final PsiMethodStubImpl stub, final List<String> args) {
+ @NotNull
+ public static String parseMethodViaDescription(@NotNull String desc, @NotNull PsiMethodStubImpl stub, @NotNull List<String> args) {
final String returnType = getTypeText(Type.getReturnType(desc));
final Type[] argTypes = Type.getArgumentTypes(desc);
for (Type argType : argTypes) {
@@ -512,10 +502,11 @@ public class StubBuildingVisitor<T> extends ClassVisitor {
return returnType;
}
- private static String parseMethodViaGenericSignature(final String signature,
- final PsiMethodStubImpl stub,
- final List<String> args,
- final List<String> throwables) throws ClsFormatException {
+ @NotNull
+ public static String parseMethodViaGenericSignature(@NotNull String signature,
+ @NotNull PsiMethodStubImpl stub,
+ @NotNull List<String> args,
+ @Nullable List<String> throwables) throws ClsFormatException {
StringCharacterIterator iterator = new StringCharacterIterator(signature);
SignatureParsing.parseTypeParametersDeclaration(iterator, stub);
@@ -651,12 +642,12 @@ public class StubBuildingVisitor<T> extends ClassVisitor {
private int myUsedParamSize = 0;
private int myUsedParamCount = 0;
- private AnnotationParamCollectingVisitor(final PsiMethodStub owner,
- final PsiModifierListStub modList,
+ private AnnotationParamCollectingVisitor(@NotNull PsiMethodStub owner,
+ @NotNull PsiModifierListStub modList,
final int ignoreCount,
final int paramIgnoreCount,
final int paramCount,
- final PsiParameterStubImpl[] paramStubs) {
+ @NotNull PsiParameterStubImpl[] paramStubs) {
super(ASM_API);
myOwner = owner;
myModList = modList;
@@ -758,7 +749,7 @@ public class StubBuildingVisitor<T> extends ClassVisitor {
}
if (value instanceof Double) {
- final double d = ((Double)value).doubleValue();
+ final double d = (Double)value;
if (Double.isInfinite(d)) {
return d > 0 ? DOUBLE_POSITIVE_INF : DOUBLE_NEGATIVE_INF;
}
@@ -769,7 +760,7 @@ public class StubBuildingVisitor<T> extends ClassVisitor {
}
if (value instanceof Float) {
- final float v = ((Float)value).floatValue();
+ final float v = (Float)value;
if (Float.isInfinite(v)) {
return v > 0 ? FLOAT_POSITIVE_INF : FLOAT_NEGATIVE_INF;
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiMethodStubImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiMethodStubImpl.java
index 1463355455c2..13487c5514d0 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiMethodStubImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiMethodStubImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,19 +21,23 @@ package com.intellij.psi.impl.java.stubs.impl;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.impl.cache.TypeInfo;
+import com.intellij.psi.impl.compiled.StubBuildingVisitor;
import com.intellij.psi.impl.java.stubs.JavaStubElementTypes;
import com.intellij.psi.impl.java.stubs.PsiMethodStub;
import com.intellij.psi.impl.java.stubs.PsiParameterListStub;
import com.intellij.psi.impl.java.stubs.PsiParameterStub;
import com.intellij.psi.stubs.StubBase;
import com.intellij.psi.stubs.StubElement;
+import com.intellij.util.BitUtil;
+import com.intellij.util.cls.ClsFormatException;
import com.intellij.util.io.StringRef;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.util.List;
public class PsiMethodStubImpl extends StubBase<PsiMethod> implements PsiMethodStub {
- private TypeInfo myReturnType;
+ private final TypeInfo myReturnType;
private final byte myFlags;
private final StringRef myName;
private StringRef myDefaultValueText;
@@ -43,15 +47,40 @@ public class PsiMethodStubImpl extends StubBase<PsiMethod> implements PsiMethodS
private static final int ANNOTATION = 0x04;
private static final int DEPRECATED = 0x08;
private static final int DEPRECATED_ANNOTATION = 0x10;
-
- public PsiMethodStubImpl(StubElement parent, StringRef name, byte flags, StringRef defaultValueText) {
+ private static final int PARSED_VIA_GENERIC_SIGNATURE = 0x20;
+
+ public PsiMethodStubImpl(StubElement parent,
+ StringRef name,
+ byte flags,
+ String signature,
+ @NotNull List<String> args,
+ @Nullable List<String> throwables,
+ String desc,
+ int modifiersMask) {
super(parent, isAnnotationMethod(flags) ? JavaStubElementTypes.ANNOTATION_METHOD : JavaStubElementTypes.METHOD);
- myFlags = flags;
myName = name;
- myDefaultValueText = defaultValueText;
+ myDefaultValueText = null;
+
+ new PsiModifierListStubImpl(this, modifiersMask);
+
+ String returnType = null;
+ boolean parsedViaGenericSignature = false;
+ if (signature != null) {
+ try {
+ returnType = StubBuildingVisitor.parseMethodViaGenericSignature(signature, this, args, throwables);
+ parsedViaGenericSignature = true;
+ }
+ catch (ClsFormatException ignored) { }
+ }
+ if (returnType == null) {
+ returnType = StubBuildingVisitor.parseMethodViaDescription(desc, this, args);
+ }
+
+ myReturnType = TypeInfo.fromString(returnType);
+ myFlags = (byte)(flags | (parsedViaGenericSignature ? PARSED_VIA_GENERIC_SIGNATURE : 0));
}
- public PsiMethodStubImpl(StubElement parent, StringRef name, TypeInfo returnType, byte flags, StringRef defaultValueText) {
+ public PsiMethodStubImpl(StubElement parent, StringRef name, @NotNull TypeInfo returnType, byte flags, StringRef defaultValueText) {
super(parent, isAnnotationMethod(flags) ? JavaStubElementTypes.ANNOTATION_METHOD : JavaStubElementTypes.METHOD);
myReturnType = returnType;
myFlags = flags;
@@ -59,10 +88,6 @@ public class PsiMethodStubImpl extends StubBase<PsiMethod> implements PsiMethodS
myDefaultValueText = defaultValueText;
}
- public void setReturnType(TypeInfo returnType) {
- myReturnType = returnType;
- }
-
@Override
public boolean isConstructor() {
return (myFlags & CONSTRUCTOR) != 0;
@@ -73,6 +98,9 @@ public class PsiMethodStubImpl extends StubBase<PsiMethod> implements PsiMethodS
return (myFlags & VARARGS) != 0;
}
+ public boolean isParsedViaGenericSignature() {
+ return BitUtil.isSet(myFlags, PARSED_VIA_GENERIC_SIGNATURE);
+ }
@Override
public boolean isAnnotationMethod() {
return isAnnotationMethod(myFlags);
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveCache.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveCache.java
index 58b1e2253d14..b2c934ef9783 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveCache.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveCache.java
@@ -86,12 +86,13 @@ public class JavaResolveCache {
@Nullable
public <T extends PsiExpression> PsiType getType(@NotNull T expr, @NotNull Function<T, PsiType> f) {
- PsiType type = getCachedType(expr);
+ final boolean isOverloadCheck = MethodCandidateInfo.isOverloadCheck();
+ PsiType type = !isOverloadCheck ? getCachedType(expr) : null;
if (type == null) {
final RecursionGuard.StackStamp dStackStamp = PsiDiamondType.ourDiamondGuard.markStack();
final RecursionGuard.StackStamp gStackStamp = PsiResolveHelper.ourGraphGuard.markStack();
type = f.fun(expr);
- if (!dStackStamp.mayCacheNow() || !gStackStamp.mayCacheNow() || !MethodCandidateInfo.ourOverloadGuard.currentStack().isEmpty()) {
+ if (!dStackStamp.mayCacheNow() || !gStackStamp.mayCacheNow() || isOverloadCheck) {
return type;
}
if (type == null) type = TypeConversionUtil.NULL_TYPE;
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java
index 6098199c591c..7d6166a7f95a 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java
@@ -349,13 +349,17 @@ public class InferenceSession {
}
public boolean initBounds(PsiTypeParameter... typeParameters) {
+ return initBounds(myContext, typeParameters);
+ }
+
+ public boolean initBounds(PsiElement context, PsiTypeParameter... typeParameters) {
boolean sameMethodCall = false;
for (PsiTypeParameter parameter : typeParameters) {
if (myInferenceVariables.containsKey(parameter)) {
sameMethodCall = true;
continue;
}
- InferenceVariable variable = new InferenceVariable(parameter);
+ InferenceVariable variable = new InferenceVariable(context, parameter);
boolean added = false;
final PsiClassType[] extendsListTypes = parameter.getExtendsListTypes();
for (PsiType classType : extendsListTypes) {
@@ -415,7 +419,7 @@ public class InferenceSession {
for (int i = 0; i < typeParameters.length; i++) {
PsiTypeParameter typeParameter = typeParameters[i];
copy[i] = elementFactory.createTypeParameterFromText("rCopy" + typeParameter.getName(), null);
- initBounds(copy[i]);
+ initBounds(myContext, copy[i]);
subst = subst.put(typeParameter, elementFactory.createType(copy[i]));
}
final PsiType substitutedCapture = PsiUtil.captureToplevelWildcards(subst.substitute(returnType), myContext);
@@ -446,7 +450,7 @@ public class InferenceSession {
}
private static boolean hasPrimitiveWrapperBound(InferenceVariable inferenceVariable) {
- final InferenceBound[] boundTypes = {InferenceBound.UPPER, InferenceBound.LOWER};
+ final InferenceBound[] boundTypes = {InferenceBound.UPPER, InferenceBound.LOWER, InferenceBound.EQ};
for (InferenceBound inferenceBound : boundTypes) {
final List<PsiType> bounds = inferenceVariable.getBounds(inferenceBound);
for (PsiType bound : bounds) {
@@ -701,7 +705,7 @@ public class InferenceSession {
final PsiTypeParameter copy = elementFactory.createTypeParameterFromText("z" + parameter.getName(), null);
final PsiType lub = getLowerBound(var, substitutor);
final PsiType glb = getUpperBound(var, substitutor);
- final InferenceVariable zVariable = new InferenceVariable(copy);
+ final InferenceVariable zVariable = new InferenceVariable(var.getCallContext(), copy);
zVariable.addBound(glb, InferenceBound.UPPER);
if (lub != PsiType.NULL) {
if (!TypeConversionUtil.isAssignable(glb, lub)) {
@@ -1026,7 +1030,7 @@ public class InferenceSession {
boolean varargs) {
final InferenceSession session = new InferenceSession(PsiTypeParameter.EMPTY_ARRAY, PsiSubstitutor.EMPTY, m2.getManager(), context);
for (PsiTypeParameter param : PsiUtil.typeParametersIterable(m2)) {
- session.initBounds(param);
+ session.initBounds(context, param);
}
final PsiParameter[] parameters1 = m1.getParameterList().getParameters();
@@ -1250,14 +1254,17 @@ public class InferenceSession {
return myIncorporationPhase.hasCaptureConstraints(Arrays.asList(inferenceVariable));
}
- public void liftBounds(Collection<InferenceVariable> variables) {
+ public void liftBounds(PsiElement context, Collection<InferenceVariable> variables) {
for (InferenceVariable variable : variables) {
final PsiTypeParameter parameter = variable.getParameter();
final InferenceVariable inferenceVariable = getInferenceVariable(parameter);
if (inferenceVariable != null) {
- for (InferenceBound boundType : InferenceBound.values()) {
- for (PsiType bound : variable.getBounds(boundType)) {
- inferenceVariable.addBound(bound, boundType);
+ final PsiElement callContext = inferenceVariable.getCallContext();
+ if (context.equals(callContext) || myContext.equals(callContext)) {
+ for (InferenceBound boundType : InferenceBound.values()) {
+ for (PsiType bound : variable.getBounds(boundType)) {
+ inferenceVariable.addBound(bound, boundType);
+ }
}
}
} else {
@@ -1270,4 +1277,8 @@ public class InferenceSession {
final Boolean erased = call.getUserData(ERASED);
return erased != null && erased.booleanValue();
}
+
+ public PsiElement getContext() {
+ return myContext;
+ }
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceVariable.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceVariable.java
index a606e90e8a98..a19961f4c3a9 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceVariable.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceVariable.java
@@ -26,6 +26,8 @@ import java.util.*;
* User: anna
*/
public class InferenceVariable extends LightTypeParameter {
+ private PsiElement myContext;
+
public PsiTypeParameter getParameter() {
return getDelegate();
}
@@ -35,8 +37,9 @@ public class InferenceVariable extends LightTypeParameter {
private PsiType myInstantiation = PsiType.NULL;
- InferenceVariable(PsiTypeParameter parameter) {
+ InferenceVariable(PsiElement context, PsiTypeParameter parameter) {
super(parameter);
+ myContext = context;
}
public PsiType getInstantiation() {
@@ -129,4 +132,8 @@ public class InferenceVariable extends LightTypeParameter {
public String toString() {
return getDelegate().toString();
}
+
+ public PsiElement getCallContext() {
+ return myContext;
+ }
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ExpressionCompatibilityConstraint.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ExpressionCompatibilityConstraint.java
index c33e2c31fa12..82b320ae99f3 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ExpressionCompatibilityConstraint.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ExpressionCompatibilityConstraint.java
@@ -110,7 +110,7 @@ public class ExpressionCompatibilityConstraint extends InputOutputConstraintForm
if (typeParams != null) {
final Set<PsiTypeParameter> oldBounds = ContainerUtil.newHashSet(session.getParamsToInfer());
- final boolean sameMethodCall = session.initBounds(typeParams);
+ final boolean sameMethodCall = session.initBounds(myExpression, typeParams);
PsiSubstitutor substitutor = PsiSubstitutor.EMPTY;
final HashSet<InferenceVariable> variables = new HashSet<InferenceVariable>();
session.collectDependencies(returnType, variables);
@@ -138,8 +138,8 @@ public class ExpressionCompatibilityConstraint extends InputOutputConstraintForm
}
final Collection<PsiTypeParameter> params1 = session.getTypeParams();
- final InferenceSession callSession = new InferenceSession(params1.toArray(new PsiTypeParameter[params1.size()]), substitutor, myExpression.getManager(), myExpression);
- callSession.initBounds(params);
+ final InferenceSession callSession = new InferenceSession(params, substitutor, myExpression.getManager(), myExpression);
+ callSession.initBounds(session.getContext(), params1.toArray(new PsiTypeParameter[params1.size()]));
if (method != null) {
final PsiExpression[] args = argumentList.getExpressions();
final PsiParameter[] parameters = method.getParameterList().getParameters();
@@ -163,7 +163,7 @@ public class ExpressionCompatibilityConstraint extends InputOutputConstraintForm
}
}
}
- session.liftBounds(inferenceVariables);
+ session.liftBounds(myExpression, inferenceVariables);
} else {
return false;
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/PsiMethodReferenceCompatibilityConstraint.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/PsiMethodReferenceCompatibilityConstraint.java
index 18d0c49e79d4..9516265a8cb5 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/PsiMethodReferenceCompatibilityConstraint.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/PsiMethodReferenceCompatibilityConstraint.java
@@ -91,7 +91,7 @@ public class PsiMethodReferenceCompatibilityConstraint implements ConstraintForm
}
final PsiParameter[] parameters = applicableMember instanceof PsiMethod ? ((PsiMethod)applicableMember).getParameterList().getParameters() : PsiParameter.EMPTY_ARRAY;
if (targetParameters.length == parameters.length + 1) {
- specialCase(session, constraints, substitutor, targetParameters);
+ specialCase(session, constraints, substitutor, targetParameters, true);
for (int i = 1; i < targetParameters.length; i++) {
constraints.add(new TypeCompatibilityConstraint(psiSubstitutor.substitute(parameters[i - 1].getType()), substitutor.substitute(targetParameters[i].getType())));
}
@@ -198,7 +198,7 @@ public class PsiMethodReferenceCompatibilityConstraint implements ConstraintForm
final PsiParameter[] parameters = method.getParameterList().getParameters();
if (targetParameters.length == parameters.length + 1 && !method.isVarArgs() &&
PsiPolyExpressionUtil.mentionsTypeParameters(referencedMethodReturnType, ContainerUtil.newHashSet(containingClass.getTypeParameters()))) { //todo specification bug?
- specialCase(session, constraints, substitutor, targetParameters);
+ specialCase(session, constraints, substitutor, targetParameters, false);
}
constraints.add(new TypeCompatibilityConstraint(returnType, psiSubstitutor.substitute(referencedMethodReturnType)));
}
@@ -209,7 +209,8 @@ public class PsiMethodReferenceCompatibilityConstraint implements ConstraintForm
private void specialCase(InferenceSession session,
List<ConstraintFormula> constraints,
PsiSubstitutor substitutor,
- PsiParameter[] targetParameters) {
+ PsiParameter[] targetParameters,
+ boolean ignoreRaw) {
final PsiElement qualifier = myExpression.getQualifier();
PsiType qualifierType = null;
if (qualifier instanceof PsiTypeElement) {
@@ -226,8 +227,7 @@ public class PsiMethodReferenceCompatibilityConstraint implements ConstraintForm
final PsiElement res = resolveResult.getElement();
if (res instanceof PsiClass) {
PsiClass containingClass = (PsiClass)res;
- final boolean isRawSubst = !myExpression.isConstructor() &&
- PsiUtil.isRawSubstitutor(containingClass, resolveResult.getSubstitutor());
+ final boolean isRawSubst = !ignoreRaw && !myExpression.isConstructor() && PsiUtil.isRawSubstitutor(containingClass, resolveResult.getSubstitutor());
qualifierType = JavaPsiFacade.getElementFactory(res.getProject()).createType(containingClass, isRawSubst ? PsiSubstitutor.EMPTY : resolveResult.getSubstitutor());
}
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaSourceUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaSourceUtil.java
index e2af7b08df0d..d4d0f3f0c88d 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaSourceUtil.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaSourceUtil.java
@@ -22,6 +22,7 @@ import com.intellij.lang.LighterASTNode;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
+import com.intellij.psi.impl.PsiImplUtil;
import com.intellij.psi.impl.source.DummyHolder;
import com.intellij.psi.impl.source.SourceJavaCodeReference;
import com.intellij.psi.impl.source.SourceTreeToPsiMap;
@@ -142,4 +143,41 @@ public class JavaSourceUtil {
TreeUtil.clearCaches(TreeUtil.getFileElement(parenthExpr));
return parenthExpr;
}
+
+ public static void deleteSeparatingComma(@NotNull CompositeElement element, @NotNull ASTNode child) {
+ assert child.getElementType() != JavaTokenType.COMMA : child;
+
+ ASTNode next = PsiImplUtil.skipWhitespaceAndComments(child.getTreeNext());
+ if (next != null && next.getElementType() == JavaTokenType.COMMA) {
+ element.deleteChildInternal(next);
+ }
+ else {
+ ASTNode prev = PsiImplUtil.skipWhitespaceAndCommentsBack(child.getTreePrev());
+ if (prev != null && prev.getElementType() == JavaTokenType.COMMA) {
+ element.deleteChildInternal(prev);
+ }
+ }
+ }
+
+ public static void addSeparatingComma(@NotNull CompositeElement element, @NotNull ASTNode child, @NotNull TokenSet listTypes) {
+ assert child.getElementType() != JavaTokenType.COMMA : child;
+
+ scanChildren(element, child, listTypes, true);
+ scanChildren(element, child, listTypes, false);
+ }
+
+ private static void scanChildren(CompositeElement element, ASTNode node, TokenSet listTypes, boolean forward) {
+ ASTNode child = node;
+ while (true) {
+ child = (forward ? child.getTreeNext() : child.getTreePrev());
+ if (child == null || child.getElementType() == JavaTokenType.COMMA) break;
+ if (listTypes.contains(child.getElementType())) {
+ CharTable charTable = SharedImplUtil.findCharTableByTree(element);
+ PsiManager manager = element.getPsi().getManager();
+ TreeElement comma = Factory.createSingleLeafElement(JavaTokenType.COMMA, ",", 0, 1, charTable, manager);
+ element.addInternal(comma, comma, (forward ? node : child), Boolean.FALSE);
+ break;
+ }
+ }
+ }
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/AnnotationParamListElement.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/AnnotationParamListElement.java
index 4953bd2d3804..e1ffc8b91766 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/AnnotationParamListElement.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/AnnotationParamListElement.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,8 +19,9 @@ import com.intellij.lang.ASTNode;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.tree.*;
-import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.ChildRoleBase;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.tree.TokenSet;
import com.intellij.util.CharTable;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
@@ -28,47 +29,29 @@ import org.jetbrains.annotations.NotNull;
/**
* @author ven
*/
-public class AnnotationParamListElement extends PsiCommaSeparatedListImpl implements PsiAnnotationParameterList {
+public class AnnotationParamListElement extends CompositeElement {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.java.AnnotationParamListElement");
- private volatile PsiNameValuePair[] myCachedMembers = null;
+ private static final TokenSet NAME_VALUE_PAIR_BIT_SET = TokenSet.create(JavaElementType.NAME_VALUE_PAIR);
public AnnotationParamListElement() {
- super(ANNOTATION_PARAMETER_LIST, NAME_VALUE_PAIR_BIT_SET);
- }
-
- @Override
- public void clearCaches() {
- super.clearCaches();
- myCachedMembers = null;
- }
-
- @Override
- @NotNull
- public PsiNameValuePair[] getAttributes() {
- PsiNameValuePair[] cachedMembers = myCachedMembers;
- if (cachedMembers == null) {
- myCachedMembers = cachedMembers = getChildrenAsPsiElements(NAME_VALUE_PAIR_BIT_SET, PsiNameValuePair.ARRAY_FACTORY);
- }
-
- return cachedMembers;
+ super(JavaElementType.ANNOTATION_PARAMETER_LIST);
}
@Override
public int getChildRole(ASTNode child) {
IElementType i = child.getElementType();
- if (i == COMMA) {
+ if (i == JavaTokenType.COMMA) {
return ChildRole.COMMA;
}
- else if (i == LPARENTH) {
+ else if (i == JavaTokenType.LPARENTH) {
return ChildRole.LPARENTH;
}
- else if (i == RPARENTH) {
+ else if (i == JavaTokenType.RPARENTH) {
return ChildRole.RPARENTH;
}
- else if (ANNOTATION_MEMBER_VALUE_BIT_SET.contains(child.getElementType())
- || (i == NAME_VALUE_PAIR && child.getFirstChildNode() != null
- && child.getFirstChildNode().getElementType() == ANNOTATION_ARRAY_INITIALIZER))
- {
+ else if (ElementType.ANNOTATION_MEMBER_VALUE_BIT_SET.contains(i) ||
+ (i == JavaElementType.NAME_VALUE_PAIR && child.getFirstChildNode() != null &&
+ child.getFirstChildNode().getElementType() == JavaElementType.ANNOTATION_ARRAY_INITIALIZER)) {
return ChildRole.ANNOTATION_VALUE;
}
else {
@@ -83,65 +66,69 @@ public class AnnotationParamListElement extends PsiCommaSeparatedListImpl implem
LOG.assertTrue(false);
return null;
case ChildRole.LPARENTH:
- return findChildByType(LPARENTH);
+ return findChildByType(JavaTokenType.LPARENTH);
case ChildRole.RPARENTH:
- return findChildByType(RPARENTH);
- }
- }
-
- public String toString() {
- return "PsiAnnotationParameterList";
- }
-
- @Override
- public void accept(@NotNull PsiElementVisitor visitor) {
- if (visitor instanceof JavaElementVisitor) {
- ((JavaElementVisitor)visitor).visitAnnotationParameterList(this);
- }
- else {
- visitor.visitElement(this);
+ return findChildByType(JavaTokenType.RPARENTH);
}
}
@Override
public TreeElement addInternal(TreeElement first, ASTNode last, ASTNode anchor, Boolean before) {
- if (first.getElementType() == NAME_VALUE_PAIR && last.getElementType() == NAME_VALUE_PAIR) {
- final CharTable treeCharTab = SharedImplUtil.findCharTableByTree(this);
- ASTNode lparenth = findChildByRole(ChildRole.LPARENTH);
+ if (first.getElementType() == JavaElementType.NAME_VALUE_PAIR && last.getElementType() == JavaElementType.NAME_VALUE_PAIR) {
+ ASTNode lparenth = findChildByType(JavaTokenType.LPARENTH);
if (lparenth == null) {
- LeafElement created = Factory.createSingleLeafElement(LPARENTH, "(", 0, 1, treeCharTab, getManager());
+ CharTable treeCharTab = SharedImplUtil.findCharTableByTree(this);
+ LeafElement created = Factory.createSingleLeafElement(JavaTokenType.LPARENTH, "(", 0, 1, treeCharTab, getManager());
super.addInternal(created, created, getFirstChildNode(), true);
}
- ASTNode rparenth = findChildByRole(ChildRole.RPARENTH);
+
+ ASTNode rparenth = findChildByType(JavaTokenType.RPARENTH);
if (rparenth == null) {
- LeafElement created = Factory.createSingleLeafElement(RPARENTH, ")", 0, 1, treeCharTab, getManager());
+ CharTable treeCharTab = SharedImplUtil.findCharTableByTree(this);
+ LeafElement created = Factory.createSingleLeafElement(JavaTokenType.RPARENTH, ")", 0, 1, treeCharTab, getManager());
super.addInternal(created, created, getLastChildNode(), false);
}
- final ASTNode[] nodes = getChildren(NAME_VALUE_PAIR_BIT_SET);
+ ASTNode[] nodes = getChildren(NAME_VALUE_PAIR_BIT_SET);
if (nodes.length == 1) {
- final ASTNode node = nodes[0];
+ ASTNode node = nodes[0];
if (node instanceof PsiNameValuePair) {
- final PsiNameValuePair pair = (PsiNameValuePair)node;
+ PsiNameValuePair pair = (PsiNameValuePair)node;
if (pair.getName() == null) {
- final String text = pair.getValue().getText();
- try {
- final PsiAnnotation annotation = JavaPsiFacade.getInstance(getProject()).getElementFactory().createAnnotationFromText("@AAA(value = " + text + ")", null);
- replaceChild(node, annotation.getParameterList().getAttributes()[0].getNode());
- }
- catch (IncorrectOperationException e) {
- LOG.error(e);
+ PsiAnnotationMemberValue value = pair.getValue();
+ if (value != null) {
+ try {
+ PsiElementFactory factory = JavaPsiFacade.getInstance(getPsi().getProject()).getElementFactory();
+ PsiAnnotation annotation = factory.createAnnotationFromText("@AAA(value = " + value.getText() + ")", null);
+ replaceChild(node, annotation.getParameterList().getAttributes()[0].getNode());
+ }
+ catch (IncorrectOperationException e) {
+ LOG.error(e);
+ }
}
}
}
}
if (anchor == null && before != null) {
- anchor = findChildByRole(before.booleanValue() ? ChildRole.RPARENTH : ChildRole.LPARENTH);
+ anchor = findChildByType(before ? JavaTokenType.RPARENTH : JavaTokenType.LPARENTH);
}
+
+ TreeElement firstAdded = super.addInternal(first, last, anchor, before);
+ JavaSourceUtil.addSeparatingComma(this, first, NAME_VALUE_PAIR_BIT_SET);
+ return firstAdded;
}
return super.addInternal(first, last, anchor, before);
}
+
+ @Override
+ public void deleteChildInternal(@NotNull ASTNode child) {
+ if (child.getElementType() == JavaElementType.NAME_VALUE_PAIR) {
+ JavaSourceUtil.deleteSeparatingComma(this, child);
+ }
+
+ super.deleteChildInternal(child);
+ }
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/ClassElement.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/ClassElement.java
index 712b32ca6d5b..14d72a92da1c 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/ClassElement.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/ClassElement.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,6 +34,15 @@ import org.jetbrains.annotations.Nullable;
public class ClassElement extends CompositeElement implements Constants {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.java.ClassElement");
+ private static final TokenSet MODIFIERS_TO_REMOVE_IN_INTERFACE_BIT_SET = TokenSet.create(
+ PUBLIC_KEYWORD, ABSTRACT_KEYWORD, STATIC_KEYWORD, FINAL_KEYWORD, NATIVE_KEYWORD);
+ private static final TokenSet MODIFIERS_TO_REMOVE_IN_INTERFACE_BIT_SET_18_METHOD = TokenSet.create(
+ PUBLIC_KEYWORD, ABSTRACT_KEYWORD, FINAL_KEYWORD, NATIVE_KEYWORD);
+ private static final TokenSet MODIFIERS_TO_REMOVE_IN_ENUM_BIT_SET = TokenSet.create(
+ PUBLIC_KEYWORD, FINAL_KEYWORD);
+ private static final TokenSet ENUM_CONSTANT_LIST_ELEMENTS_BIT_SET = TokenSet.create(
+ ENUM_CONSTANT, COMMA, SEMICOLON);
+
public ClassElement(IElementType type) {
super(type);
}
@@ -181,19 +190,8 @@ public class ClassElement extends CompositeElement implements Constants {
@Override
public void deleteChildInternal(@NotNull ASTNode child) {
- if (isEnum()) {
- if (child.getElementType() == ENUM_CONSTANT) {
- ASTNode next = PsiImplUtil.skipWhitespaceAndComments(child.getTreeNext());
- if (next != null && next.getElementType() == COMMA) {
- deleteChildInternal(next);
- }
- else {
- ASTNode prev = PsiImplUtil.skipWhitespaceAndCommentsBack(child.getTreePrev());
- if (prev != null && prev.getElementType() == COMMA) {
- deleteChildInternal(prev);
- }
- }
- }
+ if (isEnum() && child.getElementType() == ENUM_CONSTANT) {
+ JavaSourceUtil.deleteSeparatingComma(this, child);
}
if (child.getElementType() == FIELD) {
@@ -233,27 +231,6 @@ public class ClassElement extends CompositeElement implements Constants {
return findChildByRole(ChildRole.AT) != null;
}
- private static final TokenSet MODIFIERS_TO_REMOVE_IN_INTERFACE_BIT_SET = TokenSet.create(
- PUBLIC_KEYWORD, ABSTRACT_KEYWORD,
- STATIC_KEYWORD, FINAL_KEYWORD,
- NATIVE_KEYWORD
- );
-
- private static final TokenSet MODIFIERS_TO_REMOVE_IN_INTERFACE_BIT_SET_18_METHOD = TokenSet.create(
- PUBLIC_KEYWORD, ABSTRACT_KEYWORD,
- FINAL_KEYWORD,
- NATIVE_KEYWORD
- );
-
- private static final TokenSet MODIFIERS_TO_REMOVE_IN_ENUM_BIT_SET = TokenSet.create(
- PUBLIC_KEYWORD, FINAL_KEYWORD
- );
-
- private static final TokenSet ENUM_CONSTANT_LIST_ELEMENTS_BIT_SET = TokenSet.create(
- ENUM_CONSTANT, COMMA, SEMICOLON
- );
-
-
@Override
public ASTNode findChildByRole(int role) {
assert ChildRole.isUnique(role);
@@ -266,10 +243,7 @@ public class ClassElement extends CompositeElement implements Constants {
return PsiImplUtil.findDocComment(this);
case ChildRole.ENUM_CONSTANT_LIST_DELIMITER:
- if (!isEnum()) {
- return null;
- }
- return findEnumConstantListDelimiter();
+ return isEnum() ? findEnumConstantListDelimiter() : null;
case ChildRole.MODIFIER_LIST:
return findChildByType(MODIFIER_LIST);
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/ParameterListElement.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/ParameterListElement.java
index a5e32e9ce95b..20d504d8dbae 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/ParameterListElement.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/ParameterListElement.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,18 +18,21 @@ package com.intellij.psi.impl.source.tree.java;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.codeStyle.CodeStyleManager;
-import com.intellij.psi.impl.PsiImplUtil;
import com.intellij.psi.impl.source.Constants;
-import com.intellij.psi.impl.source.tree.*;
+import com.intellij.psi.impl.source.tree.ChildRole;
+import com.intellij.psi.impl.source.tree.CompositeElement;
+import com.intellij.psi.impl.source.tree.JavaSourceUtil;
+import com.intellij.psi.impl.source.tree.TreeElement;
import com.intellij.psi.tree.ChildRoleBase;
import com.intellij.psi.tree.IElementType;
-import com.intellij.util.CharTable;
+import com.intellij.psi.tree.TokenSet;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class ParameterListElement extends CompositeElement implements Constants {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.java.ParameterListElement");
+ private static final TokenSet PARAMETER_SET = TokenSet.create(PARAMETER);
public ParameterListElement() {
super(PARAMETER_LIST);
@@ -49,23 +52,7 @@ public class ParameterListElement extends CompositeElement implements Constants
}
TreeElement firstAdded = super.addInternal(first, last, anchor, before);
if (first == last && first.getElementType() == PARAMETER) {
- final CharTable treeCharTab = SharedImplUtil.findCharTableByTree(this);
- for (ASTNode child = ((ASTNode)first).getTreeNext(); child != null; child = child.getTreeNext()) {
- if (child.getElementType() == COMMA) break;
- if (child.getElementType() == PARAMETER) {
- TreeElement comma = Factory.createSingleLeafElement(COMMA, ",", 0, 1, treeCharTab, getManager());
- super.addInternal(comma, comma, first, Boolean.FALSE);
- break;
- }
- }
- for (ASTNode child = ((ASTNode)first).getTreePrev(); child != null; child = child.getTreePrev()) {
- if (child.getElementType() == COMMA) break;
- if (child.getElementType() == PARAMETER) {
- TreeElement comma = Factory.createSingleLeafElement(COMMA, ",", 0, 1, treeCharTab, getManager());
- super.addInternal(comma, comma, child, Boolean.FALSE);
- break;
- }
- }
+ JavaSourceUtil.addSeparatingComma(this, first, PARAMETER_SET);
}
//todo[max] hack?
@@ -83,16 +70,7 @@ public class ParameterListElement extends CompositeElement implements Constants
final TreeElement oldLastNodeInsideParens = getLastNodeInsideParens();
final TreeElement oldFirstNodeInsideParens = getFirstNodeInsideParens();
if (child.getElementType() == PARAMETER) {
- ASTNode next = PsiImplUtil.skipWhitespaceAndComments(child.getTreeNext());
- if (next != null && next.getElementType() == COMMA) {
- deleteChildInternal(next);
- }
- else {
- ASTNode prev = PsiImplUtil.skipWhitespaceAndCommentsBack(child.getTreePrev());
- if (prev != null && prev.getElementType() == COMMA) {
- deleteChildInternal(prev);
- }
- }
+ JavaSourceUtil.deleteSeparatingComma(this, child);
}
super.deleteChildInternal(child);
@@ -135,20 +113,12 @@ public class ParameterListElement extends CompositeElement implements Constants
return null;
case ChildRole.LPARENTH:
- if (getFirstChildNode().getElementType() == LPARENTH) {
- return getFirstChildNode();
- }
- else {
- return null;
- }
+ TreeElement firstNode = getFirstChildNode();
+ return firstNode.getElementType() == LPARENTH ? firstNode : null;
case ChildRole.RPARENTH:
- if (getLastChildNode().getElementType() == RPARENTH) {
- return getLastChildNode();
- }
- else {
- return null;
- }
+ TreeElement lastNode = getLastChildNode();
+ return lastNode.getElementType() == RPARENTH ? lastNode : null;
}
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiAnnotationParamListImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiAnnotationParamListImpl.java
index 5a3ccb23e420..0923d7cdd675 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiAnnotationParamListImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiAnnotationParamListImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,20 +16,20 @@
package com.intellij.psi.impl.source.tree.java;
import com.intellij.lang.ASTNode;
+import com.intellij.psi.JavaElementVisitor;
import com.intellij.psi.PsiAnnotationParameterList;
+import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiNameValuePair;
import com.intellij.psi.impl.java.stubs.JavaStubElementTypes;
import com.intellij.psi.impl.java.stubs.PsiAnnotationParameterListStub;
import com.intellij.psi.impl.source.JavaStubPsiElement;
-import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
/**
* @author Dmitry Avdeev
- * Date: 7/27/12
+ * @since 27.07.2012
*/
-public class PsiAnnotationParamListImpl extends JavaStubPsiElement<PsiAnnotationParameterListStub> implements
- PsiAnnotationParameterList {
+public class PsiAnnotationParamListImpl extends JavaStubPsiElement<PsiAnnotationParameterListStub> implements PsiAnnotationParameterList {
public PsiAnnotationParamListImpl(@NotNull PsiAnnotationParameterListStub stub) {
super(stub, JavaStubElementTypes.ANNOTATION_PARAMETER_LIST);
}
@@ -44,8 +44,18 @@ public class PsiAnnotationParamListImpl extends JavaStubPsiElement<PsiAnnotation
return getStubOrPsiChildren(JavaStubElementTypes.NAME_VALUE_PAIR, PsiNameValuePair.ARRAY_FACTORY);
}
- @NonNls
- public String toString(){
- return "PsiAnnotationParameterList:" + getText();
+ @Override
+ public void accept(@NotNull PsiElementVisitor visitor) {
+ if (visitor instanceof JavaElementVisitor) {
+ ((JavaElementVisitor)visitor).visitAnnotationParameterList(this);
+ }
+ else {
+ visitor.visitElement(this);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "PsiAnnotationParameterList";
}
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiArrayInitializerMemberValueImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiArrayInitializerMemberValueImpl.java
index dd64ed7e41fb..b03766f54d55 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiArrayInitializerMemberValueImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiArrayInitializerMemberValueImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,68 +17,84 @@ package com.intellij.psi.impl.source.tree.java;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.psi.JavaElementVisitor;
-import com.intellij.psi.PsiAnnotationMemberValue;
-import com.intellij.psi.PsiArrayInitializerMemberValue;
-import com.intellij.psi.PsiElementVisitor;
-import com.intellij.psi.impl.source.tree.ChildRole;
-import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.*;
+import com.intellij.psi.impl.source.tree.*;
import com.intellij.psi.tree.ChildRoleBase;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.tree.TokenSet;
import org.jetbrains.annotations.NotNull;
/**
* @author ven
*/
-public class PsiArrayInitializerMemberValueImpl extends PsiCommaSeparatedListImpl implements PsiArrayInitializerMemberValue {
- private static final Logger LOG = Logger.getInstance("com.intellij.psi.impl.source.tree.java.PsiArrayInitializerMemberValueImpl");
+public class PsiArrayInitializerMemberValueImpl extends CompositePsiElement implements PsiArrayInitializerMemberValue {
+ private static final Logger LOG = Logger.getInstance(PsiArrayInitializerMemberValueImpl.class);
+ private static final TokenSet MEMBER_SET = ElementType.ANNOTATION_MEMBER_VALUE_BIT_SET;
+
public PsiArrayInitializerMemberValueImpl() {
- super(ANNOTATION_ARRAY_INITIALIZER, ANNOTATION_MEMBER_VALUE_BIT_SET);
+ super(JavaElementType.ANNOTATION_ARRAY_INITIALIZER);
}
@Override
@NotNull
public PsiAnnotationMemberValue[] getInitializers() {
- return getChildrenAsPsiElements(ANNOTATION_MEMBER_VALUE_BIT_SET, PsiAnnotationMemberValue.ARRAY_FACTORY);
+ return getChildrenAsPsiElements(MEMBER_SET, PsiAnnotationMemberValue.ARRAY_FACTORY);
}
@Override
public ASTNode findChildByRole(int role) {
LOG.assertTrue(ChildRole.isUnique(role));
- switch(role){
+
+ switch (role) {
default:
return null;
case ChildRole.LBRACE:
- return findChildByType(LBRACE);
+ return findChildByType(JavaTokenType.LBRACE);
case ChildRole.RBRACE:
- return findChildByType(RBRACE);
+ return findChildByType(JavaTokenType.RBRACE);
}
}
@Override
public int getChildRole(ASTNode child) {
LOG.assertTrue(child.getTreeParent() == this);
+
IElementType i = child.getElementType();
- if (i == COMMA) {
+ if (i == JavaTokenType.COMMA) {
return ChildRole.COMMA;
}
- else if (i == LBRACE) {
+ else if (i == JavaTokenType.LBRACE) {
return ChildRole.LBRACE;
}
- else if (i == RBRACE) {
+ else if (i == JavaTokenType.RBRACE) {
return ChildRole.RBRACE;
}
- else {
- if (ANNOTATION_MEMBER_VALUE_BIT_SET.contains(child.getElementType())) {
- return ChildRole.ANNOTATION_VALUE;
- }
- return ChildRoleBase.NONE;
+ else if (MEMBER_SET.contains(child.getElementType())) {
+ return ChildRole.ANNOTATION_VALUE;
}
+ return ChildRoleBase.NONE;
}
- public String toString(){
- return "PsiArrayInitializerMemberValue:" + getText();
+ @Override
+ public TreeElement addInternal(TreeElement first, ASTNode last, ASTNode anchor, Boolean before) {
+ if (MEMBER_SET.contains(first.getElementType()) && MEMBER_SET.contains(last.getElementType())) {
+ TreeElement firstAdded = super.addInternal(first, last, anchor, before);
+ JavaSourceUtil.addSeparatingComma(this, first, MEMBER_SET);
+ return firstAdded;
+ }
+
+ return super.addInternal(first, last, anchor, before);
+ }
+
+ @Override
+ public void deleteChildInternal(@NotNull ASTNode child) {
+ if (MEMBER_SET.contains(child.getElementType())) {
+ JavaSourceUtil.deleteSeparatingComma(this, child);
+ }
+
+ super.deleteChildInternal(child);
}
@Override
@@ -90,4 +106,9 @@ public class PsiArrayInitializerMemberValueImpl extends PsiCommaSeparatedListImp
visitor.visitElement(this);
}
}
+
+ @Override
+ public String toString() {
+ return "PsiArrayInitializerMemberValue:" + getText();
+ }
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiCommaSeparatedListImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiCommaSeparatedListImpl.java
deleted file mode 100644
index 475542fdc868..000000000000
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiCommaSeparatedListImpl.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright 2000-2009 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.intellij.psi.impl.source.tree.java;
-
-import com.intellij.lang.ASTNode;
-import com.intellij.psi.impl.PsiImplUtil;
-import com.intellij.psi.impl.source.Constants;
-import com.intellij.psi.impl.source.tree.*;
-import com.intellij.psi.tree.IElementType;
-import com.intellij.psi.tree.TokenSet;
-import com.intellij.util.CharTable;
-import org.jetbrains.annotations.NotNull;
-
-/**
- * Adds or removes comma
- *
- * @author ven
- */
-public abstract class PsiCommaSeparatedListImpl extends CompositePsiElement implements Constants {
- private final TokenSet myTypesOfElements;
-
- protected PsiCommaSeparatedListImpl(IElementType type, final TokenSet typeOfElements) {
- super(type);
- myTypesOfElements = typeOfElements;
- }
-
- @Override
- public TreeElement addInternal(TreeElement first, ASTNode last, ASTNode anchor, Boolean before) {
- if (myTypesOfElements.contains(first.getElementType()) && myTypesOfElements.contains(last.getElementType())) {
- final CharTable treeCharTab = SharedImplUtil.findCharTableByTree(this);
- final TreeElement firstAdded = super.addInternal(first, last, anchor, before);
- for (ASTNode child = ((ASTNode)first).getTreeNext(); child != null; child = child.getTreeNext()) {
- if (child.getElementType() == COMMA) break;
- if (myTypesOfElements.contains(child.getElementType())) {
- TreeElement comma = Factory.createSingleLeafElement(COMMA, ",", 0, 1, treeCharTab, getManager());
- super.addInternal(comma, comma, first, Boolean.FALSE);
- break;
- }
- }
-
- for (ASTNode child = ((ASTNode)first).getTreePrev(); child != null; child = child.getTreePrev()) {
- if (child.getElementType() == COMMA) break;
- if (myTypesOfElements.contains(child.getElementType())) {
- TreeElement comma = Factory.createSingleLeafElement(COMMA, ",", 0, 1, treeCharTab, getManager());
- super.addInternal(comma, comma, child, Boolean.FALSE);
- break;
- }
- }
- return firstAdded;
- }
-
- return super.addInternal(first, last, anchor, before);
- }
-
- @Override
- public void deleteChildInternal(@NotNull ASTNode child) {
- if (myTypesOfElements.contains(child.getElementType())) {
- ASTNode next = PsiImplUtil.skipWhitespaceAndComments(child.getTreeNext());
- if (next != null && next.getElementType() == COMMA) {
- deleteChildInternal(next);
- }
- else {
- ASTNode prev = PsiImplUtil.skipWhitespaceAndCommentsBack(child.getTreePrev());
- if (prev != null && prev.getElementType() == COMMA) {
- deleteChildInternal(prev);
- }
- }
- }
- super.deleteChildInternal(child);
- }
-}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiExpressionListImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiExpressionListImpl.java
index ae45273b57f1..98df0baa4134 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiExpressionListImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiExpressionListImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,7 +18,6 @@ package com.intellij.psi.impl.source.tree.java;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.*;
-import com.intellij.psi.impl.PsiImplUtil;
import com.intellij.psi.impl.source.tree.*;
import com.intellij.psi.tree.ChildRoleBase;
import com.intellij.psi.tree.IElementType;
@@ -123,7 +122,8 @@ public class PsiExpressionListImpl extends CompositePsiElement implements PsiExp
}
TreeElement firstAdded = super.addInternal(first, last, anchor, before);
if (ElementType.EXPRESSION_BIT_SET.contains(first.getElementType())) {
- ASTNode element = first;
+ JavaSourceUtil.addSeparatingComma(this, first, ElementType.EXPRESSION_BIT_SET);
+ /*ASTNode element = first;
for (ASTNode child = element.getTreeNext(); child != null; child = child.getTreeNext()) {
if (child.getElementType() == JavaTokenType.COMMA) break;
if (ElementType.EXPRESSION_BIT_SET.contains(child.getElementType())) {
@@ -140,7 +140,7 @@ public class PsiExpressionListImpl extends CompositePsiElement implements PsiExp
super.addInternal(comma, comma, child, Boolean.FALSE);
break;
}
- }
+ }*/
}
return firstAdded;
}
@@ -148,17 +148,9 @@ public class PsiExpressionListImpl extends CompositePsiElement implements PsiExp
@Override
public void deleteChildInternal(@NotNull ASTNode child) {
if (ElementType.EXPRESSION_BIT_SET.contains(child.getElementType())) {
- ASTNode next = PsiImplUtil.skipWhitespaceAndComments(child.getTreeNext());
- if (next != null && next.getElementType() == JavaTokenType.COMMA) {
- deleteChildInternal(next);
- }
- else {
- ASTNode prev = PsiImplUtil.skipWhitespaceAndCommentsBack(child.getTreePrev());
- if (prev != null && prev.getElementType() == JavaTokenType.COMMA) {
- deleteChildInternal(prev);
- }
- }
+ JavaSourceUtil.deleteSeparatingComma(this, child);
}
+
super.deleteChildInternal(child);
}
@@ -172,6 +164,7 @@ public class PsiExpressionListImpl extends CompositePsiElement implements PsiExp
}
}
+ @Override
public String toString() {
return "PsiExpressionList";
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java
index 95171ba30bc9..32ed1aac5c91 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java
@@ -25,6 +25,7 @@ import com.intellij.psi.impl.PsiManagerEx;
import com.intellij.psi.impl.source.resolve.ResolveCache;
import com.intellij.psi.impl.source.resolve.graphInference.FunctionalInterfaceParameterizationUtil;
import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession;
+import com.intellij.psi.impl.source.resolve.graphInference.PsiPolyExpressionUtil;
import com.intellij.psi.impl.source.tree.ChildRole;
import com.intellij.psi.impl.source.tree.FileElement;
import com.intellij.psi.impl.source.tree.JavaElementType;
@@ -39,13 +40,12 @@ import com.intellij.psi.scope.util.PsiScopesUtil;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.*;
import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase implements PsiMethodReferenceExpression {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.java.PsiMethodReferenceExpressionImpl");
@@ -153,7 +153,8 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase
if (arrayClass == containingClass) {
final PsiType componentType = qualifierResolveResult.getSubstitutor().substitute(arrayClass.getTypeParameters()[0]);
LOG.assertTrue(componentType != null, qualifierResolveResult.getSubstitutor());
- methods = new PsiMethod[] {factory.createMethodFromText("public " + componentType.createArrayType().getCanonicalText() + " __array__(int i) {return null;}", this)};
+ //15.13.1 A method reference expression of the form ArrayType :: new is always exact.
+ return factory.createMethodFromText("public " + componentType.createArrayType().getCanonicalText() + " __array__(int i) {return null;}", this);
} else {
methods = containingClass.getConstructors();
}
@@ -172,25 +173,38 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase
if (psiMethod.getTypeParameters().length > 0) {
final PsiReferenceParameterList parameterList = getParameterList();
return parameterList != null && parameterList.getTypeParameterElements().length > 0 ? psiMethod : null;
+ } else {
+ final PsiSubstitutor classSubstitutor = TypeConversionUtil.getClassSubstitutor(psiMethod.getContainingClass(), containingClass, PsiSubstitutor.EMPTY);
+ final Set<PsiType> signature = new HashSet<PsiType>(Arrays.asList(psiMethod.getSignature(PsiSubstitutor.EMPTY).getParameterTypes()));
+ signature.add(psiMethod.getReturnType());
+ boolean free = true;
+ for (PsiType type : signature) {
+ if (classSubstitutor != null) {
+ type = classSubstitutor.substitute(type);
+ }
+ if (type != null && PsiPolyExpressionUtil.mentionsTypeParameters(type, ContainerUtil.newHashSet(containingClass.getTypeParameters()))) {
+ free = false;
+ break;
+ }
+ }
+ if (free) return psiMethod;
}
}
- if (containingClass.isPhysical() && containingClass.hasTypeParameters()) {
+ if (containingClass.hasTypeParameters()) {
final PsiElement qualifier = getQualifier();
+ PsiJavaCodeReferenceElement referenceElement = null;
if (qualifier instanceof PsiTypeElement) {
- final PsiJavaCodeReferenceElement referenceElement = ((PsiTypeElement)qualifier).getInnermostComponentReferenceElement();
- if (referenceElement != null) {
- final PsiReferenceParameterList parameterList = referenceElement.getParameterList();
- if (parameterList == null || parameterList.getTypeParameterElements().length == 0) {
- return null;
- }
- }
+ referenceElement = ((PsiTypeElement)qualifier).getInnermostComponentReferenceElement();
} else if (qualifier instanceof PsiReferenceExpression) {
final PsiReferenceExpression expression = (PsiReferenceExpression)qualifier;
if (qualifierResolveResult.isReferenceTypeQualified()) {
- final PsiReferenceParameterList parameterList = expression.getParameterList();
- if (parameterList == null || parameterList.getTypeParameterElements().length == 0) {
- return null;
- }
+ referenceElement = expression;
+ }
+ }
+ if (referenceElement != null) {
+ final PsiReferenceParameterList parameterList = referenceElement.getParameterList();
+ if (parameterList == null || parameterList.getTypeParameterElements().length == 0) {
+ return null;
}
}
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiReferenceParameterListImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiReferenceParameterListImpl.java
index e85e81cb4bd8..743bd36abf5f 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiReferenceParameterListImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiReferenceParameterListImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@ import com.intellij.psi.impl.PsiImplUtil;
import com.intellij.psi.impl.source.tree.*;
import com.intellij.psi.tree.ChildRoleBase;
import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.tree.TokenSet;
import com.intellij.util.CharTable;
import org.jetbrains.annotations.NotNull;
@@ -30,6 +31,7 @@ import org.jetbrains.annotations.NotNull;
*/
public class PsiReferenceParameterListImpl extends CompositePsiElement implements PsiReferenceParameterList {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.java.PsiReferenceParameterListImpl");
+ private static final TokenSet TYPE_SET = TokenSet.create(JavaElementType.TYPE);
public PsiReferenceParameterListImpl() {
super(JavaElementType.REFERENCE_PARAMETER_LIST);
@@ -124,23 +126,8 @@ public class PsiReferenceParameterListImpl extends CompositePsiElement implement
final TreeElement firstAdded = super.addInternal(first, last, anchor, before);
- if (first == last && first.getElementType() == JavaElementType.TYPE){
- for(ASTNode child = first.getTreeNext(); child != null; child = child.getTreeNext()){
- if (child.getElementType() == JavaTokenType.COMMA) break;
- if (child.getElementType() == JavaElementType.TYPE){
- TreeElement comma = Factory.createSingleLeafElement(JavaTokenType.COMMA, ",", 0, 1, treeCharTab, getManager());
- super.addInternal(comma, comma, first, Boolean.FALSE);
- break;
- }
- }
- for(ASTNode child = first.getTreePrev(); child != null; child = child.getTreePrev()){
- if (child.getElementType() == JavaTokenType.COMMA) break;
- if (child.getElementType() == JavaElementType.TYPE){
- TreeElement comma = Factory.createSingleLeafElement(JavaTokenType.COMMA, ",", 0, 1, treeCharTab, getManager());
- super.addInternal(comma, comma, child, Boolean.FALSE);
- break;
- }
- }
+ if (first == last && first.getElementType() == JavaElementType.TYPE) {
+ JavaSourceUtil.addSeparatingComma(this, first, TYPE_SET);
}
return firstAdded;
@@ -148,17 +135,8 @@ public class PsiReferenceParameterListImpl extends CompositePsiElement implement
@Override
public void deleteChildInternal(@NotNull ASTNode child) {
- if (child.getElementType() == JavaElementType.TYPE){
- ASTNode next = PsiImplUtil.skipWhitespaceAndComments(child.getTreeNext());
- if (next != null && next.getElementType() == JavaTokenType.COMMA){
- deleteChildInternal(next);
- }
- else{
- ASTNode prev = PsiImplUtil.skipWhitespaceAndCommentsBack(child.getTreePrev());
- if (prev != null && prev.getElementType() == JavaTokenType.COMMA){
- deleteChildInternal(prev);
- }
- }
+ if (child.getElementType() == JavaElementType.TYPE) {
+ JavaSourceUtil.deleteSeparatingComma(this, child);
}
super.deleteChildInternal(child);
@@ -186,6 +164,7 @@ public class PsiReferenceParameterListImpl extends CompositePsiElement implement
}
}
+ @Override
public String toString() {
return "PsiReferenceParameterList";
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/TypeParameterListElement.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/TypeParameterListElement.java
index 43d9d80c5742..2a3bdbaa2f4e 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/TypeParameterListElement.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/TypeParameterListElement.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@ import com.intellij.psi.impl.PsiImplUtil;
import com.intellij.psi.impl.source.tree.*;
import com.intellij.psi.tree.ChildRoleBase;
import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.tree.TokenSet;
import com.intellij.util.CharTable;
import org.jetbrains.annotations.NotNull;
@@ -30,6 +31,7 @@ import org.jetbrains.annotations.NotNull;
*/
public class TypeParameterListElement extends CompositeElement {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.java.TypeParameterListElement");
+ private static final TokenSet TYPE_PARAMETER_SET = TokenSet.create(JavaElementType.TYPE_PARAMETER);
public TypeParameterListElement() {
super(JavaElementType.TYPE_PARAMETER_LIST);
@@ -82,25 +84,9 @@ public class TypeParameterListElement extends CompositeElement {
}
}
- final TreeElement firstAdded = super.addInternal(first, last, anchor, before);
-
+ TreeElement firstAdded = super.addInternal(first, last, anchor, before);
if (first == last && first.getElementType() == JavaElementType.TYPE_PARAMETER) {
- for(ASTNode child = first.getTreeNext(); child != null; child = child.getTreeNext()){
- if (child.getElementType() == JavaTokenType.COMMA) break;
- if (child.getElementType() == JavaElementType.TYPE_PARAMETER){
- final TreeElement comma = Factory.createSingleLeafElement(JavaTokenType.COMMA, ",", 0, 1, treeCharTab, getManager());
- super.addInternal(comma, comma, first, Boolean.FALSE);
- break;
- }
- }
- for(ASTNode child = first.getTreePrev(); child != null; child = child.getTreePrev()){
- if (child.getElementType() == JavaTokenType.COMMA) break;
- if (child.getElementType() == JavaElementType.TYPE_PARAMETER){
- final TreeElement comma = Factory.createSingleLeafElement(JavaTokenType.COMMA, ",", 0, 1, treeCharTab, getManager());
- super.addInternal(comma, comma, child, Boolean.FALSE);
- break;
- }
- }
+ JavaSourceUtil.addSeparatingComma(this, first, TYPE_PARAMETER_SET);
}
return firstAdded;
}
@@ -108,18 +94,11 @@ public class TypeParameterListElement extends CompositeElement {
@Override
public void deleteChildInternal(@NotNull final ASTNode child) {
if (child.getElementType() == JavaElementType.TYPE_PARAMETER){
- final ASTNode next = PsiImplUtil.skipWhitespaceAndComments(child.getTreeNext());
- if (next != null && next.getElementType() == JavaTokenType.COMMA){
- deleteChildInternal(next);
- }
- else{
- final ASTNode prev = PsiImplUtil.skipWhitespaceAndCommentsBack(child.getTreePrev());
- if (prev != null && prev.getElementType() == JavaTokenType.COMMA){
- deleteChildInternal(prev);
- }
- }
+ JavaSourceUtil.deleteSeparatingComma(this, child);
}
+
super.deleteChildInternal(child);
+
if (child.getElementType() == JavaElementType.TYPE_PARAMETER) {
final ASTNode lt = findChildByRole(ChildRole.LT_IN_TYPE_LIST);
final ASTNode next = PsiImplUtil.skipWhitespaceAndComments(lt.getTreeNext());
diff --git a/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java b/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java
index 59083c625f82..3d9ea08125a8 100644
--- a/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java
+++ b/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java
@@ -316,7 +316,8 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
// prefer derived class
signatures.put(signature, info);
- } else {
+ }
+ else {
final PsiMethodCallExpression methodCallExpression = PsiTreeUtil.getParentOfType(myArgumentsList, PsiMethodCallExpression.class);
if (methodCallExpression != null) {
final PsiReferenceExpression expression = methodCallExpression.getMethodExpression();
@@ -324,14 +325,16 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
PsiClass currentClass;
if (qualifierExpression != null) {
currentClass = PsiUtil.resolveClassInClassTypeOnly(qualifierExpression.getType());
- } else {
+ }
+ else {
currentClass = PsiTreeUtil.getParentOfType(expression, PsiClass.class);
}
- if (currentClass != null && InheritanceUtil.isInheritorOrSelf(currentClass, class1, true) && InheritanceUtil.isInheritorOrSelf(currentClass, existingClass, true)) {
- final PsiSubstitutor eSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(existingClass, currentClass, PsiSubstitutor.EMPTY);
- final PsiSubstitutor cSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(class1, currentClass, PsiSubstitutor.EMPTY);
- if (MethodSignatureUtil.areSignaturesEqual(existingMethod.getSignature(eSubstitutor), method.getSignature(cSubstitutor))) {
+ if (currentClass != null) {
+ final PsiSubstitutor eSubstitutor = TypeConversionUtil.getMaybeSuperClassSubstitutor(existingClass, currentClass, PsiSubstitutor.EMPTY, null);
+ final PsiSubstitutor cSubstitutor = TypeConversionUtil.getMaybeSuperClassSubstitutor(class1, currentClass, PsiSubstitutor.EMPTY, null);
+ if (eSubstitutor != null && cSubstitutor != null &&
+ MethodSignatureUtil.areSignaturesEqual(existingMethod.getSignature(eSubstitutor), method.getSignature(cSubstitutor))) {
final PsiType returnType = eSubstitutor.substitute(existingMethod.getReturnType());
final PsiType returnType1 = cSubstitutor.substitute(method.getReturnType());
if (returnType != null && returnType1 != null && !returnType1.equals(returnType)) {
diff --git a/java/java-psi-impl/src/com/intellij/psi/scope/processor/MethodCandidatesProcessor.java b/java/java-psi-impl/src/com/intellij/psi/scope/processor/MethodCandidatesProcessor.java
index 2b36a9c49b47..c12972d354c7 100644
--- a/java/java-psi-impl/src/com/intellij/psi/scope/processor/MethodCandidatesProcessor.java
+++ b/java/java-psi-impl/src/com/intellij/psi/scope/processor/MethodCandidatesProcessor.java
@@ -83,7 +83,7 @@ public class MethodCandidatesProcessor extends MethodsProcessor{
public PsiType[] getArgumentTypes() {
if (myExpressionTypes == null && argumentList != null) {
final PsiType[] expressionTypes = getExpressionTypes(argumentList);
- if (!MethodCandidateInfo.ourOverloadGuard.currentStack().isEmpty()) {
+ if (MethodCandidateInfo.isOverloadCheck()) {
return expressionTypes;
}
myExpressionTypes = expressionTypes;
diff --git a/java/java-structure-view/src/com/intellij/ide/structureView/impl/java/PsiMethodTreeElement.java b/java/java-structure-view/src/com/intellij/ide/structureView/impl/java/PsiMethodTreeElement.java
index c1afbee6ada4..669080107623 100644
--- a/java/java-structure-view/src/com/intellij/ide/structureView/impl/java/PsiMethodTreeElement.java
+++ b/java/java-structure-view/src/com/intellij/ide/structureView/impl/java/PsiMethodTreeElement.java
@@ -51,12 +51,12 @@ public class PsiMethodTreeElement extends JavaClassTreeElementBase<PsiMethod> im
final PsiMethod element = getElement();
if (element == null || element instanceof SyntheticElement) return result;
- final TextRange range = element.getTextRange();
- if (range == null) return result;
-
final PsiFile psiFile = element.getContainingFile();
if (psiFile == null || psiFile instanceof PsiCompiledElement) return result;
+ final TextRange range = element.getTextRange();
+ if (range == null) return result;
+
final String fileText = psiFile.getText();
if (fileText == null) return result;
diff --git a/java/java-tests/testData/codeInsight/clsHighlighting/IDEA127714.java b/java/java-tests/testData/codeInsight/clsHighlighting/IDEA127714.java
new file mode 100644
index 000000000000..08713f898f15
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/clsHighlighting/IDEA127714.java
@@ -0,0 +1,9 @@
+import a.A;
+
+class IDEA127714 {
+ {
+ A<E, String> strings = new A<>(E.class);
+ }
+}
+
+enum E {} \ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/clsHighlighting/libs/IDEA127714.jar b/java/java-tests/testData/codeInsight/clsHighlighting/libs/IDEA127714.jar
new file mode 100644
index 000000000000..915d3a074810
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/clsHighlighting/libs/IDEA127714.jar
Binary files differ
diff --git a/java/java-tests/testData/codeInsight/completeStatement/AlreadyCompleteCatch.java b/java/java-tests/testData/codeInsight/completeStatement/AlreadyCompleteCatch.java
new file mode 100644
index 000000000000..d8ea6191cef8
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completeStatement/AlreadyCompleteCatch.java
@@ -0,0 +1,12 @@
+
+class Foo {
+ {
+ try
+ {
+
+ } catch (Ex<caret>ception e)
+ {
+
+ }
+ }
+} \ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/completeStatement/AlreadyCompleteCatch_after.java b/java/java-tests/testData/codeInsight/completeStatement/AlreadyCompleteCatch_after.java
new file mode 100644
index 000000000000..f4874b45962e
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completeStatement/AlreadyCompleteCatch_after.java
@@ -0,0 +1,12 @@
+
+class Foo {
+ {
+ try
+ {
+
+ } catch (Exception e)
+ {
+ <caret>
+ }
+ }
+} \ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/completion/normal/MulticaretCompletionFromNonPrimaryCaret.java b/java/java-tests/testData/codeInsight/completion/normal/MulticaretCompletionFromNonPrimaryCaret.java
new file mode 100644
index 000000000000..077ff80bd5c7
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/normal/MulticaretCompletionFromNonPrimaryCaret.java
@@ -0,0 +1,4 @@
+class Foo {{
+ System.<caret>
+ System.<caret>
+}}
diff --git a/java/java-tests/testData/codeInsight/completion/smartType/DontSuggestWildcardGenerics-out.java b/java/java-tests/testData/codeInsight/completion/smartType/DontSuggestWildcardGenerics-out.java
new file mode 100644
index 000000000000..41f3d57525a2
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/smartType/DontSuggestWildcardGenerics-out.java
@@ -0,0 +1,16 @@
+class Main {
+ void foo(List<? extends Number> list) {
+ list.forEach(new Consumer<Number>() {
+ @Override
+ public void consume(Number number) {
+ <caret>
+ }
+ });
+ }
+}
+
+class List<T> {
+ void forEach(Consumer<? super T> consumer);
+}
+
+interface Consumer<T> { void consume(T t); } \ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/completion/smartType/DontSuggestWildcardGenerics.java b/java/java-tests/testData/codeInsight/completion/smartType/DontSuggestWildcardGenerics.java
new file mode 100644
index 000000000000..b1d18904a6fb
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/smartType/DontSuggestWildcardGenerics.java
@@ -0,0 +1,11 @@
+class Main {
+ void foo(List<? extends Number> list) {
+ list.forEach(new <caret>);
+ }
+}
+
+class List<T> {
+ void forEach(Consumer<? super T> consumer);
+}
+
+interface Consumer<T> { void consume(T t); } \ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/completion/smartTypeSorting/PreferFieldsToConstants.java b/java/java-tests/testData/codeInsight/completion/smartTypeSorting/PreferFieldsToConstants.java
new file mode 100644
index 000000000000..2b47bb58a498
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/smartTypeSorting/PreferFieldsToConstants.java
@@ -0,0 +1,17 @@
+public class Foo {
+
+ private LocalDate dateField;
+
+ void foo(LocalDate date) {
+
+ }
+
+ void bar() {
+ foo(<caret>)
+ }
+}
+
+class LocalDate {
+ public static final LocalDate MAX;
+ public static final LocalDate MIN;
+} \ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/PolymorphicTypeCast.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/PolymorphicTypeCast.java
index 8be16fc1db85..8ba3ea4f8037 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/PolymorphicTypeCast.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/PolymorphicTypeCast.java
@@ -94,4 +94,96 @@ class C {
void asLongs(Integer i) {
long l = (long) i;
}
+
+ void foo(Object o) {}
+ public void cast2(Byte operand) {
+ foo((<warning descr="Casting 'operand' to 'byte' is redundant">byte</warning>)operand);
+ foo((short)operand);
+ foo(<error descr="Inconvertible types; cannot cast 'java.lang.Byte' to 'char'">(char)operand</error>);
+ foo((int)operand);
+ foo((long)operand);
+ foo((float)operand);
+ foo((double)operand);
+ foo(<error descr="Inconvertible types; cannot cast 'java.lang.Byte' to 'boolean'">(boolean)operand</error>);
+ }
+ public void cast2(Short operand) {
+ foo(<error descr="Inconvertible types; cannot cast 'java.lang.Short' to 'byte'">(byte)operand</error>);
+ foo((<warning descr="Casting 'operand' to 'short' is redundant">short</warning>)operand);
+ foo(<error descr="Inconvertible types; cannot cast 'java.lang.Short' to 'char'">(char)operand</error>);
+ foo((int)operand);
+ foo((long)operand);
+ foo((float)operand);
+ foo((double)operand);
+ foo(<error descr="Inconvertible types; cannot cast 'java.lang.Short' to 'boolean'">(boolean)operand</error>);
+ }
+ public void cast2(Character operand) {
+ foo(<error descr="Inconvertible types; cannot cast 'java.lang.Character' to 'byte'">(byte)operand</error>);
+ foo(<error descr="Inconvertible types; cannot cast 'java.lang.Character' to 'short'">(short)operand</error>);
+ foo((<warning descr="Casting 'operand' to 'char' is redundant">char</warning>)operand);
+ foo((int)operand);
+ foo((long)operand);
+ foo((float)operand);
+ foo((double)operand);
+ foo(<error descr="Inconvertible types; cannot cast 'java.lang.Character' to 'boolean'">(boolean)operand</error>);
+ }
+ public void cast2(Integer operand) {
+ foo(<error descr="Inconvertible types; cannot cast 'java.lang.Integer' to 'byte'">(byte)operand</error>);
+ foo(<error descr="Inconvertible types; cannot cast 'java.lang.Integer' to 'short'">(short)operand</error>);
+ foo(<error descr="Inconvertible types; cannot cast 'java.lang.Integer' to 'char'">(char)operand</error>);
+ foo((<warning descr="Casting 'operand' to 'int' is redundant">int</warning>)operand);
+ foo((long)operand);
+ foo((float)operand);
+ foo((double)operand);
+ foo(<error descr="Inconvertible types; cannot cast 'java.lang.Integer' to 'boolean'">(boolean)operand</error>);
+ }
+ public void cast2(Long operand) {
+ foo(<error descr="Inconvertible types; cannot cast 'java.lang.Long' to 'byte'">(byte)operand</error>);
+ foo(<error descr="Inconvertible types; cannot cast 'java.lang.Long' to 'short'">(short)operand</error>);
+ foo(<error descr="Inconvertible types; cannot cast 'java.lang.Long' to 'char'">(char)operand</error>);
+ foo(<error descr="Inconvertible types; cannot cast 'java.lang.Long' to 'int'">(int)operand</error>);
+ foo((<warning descr="Casting 'operand' to 'long' is redundant">long</warning>)operand);
+ foo((float)operand);
+ foo((double)operand);
+ foo(<error descr="Inconvertible types; cannot cast 'java.lang.Long' to 'boolean'">(boolean)operand</error>);
+ }
+ public void cast2(Float operand) {
+ foo(<error descr="Inconvertible types; cannot cast 'java.lang.Float' to 'byte'">(byte)operand</error>);
+ foo(<error descr="Inconvertible types; cannot cast 'java.lang.Float' to 'short'">(short)operand</error>);
+ foo(<error descr="Inconvertible types; cannot cast 'java.lang.Float' to 'char'">(char)operand</error>);
+ foo(<error descr="Inconvertible types; cannot cast 'java.lang.Float' to 'int'">(int)operand</error>);
+ foo(<error descr="Inconvertible types; cannot cast 'java.lang.Float' to 'long'">(long)operand</error>);
+ foo((<warning descr="Casting 'operand' to 'float' is redundant">float</warning>)operand);
+ foo((double)operand);
+ foo(<error descr="Inconvertible types; cannot cast 'java.lang.Float' to 'boolean'">(boolean)operand</error>);
+ }
+ public void cast2(Double operand) {
+ foo(<error descr="Inconvertible types; cannot cast 'java.lang.Double' to 'byte'">(byte)operand</error>);
+ foo(<error descr="Inconvertible types; cannot cast 'java.lang.Double' to 'short'">(short)operand</error>);
+ foo(<error descr="Inconvertible types; cannot cast 'java.lang.Double' to 'char'">(char)operand</error>);
+ foo(<error descr="Inconvertible types; cannot cast 'java.lang.Double' to 'int'">(int)operand</error>);
+ foo(<error descr="Inconvertible types; cannot cast 'java.lang.Double' to 'long'">(long)operand</error>);
+ foo(<error descr="Inconvertible types; cannot cast 'java.lang.Double' to 'float'">(float)operand</error>);
+ foo((<warning descr="Casting 'operand' to 'double' is redundant">double</warning>)operand);
+ foo(<error descr="Inconvertible types; cannot cast 'java.lang.Double' to 'boolean'">(boolean)operand</error>);
+ }
+ public void cast2(Boolean operand) {
+ foo(<error descr="Inconvertible types; cannot cast 'java.lang.Boolean' to 'byte'">(byte)operand</error>);
+ foo(<error descr="Inconvertible types; cannot cast 'java.lang.Boolean' to 'short'">(short)operand</error>);
+ foo(<error descr="Inconvertible types; cannot cast 'java.lang.Boolean' to 'char'">(char)operand</error>);
+ foo(<error descr="Inconvertible types; cannot cast 'java.lang.Boolean' to 'int'">(int)operand</error>);
+ foo(<error descr="Inconvertible types; cannot cast 'java.lang.Boolean' to 'long'">(long)operand</error>);
+ foo(<error descr="Inconvertible types; cannot cast 'java.lang.Boolean' to 'float'">(float)operand</error>);
+ foo(<error descr="Inconvertible types; cannot cast 'java.lang.Boolean' to 'double'">(double)operand</error>);
+ foo((<warning descr="Casting 'operand' to 'boolean' is redundant">boolean</warning>)operand);
+ }
+ public void cast2(Object operand) {
+ foo((<warning descr="Casting 'operand' to 'byte' is redundant">byte</warning>)operand);
+ foo((<warning descr="Casting 'operand' to 'short' is redundant">short</warning>)operand);
+ foo((<warning descr="Casting 'operand' to 'char' is redundant">char</warning>)operand);
+ foo((<warning descr="Casting 'operand' to 'int' is redundant">int</warning>)operand);
+ foo((<warning descr="Casting 'operand' to 'long' is redundant">long</warning>)operand);
+ foo((<warning descr="Casting 'operand' to 'float' is redundant">float</warning>)operand);
+ foo((<warning descr="Casting 'operand' to 'double' is redundant">double</warning>)operand);
+ foo((<warning descr="Casting 'operand' to 'boolean' is redundant">boolean</warning>)operand);
+ }
} \ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/IDEA128101.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/IDEA128101.java
new file mode 100644
index 000000000000..42be49b62f04
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/IDEA128101.java
@@ -0,0 +1,29 @@
+class TestIDEA128101 {
+
+ static class Attribute<Y> {};
+ static class Path<X> {};
+
+ static Attribute<Integer> integerAttribute;
+ static Attribute<String> stringAttribute;
+
+ static <Y> Path<Y> createPath(Attribute<Y> attribute) {
+ return new Path<>();
+ }
+ static <Y> Path<Y> createPath1(Attribute<Y> attribute) {
+ return new Path<>();
+ }
+ static <T> void construct(Class<T> aClass, Path<?>... paths) {}
+ static <T, K> void construct1(Class<T> aClass, Path<K>... paths) {}
+ static <T, K> void construct2(Class<T> aClass, Path<? extends K>... paths) {}
+ static <T, K> void construct3(Class<T> aClass, Path<? super K>... paths) {}
+ static <T, K> void construct4(Class<T> aClass, Path<? super K> path1, Path<? super K> path2) {}
+
+ public static void test() {
+ construct(String.class, createPath(integerAttribute), createPath(stringAttribute));
+ construct1<error descr="Cannot resolve method 'construct1(java.lang.Class<java.lang.String>, TestIDEA128101.Path<java.lang.Integer>, TestIDEA128101.Path<java.lang.String>)'">(String.class, createPath(integerAttribute), createPath(stringAttribute))</error>;
+ construct2(String.class, createPath(integerAttribute), createPath(stringAttribute));
+ <error descr="Type parameter K has incompatible upper bounds: Integer and String">construct3(String.class, createPath(integerAttribute), createPath(stringAttribute));</error>
+ <error descr="Type parameter K has incompatible upper bounds: Integer and String">construct4(String.class, createPath(integerAttribute), createPath(stringAttribute));</error>
+ }
+
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/IDEA128174.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/IDEA128174.java
new file mode 100644
index 000000000000..650114b06e50
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/IDEA128174.java
@@ -0,0 +1,24 @@
+import java.util.Collection;
+import java.util.List;
+
+class Test {
+
+ {
+ Matcher<? super List<String>> m = not(empty());
+ }
+
+ static <E> Matcher<Collection<E>> empty() {
+ return null;
+ }
+
+ static <T> Matcher<T> not(Matcher<T> matcher) {
+ return null;
+ }
+
+ static <T> Matcher<T> not(T value) {
+ return null;
+ }
+
+ static class Matcher<K> {}
+}
+
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/InferFromConditionalExpressionCondition.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/InferFromConditionalExpressionCondition.java
new file mode 100644
index 000000000000..8fad96c118ed
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/InferFromConditionalExpressionCondition.java
@@ -0,0 +1,14 @@
+class Test {
+ static class TKey<T> {
+ }
+
+ public interface Getter {
+ <T> T getValue(TKey<T> key);
+ }
+
+ static final TKey<Boolean> KEY_B = new TKey<>();
+
+ public static void f(Getter getter) {
+ String name = getter.getValue(KEY_B) ? "foo" : "bar";
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/PrimitiveWrapperConditionInReturnConstraint.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/PrimitiveWrapperConditionInReturnConstraint.java
new file mode 100644
index 000000000000..6788a98b215c
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/PrimitiveWrapperConditionInReturnConstraint.java
@@ -0,0 +1,15 @@
+class Test {
+ static class TKey<T> {
+ }
+
+ public interface Getter {
+ <T> T getValue(TKey<T> key);
+ }
+
+ static final TKey<Integer> KEY_I = null;
+
+
+ public static void f(Getter getter, TKey<Integer> key) {
+ double d1 = getter.getValue (key);
+ }
+} \ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/EffectiveFinal.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/EffectiveFinal.java
index 254ec7191a47..92b268394994 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/EffectiveFinal.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/EffectiveFinal.java
@@ -39,7 +39,7 @@ public class XXX {
void m3(int x, boolean cond) {
int y;
if (cond) y = 1;
- foo(() -> x+<error descr="Variable used in lambda expression should be effectively final">y</error>);
+ foo(() -> x+<error descr="Variable 'y' might not have been initialized">y</error>);
}
void m4(int x, boolean cond) {
@@ -128,3 +128,17 @@ class IDEA114737 {
};
}
}
+
+class IDEA128196 {
+ void a() {
+ int value;
+
+ try {
+ value = 1;
+ } catch (Exception e) {
+ return;
+ }
+
+ new Thread(() -> System.out.println(value));
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/IDEA127765.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/IDEA127765.java
new file mode 100644
index 000000000000..095448e262b3
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/IDEA127765.java
@@ -0,0 +1,19 @@
+import java.util.Map;
+import java.util.Optional;
+import java.util.function.Function;
+import java.util.function.Predicate;
+
+class IDEA127765 {
+ void a(final Map<String, Optional<Double>> allValues, final Function<Optional<Double>, Double> get) {
+ final Map<String, Double> presentValues = transformValues(filterValues(allValues, Optional::isPresent), get);
+ }
+
+ public static <K, V1, V2> Map<K, V2> transformValues(Map<K, V1> fromMap, Function<? super V1, V2> function) {
+ return null;
+ }
+
+ public static <K, V> Map<K, V> filterValues(Map<K, V> unfiltered, Predicate<? super V> valuePredicate) {
+ return null;
+ }
+
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/afterOnVarargsPlace.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/afterOnVarargsPlace.java
new file mode 100644
index 000000000000..82e3cc9aa3e6
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/afterOnVarargsPlace.java
@@ -0,0 +1,10 @@
+// "Replace with lambda" "true"
+class Test2 {
+
+ void f(Runnable... rs){}
+ {
+ f(null, () -> {
+
+ });
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/beforeOnVarargsPlace.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/beforeOnVarargsPlace.java
new file mode 100644
index 000000000000..af9db7767997
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/beforeOnVarargsPlace.java
@@ -0,0 +1,13 @@
+// "Replace with lambda" "true"
+class Test2 {
+
+ void f(Runnable... rs){}
+ {
+ f(null, new Run<caret>nable() {
+ @Override
+ public void run() {
+
+ }
+ });
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/null/singleExclamationIgnored.java b/java/java-tests/testData/codeInsight/template/postfix/templates/null/singleExclamationIgnored.java
new file mode 100644
index 000000000000..1af8cd0813a9
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/null/singleExclamationIgnored.java
@@ -0,0 +1,5 @@
+public class Foo {
+ void m(Object o) {
+ !.null<caret>
+ }
+} \ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/null/singleExclamationIgnored_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/null/singleExclamationIgnored_after.java
new file mode 100644
index 000000000000..1334be6b7029
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/null/singleExclamationIgnored_after.java
@@ -0,0 +1,5 @@
+public class Foo {
+ void m(Object o) {
+ !.null <caret>
+ }
+} \ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/typing/invalidInitialSyntax_after.java b/java/java-tests/testData/codeInsight/typing/invalidInitialSyntax_after.java
new file mode 100644
index 000000000000..08b2afd09cb9
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/typing/invalidInitialSyntax_after.java
@@ -0,0 +1,7 @@
+class Foo {
+ public static void main(String[] args) {
+ String s = "";
+ s.replaceAll("\\<caret>");
+ System.out.println();
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/typing/invalidInitialSyntax_before.java b/java/java-tests/testData/codeInsight/typing/invalidInitialSyntax_before.java
new file mode 100644
index 000000000000..bee6f10053c2
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/typing/invalidInitialSyntax_before.java
@@ -0,0 +1,7 @@
+class Foo {
+ public static void main(String[] args) {
+ String s = "";
+ s.replaceAll("<caret>");
+ System.out.println();
+ }
+}
diff --git a/java/java-tests/testData/find/findInEditor/BasicFind.gold b/java/java-tests/testData/find/findInEditor/BasicFind.gold
index 14e4182499b7..46486765486d 100644
--- a/java/java-tests/testData/find/findInEditor/BasicFind.gold
+++ b/java/java-tests/testData/find/findInEditor/BasicFind.gold
@@ -3,8 +3,7 @@ myStringToFind =a
myStringToReplace =
isReplaceState =false
isWholeWordsOnly =false
-isInStringLiterals =false
-isInComments =false
+searchContext =ANY
isFromCursor =true
isForward =true
isGlobal =true
@@ -22,6 +21,7 @@ isWithSubdirectories =true
fileFilter =null
moduleName =null
customScopeName =null
+searchInProjectFiles =false
--
diff --git a/java/java-tests/testData/find/findInEditor/EmacsLikeFallback.gold b/java/java-tests/testData/find/findInEditor/EmacsLikeFallback.gold
index a2168ba66e2a..bfda616a3ac1 100644
--- a/java/java-tests/testData/find/findInEditor/EmacsLikeFallback.gold
+++ b/java/java-tests/testData/find/findInEditor/EmacsLikeFallback.gold
@@ -3,8 +3,7 @@ myStringToFind =a
myStringToReplace =
isReplaceState =false
isWholeWordsOnly =false
-isInStringLiterals =false
-isInComments =false
+searchContext =ANY
isFromCursor =true
isForward =true
isGlobal =true
@@ -22,6 +21,7 @@ isWithSubdirectories =true
fileFilter =null
moduleName =null
customScopeName =null
+searchInProjectFiles =false
--
@@ -37,8 +37,7 @@ myStringToFind =ab
myStringToReplace =
isReplaceState =false
isWholeWordsOnly =false
-isInStringLiterals =false
-isInComments =false
+searchContext =ANY
isFromCursor =true
isForward =true
isGlobal =true
@@ -56,6 +55,7 @@ isWithSubdirectories =true
fileFilter =null
moduleName =null
customScopeName =null
+searchInProjectFiles =false
--
@@ -70,8 +70,7 @@ myStringToFind =a
myStringToReplace =
isReplaceState =false
isWholeWordsOnly =false
-isInStringLiterals =false
-isInComments =false
+searchContext =ANY
isFromCursor =true
isForward =true
isGlobal =true
@@ -89,6 +88,7 @@ isWithSubdirectories =true
fileFilter =null
moduleName =null
customScopeName =null
+searchInProjectFiles =false
--
diff --git a/java/java-tests/testData/find/findInEditor/ReplacementWithEmptyString.gold b/java/java-tests/testData/find/findInEditor/ReplacementWithEmptyString.gold
index 478eb649684d..a4d44cbfa445 100644
--- a/java/java-tests/testData/find/findInEditor/ReplacementWithEmptyString.gold
+++ b/java/java-tests/testData/find/findInEditor/ReplacementWithEmptyString.gold
@@ -3,8 +3,7 @@ myStringToFind =
myStringToReplace =
isReplaceState =false
isWholeWordsOnly =false
-isInStringLiterals =false
-isInComments =false
+searchContext =ANY
isFromCursor =true
isForward =true
isGlobal =true
@@ -22,6 +21,7 @@ isWithSubdirectories =true
fileFilter =null
moduleName =null
customScopeName =null
+searchInProjectFiles =false
--
@@ -33,8 +33,7 @@ myStringToFind =a
myStringToReplace =
isReplaceState =false
isWholeWordsOnly =false
-isInStringLiterals =false
-isInComments =false
+searchContext =ANY
isFromCursor =true
isForward =true
isGlobal =true
@@ -52,6 +51,7 @@ isWithSubdirectories =true
fileFilter =null
moduleName =null
customScopeName =null
+searchInProjectFiles =false
--
@@ -65,8 +65,7 @@ myStringToFind =a
myStringToReplace =
isReplaceState =true
isWholeWordsOnly =false
-isInStringLiterals =false
-isInComments =false
+searchContext =ANY
isFromCursor =true
isForward =true
isGlobal =true
@@ -84,6 +83,7 @@ isWithSubdirectories =true
fileFilter =null
moduleName =null
customScopeName =null
+searchInProjectFiles =false
--
Replacement Preview: <Empty string>
@@ -99,8 +99,7 @@ myStringToFind =a
myStringToReplace =
isReplaceState =true
isWholeWordsOnly =false
-isInStringLiterals =false
-isInComments =false
+searchContext =ANY
isFromCursor =true
isForward =true
isGlobal =true
@@ -118,6 +117,7 @@ isWithSubdirectories =true
fileFilter =null
moduleName =null
customScopeName =null
+searchInProjectFiles =false
--
diff --git a/java/java-tests/testData/inspection/dataFlow/CheckedExceptionDominance/src/Test.java b/java/java-tests/testData/inspection/dataFlow/CheckedExceptionDominance/src/Test.java
index 4a0a690f0e21..4f0586d30a96 100644
--- a/java/java-tests/testData/inspection/dataFlow/CheckedExceptionDominance/src/Test.java
+++ b/java/java-tests/testData/inspection/dataFlow/CheckedExceptionDominance/src/Test.java
@@ -19,6 +19,6 @@
}
public static void bar() throws CheckedException {
- throw new CheckedException();
+ if (new Random().nextInt() > 2) throw new CheckedException();
}
}
diff --git a/java/java-tests/testData/inspection/dataFlow/IDEADEV10489/expected.xml b/java/java-tests/testData/inspection/dataFlow/IDEADEV10489/expected.xml
index bb6256f74012..4a088210968c 100644
--- a/java/java-tests/testData/inspection/dataFlow/IDEADEV10489/expected.xml
+++ b/java/java-tests/testData/inspection/dataFlow/IDEADEV10489/expected.xml
@@ -7,7 +7,7 @@
</problem>
<problem>
<file>IDEADEV10489.java</file>
- <line>12</line>
+ <line>8</line>
<description>Method invocation 's.length()' may produce NullPointerException</description>
</problem>
</problems> \ No newline at end of file
diff --git a/java/java-tests/testData/inspection/dataFlow/IDEADEV10489/src/IDEADEV10489.java b/java/java-tests/testData/inspection/dataFlow/IDEADEV10489/src/IDEADEV10489.java
index 60259479d353..ee41e588dd3e 100644
--- a/java/java-tests/testData/inspection/dataFlow/IDEADEV10489/src/IDEADEV10489.java
+++ b/java/java-tests/testData/inspection/dataFlow/IDEADEV10489/src/IDEADEV10489.java
@@ -1,7 +1,5 @@
class IDEADEV10489 {
- static String getS() {
- return null;
- }
+ static native String getS();
static void f() {
String s = getS();
@@ -17,7 +15,5 @@ class IDEADEV10489 {
}
}
- private static boolean foo() {
- return false;
- }
+ private static native boolean foo();
} \ No newline at end of file
diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/AssertFailInCatch.java b/java/java-tests/testData/inspection/dataFlow/fixture/AssertFailInCatch.java
index 93fcf6d5c2d2..55c7c2b51de0 100644
--- a/java/java-tests/testData/inspection/dataFlow/fixture/AssertFailInCatch.java
+++ b/java/java-tests/testData/inspection/dataFlow/fixture/AssertFailInCatch.java
@@ -18,7 +18,5 @@ class Test {
}
}
- private static @NotNull String createString() {
- throw new NullPointerException();
- }
+ private static native @NotNull String createString();
} \ No newline at end of file
diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/CatchThrowable.java b/java/java-tests/testData/inspection/dataFlow/fixture/CatchThrowable.java
index ecb9b264bb62..a30d934f64b6 100644
--- a/java/java-tests/testData/inspection/dataFlow/fixture/CatchThrowable.java
+++ b/java/java-tests/testData/inspection/dataFlow/fixture/CatchThrowable.java
@@ -1,3 +1,5 @@
+import java.util.Random;
+
class BrokenAlignment {
public static void main(String[] args) {
@@ -20,7 +22,7 @@ class BrokenAlignment {
}
public static void doSomething() {
- throw new RuntimeException("dummy");
+ if (new Random().nextInt() > 2) throw new RuntimeException("dummy");
}
} \ No newline at end of file
diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/ContractWithNoArgs.java b/java/java-tests/testData/inspection/dataFlow/fixture/ContractWithNoArgs.java
new file mode 100644
index 000000000000..006c2e3407ec
--- /dev/null
+++ b/java/java-tests/testData/inspection/dataFlow/fixture/ContractWithNoArgs.java
@@ -0,0 +1,24 @@
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+class Doo {
+
+ @NotNull
+ public String doSomething() {
+ String s = getSomeString();
+ if (s == null) {
+ throwSomeError();
+ }
+ return s;
+ }
+
+ private static void throwSomeError() {
+ throw new RuntimeException();
+ }
+
+ @Nullable
+ public String getSomeString() {
+ return Math.random() > 0.5 ? null : "Yeah";
+ }
+
+}
diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/CustomTypeQualifierDefault.java b/java/java-tests/testData/inspection/dataFlow/fixture/CustomTypeQualifierDefault.java
new file mode 100644
index 000000000000..e9ec6b1dbe11
--- /dev/null
+++ b/java/java-tests/testData/inspection/dataFlow/fixture/CustomTypeQualifierDefault.java
@@ -0,0 +1,25 @@
+import foo.*;
+import org.jetbrains.annotations.NotNull;
+
+class Some {
+ void foo(@NotNull String s) {
+ NotNullClass.foo(null);
+ if (<warning descr="Condition 'NotNullClass.foo(s) == null' is always 'false'">NotNullClass.foo(s) == null</warning>) {}
+
+ NullableClass.foo(null);
+ if (NullableClass.foo("a") == null) {}
+
+ AnotherPackageNotNull.foo(null);
+ if (<warning descr="Condition 'AnotherPackageNotNull.foo(s) == null' is always 'false'">AnotherPackageNotNull.foo(s) == null</warning>) {}
+ }
+
+}
+
+@bar.MethodsAreNotNullByDefault
+class NotNullClass {
+ static native Object foo(String s);
+
+}
+class NullableClass {
+ static native Object foo(String s);
+} \ No newline at end of file
diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/FloatComparisons.java b/java/java-tests/testData/inspection/dataFlow/fixture/FloatComparisons.java
new file mode 100644
index 000000000000..5c553bcba0bf
--- /dev/null
+++ b/java/java-tests/testData/inspection/dataFlow/fixture/FloatComparisons.java
@@ -0,0 +1,7 @@
+class Test {
+ public static void testFunc(final float width, final float height) {
+ if (width < 0f || height < 0f) {
+ throw new IllegalArgumentException("Size must be non-negative");
+ }
+ }
+} \ No newline at end of file
diff --git a/java/java-tests/testData/refactoring/renameCollisions/RenameMethodNoCollisionWithOtherSignatureMethodRef.java b/java/java-tests/testData/refactoring/renameCollisions/RenameMethodNoCollisionWithOtherSignatureMethodRef.java
new file mode 100644
index 000000000000..dd815139efa5
--- /dev/null
+++ b/java/java-tests/testData/refactoring/renameCollisions/RenameMethodNoCollisionWithOtherSignatureMethodRef.java
@@ -0,0 +1,9 @@
+class Test {
+
+ static void f<caret>oo() {}
+ static void foo2(int i) {}
+
+ {
+ Runnable r = Test :: foo;
+ }
+} \ No newline at end of file
diff --git a/java/java-tests/testData/refactoring/renameCollisions/RenameMethodNoCollisionWithOtherSignatureMethodRef.java.after b/java/java-tests/testData/refactoring/renameCollisions/RenameMethodNoCollisionWithOtherSignatureMethodRef.java.after
new file mode 100644
index 000000000000..8dab0803fcec
--- /dev/null
+++ b/java/java-tests/testData/refactoring/renameCollisions/RenameMethodNoCollisionWithOtherSignatureMethodRef.java.after
@@ -0,0 +1,9 @@
+class Test {
+
+ static void foo2() {}
+ static void foo2(int i) {}
+
+ {
+ Runnable r = Test ::foo2;
+ }
+} \ No newline at end of file
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/ClsGenerics18HighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/ClsGenerics18HighlightingTest.java
index ae0ec20ab4d2..8383550b3e5c 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/ClsGenerics18HighlightingTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/ClsGenerics18HighlightingTest.java
@@ -20,6 +20,8 @@ import com.intellij.pom.java.LanguageLevel;
public class ClsGenerics18HighlightingTest extends ClsGenericsHighlightingTest {
public void testIDEA121866() { doTest(); }
+ public void testIDEA127714() { doTest(); }
+
@Override
protected LanguageLevel getLanguageLevel() {
return LanguageLevel.JDK_1_8;
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/CompleteStatementTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/CompleteStatementTest.java
index 2eecdaa9b221..3f199d44ea13 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/CompleteStatementTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/CompleteStatementTest.java
@@ -17,9 +17,6 @@ package com.intellij.codeInsight;
import com.intellij.JavaTestUtil;
import com.intellij.openapi.actionSystem.IdeActions;
-import com.intellij.openapi.roots.LanguageLevelProjectExtension;
-import com.intellij.pom.java.LanguageLevel;
-import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
@@ -54,6 +51,18 @@ public class CompleteStatementTest extends EditorActionTestCase {
public void testCompleteCatchLParen() throws Exception { doTest(); }
+ public void testAlreadyCompleteCatch() throws Exception {
+ CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject());
+ int old = settings.BRACE_STYLE;
+ settings.BRACE_STYLE = CommonCodeStyleSettings.NEXT_LINE;
+ try {
+ doTest();
+ }
+ finally {
+ settings.BRACE_STYLE = old;
+ }
+ }
+
public void testCompleteCatchWithExpression() throws Exception { doTest(); }
public void testCompleteCatchBody() throws Exception { doTest(); }
@@ -171,8 +180,6 @@ public class CompleteStatementTest extends EditorActionTestCase {
}
public void testSCR36110() throws Exception {
- JavaPsiFacade facade = JavaPsiFacade.getInstance(getProject());
- LanguageLevel old = LanguageLevelProjectExtension.getInstance(facade.getProject()).getLanguageLevel();
doTest();
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/JavaTypingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/JavaTypingTest.java
index f59162a6d5b2..9ca3b6084a43 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/JavaTypingTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/JavaTypingTest.java
@@ -16,6 +16,7 @@
package com.intellij.codeInsight;
import com.intellij.openapi.editor.ex.EditorEx;
+import com.intellij.psi.PsiDocumentManager;
import com.intellij.testFramework.PlatformTestUtil;
import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase;
@@ -65,6 +66,14 @@ public class JavaTypingTest extends LightPlatformCodeInsightFixtureTestCase {
myFixture.checkResultByFile(getTestName(true) + "_after.java");
}
+ public void testInvalidInitialSyntax() {
+ myFixture.configureByFile(getTestName(true) + "_before.java");
+ myFixture.type('\\');
+ PsiDocumentManager.getInstance(getProject()).commitAllDocuments(); // emulates background commit after typing first character
+ myFixture.type('\\');
+ myFixture.checkResultByFile(getTestName(true) + "_after.java");
+ }
+
private void doTest(char c) {
myFixture.configureByFile(getTestName(true) + "_before.java");
myFixture.type(c);
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy
index 77b4c0cc64a7..f5fc39041106 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy
@@ -1423,6 +1423,11 @@ class XInternalError {}
checkResult()
}
+ public void testMulticaretCompletionFromNonPrimaryCaret() {
+ configure()
+ myFixture.assertPreferredCompletionItems(0, "arraycopy")
+ }
+
public void "test complete lowercase class name"() {
myFixture.addClass("package foo; public class myClass {}")
myFixture.configureByText "a.java", """
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionOrderingTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionOrderingTest.groovy
index 1d258fe01367..f37b90e21523 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionOrderingTest.groovy
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionOrderingTest.groovy
@@ -160,6 +160,10 @@ public class SmartTypeCompletionOrderingTest extends CompletionSortingTestCase {
checkPreferredItems(0, "myVersion", "getVersion", "getSelectedVersion", "calculateVersion");
}
+ public void testPreferFieldsToConstants() {
+ checkPreferredItems(0, "dateField", "LocalDate.MAX", "LocalDate.MIN");
+ }
+
public void testPreferParametersToGetters() throws Throwable {
checkPreferredItems(0, "a", "I._1", "getLastI", "valueOf");
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java
index d2e8825cc16d..5153f19fe94a 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java
@@ -716,7 +716,7 @@ public class SmartTypeCompletionTest extends LightFixtureCompletionTestCase {
public void testMethodColon() throws Exception { doFirstItemTest(':'); }
public void testVariableColon() throws Exception { doFirstItemTest(':'); }
- private void doFirstItemTest(char c) throws Exception {
+ private void doFirstItemTest(char c) {
configureByTestName();
select(c);
checkResultByTestName();
@@ -824,6 +824,8 @@ public class SmartTypeCompletionTest extends LightFixtureCompletionTestCase {
doActionTest();
}
+ public void testDontSuggestWildcardGenerics() { doItemTest(); }
+
public void testCastWith2TypeParameters() throws Throwable { doTest(); }
public void testClassLiteralInArrayAnnoInitializer() throws Throwable { doTest(); }
public void testClassLiteralInArrayAnnoInitializer2() throws Throwable { doTest(); }
@@ -1141,7 +1143,7 @@ public class SmartTypeCompletionTest extends LightFixtureCompletionTestCase {
checkResultByTestName();
}
- private void doItemTest() throws Exception {
+ private void doItemTest() {
doFirstItemTest('\n');
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GraphInferenceHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GraphInferenceHighlightingTest.java
index 79506280a778..6ccefa35ae51 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GraphInferenceHighlightingTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GraphInferenceHighlightingTest.java
@@ -188,6 +188,22 @@ public class GraphInferenceHighlightingTest extends LightDaemonAnalyzerTestCase
doTest();
}
+ public void testInferFromConditionalExpressionCondition() throws Exception {
+ doTest();
+ }
+
+ public void testPrimitiveWrapperConditionInReturnConstraint() throws Exception {
+ doTest();
+ }
+
+ public void testIDEA128174() throws Exception {
+ doTest();
+ }
+
+ public void testIDEA128101() throws Exception {
+ doTest();
+ }
+
private void doTest() throws Exception {
doTest(false);
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/MethodRefHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/MethodRefHighlightingTest.java
index fbf8036e8e35..156aac5613c1 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/MethodRefHighlightingTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/MethodRefHighlightingTest.java
@@ -106,6 +106,10 @@ public class MethodRefHighlightingTest extends LightDaemonAnalyzerTestCase {
doTest();
}
+ public void testIDEA127765() throws Exception {
+ doTest();
+ }
+
private void doTest() {
doTest(false);
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/folding/JavaFoldingGotoTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/folding/JavaFoldingGotoTest.java
new file mode 100644
index 000000000000..b94e54d91323
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/folding/JavaFoldingGotoTest.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.folding;
+
+import com.intellij.codeInsight.navigation.actions.GotoDeclarationAction;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.ex.FoldingModelEx;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase;
+
+public class JavaFoldingGotoTest extends JavaCodeInsightFixtureTestCase {
+
+ public void testIDEA127145() {
+ PsiFile file = myFixture.addFileToProject("Program.java",
+ "import java.io.InputStream;\n" +
+ "import java.util.HashMap;\n" +
+ "import java.util.Map;\n" +
+ "\n" +
+ "class Program {\n" +
+ " private static InputStream getFile(String name, Map<String, Object> args) {\n" +
+ " return Program.class.getResourceAsStream(name);\n" +
+ " }\n" +
+ "\n" +
+ " public static void main(String[] args) {\n" +
+ " // Ctrl + B or Ctrl + Left Mouse Button work correctly for following string:\n" +
+ " final String name = \"file.sql\";\n" +
+ " // But it jumps only to folder in following case:\n" +
+ " final InputStream inputStream = getFile(\"dir/fil<caret>e.sql\", new HashMap<String, Object>());\n" +
+ " }\n" +
+ "}");
+
+ PsiFile fileSql = myFixture.addFileToProject("dir/file.sql", "select 1;");
+ myFixture.configureFromExistingVirtualFile(file.getVirtualFile());
+
+ Editor editor = myFixture.getEditor();
+ CodeFoldingManager.getInstance(getProject()).buildInitialFoldings(editor);
+ FoldingModelEx foldingModel = (FoldingModelEx)editor.getFoldingModel();
+ foldingModel.rebuild();
+ myFixture.doHighlighting();
+
+ PsiElement element = GotoDeclarationAction.findTargetElement(getProject(), editor, editor.getCaretModel().getOffset());
+ assertTrue("Should navigate to: file.sql instead of " + element, element != null && element.equals(fileSql));
+ }
+
+}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/folding/JavaFoldingTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/folding/JavaFoldingTest.groovy
index 5d823e001f82..095de51543af 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/folding/JavaFoldingTest.groovy
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/folding/JavaFoldingTest.groovy
@@ -568,14 +568,20 @@ class Test {
public void "test fold one-line methods"() {
configure """class Foo {
+ @Override
int someMethod() {
return 0;
}
+ int someOtherMethod(
+ int param) {
+ return 0;
+ }
+
}"""
PsiClass fooClass = JavaPsiFacade.getInstance(project).findClass('Foo', GlobalSearchScope.allScope(project))
def regions = myFixture.editor.foldingModel.allFoldRegions.sort { it.startOffset }
- assert regions.size() == 2
+ assert regions.size() == 3
checkAccessorFolding(regions[0], regions[1], fooClass.methods[0])
}
@@ -792,13 +798,14 @@ public class CharSymbol {
assert regions[3].placeholderText == 'seq: "Hi!"'
}
- public void "test inline negative numbers (IDEA-126753)"() {
+ public void "test inline negative and positive numbers"() {
def text = """
public class CharSymbol {
public void main() {
Object obj = new Object();
count(-1, obj);
+ count(+1, obj);
}
public void count(int test, Object obj) {
@@ -809,10 +816,13 @@ public class CharSymbol {
"""
configure text
def regions = myFixture.editor.foldingModel.allFoldRegions.sort { it.startOffset }
- assert regions.size() == 3
+ assert regions.size() == 4
checkRangeOffsetByPositionInText(regions[1], text, "-1")
assert regions[1].placeholderText == "test: -1"
+
+ checkRangeOffsetByPositionInText(regions[2], text, "+1")
+ assert regions[2].placeholderText == "test: +1"
}
public void "test inline constructor literal arguments names"() {
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/NullPostfixTemplateTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/NullPostfixTemplateTest.java
index 7f47795881bc..70061e56afa9 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/NullPostfixTemplateTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/NullPostfixTemplateTest.java
@@ -38,4 +38,9 @@ public class NullPostfixTemplateTest extends PostfixTemplateTestCase {
public void testSecondStatement() {
doTest();
}
+
+
+ public void testSingleExclamationIgnored() {
+ doTest();
+ }
} \ No newline at end of file
diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/ContractInferenceFromSourceTest.groovy b/java/java-tests/testSrc/com/intellij/codeInspection/ContractInferenceFromSourceTest.groovy
index 23eac589e2db..89762efe5dd2 100644
--- a/java/java-tests/testSrc/com/intellij/codeInspection/ContractInferenceFromSourceTest.groovy
+++ b/java/java-tests/testSrc/com/intellij/codeInspection/ContractInferenceFromSourceTest.groovy
@@ -228,6 +228,34 @@ class ContractInferenceFromSourceTest extends LightCodeInsightFixtureTestCase {
assert c == []
}
+ public void "test boolean autoboxing in delegation"() {
+ def c = inferContracts("""
+ static Boolean test04(String s) {
+ return test03(s);
+ }
+ static boolean test03(String s) {
+ return s == null;
+ }
+ """)
+ assert c == []
+ }
+
+ public void "test boolean auto-unboxing"() {
+ def c = inferContracts("""
+ static boolean test02(String s) {
+ return test01(s);
+ }
+
+ static Boolean test01(String s) {
+ if (s == null)
+ return new Boolean(false);
+ else
+ return null;
+ }
+ """)
+ assert c == []
+ }
+
public void "test non-returning delegation"() {
def c = inferContracts("""
static void test2(Object o) {
diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java
index 4cba2ab918a7..33eb32eb0ec6 100644
--- a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java
@@ -18,6 +18,7 @@ package com.intellij.codeInspection;
import com.intellij.JavaTestUtil;
import com.intellij.codeInspection.dataFlow.DataFlowInspection;
import com.intellij.testFramework.LightProjectDescriptor;
+import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture;
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
import org.jetbrains.annotations.NotNull;
@@ -251,15 +252,17 @@ public class DataFlowInspectionTest extends LightCodeInsightFixtureTestCase {
public void testRootThrowableCause() { doTest(); }
public void testUseInferredContracts() { doTest(); }
+ public void testContractWithNoArgs() { doTest(); }
public void testContractInferenceBewareOverriding() { doTest(); }
public void testNumberComparisonsWhenValueIsKnown() { doTest(); }
+ public void testFloatComparisons() { doTest(); }
public void testAccessingSameArrayElements() { doTest(); }
public void testParametersAreNonnullByDefault() {
- myFixture.addClass("package javax.annotation; public @interface ParametersAreNonnullByDefault {}");
- myFixture.addClass("package javax.annotation; public @interface ParametersAreNullableByDefault {}");
+ addJavaxNullabilityAnnotations(myFixture);
+ addJavaxDefaultNullabilityAnnotations(myFixture);
myFixture.addClass("package foo; public class AnotherPackageNotNull { public static void foo(String s) {}}");
myFixture.addFileToProject("foo/package-info.java", "@javax.annotation.ParametersAreNonnullByDefault package foo;");
@@ -267,6 +270,37 @@ public class DataFlowInspectionTest extends LightCodeInsightFixtureTestCase {
doTest();
}
+ public static void addJavaxDefaultNullabilityAnnotations(final JavaCodeInsightTestFixture fixture) {
+ fixture.addClass("package javax.annotation;" +
+ "@javax.annotation.meta.TypeQualifierDefault(java.lang.annotation.ElementType.PARAMETER) @javax.annotation.Nonnull " +
+ "public @interface ParametersAreNonnullByDefault {}");
+ fixture.addClass("package javax.annotation;" +
+ "@javax.annotation.meta.TypeQualifierDefault(java.lang.annotation.ElementType.PARAMETER) @javax.annotation.Nullable " +
+ "public @interface ParametersAreNullableByDefault {}");
+ }
+
+ public static void addJavaxNullabilityAnnotations(final JavaCodeInsightTestFixture fixture) {
+ fixture.addClass("package javax.annotation;" +
+ "public @interface Nonnull {}");
+ fixture.addClass("package javax.annotation;" +
+ "public @interface Nullable {}");
+ fixture.addClass("package javax.annotation.meta;" +
+ "public @interface TypeQualifierDefault { java.lang.annotation.ElementType[] value() default {};}");
+ }
+
+ public void testCustomTypeQualifierDefault() {
+ addJavaxNullabilityAnnotations(myFixture);
+ myFixture.addClass("package bar;" +
+ "@javax.annotation.meta.TypeQualifierDefault(java.lang.annotation.ElementType.METHOD) @javax.annotation.Nonnull " +
+ "public @interface MethodsAreNotNullByDefault {}");
+
+ myFixture.addClass("package foo; public class AnotherPackageNotNull { public static native Object foo(String s); }");
+ myFixture.addFileToProject("foo/package-info.java", "@bar.MethodsAreNotNullByDefault package foo;");
+
+ myFixture.enableInspections(new DataFlowInspection());
+ myFixture.testHighlighting(true, false, true, getTestName(false) + ".java");
+ }
+
public void testTrueOrEqualsSomething() {
doTest();
myFixture.launchAction(myFixture.findSingleIntention("Remove redundant assignment"));
diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/NullableStuffInspectionTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/NullableStuffInspectionTest.java
index e925dd49a8ea..3520ec08d750 100644
--- a/java/java-tests/testSrc/com/intellij/codeInspection/NullableStuffInspectionTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInspection/NullableStuffInspectionTest.java
@@ -40,8 +40,8 @@ public class NullableStuffInspectionTest extends LightCodeInsightFixtureTestCase
}
public void testHonorSuperParameterDefault() {
- myFixture.addClass("package javax.annotation; public @interface ParametersAreNonnullByDefault {}");
- myFixture.addClass("package javax.annotation; public @interface Nullable {}");
+ DataFlowInspectionTest.addJavaxNullabilityAnnotations(myFixture);
+ DataFlowInspectionTest.addJavaxDefaultNullabilityAnnotations(myFixture);
myFixture.addFileToProject("foo/package-info.java", "@javax.annotation.ParametersAreNonnullByDefault package foo;");
myFixture.addClass("import javax.annotation.*; package foo; public interface NullableFunction { void fun(@Nullable Object o); }");
@@ -51,7 +51,8 @@ public class NullableStuffInspectionTest extends LightCodeInsightFixtureTestCase
}
public void testHonorThisParameterDefault() {
- myFixture.addClass("package javax.annotation; public @interface ParametersAreNonnullByDefault {}");
+ DataFlowInspectionTest.addJavaxNullabilityAnnotations(myFixture);
+ DataFlowInspectionTest.addJavaxDefaultNullabilityAnnotations(myFixture);
myFixture.addFileToProject("foo/package-info.java", "@javax.annotation.ParametersAreNonnullByDefault package foo;");
myFixture.configureFromExistingVirtualFile(myFixture.copyFileToProject(getTestName(false) + ".java", "foo/Classes.java"));
@@ -60,8 +61,8 @@ public class NullableStuffInspectionTest extends LightCodeInsightFixtureTestCase
}
public void testHonorParameterDefaultInSetters() {
- myFixture.addClass("package javax.annotation; public @interface ParametersAreNonnullByDefault {}");
- myFixture.addClass("package javax.annotation; public @interface Nullable {}");
+ DataFlowInspectionTest.addJavaxNullabilityAnnotations(myFixture);
+ DataFlowInspectionTest.addJavaxDefaultNullabilityAnnotations(myFixture);
myFixture.addFileToProject("foo/package-info.java", "@javax.annotation.ParametersAreNonnullByDefault package foo;");
myFixture.configureFromExistingVirtualFile(myFixture.copyFileToProject(getTestName(false) + ".java", "foo/Classes.java"));
diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisTest.java
index 09fa87fa95e9..9d26fd804f68 100644
--- a/java/java-tests/testSrc/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisTest.java
@@ -183,7 +183,7 @@ public class BytecodeAnalysisTest extends JavaCodeInsightFixtureTestCase {
private void checkCompoundId(Method method, PsiMethod psiMethod, boolean noKey) throws IOException {
Direction direction = new Out();
- int psiKey = myBytecodeAnalysisConverter.mkPsiKey(psiMethod, direction);
+ long psiKey = myBytecodeAnalysisConverter.mkPsiKey(psiMethod, direction);
if (noKey) {
assertTrue(-1 == psiKey);
return;
@@ -192,7 +192,7 @@ public class BytecodeAnalysisTest extends JavaCodeInsightFixtureTestCase {
assertFalse(-1 == psiKey);
}
- int asmKey = myBytecodeAnalysisConverter.mkAsmKey(new Key(method, direction, true));
+ long asmKey = myBytecodeAnalysisConverter.mkAsmKey(new Key(method, direction, true));
Assert.assertEquals(asmKey, psiKey);
}
diff --git a/java/java-tests/testSrc/com/intellij/find/FindInEditorMultiCaretTest.java b/java/java-tests/testSrc/com/intellij/find/FindInEditorMultiCaretTest.java
index 02f8c589c43b..3cc6c19618a1 100644
--- a/java/java-tests/testSrc/com/intellij/find/FindInEditorMultiCaretTest.java
+++ b/java/java-tests/testSrc/com/intellij/find/FindInEditorMultiCaretTest.java
@@ -19,7 +19,9 @@ import com.intellij.find.editorHeaderActions.*;
import com.intellij.openapi.actionSystem.ActionPlaces;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.IdeActions;
+import com.intellij.openapi.editor.impl.EditorImpl;
import com.intellij.openapi.util.Getter;
+import com.intellij.testFramework.fixtures.EditorMouseFixture;
import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase;
import javax.swing.text.JTextComponent;
@@ -58,7 +60,7 @@ public class FindInEditorMultiCaretTest extends LightPlatformCodeInsightFixtureT
assertNull(getEditorSearchComponent());
}
- public void testActionsWorkFromEditor() throws IOException {
+ public void testActionsInEditorWorkIndependently() throws IOException {
init("abc\n" +
"abc\n" +
"abc");
@@ -67,27 +69,29 @@ public class FindInEditorMultiCaretTest extends LightPlatformCodeInsightFixtureT
checkResultByText("a<selection>b<caret></selection>c\n" +
"abc\n" +
"abc");
+ new EditorMouseFixture((EditorImpl)myFixture.getEditor()).clickAt(0, 1);
addOccurrenceFromEditor();
- checkResultByText("a<selection>b<caret></selection>c\n" +
- "a<selection>b<caret></selection>c\n" +
+ addOccurrenceFromEditor();
+ checkResultByText("<selection>a<caret>bc</selection>\n" +
+ "<selection>a<caret>bc</selection>\n" +
"abc");
nextOccurrenceFromEditor();
- checkResultByText("a<selection>b<caret></selection>c\n" +
+ checkResultByText("<selection>a<caret>bc</selection>\n" +
"abc\n" +
- "a<selection>b<caret></selection>c");
+ "<selection>a<caret>bc</selection>");
prevOccurrenceFromEditor();
- checkResultByText("a<selection>b<caret></selection>c\n" +
- "a<selection>b<caret></selection>c\n" +
+ checkResultByText("<selection>a<caret>bc</selection>\n" +
+ "<selection>a<caret>bc</selection>\n" +
"abc");
removeOccurrenceFromEditor();
- checkResultByText("a<selection>b<caret></selection>c\n" +
+ checkResultByText("<selection>a<caret>bc</selection>\n" +
"abc\n" +
"abc");
allOccurrencesFromEditor();
- checkResultByText("a<selection>b<caret></selection>c\n" +
- "a<selection>b<caret></selection>c\n" +
- "a<selection>b<caret></selection>c");
- assertNull(getEditorSearchComponent());
+ checkResultByText("<selection>a<caret>bc</selection>\n" +
+ "<selection>a<caret>bc</selection>\n" +
+ "<selection>a<caret>bc</selection>");
+ assertNotNull(getEditorSearchComponent());
}
public void testCloseRetainsMulticaretSelection() throws IOException {
diff --git a/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java b/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java
index 92caad03d8ef..f83d836bb55a 100644
--- a/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java
+++ b/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java
@@ -579,7 +579,7 @@ public class FindManagerTest extends DaemonAnalyzerTestCase {
FindModel findModel = FindManagerTestUtils.configureFindModel("done");
String text = "/** done done done */";
- findModel.setInCommentsOnly(true);
+ findModel.setSearchContext(FindModel.SearchContext.IN_COMMENTS);
FindManagerTestUtils.runFindForwardAndBackward(myFindManager, findModel, text);
findModel.setRegularExpressions(true);
@@ -592,7 +592,7 @@ public class FindManagerTest extends DaemonAnalyzerTestCase {
String prefix = "/*";
String text = prefix + "done*/";
- findModel.setInCommentsOnly(true);
+ findModel.setSearchContext(FindModel.SearchContext.IN_COMMENTS);
LightVirtualFile file = new LightVirtualFile("A.java", text);
FindResult findResult = myFindManager.findString(text, prefix.length(), findModel, file);
@@ -615,8 +615,7 @@ public class FindManagerTest extends DaemonAnalyzerTestCase {
FindModel findModel = FindManagerTestUtils.configureFindModel("^done$");
findModel.setRegularExpressions(true);
- findModel.setInStringLiteralsOnly(true);
- findModel.setInCommentsOnly(false);
+ findModel.setSearchContext(FindModel.SearchContext.IN_STRING_LITERALS);
String text = "\"done\"; 'done'; 'done' \"done2\"";
FindManagerTestUtils.runFindForwardAndBackward(myFindManager, findModel, text, "java");
@@ -633,7 +632,7 @@ public class FindManagerTest extends DaemonAnalyzerTestCase {
String text = "/** do ne do ne do ne */";
- findModel.setInCommentsOnly(true);
+ findModel.setSearchContext(FindModel.SearchContext.IN_COMMENTS);
FindManagerTestUtils.runFindForwardAndBackward(myFindManager, findModel, text, "java");
}
@@ -651,4 +650,42 @@ public class FindManagerTest extends DaemonAnalyzerTestCase {
findModel.setWholeWordsOnly(true);
assertSize(1, findUsages(findModel));
}
+
+ public void testFindExceptComments() {
+ FindModel findModel = FindManagerTestUtils.configureFindModel("done");
+
+ String prefix = "/*";
+ String text = prefix + "done*/done";
+
+ findModel.setSearchContext(FindModel.SearchContext.EXCEPT_COMMENTS);
+ LightVirtualFile file = new LightVirtualFile("A.java", text);
+
+ FindResult findResult = myFindManager.findString(text, prefix.length(), findModel, file);
+ assertTrue(findResult.isStringFound());
+ assertTrue(findResult.getStartOffset() > prefix.length());
+
+ findModel.setRegularExpressions(true);
+ findResult = myFindManager.findString(text, prefix.length(), findModel, file);
+ assertTrue(findResult.isStringFound());
+ assertTrue(findResult.getStartOffset() > prefix.length());
+ }
+
+ public void testFindExceptLiterals() {
+ FindModel findModel = FindManagerTestUtils.configureFindModel("done");
+
+ String prefix = "\"";
+ String text = prefix + "done\"done";
+
+ findModel.setSearchContext(FindModel.SearchContext.EXCEPT_STRING_LITERALS);
+ LightVirtualFile file = new LightVirtualFile("A.java", text);
+
+ FindResult findResult = myFindManager.findString(text, prefix.length(), findModel, file);
+ assertTrue(findResult.isStringFound());
+ assertTrue(findResult.getStartOffset() > prefix.length());
+
+ findModel.setRegularExpressions(true);
+ findResult = myFindManager.findString(text, prefix.length(), findModel, file);
+ assertTrue(findResult.isStringFound());
+ assertTrue(findResult.getStartOffset() > prefix.length());
+ }
}
diff --git a/java/java-tests/testSrc/com/intellij/navigation/ChooseByNameTest.groovy b/java/java-tests/testSrc/com/intellij/navigation/ChooseByNameTest.groovy
index dabe06ba79fa..9a97a825964a 100644
--- a/java/java-tests/testSrc/com/intellij/navigation/ChooseByNameTest.groovy
+++ b/java/java-tests/testSrc/com/intellij/navigation/ChooseByNameTest.groovy
@@ -24,7 +24,6 @@ import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
import com.intellij.util.Consumer
import com.intellij.util.concurrency.Semaphore
import org.jetbrains.annotations.NotNull
-
/**
* @author peter
*/
@@ -197,6 +196,33 @@ class Intf {
assert getPopupElements(new GotoClassModel2(project), 'Bar:[2,3]') == [c]
}
+ public void "test dollar"() {
+ def bar = myFixture.addClass("package foo; class Bar { class Foo {} }")
+ def foo = bar.innerClasses[0]
+ myFixture.addClass("package goo; class Goo { }")
+ assert getPopupElements(new GotoClassModel2(project), 'Bar$Foo') == [foo]
+ assert getPopupElements(new GotoClassModel2(project), 'foo.Bar$Foo') == [foo]
+ assert getPopupElements(new GotoClassModel2(project), 'foo.B$F') == [foo]
+ assert !getPopupElements(new GotoClassModel2(project), 'foo$Foo')
+ assert !getPopupElements(new GotoClassModel2(project), 'foo$Bar')
+ assert !getPopupElements(new GotoClassModel2(project), 'foo$Bar$Foo')
+ assert !getPopupElements(new GotoClassModel2(project), 'foo$Goo')
+ }
+
+ public void "test anonymous classes"() {
+ def goo = myFixture.addClass("package goo; class Goo { Runnable r = new Runnable() {}; }")
+ assert getPopupElements(new GotoClassModel2(project), 'Goo$1') == [goo]
+ }
+
+ public void "test qualified name matching"() {
+ def bar = myFixture.addClass("package foo.bar; class Bar { }")
+ def bar2 = myFixture.addClass("package goo.baz; class Bar { }")
+ assert getPopupElements(new GotoClassModel2(project), 'foo.Bar') == [bar]
+ assert getPopupElements(new GotoClassModel2(project), 'foo.bar.Bar') == [bar]
+ assert getPopupElements(new GotoClassModel2(project), 'goo.Bar') == [bar2]
+ assert getPopupElements(new GotoClassModel2(project), 'goo.baz.Bar') == [bar2]
+ }
+
public void "test super method in jdk"() {
def ourRun = myFixture.addClass("package foo.bar; class Goo implements Runnable { public void run() {} }").methods[0]
def sdkRun
diff --git a/java/java-tests/testSrc/com/intellij/openapi/roots/impl/DirectoryIndexTest.java b/java/java-tests/testSrc/com/intellij/openapi/roots/impl/DirectoryIndexTest.java
index 1e3e08a33ae7..56624594bb0e 100644
--- a/java/java-tests/testSrc/com/intellij/openapi/roots/impl/DirectoryIndexTest.java
+++ b/java/java-tests/testSrc/com/intellij/openapi/roots/impl/DirectoryIndexTest.java
@@ -49,7 +49,7 @@ import static java.util.Collections.singletonList;
public class DirectoryIndexTest extends IdeaTestCase {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.roots.impl.DirectoryIndexTest");
- private DirectoryIndex myIndex;
+ private DirectoryIndexImpl myIndex;
private Module myModule2, myModule3;
private VirtualFile myRootVFile;
@@ -65,6 +65,7 @@ public class DirectoryIndexTest extends IdeaTestCase {
private VirtualFile myModule1OutputDir;
private VirtualFile myResDir, myTestResDir;
private VirtualFile myExcludedLibSrcDir, myExcludedLibClsDir;
+ private ProjectFileIndex myFileIndex;
@Override
protected void setUp() throws Exception {
@@ -176,7 +177,8 @@ public class DirectoryIndexTest extends IdeaTestCase {
}
});
- myIndex = DirectoryIndex.getInstance(myProject);
+ myIndex = (DirectoryIndexImpl)DirectoryIndex.getInstance(myProject);
+ myFileIndex = ProjectRootManager.getInstance(myProject).getFileIndex();
// to not interfere with previous test firing vfs events
VirtualFileManager.getInstance().syncRefresh();
}
@@ -221,12 +223,12 @@ public class DirectoryIndexTest extends IdeaTestCase {
VirtualFile cvs = myPack1Dir.createChildDirectory(this, "CVS");
assertNotInProject(cvs);
- assertNull(ProjectRootManager.getInstance(myProject).getFileIndex().getPackageNameByDirectory(cvs));
+ assertNull(myFileIndex.getPackageNameByDirectory(cvs));
}
public void testDirsByPackageName() throws IOException {
- checkPackage("", true, mySrcDir1, myTestSrc1, myResDir, myTestResDir, myFileLibSrc, myFileLibCls, mySrcDir2, myLibSrcDir, myLibClsDir);
- checkPackage("", false, mySrcDir1, myTestSrc1, myResDir, myTestResDir, myFileLibCls, mySrcDir2, myLibClsDir);
+ checkPackage("", true, mySrcDir1, myTestSrc1, myResDir, myTestResDir, mySrcDir2, myLibSrcDir, myLibClsDir);
+ checkPackage("", false, mySrcDir1, myTestSrc1, myResDir, myTestResDir, mySrcDir2, myLibClsDir);
checkPackage("pack1", true, myPack1Dir);
checkPackage("pack1", false, myPack1Dir);
@@ -257,6 +259,18 @@ public class DirectoryIndexTest extends IdeaTestCase {
checkPackage("pack1", true, myPack1Dir, myModule3Dir);
}
+ public void testPackageDirectoriesWithDots() throws IOException {
+ VirtualFile fooBar = mySrcDir1.createChildDirectory(this, "foo.bar");
+ VirtualFile goo1 = fooBar.createChildDirectory(this, "goo");
+ VirtualFile foo = mySrcDir2.createChildDirectory(this, "foo");
+ VirtualFile bar = foo.createChildDirectory(this, "bar");
+ VirtualFile goo2 = bar.createChildDirectory(this, "goo");
+
+ checkPackage("foo", false, foo);
+ checkPackage("foo.bar", false, bar, fooBar);
+ checkPackage("foo.bar.goo", false, goo2, goo1);
+ }
+
public void testCreateDir() throws Exception {
String path = mySrcDir1.getPath().replace('/', File.separatorChar);
assertTrue(new File(path + File.separatorChar + "dir1" + File.separatorChar + "dir2").mkdirs());
@@ -362,7 +376,8 @@ public class DirectoryIndexTest extends IdeaTestCase {
VirtualFile ignoredFile = myModule1Dir.createChildData(this, "CVS");
DirectoryInfo info = myIndex.getInfoForFile(ignoredFile);
assertTrue(info.isIgnored());
- assertTrue(ProjectRootManager.getInstance(myProject).getFileIndex().isExcluded(ignoredFile));
+ assertTrue(myFileIndex.isExcluded(ignoredFile));
+ assertTrue(myFileIndex.isUnderIgnored(ignoredFile));
}
public void testAddModule() throws Exception {
@@ -386,10 +401,12 @@ public class DirectoryIndexTest extends IdeaTestCase {
public void testModuleUnderIgnoredDir() throws IOException {
final VirtualFile ignored = myRootVFile.createChildDirectory(this, "RCS");
assertTrue(FileTypeManager.getInstance().isFileIgnored(ignored));
- assertTrue(ProjectRootManager.getInstance(myProject).getFileIndex().isExcluded(ignored));
+ assertTrue(myFileIndex.isExcluded(ignored));
+ assertTrue(myFileIndex.isUnderIgnored(ignored));
final VirtualFile module4 = ignored.createChildDirectory(this, "module4");
assertFalse(FileTypeManager.getInstance().isFileIgnored(module4));
- assertTrue(ProjectRootManager.getInstance(myProject).getFileIndex().isExcluded(module4));
+ assertTrue(myFileIndex.isExcluded(module4));
+ assertTrue(myFileIndex.isUnderIgnored(module4));
new WriteCommandAction.Simple(getProject()) {
@Override
@@ -425,11 +442,12 @@ public class DirectoryIndexTest extends IdeaTestCase {
}
public void testExcludedDirsInLibraries() {
- ProjectFileIndex index = ProjectRootManager.getInstance(myProject).getFileIndex();
- assertFalse(index.isInLibraryClasses(myExcludedLibClsDir));
- assertTrue(index.isExcluded(myExcludedLibClsDir));
- assertFalse(index.isInLibrarySource(myExcludedLibSrcDir));
- assertTrue(index.isExcluded(myExcludedLibSrcDir));
+ assertFalse(myFileIndex.isInLibraryClasses(myExcludedLibClsDir));
+ assertTrue(myFileIndex.isExcluded(myExcludedLibClsDir));
+ assertFalse(myFileIndex.isUnderIgnored(myExcludedLibClsDir));
+ assertFalse(myFileIndex.isInLibrarySource(myExcludedLibSrcDir));
+ assertTrue(myFileIndex.isExcluded(myExcludedLibSrcDir));
+ assertFalse(myFileIndex.isUnderIgnored(myExcludedLibSrcDir));
}
public void testExplicitExcludeOfInner() throws Exception {
@@ -469,12 +487,12 @@ public class DirectoryIndexTest extends IdeaTestCase {
ModuleRootModificationUtil.addModuleLibrary(myModule, "someLib", Collections.<String>emptyList(), Arrays.asList(mySrcDir1.getUrl()));
checkInfo(mySrcDir1, myModule, false, true, "", JavaSourceRootType.SOURCE, myModule, myModule);
- OrderEntry[] entries = myIndex.getInfoForFile(mySrcDir1).getOrderEntries();
+ OrderEntry[] entries = myIndex.getOrderEntries(myIndex.getInfoForFile(mySrcDir1));
assertInstanceOf(entries[0], LibraryOrderEntry.class);
assertInstanceOf(entries[1], ModuleSourceOrderEntry.class);
checkInfo(myTestSrc1, myModule, false, true, "testSrc", JavaSourceRootType.TEST_SOURCE, myModule, myModule);
- entries = myIndex.getInfoForFile(myTestSrc1).getOrderEntries();
+ entries = myIndex.getOrderEntries(myIndex.getInfoForFile(myTestSrc1));
assertInstanceOf(entries[0], LibraryOrderEntry.class);
assertInstanceOf(entries[1], ModuleSourceOrderEntry.class);
}
@@ -482,7 +500,7 @@ public class DirectoryIndexTest extends IdeaTestCase {
public void testModuleSourceAsLibraryClasses() throws Exception {
ModuleRootModificationUtil.addModuleLibrary(myModule, "someLib", Arrays.asList(mySrcDir1.getUrl()), Collections.<String>emptyList());
checkInfo(mySrcDir1, myModule, true, false, "", JavaSourceRootType.SOURCE, myModule);
- assertInstanceOf(assertOneElement(assertInProject(mySrcDir1).getOrderEntries()), ModuleSourceOrderEntry.class);
+ assertInstanceOf(assertOneElement(myIndex.getOrderEntries(assertInProject(mySrcDir1))), ModuleSourceOrderEntry.class);
}
public void testModulesWithSameSourceContentRoot() {
@@ -645,7 +663,7 @@ public class DirectoryIndexTest extends IdeaTestCase {
checkInfo(myLibSrcDir, myModule, true, true, "", null, myModule, myModule3);
checkInfo(myResDir, myModule, true, false, "", JavaResourceRootType.RESOURCE, myModule);
- assertInstanceOf(assertOneElement(assertInProject(myResDir).getOrderEntries()), ModuleSourceOrderEntry.class);
+ assertInstanceOf(assertOneElement(myIndex.getOrderEntries(assertInProject(myResDir))), ModuleSourceOrderEntry.class);
checkInfo(myExcludedLibSrcDir, null, true, false, "lib.src.exc", null, myModule3, myModule);
checkInfo(myExcludedLibClsDir, null, true, false, "lib.cls.exc", null, myModule3);
@@ -661,10 +679,10 @@ public class DirectoryIndexTest extends IdeaTestCase {
}
public void testExcludeCompilerOutputOutsideOfContentRoot() throws Exception {
- final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(myProject).getFileIndex();
- assertTrue(fileIndex.isExcluded(myOutputDir));
- assertTrue(fileIndex.isExcluded(myModule1OutputDir));
- assertFalse(fileIndex.isExcluded(myOutputDir.getParent()));
+ assertTrue(myFileIndex.isExcluded(myOutputDir));
+ assertFalse(myFileIndex.isUnderIgnored(myOutputDir));
+ assertTrue(myFileIndex.isExcluded(myModule1OutputDir));
+ assertFalse(myFileIndex.isExcluded(myOutputDir.getParent()));
assertExcludedFromProject(myOutputDir);
assertExcludedFromProject(myModule1OutputDir);
String moduleOutputUrl = myModule1OutputDir.getUrl();
@@ -677,7 +695,7 @@ public class DirectoryIndexTest extends IdeaTestCase {
assertExcludedFromProject(myOutputDir);
assertExcludedFromProject(myModule1OutputDir);
- assertTrue(fileIndex.isExcluded(myModule1OutputDir));
+ assertTrue(myFileIndex.isExcluded(myModule1OutputDir));
PsiTestUtil.setCompilerOutputPath(myModule, moduleOutputUrl, true);
PsiTestUtil.setCompilerOutputPath(myModule2, moduleOutputUrl, false);
@@ -703,49 +721,47 @@ public class DirectoryIndexTest extends IdeaTestCase {
}
public void testFileContentAndSourceRoots() throws IOException {
- ProjectFileIndex fileIndex = ProjectRootManager.getInstance(myProject).getFileIndex();
-
VirtualFile fileRoot = myRootVFile.createChildData(this, "fileRoot.txt");
VirtualFile fileSourceRoot = myRootVFile.createChildData(this, "fileSourceRoot.txt");
VirtualFile fileTestSourceRoot = myRootVFile.createChildData(this, "fileTestSourceRoot.txt");
assertNotInProject(fileRoot);
- assertFalse(fileIndex.isInContent(fileRoot));
- assertIteratedContent(fileIndex, null, Arrays.asList(fileRoot, fileSourceRoot, fileTestSourceRoot));
+ assertFalse(myFileIndex.isInContent(fileRoot));
+ assertIteratedContent(myFileIndex, null, Arrays.asList(fileRoot, fileSourceRoot, fileTestSourceRoot));
ContentEntry contentEntry = PsiTestUtil.addContentRoot(myModule, fileRoot);
assertEquals(fileRoot, contentEntry.getFile());
checkInfo(fileRoot, myModule, false, false, "", null);
- assertTrue(fileIndex.isInContent(fileRoot));
- assertFalse(fileIndex.isInSource(fileRoot));
+ assertTrue(myFileIndex.isInContent(fileRoot));
+ assertFalse(myFileIndex.isInSource(fileRoot));
PsiTestUtil.addContentRoot(myModule, fileSourceRoot);
PsiTestUtil.addSourceRoot(myModule, fileSourceRoot);
checkInfo(fileSourceRoot, myModule, false, false, "", JavaSourceRootType.SOURCE, myModule);
- assertTrue(fileIndex.isInContent(fileSourceRoot));
- assertTrue(fileIndex.isInSource(fileSourceRoot));
+ assertTrue(myFileIndex.isInContent(fileSourceRoot));
+ assertTrue(myFileIndex.isInSource(fileSourceRoot));
PsiTestUtil.addContentRoot(myModule, fileTestSourceRoot);
PsiTestUtil.addSourceRoot(myModule, fileTestSourceRoot, true);
checkInfo(fileTestSourceRoot, myModule, false, false, "", JavaSourceRootType.TEST_SOURCE, myModule);
- assertTrue(fileIndex.isInContent(fileTestSourceRoot));
- assertTrue(fileIndex.isInSource(fileTestSourceRoot));
+ assertTrue(myFileIndex.isInContent(fileTestSourceRoot));
+ assertTrue(myFileIndex.isInSource(fileTestSourceRoot));
- assertIteratedContent(fileIndex, Arrays.asList(fileRoot, fileSourceRoot, fileTestSourceRoot), null);
+ assertIteratedContent(myFileIndex, Arrays.asList(fileRoot, fileSourceRoot, fileTestSourceRoot), null);
// removing file source root
PsiTestUtil.removeSourceRoot(myModule, fileTestSourceRoot);
checkInfo(fileTestSourceRoot, myModule, false, false, "", null);
- assertTrue(fileIndex.isInContent(fileTestSourceRoot));
- assertFalse(fileIndex.isInSource(fileTestSourceRoot));
- assertIteratedContent(fileIndex, Arrays.asList(fileRoot, fileSourceRoot, fileTestSourceRoot), null);
+ assertTrue(myFileIndex.isInContent(fileTestSourceRoot));
+ assertFalse(myFileIndex.isInSource(fileTestSourceRoot));
+ assertIteratedContent(myFileIndex, Arrays.asList(fileRoot, fileSourceRoot, fileTestSourceRoot), null);
// removing file content root
- PsiTestUtil.removeContentEntry(myModule, contentEntry);
+ PsiTestUtil.removeContentEntry(myModule, contentEntry.getFile());
assertNotInProject(fileRoot);
- assertFalse(fileIndex.isInContent(fileRoot));
- assertFalse(fileIndex.isInSource(fileRoot));
- assertIteratedContent(fileIndex, Arrays.asList(fileSourceRoot, fileTestSourceRoot), Arrays.asList(fileRoot));
+ assertFalse(myFileIndex.isInContent(fileRoot));
+ assertFalse(myFileIndex.isInSource(fileRoot));
+ assertIteratedContent(myFileIndex, Arrays.asList(fileSourceRoot, fileTestSourceRoot), Arrays.asList(fileRoot));
}
private void assertIteratedContent(ProjectFileIndex fileIndex,
@@ -764,63 +780,57 @@ public class DirectoryIndexTest extends IdeaTestCase {
}
public void testFileSourceRootsUnderDirContentRoot() throws IOException {
- ProjectFileIndex fileIndex = ProjectRootManager.getInstance(myProject).getFileIndex();
-
VirtualFile fileSourceRoot = myModule1Dir.createChildData(this, "fileSourceRoot.txt");
- assertTrue(fileIndex.isInContent(fileSourceRoot));
- assertFalse(fileIndex.isInSource(fileSourceRoot));
+ assertTrue(myFileIndex.isInContent(fileSourceRoot));
+ assertFalse(myFileIndex.isInSource(fileSourceRoot));
PsiTestUtil.addSourceRoot(myModule, fileSourceRoot);
- assertTrue(fileIndex.isInContent(fileSourceRoot));
- assertTrue(fileIndex.isInSource(fileSourceRoot));
+ assertTrue(myFileIndex.isInContent(fileSourceRoot));
+ assertTrue(myFileIndex.isInSource(fileSourceRoot));
checkInfo(fileSourceRoot, myModule, false, false, "", JavaSourceRootType.SOURCE, myModule);
// removing file source root
PsiTestUtil.removeSourceRoot(myModule, fileSourceRoot);
- assertTrue(fileIndex.isInContent(fileSourceRoot));
- assertFalse(fileIndex.isInSource(fileSourceRoot));
+ assertTrue(myFileIndex.isInContent(fileSourceRoot));
+ assertFalse(myFileIndex.isInSource(fileSourceRoot));
}
public void testFileModuleExcludeRootUnderDirectoryRoot() throws IOException {
- ProjectFileIndex fileIndex = ProjectRootManager.getInstance(myProject).getFileIndex();
-
VirtualFile fileExcludeRoot = mySrcDir1.createChildData(this, "fileExcludeRoot.txt");
- assertTrue(fileIndex.isInContent(fileExcludeRoot));
- assertTrue(fileIndex.isInSource(fileExcludeRoot));
- assertIteratedContent(fileIndex, Arrays.asList(fileExcludeRoot), null);
+ assertTrue(myFileIndex.isInContent(fileExcludeRoot));
+ assertTrue(myFileIndex.isInSource(fileExcludeRoot));
+ assertIteratedContent(myFileIndex, Arrays.asList(fileExcludeRoot), null);
PsiTestUtil.addExcludedRoot(myModule, fileExcludeRoot);
- assertFalse(fileIndex.isInContent(fileExcludeRoot));
- assertFalse(fileIndex.isInSource(fileExcludeRoot));
+ assertFalse(myFileIndex.isInContent(fileExcludeRoot));
+ assertFalse(myFileIndex.isInSource(fileExcludeRoot));
assertExcluded(fileExcludeRoot, myModule);
- assertIteratedContent(fileIndex, null, Arrays.asList(fileExcludeRoot));
+ assertIteratedContent(myFileIndex, null, Arrays.asList(fileExcludeRoot));
// removing file exclude root
PsiTestUtil.removeExcludedRoot(myModule, fileExcludeRoot);
- assertTrue(fileIndex.isInContent(fileExcludeRoot));
- assertTrue(fileIndex.isInSource(fileExcludeRoot));
- assertIteratedContent(fileIndex, Arrays.asList(fileExcludeRoot), null);
+ assertTrue(myFileIndex.isInContent(fileExcludeRoot));
+ assertTrue(myFileIndex.isInSource(fileExcludeRoot));
+ assertIteratedContent(myFileIndex, Arrays.asList(fileExcludeRoot), null);
}
public void testFileModuleExcludeRootUnderFileRoot() throws IOException {
- ProjectFileIndex fileIndex = ProjectRootManager.getInstance(myProject).getFileIndex();
-
VirtualFile fileRoot = myRootVFile.createChildData(this, "fileRoot.txt");
PsiTestUtil.addContentRoot(myModule, fileRoot);
checkInfo(fileRoot, myModule, false, false, "", null);
- assertTrue(fileIndex.isInContent(fileRoot));
- assertIteratedContent(fileIndex, Arrays.asList(fileRoot), null);
+ assertTrue(myFileIndex.isInContent(fileRoot));
+ assertIteratedContent(myFileIndex, Arrays.asList(fileRoot), null);
PsiTestUtil.addExcludedRoot(myModule, fileRoot);
- assertFalse(fileIndex.isInContent(fileRoot));
+ assertFalse(myFileIndex.isInContent(fileRoot));
assertExcluded(fileRoot, myModule);
- assertIteratedContent(fileIndex, null, Arrays.asList(fileRoot));
+ assertIteratedContent(myFileIndex, null, Arrays.asList(fileRoot));
// removing file exclude root
PsiTestUtil.removeExcludedRoot(myModule, fileRoot);
checkInfo(fileRoot, myModule, false, false, "", null);
- assertTrue(fileIndex.isInContent(fileRoot));
- assertIteratedContent(fileIndex, Arrays.asList(fileRoot), null);
+ assertTrue(myFileIndex.isInContent(fileRoot));
+ assertIteratedContent(myFileIndex, Arrays.asList(fileRoot), null);
}
public void testFileLibraryInsideFolderLibrary() throws IOException {
@@ -835,8 +845,6 @@ public class DirectoryIndexTest extends IdeaTestCase {
}
public void testFileContentRootsModifications() throws IOException {
- ProjectFileIndex fileIndex = ProjectRootManager.getInstance(myProject).getFileIndex();
-
VirtualFile temp = myRootVFile.createChildDirectory(this, "temp");
VirtualFile fileSourceRoot = myRootVFile.createChildData(this, "fileSourceRoot.txt");
@@ -845,54 +853,54 @@ public class DirectoryIndexTest extends IdeaTestCase {
PsiTestUtil.addContentRoot(myModule, fileSourceRoot);
PsiTestUtil.addSourceRoot(myModule, fileSourceRoot);
checkInfo(fileSourceRoot, myModule, false, false, "", JavaSourceRootType.SOURCE, myModule);
- assertTrue(fileIndex.isInContent(fileSourceRoot));
- assertTrue(fileIndex.isInSource(fileSourceRoot));
+ assertTrue(myFileIndex.isInContent(fileSourceRoot));
+ assertTrue(myFileIndex.isInSource(fileSourceRoot));
// delete and recreate
fileSourceRoot.delete(this);
assertNotInProject(fileSourceRoot);
- assertFalse(fileIndex.isInContent(fileSourceRoot));
- assertFalse(fileIndex.isInSource(fileSourceRoot));
+ assertFalse(myFileIndex.isInContent(fileSourceRoot));
+ assertFalse(myFileIndex.isInSource(fileSourceRoot));
fileSourceRoot = myRootVFile.createChildData(this, "fileSourceRoot.txt");
checkInfo(fileSourceRoot, myModule, false, false, "", JavaSourceRootType.SOURCE, myModule);
- assertTrue(fileIndex.isInContent(fileSourceRoot));
- assertTrue(fileIndex.isInSource(fileSourceRoot));
+ assertTrue(myFileIndex.isInContent(fileSourceRoot));
+ assertTrue(myFileIndex.isInSource(fileSourceRoot));
// delete and move from another dir
fileSourceRoot.delete(this);
assertNotInProject(fileSourceRoot);
- assertFalse(fileIndex.isInContent(fileSourceRoot));
- assertFalse(fileIndex.isInSource(fileSourceRoot));
+ assertFalse(myFileIndex.isInContent(fileSourceRoot));
+ assertFalse(myFileIndex.isInSource(fileSourceRoot));
fileSourceRoot = temp.createChildData(this, "fileSourceRoot.txt");
assertNotInProject(fileSourceRoot);
fileSourceRoot.move(this, myRootVFile);
checkInfo(fileSourceRoot, myModule, false, false, "", JavaSourceRootType.SOURCE, myModule);
- assertTrue(fileIndex.isInContent(fileSourceRoot));
- assertTrue(fileIndex.isInSource(fileSourceRoot));
+ assertTrue(myFileIndex.isInContent(fileSourceRoot));
+ assertTrue(myFileIndex.isInSource(fileSourceRoot));
// delete and copy from another dir
fileSourceRoot.delete(this);
assertNotInProject(fileSourceRoot);
- assertFalse(fileIndex.isInContent(fileSourceRoot));
- assertFalse(fileIndex.isInSource(fileSourceRoot));
+ assertFalse(myFileIndex.isInContent(fileSourceRoot));
+ assertFalse(myFileIndex.isInSource(fileSourceRoot));
fileSourceRoot = temp.createChildData(this, "fileSourceRoot.txt");
assertNotInProject(fileSourceRoot);
fileSourceRoot = fileSourceRoot.copy(this, myRootVFile, "fileSourceRoot.txt");
checkInfo(fileSourceRoot, myModule, false, false, "", JavaSourceRootType.SOURCE, myModule);
- assertTrue(fileIndex.isInContent(fileSourceRoot));
- assertTrue(fileIndex.isInSource(fileSourceRoot));
+ assertTrue(myFileIndex.isInContent(fileSourceRoot));
+ assertTrue(myFileIndex.isInSource(fileSourceRoot));
// delete and rename from another file
fileSourceRoot.delete(this);
assertNotInProject(fileSourceRoot);
- assertFalse(fileIndex.isInContent(fileSourceRoot));
- assertFalse(fileIndex.isInSource(fileSourceRoot));
+ assertFalse(myFileIndex.isInContent(fileSourceRoot));
+ assertFalse(myFileIndex.isInSource(fileSourceRoot));
fileSourceRoot = myRootVFile.createChildData(this, "temp_file.txt");
assertNotInProject(fileSourceRoot);
fileSourceRoot.rename(this, "fileSourceRoot.txt");
checkInfo(fileSourceRoot, myModule, false, false, "", JavaSourceRootType.SOURCE, myModule);
- assertTrue(fileIndex.isInContent(fileSourceRoot));
- assertTrue(fileIndex.isInSource(fileSourceRoot));
+ assertTrue(myFileIndex.isInContent(fileSourceRoot));
+ assertTrue(myFileIndex.isInSource(fileSourceRoot));
}
private void checkInfo(VirtualFile file,
@@ -914,15 +922,14 @@ public class DirectoryIndexTest extends IdeaTestCase {
assertEquals(isInLibrary, info.hasLibraryClassRoot());
assertEquals(isInLibrarySource, info.isInLibrarySource());
- final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(myProject).getFileIndex();
if (file.isDirectory()) {
- assertEquals(packageName, fileIndex.getPackageNameByDirectory(file));
+ assertEquals(packageName, myFileIndex.getPackageNameByDirectory(file));
}
- assertEquals(Arrays.toString(info.getOrderEntries()), modulesOfOrderEntries.length, info.getOrderEntries().length);
+ assertEquals(Arrays.toString(myIndex.getOrderEntries(info)), modulesOfOrderEntries.length, myIndex.getOrderEntries(info).length);
for (Module aModule : modulesOfOrderEntries) {
- OrderEntry found = info.findOrderEntryWithOwnerModule(aModule);
- assertNotNull("not found: " + aModule + " in " + Arrays.toString(info.getOrderEntries()), found);
+ OrderEntry found = myIndex.findOrderEntryWithOwnerModule(info, aModule);
+ assertNotNull("not found: " + aModule + " in " + Arrays.toString(myIndex.getOrderEntries(info)), found);
}
}
@@ -941,7 +948,7 @@ public class DirectoryIndexTest extends IdeaTestCase {
private DirectoryInfo assertInProject(VirtualFile file) {
DirectoryInfo info = myIndex.getInfoForFile(file);
assertTrue(file.toString(), info.isInProject());
- info.assertConsistency();
+ myIndex.assertConsistency(info);
return info;
}
@@ -957,6 +964,11 @@ public class DirectoryIndexTest extends IdeaTestCase {
VirtualFile[] actualDirs = myIndex.getDirectoriesByPackageName(packageName, includeLibrarySources).toArray(VirtualFile.EMPTY_ARRAY);
assertNotNull(actualDirs);
assertOrderedEquals(actualDirs, expectedDirs);
+
+ for (VirtualFile dir : expectedDirs) {
+ String actualName = myIndex.getPackageName(dir);
+ assertEquals("Invalid package name for dir " + dir + ": " + packageName, packageName, actualName);
+ }
}
}
diff --git a/java/java-tests/testSrc/com/intellij/psi/MiscPsiTest.java b/java/java-tests/testSrc/com/intellij/psi/MiscPsiTest.java
index 096547c4f4db..61414ab0b416 100644
--- a/java/java-tests/testSrc/com/intellij/psi/MiscPsiTest.java
+++ b/java/java-tests/testSrc/com/intellij/psi/MiscPsiTest.java
@@ -260,4 +260,20 @@ public class MiscPsiTest extends LightCodeInsightFixtureTestCase {
assertEquals("some.unknown.Foo<? extends String>", type.getCanonicalText());
}
+ public void testNoPsiModificationsInUncommittedDocument() {
+ final PsiJavaFile file = (PsiJavaFile)myFixture.addFileToProject("a.java", "class A{}");
+ Document document = file.getViewProvider().getDocument();
+ document.insertString(0, " ");
+
+ PsiClass psiClass = file.getClasses()[0];
+ try {
+ psiClass.addBefore(PsiParserFacade.SERVICE.getInstance(getProject()).createWhiteSpaceFromText(" "), psiClass.getLBrace());
+ fail();
+ }
+ catch (IllegalStateException e) {
+ assertEquals("Attempt to modify PSI for non-committed Document!", e.getMessage());
+ }
+ assertEquals("class A{}", psiClass.getText());
+ assertEquals(" class A{}", document.getText());
+ }
}
diff --git a/java/java-tests/testSrc/com/intellij/psi/codeStyle/arrangement/JavaRearrangerFieldReferenceTest.groovy b/java/java-tests/testSrc/com/intellij/psi/codeStyle/arrangement/JavaRearrangerFieldReferenceTest.groovy
index d11a34f6e376..7b1861b9daec 100644
--- a/java/java-tests/testSrc/com/intellij/psi/codeStyle/arrangement/JavaRearrangerFieldReferenceTest.groovy
+++ b/java/java-tests/testSrc/com/intellij/psi/codeStyle/arrangement/JavaRearrangerFieldReferenceTest.groovy
@@ -385,4 +385,28 @@ public class test {
]
)
}
+
+ void "test IDEA-128071"() {
+ doTest(
+ initial: '''
+public class FormatTest {
+ public int a = 3;
+ private static final String FACEBOOK_CLIENT_ID = "";
+ public static final String FACEBOOK_OAUTH_URL = "".concat(FACEBOOK_CLIENT_ID).concat("");
+}
+''',
+ expected: '''
+public class FormatTest {
+ private static final String FACEBOOK_CLIENT_ID = "";
+ public static final String FACEBOOK_OAUTH_URL = "".concat(FACEBOOK_CLIENT_ID).concat("");
+ public int a = 3;
+}
+''',
+ rules: [
+ rule(PUBLIC, STATIC, FINAL),
+ rule(PRIVATE, STATIC, FINAL),
+ rule(PUBLIC)
+ ]
+ )
+ }
}
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/RenameCollisionsTest.java b/java/java-tests/testSrc/com/intellij/refactoring/RenameCollisionsTest.java
index 204525cb6822..e830594db39f 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/RenameCollisionsTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/RenameCollisionsTest.java
@@ -208,6 +208,10 @@ public class RenameCollisionsTest extends LightRefactoringTestCase {
doTest("foo2");
}
+ public void testRenameMethodNoCollisionWithOtherSignatureMethodRef() throws Exception {
+ doTest("foo2");
+ }
+
public void testRenameNoStaticOverridingInInterfaces() throws Exception {
doTest("foo");
}
diff --git a/java/java-tests/testSrc/com/intellij/roots/ModuleScopesTest.java b/java/java-tests/testSrc/com/intellij/roots/ModuleScopesTest.java
index 514348e5913b..0ad26a34eec5 100644
--- a/java/java-tests/testSrc/com/intellij/roots/ModuleScopesTest.java
+++ b/java/java-tests/testSrc/com/intellij/roots/ModuleScopesTest.java
@@ -105,15 +105,21 @@ public class ModuleScopesTest extends ModuleTestCase {
}
private Module addDependentModule(final Module moduleA, final DependencyScope scope) {
- final Module moduleB = createModule("b.iml", StdModuleTypes.JAVA);
+ return addDependentModule("b", moduleA, scope, false);
+ }
+
+ private Module addDependentModule(final String name, final Module moduleA,
+ final DependencyScope scope,
+ final boolean exported) {
+ final Module moduleB = createModule(name + ".iml", StdModuleTypes.JAVA);
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
- VirtualFile rootB = myFixture.findOrCreateDir("b");
+ VirtualFile rootB = myFixture.findOrCreateDir(name);
VirtualFile outB = myFixture.findOrCreateDir("out");
- ModuleRootModificationUtil.addDependency(moduleA, moduleB, scope, false);
+ ModuleRootModificationUtil.addDependency(moduleA, moduleB, scope, exported);
PsiTestUtil.addSourceRoot(moduleB, rootB);
PsiTestUtil.setCompilerOutputPath(moduleB, outB.getUrl(), false);
@@ -123,6 +129,25 @@ public class ModuleScopesTest extends ModuleTestCase {
return moduleB;
}
+ public void testModuleTwiceInDependents() throws IOException {
+ Module m = createModule("m.iml", StdModuleTypes.JAVA);
+ Module a = createModule("a.iml", StdModuleTypes.JAVA);
+ Module b = createModule("b.iml", StdModuleTypes.JAVA);
+ Module c = createModule("c.iml", StdModuleTypes.JAVA);
+
+ ModuleRootModificationUtil.addDependency(a, m, DependencyScope.COMPILE, false);
+ ModuleRootModificationUtil.addDependency(b, m, DependencyScope.COMPILE, true);
+ ModuleRootModificationUtil.addDependency(a, b, DependencyScope.COMPILE, true);
+ ModuleRootModificationUtil.addDependency(c, a, DependencyScope.COMPILE, true);
+
+ VirtualFile root = myFixture.findOrCreateDir("c");
+ PsiTestUtil.addSourceContentToRoots(c, root);
+ VirtualFile file = root.createChildData(this, "x.txt");
+
+ GlobalSearchScope deps = m.getModuleWithDependentsScope();
+ assertTrue(deps.contains(file));
+ }
+
public void testTestOnlyLibraryDependency() throws IOException {
Module m = createModule("a.iml", StdModuleTypes.JAVA);
addLibrary(m, DependencyScope.TEST);
diff --git a/java/java-tests/testSrc/com/intellij/slicer/SliceTreeTest.java b/java/java-tests/testSrc/com/intellij/slicer/SliceTreeTest.java
index 6e34ebf5f939..b6d8840059ba 100644
--- a/java/java-tests/testSrc/com/intellij/slicer/SliceTreeTest.java
+++ b/java/java-tests/testSrc/com/intellij/slicer/SliceTreeTest.java
@@ -49,7 +49,8 @@ public class SliceTreeTest extends SliceTestCase {
SliceUsage usage = SliceUsage.createRootUsage(element, params);
- SlicePanel panel = new SlicePanel(getProject(), true, new SliceRootNode(getProject(), new DuplicateMap(), usage), false, ToolWindowHeadlessManagerImpl.HEADLESS_WINDOW) {
+ ToolWindowHeadlessManagerImpl.MockToolWindow toolWindow = new ToolWindowHeadlessManagerImpl.MockToolWindow(myProject);
+ SlicePanel panel = new SlicePanel(getProject(), true, new SliceRootNode(getProject(), new DuplicateMap(), usage), false, toolWindow) {
@Override
protected void close() {
}
diff --git a/java/jsp-openapi/src/com/intellij/psi/jsp/JavaJspElementVisitor.java b/java/jsp-openapi/src/com/intellij/psi/jsp/JavaJspElementVisitor.java
index 6eda197118bd..6100c98323bc 100644
--- a/java/jsp-openapi/src/com/intellij/psi/jsp/JavaJspElementVisitor.java
+++ b/java/jsp-openapi/src/com/intellij/psi/jsp/JavaJspElementVisitor.java
@@ -21,9 +21,6 @@ import com.intellij.psi.JavaElementVisitor;
* @author yole
*/
public abstract class JavaJspElementVisitor extends JavaElementVisitor {
- public void visitJspImplicitVariable(JspImplicitVariable variable){
- visitImplicitVariable(variable);
- }
public void visitJspFile(JspFile jspFile) {
visitFile(jspFile);
diff --git a/java/openapi/src/com/intellij/ui/classFilter/ClassFilter.java b/java/openapi/src/com/intellij/ui/classFilter/ClassFilter.java
index 05500e31ebd3..b93deafa1fe8 100644
--- a/java/openapi/src/com/intellij/ui/classFilter/ClassFilter.java
+++ b/java/openapi/src/com/intellij/ui/classFilter/ClassFilter.java
@@ -17,15 +17,20 @@
package com.intellij.ui.classFilter;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.DefaultJDOMExternalizer;
+import com.intellij.openapi.util.InvalidDataException;
+import com.intellij.openapi.util.JDOMExternalizable;
+import com.intellij.openapi.util.WriteExternalException;
import com.intellij.util.xmlb.annotations.Attribute;
import com.intellij.util.xmlb.annotations.Tag;
import com.intellij.util.xmlb.annotations.Transient;
+import org.jdom.Element;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@Tag("class-filter")
-public class ClassFilter implements Cloneable {
+public class ClassFilter implements JDOMExternalizable, Cloneable{
private static final Logger LOG = Logger.getInstance("#com.intellij.ui.classFilter.ClassFilter");
public static final ClassFilter[] EMPTY_ARRAY = new ClassFilter[0];
@@ -67,6 +72,16 @@ public class ClassFilter implements Cloneable {
return getPattern();
}
+ @Override
+ public void readExternal(Element element) throws InvalidDataException {
+ DefaultJDOMExternalizer.readExternal(this, element);
+ }
+
+ @Override
+ public void writeExternal(Element element) throws WriteExternalException {
+ DefaultJDOMExternalizer.writeExternal(this, element);
+ }
+
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ClassFilter)) return false;
diff --git a/java/remote-servers/impl/remote-servers-java-impl.iml b/java/remote-servers/impl/remote-servers-java-impl.iml
index 6999e2deac71..15781473aa45 100644
--- a/java/remote-servers/impl/remote-servers-java-impl.iml
+++ b/java/remote-servers/impl/remote-servers-java-impl.iml
@@ -15,6 +15,7 @@
<orderEntry type="module" module-name="remote-servers-impl" />
<orderEntry type="module" module-name="java-impl" />
<orderEntry type="module" module-name="openapi" />
+ <orderEntry type="module" module-name="idea-ui" />
</component>
</module>
diff --git a/java/remote-servers/impl/src/META-INF/RemoteServersJava.xml b/java/remote-servers/impl/src/META-INF/RemoteServersJava.xml
index 24a0776ccd29..692199e3bb2c 100644
--- a/java/remote-servers/impl/src/META-INF/RemoteServersJava.xml
+++ b/java/remote-servers/impl/src/META-INF/RemoteServersJava.xml
@@ -2,7 +2,7 @@
<extensionPoints>
<extensionPoint qualifiedName="com.intellij.remoteServer.moduleBuilderContribution"
- interface="com.intellij.remoteServer.impl.module.CloudModuleBuilderContribution"/>
+ interface="com.intellij.remoteServer.impl.module.CloudModuleBuilderContributionFactory"/>
</extensionPoints>
<extensions defaultExtensionNs="com.intellij">
diff --git a/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudApplicationConfigurable.java b/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudApplicationConfigurable.java
index 14bd043a7f23..e235eeeb55aa 100644
--- a/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudApplicationConfigurable.java
+++ b/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudApplicationConfigurable.java
@@ -15,152 +15,20 @@
*/
package com.intellij.remoteServer.impl.module;
-import com.intellij.openapi.Disposable;
import com.intellij.openapi.options.ConfigurationException;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Disposer;
import com.intellij.remoteServer.configuration.RemoteServer;
-import com.intellij.remoteServer.runtime.Deployment;
-import com.intellij.remoteServer.runtime.ServerConnection;
-import com.intellij.remoteServer.runtime.ServerConnector;
-import com.intellij.remoteServer.runtime.deployment.ServerRuntimeInstance;
-import com.intellij.remoteServer.util.*;
-import com.intellij.util.concurrency.Semaphore;
-import com.intellij.util.ui.UIUtil;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import javax.swing.*;
-import java.util.Collection;
-import java.util.concurrent.atomic.AtomicReference;
+import java.awt.*;
-public abstract class CloudApplicationConfigurable<
- SC extends CloudConfigurationBase,
- DC extends CloudDeploymentNameConfiguration,
- SR extends CloudMultiSourceServerRuntimeInstance<DC, ?, ?, ?>,
- AC extends CloudApplicationConfiguration> {
+public abstract class CloudApplicationConfigurable {
- private final Project myProject;
- private final Disposable myParentDisposable;
+ public abstract Component getComponent();
- private DelayedRunner myRunner;
+ public abstract void setAccount(RemoteServer<?> account);
- private RemoteServer<?> myAccount;
-
- public CloudApplicationConfigurable(@Nullable Project project, Disposable parentDisposable) {
- myProject = project;
- myParentDisposable = parentDisposable;
- }
-
- public void setAccount(RemoteServer<?> account) {
- myAccount = account;
- clearCloudData();
- }
-
- protected RemoteServer<SC> getAccount() {
- return (RemoteServer<SC>)myAccount;
- }
-
- public JComponent getComponent() {
- JComponent result = getMainPanel();
- if (myRunner == null) {
- myRunner = new DelayedRunner(result) {
-
- private RemoteServer<?> myPreviousAccount;
-
- @Override
- protected boolean wasChanged() {
- boolean result = myPreviousAccount != myAccount;
- if (result) {
- myPreviousAccount = myAccount;
- }
- return result;
- }
-
- @Override
- protected void run() {
- loadCloudData();
- }
- };
- Disposer.register(myParentDisposable, myRunner);
- }
- return result;
- }
-
- protected void clearCloudData() {
- getExistingComboBox().removeAllItems();
- }
-
- protected void loadCloudData() {
- new ConnectionTask<Collection<Deployment>>("Loading existing applications list") {
-
- @Override
- protected void run(final ServerConnection<DC> connection,
- final Semaphore semaphore,
- final AtomicReference<Collection<Deployment>> result) {
- connection.connectIfNeeded(new ServerConnector.ConnectionCallback<DC>() {
-
- @Override
- public void connected(@NotNull ServerRuntimeInstance<DC> serverRuntimeInstance) {
- connection.computeDeployments(new Runnable() {
-
- @Override
- public void run() {
- result.set(connection.getDeployments());
- semaphore.up();
- UIUtil.invokeLaterIfNeeded(new Runnable() {
- @Override
- public void run() {
- if (!Disposer.isDisposed(myParentDisposable)) {
- setupExistingApplications(result.get());
- }
- }
- });
- }
- });
- }
-
- @Override
- public void errorOccurred(@NotNull String errorMessage) {
- runtimeErrorOccurred(errorMessage);
- semaphore.up();
- }
- });
- }
-
- @Override
- protected Collection<Deployment> run(SR serverRuntimeInstance) throws ServerRuntimeException {
- return null;
- }
- }.performAsync();
- }
-
- private void setupExistingApplications(Collection<Deployment> deployments) {
- JComboBox existingComboBox = getExistingComboBox();
- existingComboBox.removeAllItems();
- for (Deployment deployment : deployments) {
- existingComboBox.addItem(deployment.getName());
- }
- }
-
- protected Project getProject() {
- return myProject;
- }
-
- protected abstract JComboBox getExistingComboBox();
-
- protected abstract JComponent getMainPanel();
-
- public abstract AC createConfiguration();
+ public abstract CloudApplicationConfiguration createConfiguration();
public abstract void validate() throws ConfigurationException;
-
- protected abstract class ConnectionTask<T> extends CloudConnectionTask<T, SC, DC, SR> {
-
- public ConnectionTask(String title) {
- super(myProject, title, CloudApplicationConfigurable.this.getAccount());
- }
- }
}
diff --git a/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudApplicationConfiguration.java b/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudApplicationConfiguration.java
index 9af0f1ad472b..af9fa723e82a 100644
--- a/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudApplicationConfiguration.java
+++ b/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudApplicationConfiguration.java
@@ -18,19 +18,4 @@ package com.intellij.remoteServer.impl.module;
public abstract class CloudApplicationConfiguration {
- private boolean myExisting;
- private final String myExistingAppName;
-
- protected CloudApplicationConfiguration(boolean existing, String existingAppName) {
- myExisting = existing;
- myExistingAppName = existingAppName;
- }
-
- public boolean isExisting() {
- return myExisting;
- }
-
- public String getExistingAppName() {
- return myExistingAppName;
- }
}
diff --git a/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudModuleBuilder.java b/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudModuleBuilder.java
index 4aa8d60bcea4..62e256c14c8e 100644
--- a/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudModuleBuilder.java
+++ b/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudModuleBuilder.java
@@ -16,6 +16,7 @@
package com.intellij.remoteServer.impl.module;
import com.intellij.icons.AllIcons;
+import com.intellij.ide.util.newProjectWizard.impl.FrameworkSupportModelBase;
import com.intellij.ide.util.projectWizard.JavaModuleBuilder;
import com.intellij.ide.util.projectWizard.ModuleBuilderListener;
import com.intellij.ide.util.projectWizard.ModuleWizardStep;
@@ -23,20 +24,42 @@ import com.intellij.ide.util.projectWizard.WizardContext;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.module.JavaModuleType;
import com.intellij.openapi.module.Module;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.ui.configuration.ModulesProvider;
+import com.intellij.openapi.roots.ui.configuration.projectRoot.LibrariesContainer;
+import com.intellij.openapi.roots.ui.configuration.projectRoot.LibrariesContainerFactory;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.remoteServer.ServerType;
import com.intellij.remoteServer.configuration.RemoteServer;
+import com.intellij.util.containers.hash.HashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
+import java.util.Map;
public class CloudModuleBuilder extends JavaModuleBuilder {
private RemoteServer<?> myAccount;
private CloudApplicationConfiguration myApplicationConfiguration;
+ private FrameworkSupportModelBase myFrameworkSupportModel;
+
+ private Map<ServerType<?>, CloudModuleBuilderContribution> myCloudType2Contribution;
+ private Project myProject;
public CloudModuleBuilder() {
+ myCloudType2Contribution = new HashMap<ServerType<?>, CloudModuleBuilderContribution>();
+
+ ModuleConfigurationUpdater configurationUpdater = new ModuleConfigurationUpdater() {
+
+ public void update(@NotNull final Module module, @NotNull final ModifiableRootModel rootModel) {
+ preConfigureModule(module, rootModel);
+ }
+ };
+ addModuleConfigurationUpdater(configurationUpdater);
+
addListener(new ModuleBuilderListener() {
@Override
@@ -93,7 +116,8 @@ public class CloudModuleBuilder extends JavaModuleBuilder {
@Nullable
@Override
public ModuleWizardStep getCustomOptionsStep(WizardContext context, Disposable parentDisposable) {
- return new CloudModuleWizardStep(this, context.getProject(), parentDisposable);
+ myProject = context.getProject();
+ return new CloudModuleWizardStep(this, myProject, parentDisposable);
}
public void setAccount(RemoteServer<?> account) {
@@ -108,7 +132,43 @@ public class CloudModuleBuilder extends JavaModuleBuilder {
myApplicationConfiguration = applicationConfiguration;
}
+ public CloudApplicationConfiguration getApplicationConfiguration() {
+ return myApplicationConfiguration;
+ }
+
+ public CloudModuleBuilderContribution getContribution(ServerType<?> cloudType) {
+ CloudModuleBuilderContribution result = myCloudType2Contribution.get(cloudType);
+ if (result == null) {
+ result = CloudModuleBuilderContributionFactory.getInstanceByType(cloudType).createContribution(this);
+ myCloudType2Contribution.put(cloudType, result);
+ }
+ return result;
+ }
+
+ private CloudModuleBuilderContribution getContribution() {
+ return getContribution(myAccount.getType());
+ }
+
+ private void preConfigureModule(Module module, ModifiableRootModel model) {
+ getContribution().preConfigureModule(module, model);
+ }
+
private void configureModule(final Module module) {
- CloudModuleBuilderContribution.getInstanceByType(myAccount.getType()).configureModule(module, myAccount, myApplicationConfiguration);
+ getContribution().configureModule(module);
+ }
+
+ public FrameworkSupportModelBase getFrameworkSupportModel() {
+ if (myFrameworkSupportModel == null) {
+ final LibrariesContainer librariesContainer = LibrariesContainerFactory.createContainer(myProject);
+ myFrameworkSupportModel = new FrameworkSupportModelBase(myProject, this, librariesContainer) {
+
+ @NotNull
+ @Override
+ public String getBaseDirectoryForLibrariesPath() {
+ return StringUtil.notNullize(getContentEntryPath());
+ }
+ };
+ }
+ return myFrameworkSupportModel;
}
}
diff --git a/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudModuleBuilderContribution.java b/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudModuleBuilderContribution.java
index 6643c89cc1c4..dd2d9d9af563 100644
--- a/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudModuleBuilderContribution.java
+++ b/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudModuleBuilderContribution.java
@@ -16,33 +16,51 @@
package com.intellij.remoteServer.impl.module;
import com.intellij.openapi.Disposable;
-import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.remoteServer.ServerType;
-import com.intellij.remoteServer.configuration.RemoteServer;
+import com.intellij.remoteServer.configuration.deployment.DeploymentConfiguration;
+import com.intellij.remoteServer.configuration.deployment.DeploymentSource;
import org.jetbrains.annotations.Nullable;
public abstract class CloudModuleBuilderContribution {
- public static final ExtensionPointName<CloudModuleBuilderContribution> EP_NAME
- = ExtensionPointName.create("com.intellij.remoteServer.moduleBuilderContribution");
+ private final CloudModuleBuilder myModuleBuilder;
- public abstract ServerType<?> getCloudType();
+ private final ServerType<?> myCloudType;
+ private CloudApplicationConfigurable myApplicationConfigurable;
- public abstract CloudApplicationConfigurable createApplicationConfigurable(@Nullable Project project, Disposable parentDisposable);
+ public CloudModuleBuilderContribution(CloudModuleBuilder moduleBuilder, ServerType<?> cloudType) {
+ myModuleBuilder = moduleBuilder;
+ myCloudType = cloudType;
+ }
+
+ protected CloudModuleBuilder getModuleBuilder() {
+ return myModuleBuilder;
+ }
- public abstract void configureModule(Module module,
- RemoteServer<?> account,
- CloudApplicationConfiguration configuration);
+ protected ServerType<?> getCloudType() {
+ return myCloudType;
+ }
- public static CloudModuleBuilderContribution getInstanceByType(ServerType<?> cloudType) {
- for (CloudModuleBuilderContribution contribution : EP_NAME.getExtensions()) {
- if (contribution.getCloudType() == cloudType) {
- return contribution;
- }
+ public CloudApplicationConfigurable getApplicationConfigurable(@Nullable Project project, Disposable parentDisposable) {
+ if (myApplicationConfigurable == null) {
+ myApplicationConfigurable = createApplicationConfigurable(project, parentDisposable);
}
- return null;
+ return myApplicationConfigurable;
+ }
+
+ public void preConfigureModule(Module module, ModifiableRootModel model) {
+
+ }
+
+ public abstract void configureModule(Module module);
+
+ protected abstract CloudApplicationConfigurable createApplicationConfigurable(@Nullable Project project, Disposable parentDisposable);
+
+ protected DeploymentConfiguration createDeploymentConfiguration(DeploymentSource deploymentSource) {
+ return myCloudType.createDeploymentConfigurator(null).createDefaultConfiguration(deploymentSource);
}
}
diff --git a/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudModuleBuilderContributionBase.java b/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudModuleBuilderContributionBase.java
deleted file mode 100644
index 6a927d97bb93..000000000000
--- a/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudModuleBuilderContributionBase.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright 2000-2014 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.remoteServer.impl.module;
-
-import com.intellij.execution.RunManagerEx;
-import com.intellij.execution.RunnerAndConfigurationSettings;
-import com.intellij.execution.configurations.ConfigurationType;
-import com.intellij.openapi.Disposable;
-import com.intellij.openapi.module.Module;
-import com.intellij.openapi.module.ModulePointer;
-import com.intellij.openapi.module.ModulePointerManager;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.MessageType;
-import com.intellij.remoteServer.ServerType;
-import com.intellij.remoteServer.configuration.RemoteServer;
-import com.intellij.remoteServer.impl.configuration.deployment.DeployToServerConfigurationType;
-import com.intellij.remoteServer.impl.configuration.deployment.DeployToServerRunConfiguration;
-import com.intellij.remoteServer.impl.configuration.deployment.ModuleDeploymentSourceImpl;
-import com.intellij.remoteServer.util.*;
-import com.intellij.remoteServer.util.ssh.SshKeyChecker;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-
-public abstract class CloudModuleBuilderContributionBase<
- SC extends CloudConfigurationBase,
- DC extends CloudDeploymentNameConfiguration,
- AC extends CloudApplicationConfiguration,
- SR extends CloudMultiSourceServerRuntimeInstance<DC, ?, ?, ?>>
- extends CloudModuleBuilderContribution {
-
- @Override
- public void configureModule(Module module,
- RemoteServer<?> account,
- CloudApplicationConfiguration applicationConfiguration) {
- RemoteServer<SC> castedAccount = (RemoteServer<SC>)account;
- final AC castedApplicationConfiguration = (AC)applicationConfiguration;
-
- DC deploymentConfiguration = createDeploymentConfiguration();
-
- if (applicationConfiguration.isExisting()) {
- deploymentConfiguration.setDefaultDeploymentName(false);
- deploymentConfiguration.setDeploymentName(applicationConfiguration.getExistingAppName());
- }
-
- final DeployToServerRunConfiguration<SC, DC> runConfiguration = createRunConfiguration(module, castedAccount, deploymentConfiguration);
-
- final String cloudName = account.getType().getPresentableName();
- final Project project = module.getProject();
- new CloudConnectionTask<Object, SC, DC, SR>(project, CloudBundle.getText("cloud.support", cloudName), castedAccount) {
-
- CloudNotifier myNotifier = new CloudNotifier(cloudName);
-
- boolean myFirstAttempt = true;
-
- @Override
- protected Object run(SR serverRuntime) throws ServerRuntimeException {
- doConfigureModule(castedApplicationConfiguration, runConfiguration, myFirstAttempt, serverRuntime);
- myNotifier.showMessage(CloudBundle.getText("cloud.support.added", cloudName), MessageType.INFO);
- return null;
- }
-
- @Override
- protected void runtimeErrorOccurred(@NotNull String errorMessage) {
- myFirstAttempt = false;
- new SshKeyChecker().checkServerError(errorMessage, myNotifier, project, this);
- }
- }.performAsync();
- }
-
- private DeployToServerRunConfiguration<SC, DC> createRunConfiguration(Module module,
- RemoteServer<SC> server,
- DC deploymentConfiguration) {
- Project project = module.getProject();
-
- String serverName = server.getName();
-
- String name = generateRunConfigurationName(serverName, module.getName());
-
- final RunManagerEx runManager = RunManagerEx.getInstanceEx(project);
- final RunnerAndConfigurationSettings runSettings
- = runManager.createRunConfiguration(name, getRunConfigurationType().getConfigurationFactories()[0]);
-
- final DeployToServerRunConfiguration<SC, DC> result = (DeployToServerRunConfiguration<SC, DC>)runSettings.getConfiguration();
-
- result.setServerName(serverName);
-
- final ModulePointer modulePointer = ModulePointerManager.getInstance(project).create(module);
- result.setDeploymentSource(new ModuleDeploymentSourceImpl(modulePointer));
-
- result.setDeploymentConfiguration(deploymentConfiguration);
-
- runManager.addConfiguration(runSettings, false);
- runManager.setSelectedConfiguration(runSettings);
-
- return result;
- }
-
- private static String generateRunConfigurationName(String serverName, String moduleName) {
- return CloudBundle.getText("run.configuration.name", serverName, moduleName);
- }
-
- private DeployToServerConfigurationType getRunConfigurationType() {
- String id = DeployToServerConfigurationType.getId(getCloudType());
- for (ConfigurationType configurationType : ConfigurationType.CONFIGURATION_TYPE_EP.getExtensions()) {
- if (configurationType instanceof DeployToServerConfigurationType) {
- DeployToServerConfigurationType deployConfigurationType = (DeployToServerConfigurationType)configurationType;
- if (deployConfigurationType.getId().equals(id)) {
- return deployConfigurationType;
- }
- }
- }
- return null;
- }
-
- @Override
- public abstract ServerType<SC> getCloudType();
-
- @Override
- public abstract CloudApplicationConfigurable<SC, DC, SR, AC> createApplicationConfigurable(@Nullable Project project,
- Disposable parentDisposable);
-
- protected abstract DC createDeploymentConfiguration();
-
- protected abstract void doConfigureModule(AC applicationConfiguration,
- DeployToServerRunConfiguration<SC, DC> runConfiguration,
- boolean firstAttempt,
- SR serverRuntime) throws ServerRuntimeException;
-}
diff --git a/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudModuleBuilderContributionFactory.java b/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudModuleBuilderContributionFactory.java
new file mode 100644
index 000000000000..20ebc29fe148
--- /dev/null
+++ b/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudModuleBuilderContributionFactory.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.remoteServer.impl.module;
+
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.remoteServer.ServerType;
+
+
+public abstract class CloudModuleBuilderContributionFactory {
+
+ public static final ExtensionPointName<CloudModuleBuilderContributionFactory> EP_NAME
+ = ExtensionPointName.create("com.intellij.remoteServer.moduleBuilderContribution");
+
+ public abstract ServerType<?> getCloudType();
+
+ public abstract CloudModuleBuilderContribution createContribution(CloudModuleBuilder moduleBuilder);
+
+ public static CloudModuleBuilderContributionFactory getInstanceByType(ServerType<?> cloudType) {
+ for (CloudModuleBuilderContributionFactory contribution : EP_NAME.getExtensions()) {
+ if (contribution.getCloudType() == cloudType) {
+ return contribution;
+ }
+ }
+ return null;
+ }
+}
diff --git a/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudModuleBuilderSourceContribution.java b/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudModuleBuilderSourceContribution.java
new file mode 100644
index 000000000000..b5fdcc3995c8
--- /dev/null
+++ b/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudModuleBuilderSourceContribution.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.remoteServer.impl.module;
+
+import com.intellij.ide.util.newProjectWizard.StepSequence;
+import com.intellij.ide.util.newProjectWizard.modes.CreateFromSourcesMode;
+import com.intellij.ide.util.projectWizard.AbstractStepWithProgress;
+import com.intellij.ide.util.projectWizard.ModuleWizardStep;
+import com.intellij.ide.util.projectWizard.ProjectBuilder;
+import com.intellij.ide.util.projectWizard.WizardContext;
+import com.intellij.openapi.Disposable;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.ProgressManager;
+import com.intellij.openapi.progress.Task;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.ui.configuration.DefaultModulesProvider;
+import com.intellij.openapi.roots.ui.configuration.ModulesProvider;
+import com.intellij.openapi.ui.MessageType;
+import com.intellij.openapi.util.Disposer;
+import com.intellij.remoteServer.ServerType;
+import com.intellij.remoteServer.configuration.RemoteServer;
+import com.intellij.remoteServer.impl.configuration.deployment.DeployToServerRunConfiguration;
+import com.intellij.remoteServer.util.*;
+import com.intellij.remoteServer.util.ssh.SshKeyChecker;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+
+public abstract class CloudModuleBuilderSourceContribution<
+ SC extends CloudConfigurationBase,
+ DC extends CloudDeploymentNameConfiguration,
+ AC extends CloudSourceApplicationConfiguration,
+ SR extends CloudMultiSourceServerRuntimeInstance<DC, ?, ?, ?>>
+ extends CloudModuleBuilderContribution {
+
+ private CloudNotifier myNotifier;
+
+ public CloudModuleBuilderSourceContribution(CloudModuleBuilder moduleBuilder, ServerType<SC> cloudType) {
+ super(moduleBuilder, cloudType);
+ }
+
+ @Override
+ public void configureModule(final Module module) {
+ final CloudModuleBuilder moduleBuilder = getModuleBuilder();
+ RemoteServer<SC> account = (RemoteServer<SC>)moduleBuilder.getAccount();
+ final AC applicationConfiguration = (AC)moduleBuilder.getApplicationConfiguration();
+
+ DC deploymentConfiguration = createDeploymentConfiguration();
+
+ if (applicationConfiguration.isExisting()) {
+ deploymentConfiguration.setDefaultDeploymentName(false);
+ deploymentConfiguration.setDeploymentName(applicationConfiguration.getExistingAppName());
+ }
+
+ final DeployToServerRunConfiguration<SC, DC> runConfiguration
+ = CloudRunConfigurationUtil.createRunConfiguration(account, module, deploymentConfiguration);
+
+ final ServerType<?> cloudType = account.getType();
+ final Project project = module.getProject();
+ new CloudConnectionTask<Object, SC, DC, SR>(project,
+ CloudBundle.getText("cloud.support", cloudType.getPresentableName()),
+ account) {
+
+ boolean myFirstAttempt = true;
+
+ @Override
+ protected Object run(SR serverRuntime) throws ServerRuntimeException {
+ doConfigureModule(applicationConfiguration, runConfiguration, myFirstAttempt, serverRuntime);
+ return null;
+ }
+
+ @Override
+ protected void runtimeErrorOccurred(@NotNull String errorMessage) {
+ myFirstAttempt = false;
+ new SshKeyChecker().checkServerError(errorMessage, getNotifier(), project, this);
+ }
+
+ @Override
+ protected void postPerform(Object result) {
+ detectModuleStructure(module, moduleBuilder.getContentEntryPath());
+ }
+
+ @Override
+ protected boolean shouldStartInBackground() {
+ return false;
+ }
+ }.performAsync();
+ }
+
+ private CloudNotifier getNotifier() {
+ if (myNotifier == null) {
+ myNotifier = new CloudNotifier(getCloudType().getPresentableName());
+ }
+ return myNotifier;
+ }
+
+ private void detectModuleStructure(Module module, final String contentPath) {
+ final Project project = module.getProject();
+
+ final CreateFromSourcesMode mode = new CreateFromSourcesMode() {
+
+ @Override
+ public boolean isAvailable(WizardContext context) {
+ return true;
+ }
+
+ @Override
+ public void addSteps(WizardContext context, ModulesProvider modulesProvider, StepSequence sequence, String specific) {
+ super.addSteps(context, modulesProvider, sequence, specific);
+ myProjectBuilder.setFileToImport(contentPath);
+ }
+ };
+
+ final WizardContext context = new WizardContext(project);
+
+ final StepSequence stepSequence = mode.getSteps(context, DefaultModulesProvider.createForProject(context.getProject()));
+ if (stepSequence == null) {
+ return;
+ }
+
+ Disposer.register(project, new Disposable() {
+
+ @Override
+ public void dispose() {
+ for (ModuleWizardStep step : stepSequence.getAllSteps()) {
+ step.disposeUIResources();
+ }
+ }
+ });
+
+ ProgressManager.getInstance()
+ .run(new Task.Backgroundable(project, CloudBundle.getText("detect.module.structure", getCloudType().getPresentableName()), false) {
+
+ @Override
+ public void run(@NotNull ProgressIndicator indicator) {
+ for (ModuleWizardStep step = ContainerUtil.getFirstItem(stepSequence.getSelectedSteps());
+ step != null;
+ step = stepSequence.getNextStep(step)) {
+ if (step instanceof AbstractStepWithProgress<?>) {
+ ((AbstractStepWithProgress)step).performStep();
+ }
+ else {
+ step.updateDataModel();
+ }
+ }
+ CloudAccountSelectionEditor.unsetAccountOnContext(context, getCloudType());
+ }
+
+ @Override
+ public boolean shouldStartInBackground() {
+ return false;
+ }
+
+ @Override
+ public void onSuccess() {
+ ProjectBuilder moduleBuilder = mode.getModuleBuilder();
+ if (moduleBuilder == null) {
+ return;
+ }
+ moduleBuilder.commit(project);
+ getNotifier().showMessage(CloudBundle.getText("cloud.support.added", getCloudType().getPresentableName()), MessageType.INFO);
+ }
+ });
+ }
+
+ @Override
+ protected abstract CloudSourceApplicationConfigurable<SC, DC, SR, AC> createApplicationConfigurable(@Nullable Project project,
+ Disposable parentDisposable);
+
+ protected abstract DC createDeploymentConfiguration();
+
+ protected abstract void doConfigureModule(AC applicationConfiguration,
+ DeployToServerRunConfiguration<SC, DC> runConfiguration,
+ boolean firstAttempt,
+ SR serverRuntime) throws ServerRuntimeException;
+}
diff --git a/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudModuleWizardStep.java b/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudModuleWizardStep.java
index cf0e283616b2..79b307b0658e 100644
--- a/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudModuleWizardStep.java
+++ b/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudModuleWizardStep.java
@@ -22,13 +22,13 @@ import com.intellij.openapi.project.Project;
import com.intellij.remoteServer.ServerType;
import com.intellij.remoteServer.configuration.RemoteServer;
import com.intellij.remoteServer.util.CloudAccountSelectionEditor;
-import com.intellij.util.containers.hash.HashMap;
+import com.intellij.util.containers.HashSet;
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
-import java.util.Map;
+import java.util.Set;
public class CloudModuleWizardStep extends ModuleWizardStep {
@@ -43,17 +43,17 @@ public class CloudModuleWizardStep extends ModuleWizardStep {
private CloudAccountSelectionEditor myAccountSelectionPanel;
- private Map<ServerType<?>, CloudApplicationConfigurable> myCloudType2ApplicationConfigurable;
+ private Set<ServerType<?>> myApplicationConfigurableTypes;
public CloudModuleWizardStep(CloudModuleBuilder moduleBuilder, Project project, Disposable parentDisposable) {
myModuleBuilder = moduleBuilder;
myProject = project;
myParentDisposable = parentDisposable;
- myCloudType2ApplicationConfigurable = new HashMap<ServerType<?>, CloudApplicationConfigurable>();
+ myApplicationConfigurableTypes = new HashSet<ServerType<?>>();
List<ServerType<?>> cloudTypes = new ArrayList<ServerType<?>>();
- for (CloudModuleBuilderContribution contribution : CloudModuleBuilderContribution.EP_NAME.getExtensions()) {
+ for (CloudModuleBuilderContributionFactory contribution : CloudModuleBuilderContributionFactory.EP_NAME.getExtensions()) {
cloudTypes.add(contribution.getCloudType());
}
@@ -86,11 +86,8 @@ public class CloudModuleWizardStep extends ModuleWizardStep {
ServerType<?> cloudType = account.getType();
String cardName = cloudType.getId();
- CloudApplicationConfigurable<?, ?, ?, ?> applicationConfigurable = getApplicationConfigurable();
- if (applicationConfigurable == null) {
- applicationConfigurable
- = CloudModuleBuilderContribution.getInstanceByType(cloudType).createApplicationConfigurable(myProject, myParentDisposable);
- myCloudType2ApplicationConfigurable.put(cloudType, applicationConfigurable);
+ CloudApplicationConfigurable applicationConfigurable = getApplicationConfigurable();
+ if (myApplicationConfigurableTypes.add(cloudType)) {
myApplicationPanelPlaceHolder.add(applicationConfigurable.getComponent(), cardName);
}
applicationPlaceHolderLayout.show(myApplicationPanelPlaceHolder, cardName);
@@ -103,25 +100,25 @@ public class CloudModuleWizardStep extends ModuleWizardStep {
return myMainPanel;
}
- private CloudApplicationConfigurable<?, ?, ?, ?> getApplicationConfigurable() {
+ private CloudApplicationConfigurable getApplicationConfigurable() {
RemoteServer<?> account = getSelectedAccount();
if (account == null) {
return null;
}
- return myCloudType2ApplicationConfigurable.get(account.getType());
+ return myModuleBuilder.getContribution(account.getType()).getApplicationConfigurable(myProject, myParentDisposable);
}
@Override
public void updateDataModel() {
myModuleBuilder.setAccount(myAccountSelectionPanel.getSelectedAccount());
- CloudApplicationConfigurable<?, ?, ?, ?> configurable = getApplicationConfigurable();
+ CloudApplicationConfigurable configurable = getApplicationConfigurable();
myModuleBuilder.setApplicationConfiguration(configurable == null ? null : configurable.createConfiguration());
}
@Override
public boolean validate() throws ConfigurationException {
myAccountSelectionPanel.validate();
- CloudApplicationConfigurable<?, ?, ?, ?> configurable = getApplicationConfigurable();
+ CloudApplicationConfigurable configurable = getApplicationConfigurable();
if (configurable != null) {
configurable.validate();
}
diff --git a/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudSourceApplicationConfigurable.java b/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudSourceApplicationConfigurable.java
new file mode 100644
index 000000000000..b6e0dfc857b0
--- /dev/null
+++ b/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudSourceApplicationConfigurable.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.remoteServer.impl.module;
+
+import com.intellij.openapi.Disposable;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Disposer;
+import com.intellij.remoteServer.configuration.RemoteServer;
+import com.intellij.remoteServer.runtime.Deployment;
+import com.intellij.remoteServer.runtime.ServerConnection;
+import com.intellij.remoteServer.runtime.ServerConnector;
+import com.intellij.remoteServer.runtime.deployment.ServerRuntimeInstance;
+import com.intellij.remoteServer.util.*;
+import com.intellij.util.concurrency.Semaphore;
+import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.util.Collection;
+import java.util.concurrent.atomic.AtomicReference;
+
+
+public abstract class CloudSourceApplicationConfigurable<
+ SC extends CloudConfigurationBase,
+ DC extends CloudDeploymentNameConfiguration,
+ SR extends CloudMultiSourceServerRuntimeInstance<DC, ?, ?, ?>,
+ AC extends CloudApplicationConfiguration> extends CloudApplicationConfigurable {
+
+ private final Project myProject;
+ private final Disposable myParentDisposable;
+
+ private DelayedRunner myRunner;
+
+ private RemoteServer<?> myAccount;
+
+ public CloudSourceApplicationConfigurable(@Nullable Project project, Disposable parentDisposable) {
+ myProject = project;
+ myParentDisposable = parentDisposable;
+ }
+
+ @Override
+ public void setAccount(RemoteServer<?> account) {
+ myAccount = account;
+ clearCloudData();
+ }
+
+ protected RemoteServer<SC> getAccount() {
+ return (RemoteServer<SC>)myAccount;
+ }
+
+ @Override
+ public JComponent getComponent() {
+ JComponent result = getMainPanel();
+ if (myRunner == null) {
+ myRunner = new DelayedRunner(result) {
+
+ private RemoteServer<?> myPreviousAccount;
+
+ @Override
+ protected boolean wasChanged() {
+ boolean result = myPreviousAccount != myAccount;
+ if (result) {
+ myPreviousAccount = myAccount;
+ }
+ return result;
+ }
+
+ @Override
+ protected void run() {
+ loadCloudData();
+ }
+ };
+ Disposer.register(myParentDisposable, myRunner);
+ }
+ return result;
+ }
+
+ protected void clearCloudData() {
+ getExistingComboBox().removeAllItems();
+ }
+
+ protected void loadCloudData() {
+ new ConnectionTask<Collection<Deployment>>("Loading existing applications list") {
+
+ @Override
+ protected void run(final ServerConnection<DC> connection,
+ final Semaphore semaphore,
+ final AtomicReference<Collection<Deployment>> result) {
+ connection.connectIfNeeded(new ServerConnector.ConnectionCallback<DC>() {
+
+ @Override
+ public void connected(@NotNull ServerRuntimeInstance<DC> serverRuntimeInstance) {
+ connection.computeDeployments(new Runnable() {
+
+ @Override
+ public void run() {
+ result.set(connection.getDeployments());
+ semaphore.up();
+ UIUtil.invokeLaterIfNeeded(new Runnable() {
+ @Override
+ public void run() {
+ if (!Disposer.isDisposed(myParentDisposable)) {
+ setupExistingApplications(result.get());
+ }
+ }
+ });
+ }
+ });
+ }
+
+ @Override
+ public void errorOccurred(@NotNull String errorMessage) {
+ runtimeErrorOccurred(errorMessage);
+ semaphore.up();
+ }
+ });
+ }
+
+ @Override
+ protected Collection<Deployment> run(SR serverRuntimeInstance) throws ServerRuntimeException {
+ return null;
+ }
+ }.performAsync();
+ }
+
+ private void setupExistingApplications(Collection<Deployment> deployments) {
+ JComboBox existingComboBox = getExistingComboBox();
+ existingComboBox.removeAllItems();
+ for (Deployment deployment : deployments) {
+ existingComboBox.addItem(deployment.getName());
+ }
+ }
+
+ protected Project getProject() {
+ return myProject;
+ }
+
+ protected abstract JComboBox getExistingComboBox();
+
+ protected abstract JComponent getMainPanel();
+
+ @Override
+ public abstract AC createConfiguration();
+
+ protected abstract class ConnectionTask<T> extends CloudConnectionTask<T, SC, DC, SR> {
+
+ public ConnectionTask(String title) {
+ super(myProject, title, CloudSourceApplicationConfigurable.this.getAccount());
+ }
+ }
+}
diff --git a/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudSourceApplicationConfiguration.java b/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudSourceApplicationConfiguration.java
new file mode 100644
index 000000000000..b1a3df6099ab
--- /dev/null
+++ b/java/remote-servers/impl/src/com/intellij/remoteServer/impl/module/CloudSourceApplicationConfiguration.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.remoteServer.impl.module;
+
+
+public abstract class CloudSourceApplicationConfiguration extends CloudApplicationConfiguration {
+
+ private boolean myExisting;
+ private final String myExistingAppName;
+
+ protected CloudSourceApplicationConfiguration(boolean existing, String existingAppName) {
+ myExisting = existing;
+ myExistingAppName = existingAppName;
+ }
+
+ public boolean isExisting() {
+ return myExisting;
+ }
+
+ public String getExistingAppName() {
+ return myExistingAppName;
+ }
+}
diff --git a/java/testFramework/src/com/intellij/debugger/impl/DescriptorTestCase.java b/java/testFramework/src/com/intellij/debugger/impl/DescriptorTestCase.java
index 49db796244dd..7e3c5f9cd55d 100644
--- a/java/testFramework/src/com/intellij/debugger/impl/DescriptorTestCase.java
+++ b/java/testFramework/src/com/intellij/debugger/impl/DescriptorTestCase.java
@@ -184,23 +184,24 @@ public abstract class DescriptorTestCase extends DebuggerTestCase {
for(int i = 0; i < tree.getRowCount(); i++) {
final TreeNode treeNode = (TreeNode)tree.getPathForRow(i).getLastPathComponent();
if(tree.isCollapsed(i) && !treeNode.isLeaf()) {
+ NodeDescriptor nodeDescriptor = null;
if (treeNode instanceof DebuggerTreeNodeImpl) {
- final NodeDescriptor nodeDescriptor = ((DebuggerTreeNodeImpl)treeNode).getDescriptor();
- boolean shouldExpand = filter == null || filter.shouldExpand(treeNode);
- if (shouldExpand) {
- // additional checks to prevent infinite expand
- if (nodeDescriptor instanceof ValueDescriptor) {
- final Value value = ((ValueDescriptor)nodeDescriptor).getValue();
- shouldExpand = !alreadyExpanded.contains(value);
- if (shouldExpand) {
- alreadyExpanded.add(value);
- }
+ nodeDescriptor = ((DebuggerTreeNodeImpl)treeNode).getDescriptor();
+ }
+ boolean shouldExpand = filter == null || filter.shouldExpand(treeNode);
+ if (shouldExpand) {
+ // additional checks to prevent infinite expand
+ if (nodeDescriptor instanceof ValueDescriptor) {
+ final Value value = ((ValueDescriptor)nodeDescriptor).getValue();
+ shouldExpand = !alreadyExpanded.contains(value);
+ if (shouldExpand) {
+ alreadyExpanded.add(value);
}
}
- if (shouldExpand) {
- anyCollapsed = true;
- tree.expandRow(i);
- }
+ }
+ if (shouldExpand) {
+ anyCollapsed = true;
+ tree.expandRow(i);
}
}
}
diff --git a/java/testFramework/src/com/intellij/find/FindManagerTestUtils.java b/java/testFramework/src/com/intellij/find/FindManagerTestUtils.java
index 087180bbc9a3..b65b58b8638c 100644
--- a/java/testFramework/src/com/intellij/find/FindManagerTestUtils.java
+++ b/java/testFramework/src/com/intellij/find/FindManagerTestUtils.java
@@ -24,12 +24,10 @@ public class FindManagerTestUtils {
}
public static void runFindInCommentsAndLiterals(FindManager findManager, FindModel findModel, String text, String ext) {
- findModel.setInStringLiteralsOnly(true);
- findModel.setInCommentsOnly(false);
+ findModel.setSearchContext(FindModel.SearchContext.IN_STRING_LITERALS);
runFindForwardAndBackward(findManager, findModel, text, ext);
- findModel.setInStringLiteralsOnly(false);
- findModel.setInCommentsOnly(true);
+ findModel.setSearchContext(FindModel.SearchContext.IN_COMMENTS);
runFindForwardAndBackward(findManager, findModel, text, ext);
}
diff --git a/jps/jps-builders/jps-builders.iml b/jps/jps-builders/jps-builders.iml
index 565691fb134e..993bfad6f750 100644
--- a/jps/jps-builders/jps-builders.iml
+++ b/jps/jps-builders/jps-builders.iml
@@ -35,7 +35,6 @@
<orderEntry type="module" module-name="jps-model-api" />
<orderEntry type="module" module-name="jps-model-serialization" />
<orderEntry type="module" module-name="jps-model-impl" />
- <orderEntry type="library" scope="TEST" name="Groovy" level="project" />
<orderEntry type="module" module-name="jps-serialization-tests" scope="TEST" />
<orderEntry type="library" scope="TEST" name="KotlinJavaRuntime" level="project" />
</component>
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Callbacks.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Callbacks.java
index 16a3da40fca1..18419a39f50c 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Callbacks.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Callbacks.java
@@ -29,6 +29,7 @@ public class Callbacks {
public interface Backend {
void associate(String classFileName, String sourceFileName, ClassReader cr);
+ void associate(String classFileName, Collection<String> sources, ClassReader cr);
void registerImports(String className, Collection<String> imports, Collection<String> staticImports);
}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectMultiMaplet.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectMultiMaplet.java
index b5415cebaf84..7699e2043670 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectMultiMaplet.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectMultiMaplet.java
@@ -28,7 +28,7 @@ import java.util.List;
* @author: db
* Date: 03.11.11
*/
-abstract class IntObjectMultiMaplet<V extends Streamable> implements Streamable {
+abstract class IntObjectMultiMaplet<V> implements Streamable {
abstract boolean containsKey(final int key);
abstract Collection<V> get(final int key);
@@ -78,12 +78,17 @@ abstract class IntObjectMultiMaplet<V extends Streamable> implements Streamable
final List<String> list = new LinkedList<String>();
for (final V value : b) {
- final ByteArrayOutputStream baos = new ByteArrayOutputStream();
- final PrintStream s = new PrintStream(baos);
+ if (value instanceof Streamable) {
+ final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ final PrintStream s = new PrintStream(baos);
- value.toStream(context, s);
+ ((Streamable)value).toStream(context, s);
- list.add(baos.toString());
+ list.add(baos.toString());
+ }
+ else {
+ list.add(value.toString());
+ }
}
Collections.sort(list);
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectPersistentMultiMaplet.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectPersistentMultiMaplet.java
index 3dd4d446c99a..39fbd5b91e42 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectPersistentMultiMaplet.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectPersistentMultiMaplet.java
@@ -32,7 +32,7 @@ import java.util.Collections;
* @author: db
* Date: 08.03.11
*/
-class IntObjectPersistentMultiMaplet<V extends Streamable> extends IntObjectMultiMaplet<V> {
+class IntObjectPersistentMultiMaplet<V> extends IntObjectMultiMaplet<V> {
private static final Collection NULL_COLLECTION = Collections.emptySet();
private static final int CACHE_SIZE = 128;
private final PersistentHashMap<Integer, Collection<V>> myMap;
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectTransientMultiMaplet.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectTransientMultiMaplet.java
index 2f581805a678..f19bcfdf72a3 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectTransientMultiMaplet.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectTransientMultiMaplet.java
@@ -24,7 +24,7 @@ import java.util.Collection;
* @author: db
* Date: 08.03.11
*/
-class IntObjectTransientMultiMaplet<V extends Streamable> extends IntObjectMultiMaplet<V> {
+class IntObjectTransientMultiMaplet<V> extends IntObjectMultiMaplet<V> {
private final TIntObjectHashMap<Collection<V>> myMap = new TIntObjectHashMap<Collection<V>>();
private final CollectionFactory<V> myCollectionFactory;
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Mappings.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Mappings.java
index a397d4b87a55..3e3a4793cbb6 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Mappings.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Mappings.java
@@ -85,7 +85,7 @@ public class Mappings {
*/
private IntIntMultiMaplet myClassToClassDependency;
private ObjectObjectMultiMaplet<File, ClassRepr> mySourceFileToClasses;
- private IntObjectMaplet<File> myClassToSourceFile;
+ private IntObjectMultiMaplet<File> myClassToSourceFile;
/**
* [short className] -> list of FQ names
*/
@@ -138,12 +138,17 @@ public class Mappings {
myRemovedSuperClasses = myIsDelta ? new IntIntTransientMultiMaplet() : null;
myAddedSuperClasses = myIsDelta ? new IntIntTransientMultiMaplet() : null;
+ final CollectionFactory<File> fileCollectionFactory = new CollectionFactory<File>() {
+ public Collection<File> create() {
+ return new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY); // todo: do we really need set and not a list here?
+ }
+ };
if (myIsDelta && myDeltaIsTransient) {
myClassToSubclasses = new IntIntTransientMultiMaplet();
myClassToClassDependency = new IntIntTransientMultiMaplet();
myShortClassNameIndex = null;
mySourceFileToClasses = new ObjectObjectTransientMultiMaplet<File, ClassRepr>(FileUtil.FILE_HASHING_STRATEGY, ourClassSetConstructor);
- myClassToSourceFile = new IntObjectTransientMaplet<File>();
+ myClassToSourceFile = new IntObjectTransientMultiMaplet<File>(fileCollectionFactory);
}
else {
if (myIsDelta) {
@@ -156,7 +161,7 @@ public class Mappings {
DependencyContext.getTableFile(myRootDir, SOURCE_TO_CLASS), new FileKeyDescriptor(), ClassRepr.externalizer(myContext),
ourClassSetConstructor
);
- myClassToSourceFile = new IntObjectPersistentMaplet<File>(DependencyContext.getTableFile(myRootDir, CLASS_TO_SOURCE), new FileKeyDescriptor());
+ myClassToSourceFile = new IntObjectPersistentMultiMaplet<File>(DependencyContext.getTableFile(myRootDir, CLASS_TO_SOURCE), INT_KEY_DESCRIPTOR, new FileKeyDescriptor(), fileCollectionFactory);
}
}
@@ -190,17 +195,17 @@ public class Mappings {
}
@Nullable
- private ClassRepr getReprByName(@Nullable File source, final int name) {
- if (source == null) {
- source = myClassToSourceFile.get(name);
- }
- if (source != null) {
- final Collection<ClassRepr> reprs = mySourceFileToClasses.get(source);
-
- if (reprs != null) {
- for (ClassRepr repr : reprs) {
- if (repr.name == name) {
- return repr;
+ private ClassRepr getReprByName(final @Nullable File source, final int qName) {
+ final Collection<File> sources = source != null? Collections.singleton(source) : myClassToSourceFile.get(qName);
+ if (sources != null) {
+ for (File src : sources) {
+ final Collection<ClassRepr> reprs = mySourceFileToClasses.get(src);
+
+ if (reprs != null) {
+ for (ClassRepr repr : reprs) {
+ if (repr.name == qName) {
+ return repr;
+ }
}
}
}
@@ -556,14 +561,19 @@ public class Mappings {
void affectSubclasses(final int className, final Collection<File> affectedFiles, final Collection<UsageRepr.Usage> affectedUsages, final TIntHashSet dependants, final boolean usages, final Collection<File> alreadyCompiledFiles) {
debug("Affecting subclasses of class: ", className);
- final File fileName = myClassToSourceFile.get(className);
- if (fileName == null) {
+ final Collection<File> allSources = myClassToSourceFile.get(className);
+ if (allSources == null || allSources.isEmpty()) {
debug("No source file detected for class ", className);
debug("End of affectSubclasses");
return;
}
- debug("Source file name: ", fileName);
+ for (File fName : allSources) {
+ debug("Source file name: ", fName);
+ if (!alreadyCompiledFiles.contains(fName)) {
+ affectedFiles.add(fName);
+ }
+ }
if (usages) {
debug("Class usages affection requested");
@@ -579,9 +589,6 @@ public class Mappings {
if (depClasses != null) {
addAll(dependants, depClasses);
}
- if (!alreadyCompiledFiles.contains(fileName)) {
- affectedFiles.add(fileName);
- }
final TIntHashSet directSubclasses = myClassToSubclasses.get(className);
if (directSubclasses != null) {
@@ -701,10 +708,14 @@ public class Mappings {
dependants.forEach(new TIntProcedure() {
@Override
public boolean execute(int depClass) {
- final File depFile = myClassToSourceFile.get(depClass);
- if (depFile != null && !FileUtil.filesEqual(depFile, sourceFile)) {
- if (filter == null || filter.accept(depFile)) {
- affectedFiles.add(depFile);
+ final Collection<File> allSources = myClassToSourceFile.get(depClass);
+ if (allSources != null) {
+ for (File depFile : allSources) {
+ if (!FileUtil.filesEqual(depFile, sourceFile)) {
+ if (filter == null || filter.accept(depFile)) {
+ affectedFiles.add(depFile);
+ }
+ }
}
}
return true;
@@ -757,6 +768,8 @@ public class Mappings {
return false;
}
+ final THashSet<File> toRecompile = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);
+
// Protected branch
if (member.isProtected()) {
debug("Protected access, softening non-incremental decision: adding all relevant subclasses for a recompilation");
@@ -766,10 +779,12 @@ public class Mappings {
propagated.forEach(new TIntProcedure() {
@Override
public boolean execute(int className) {
- final File fileName = myClassToSourceFile.get(className);
- if (fileName != null && !currentlyCompiled.contains(fileName)) {
- debug("Adding ", fileName);
- affectedFiles.add(fileName);
+ final Collection<File> fileNames = myClassToSourceFile.get(className);
+ if (fileNames != null) {
+ for (File fileName : fileNames) {
+ debug("Adding ", fileName);
+ }
+ toRecompile.addAll(fileNames);
}
return true;
}
@@ -782,19 +797,32 @@ public class Mappings {
debug("Package name: ", packageName);
// Package-local branch
- myClassToSourceFile.forEachEntry(new TIntObjectProcedure<File>() {
+ myClassToSourceFile.forEachEntry(new TIntObjectProcedure<Collection<File>>() {
@Override
- public boolean execute(int className, File fileName) {
+ public boolean execute(int className, Collection<File> fileNames) {
if (ClassRepr.getPackageName(myContext.getValue(className)).equals(packageName)) {
- if ((filter == null || filter.accept(fileName)) && !currentlyCompiled.contains(fileName)) {
- debug("Adding: ", fileName);
- affectedFiles.add(fileName);
+ for (File fileName : fileNames) {
+ if (filter == null || filter.accept(fileName)) {
+ debug("Adding: ", fileName);
+ toRecompile.add(fileName);
+ }
}
}
return true;
}
});
+ // filtering already compiled and non-existing paths
+ toRecompile.removeAll(currentlyCompiled);
+ for (Iterator<File> it = toRecompile.iterator(); it.hasNext(); ) {
+ final File file = it.next();
+ if (!file.exists()) {
+ it.remove();
+ }
+ }
+
+ affectedFiles.addAll(toRecompile);
+
return true;
}
@@ -1094,12 +1122,14 @@ public class Mappings {
if (overrides.satisfy(method) && isInheritor) {
debug("Current method overrides that found");
- final File file = myClassToSourceFile.get(methodClass.name);
-
- if (file != null) {
- myAffectedFiles.add(file);
- debug("Affecting file ", file);
+ final Collection<File> files = myClassToSourceFile.get(methodClass.name);
+ if (files != null) {
+ myAffectedFiles.addAll(files);
+ for (File file : files) {
+ debug("Affecting file ", file);
+ }
}
+
}
else {
debug("Current method does not override that found");
@@ -1128,12 +1158,15 @@ public class Mappings {
@Override
public boolean execute(int subClass) {
final ClassRepr r = myFuture.reprByName(subClass);
- if (r != null) {
- final File sourceFileName = myClassToSourceFile.get(subClass);
- if (sourceFileName != null && !myCompiledFiles.contains(sourceFileName)) {
- final int outerClass = r.getOuterClassName();
- if (!isEmpty(outerClass) && myFuture.isMethodVisible(outerClass, m)) {
- myAffectedFiles.add(sourceFileName);
+ if (r == null) {
+ return true;
+ }
+ final Collection<File> sourceFileNames = myClassToSourceFile.get(subClass);
+ if (sourceFileNames != null && !myCompiledFiles.containsAll(sourceFileNames)) {
+ final int outerClass = r.getOuterClassName();
+ if (!isEmpty(outerClass) && myFuture.isMethodVisible(outerClass, m)) {
+ myAffectedFiles.addAll(sourceFileNames);
+ for (File sourceFileName : sourceFileNames) {
debug("Affecting file due to local overriding: ", sourceFileName);
}
}
@@ -1186,10 +1219,12 @@ public class Mappings {
myFuture.addOverridingMethods(m, it, MethodRepr.equalByJavaRules(m), overridingMethods);
for (final Pair<MethodRepr, ClassRepr> p : overridingMethods) {
- final File fName = myClassToSourceFile.get(p.second.name);
- if (fName != null) {
- myAffectedFiles.add(fName);
- debug("Affecting file by overriding: ", fName);
+ final Collection<File> fNames = myClassToSourceFile.get(p.second.name);
+ if (fNames != null) {
+ myAffectedFiles.addAll(fNames);
+ for (File fName : fNames) {
+ debug("Affecting file by overriding: ", fName);
+ }
}
}
@@ -1229,12 +1264,14 @@ public class Mappings {
}
if (allAbstract && visited) {
- final File source = myClassToSourceFile.get(p);
+ final Collection<File> sources = myClassToSourceFile.get(p);
- if (source != null && !myCompiledFiles.contains(source)) {
- myAffectedFiles.add(source);
+ if (sources != null && !myCompiledFiles.containsAll(sources)) {
+ myAffectedFiles.addAll(sources);
debug("Removed method is not abstract & overrides some abstract method which is not then over-overridden in subclass ", p);
- debug("Affecting subclass source file ", source);
+ for (File source : sources) {
+ debug("Affecting subclass source file ", source);
+ }
}
}
}
@@ -1304,9 +1341,9 @@ public class Mappings {
final ClassRepr aClass = p.getSecond();
if (aClass != MOCK_CLASS) {
- final File fileName = myClassToSourceFile.get(aClass.name);
- if (fileName != null) {
- myAffectedFiles.add(fileName);
+ final Collection<File> fileNames = myClassToSourceFile.get(aClass.name);
+ if (fileNames != null) {
+ myAffectedFiles.addAll(fileNames);
}
}
}
@@ -1374,17 +1411,21 @@ public class Mappings {
public boolean execute(int subClass) {
final ClassRepr r = myFuture.reprByName(subClass);
if (r != null) {
- final File sourceFileName = myClassToSourceFile.get(subClass);
- if (sourceFileName != null && !myCompiledFiles.contains(sourceFileName)) {
+ final Collection<File> sourceFileNames = myClassToSourceFile.get(subClass);
+ if (sourceFileNames != null && !myCompiledFiles.containsAll(sourceFileNames)) {
if (r.isLocal()) {
- debug("Affecting local subclass (introduced field can potentially hide surrounding method parameters/local variables): ", sourceFileName);
- myAffectedFiles.add(sourceFileName);
+ for (File sourceFileName : sourceFileNames) {
+ debug("Affecting local subclass (introduced field can potentially hide surrounding method parameters/local variables): ", sourceFileName);
+ }
+ myAffectedFiles.addAll(sourceFileNames);
}
else {
final int outerClass = r.getOuterClassName();
if (!isEmpty(outerClass) && myFuture.isFieldVisible(outerClass, f)) {
- debug("Affecting inner subclass (introduced field can potentially hide surrounding class fields): ", sourceFileName);
- myAffectedFiles.add(sourceFileName);
+ for (File sourceFileName : sourceFileNames) {
+ debug("Affecting inner subclass (introduced field can potentially hide surrounding class fields): ", sourceFileName);
+ }
+ myAffectedFiles.addAll(sourceFileNames);
}
}
}
@@ -1783,7 +1824,9 @@ public class Mappings {
// checking if this newly added class duplicates already existing one
for (ClassRepr c : addedClasses) {
if (!c.isLocal() && !c.isAnonymous() && isEmpty(c.getOuterClassName())) {
- final File currentlyMappedTo = myClassToSourceFile.get(c.name);
+ final Collection<File> currentSources = myClassToSourceFile.get(c.name);
+ final File currentlyMappedTo = currentSources != null && currentSources.size() == 1? currentSources.iterator().next() : null;
+ // only check, if exactly one file is mapped
if (currentlyMappedTo != null && !FileUtil.filesEqual(currentlyMappedTo, srcFile) && currentlyMappedTo.exists() && myFilter.belongsToCurrentTargetChunk(currentlyMappedTo)) {
// Same classes from different source files.
// Schedule for recompilation both to make possible 'duplicate sources' error evident
@@ -1832,11 +1875,13 @@ public class Mappings {
toAffect.forEach(new TIntProcedure() {
@Override
public boolean execute(int depClass) {
- final File fName = myClassToSourceFile.get(depClass);
- if (fName != null) {
- if (myFilter == null || myFilter.accept(fName)) {
- debug("Adding dependent file ", fName);
- myAffectedFiles.add(fName);
+ final Collection<File> fNames = myClassToSourceFile.get(depClass);
+ if (fNames != null) {
+ for (File fName : fNames) {
+ if (myFilter == null || myFilter.accept(fName)) {
+ debug("Adding dependent file ", fName);
+ myAffectedFiles.add(fName);
+ }
}
}
return true;
@@ -1850,24 +1895,30 @@ public class Mappings {
state.myDependants.forEach(new TIntProcedure() {
@Override
public boolean execute(final int depClass) {
- final File depFile = myClassToSourceFile.get(depClass);
+ final Collection<File> depFiles = myClassToSourceFile.get(depClass);
+ if (depFiles != null) {
+ for (File depFile : depFiles) {
+ processDependentFile(depClass, depFile);
+ }
+ }
+ return true;
+ }
- if (depFile == null || myAffectedFiles.contains(depFile) || myCompiledFiles.contains(depFile)) {
- return true;
+ private void processDependentFile(int depClass, @NotNull File depFile) {
+ if (myAffectedFiles.contains(depFile) || myCompiledFiles.contains(depFile)) {
+ return;
}
debug("Dependent class: ", depClass);
final ClassRepr classRepr = getReprByName(depFile, depClass);
-
if (classRepr == null) {
- return true;
+ return;
}
final Set<UsageRepr.Usage> depUsages = classRepr.getUsages();
-
if (depUsages == null || depUsages.isEmpty()) {
- return true;
+ return;
}
for (UsageRepr.Usage usage : depUsages) {
@@ -1876,32 +1927,24 @@ public class Mappings {
if (query.satisfies(usage)) {
debug("Added file due to annotation query");
myAffectedFiles.add(depFile);
-
- return true;
+ return;
}
}
}
else if (state.myAffectedUsages.contains(usage)) {
final Util.UsageConstraint constraint = state.myUsageConstraints.get(usage);
-
if (constraint == null) {
debug("Added file with no constraints");
myAffectedFiles.add(depFile);
-
- return true;
+ return;
}
- else {
- if (constraint.checkResidence(depClass)) {
- debug("Added file with satisfied constraint");
- myAffectedFiles.add(depFile);
-
- return true;
- }
+ if (constraint.checkResidence(depClass)) {
+ debug("Added file with satisfied constraint");
+ myAffectedFiles.add(depFile);
+ return;
}
}
}
-
- return true;
}
});
}
@@ -2007,11 +2050,27 @@ public class Mappings {
private void cleanupRemovedClass(final Mappings delta, @NotNull final ClassRepr cr, File sourceFile, final Set<UsageRepr.Usage> usages, final IntIntMultiMaplet dependenciesTrashBin) {
final int className = cr.name;
- if (!FileUtil.filesEqual(sourceFile, myClassToSourceFile.get(className))) {
- // if classname is already mapped to a different source, the class with such FQ name exists elsewhere, so
- // we cannot destroy all these links
+
+ // it is safe to cleanup class information if it is mapped to non-existing files only
+ final Collection<File> currentlyMapped = myClassToSourceFile.get(className);
+ if (currentlyMapped == null || currentlyMapped.isEmpty()) {
return;
}
+ if (currentlyMapped.size() == 1) {
+ if (!FileUtil.filesEqual(sourceFile, currentlyMapped.iterator().next())) {
+ // if classname is already mapped to a different source, the class with such FQ name exists elsewhere, so
+ // we cannot destroy all these links
+ return;
+ }
+ }
+ else {
+ // many files
+ for (File file : currentlyMapped) {
+ if (!FileUtil.filesEqual(sourceFile, file) && file.exists()) {
+ return;
+ }
+ }
+ }
for (final int superSomething : cr.getSupers()) {
delta.registerRemovedSuperClass(className, superSomething);
@@ -2113,13 +2172,8 @@ public class Mappings {
delta.getChangedClasses().forEach(new TIntProcedure() {
@Override
public boolean execute(final int className) {
- final File sourceFile = delta.myClassToSourceFile.get(className);
- if (sourceFile != null) {
- myClassToSourceFile.put(className, sourceFile);
- }
- else {
- myClassToSourceFile.remove(className);
- }
+ final Collection<File> sourceFiles = delta.myClassToSourceFile.get(className);
+ myClassToSourceFile.replace(className, sourceFiles);
cleanupBackDependency(className, null, dependenciesTrashBin);
@@ -2138,7 +2192,7 @@ public class Mappings {
}
else {
myClassToSubclasses.putAll(delta.myClassToSubclasses);
- myClassToSourceFile.putAll(delta.myClassToSourceFile);
+ myClassToSourceFile.replaceAll(delta.myClassToSourceFile);
mySourceFileToClasses.replaceAll(delta.mySourceFileToClasses);
delta.mySourceFileToClasses.forEachEntry(new TObjectObjectProcedure<File, Collection<ClassRepr>>() {
public boolean execute(File src, Collection<ClassRepr> classes) {
@@ -2203,18 +2257,21 @@ public class Mappings {
public Callbacks.Backend getCallback() {
return new Callbacks.Backend() {
- public void associate(final String classFileName, final String sourceFileName, final ClassReader cr) {
+
+ public void associate(String classFileName, Collection<String> sources, ClassReader cr) {
synchronized (myLock) {
final int classFileNameS = myContext.get(classFileName);
final Pair<ClassRepr, Set<UsageRepr.Usage>> result = new ClassfileAnalyzer(myContext).analyze(classFileNameS, cr);
final ClassRepr repr = result.first;
if (repr != null) {
final Set<UsageRepr.Usage> localUsages = result.second;
- final File sourceFile = new File(sourceFileName);
final int className = repr.name;
- myClassToSourceFile.put(className, sourceFile);
- mySourceFileToClasses.put(sourceFile, repr);
+ for (String sourceFileName : sources) {
+ final File sourceFile = new File(sourceFileName);
+ myClassToSourceFile.put(className, sourceFile);
+ mySourceFileToClasses.put(sourceFile, repr);
+ }
for (final int s : repr.getSupers()) {
myClassToSubclasses.put(s, className);
@@ -2231,6 +2288,10 @@ public class Mappings {
}
}
+ public void associate(final String classFileName, final String sourceFileName, final ClassReader cr) {
+ associate(classFileName, Collections.singleton(sourceFileName), cr);
+ }
+
@Override
public void registerImports(final String className, final Collection<String> imports, Collection<String> staticImports) {
final List<String> allImports = new ArrayList<String>();
@@ -2252,14 +2313,16 @@ public class Mappings {
myPostPasses.offer(new Runnable() {
public void run() {
final int rootClassName = myContext.get(className.replace(".", "/"));
- final File fileName = myClassToSourceFile.get(rootClassName);
- final ClassRepr repr = fileName != null? getReprByName(fileName, rootClassName) : null;
+ final Collection<File> fileNames = myClassToSourceFile.get(rootClassName);
+ final ClassRepr repr = fileNames != null && !fileNames.isEmpty()? getReprByName(fileNames.iterator().next(), rootClassName) : null;
for (final String i : allImports) {
- final int iname = myContext.get(i.replace(".", "/"));
+ final int iname = myContext.get(i.replace('.', '/'));
myClassToClassDependency.put(iname, rootClassName);
if (repr != null && repr.addUsage(UsageRepr.createClassUsage(myContext, iname))) {
- mySourceFileToClasses.put(fileName, repr);
+ for (File fileName : fileNames) {
+ mySourceFileToClasses.put(fileName, repr);
+ }
}
}
}
@@ -2386,10 +2449,10 @@ public class Mappings {
assert (myChangedClasses != null && myChangedFiles != null);
myChangedClasses.add(it);
- final File file = myClassToSourceFile.get(it);
+ final Collection<File> files = myClassToSourceFile.get(it);
- if (file != null) {
- myChangedFiles.add(file);
+ if (files != null) {
+ myChangedFiles.addAll(files);
}
}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/ClassProcessingBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/ClassProcessingBuilder.java
index 551c3ce2f308..bc353aa4b144 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/ClassProcessingBuilder.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/ClassProcessingBuilder.java
@@ -144,7 +144,7 @@ public abstract class ClassProcessingBuilder extends ModuleLevelBuilder {
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
result.set(version);
}
- }, 0);
+ }, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
return result.get();
}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildDataManager.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildDataManager.java
index 823fe088d0cc..a6ed636e8d11 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildDataManager.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildDataManager.java
@@ -42,7 +42,7 @@ import java.util.concurrent.ConcurrentMap;
* Date: 10/7/11
*/
public class BuildDataManager implements StorageOwner {
- private static final int VERSION = 24;
+ private static final int VERSION = 25;
private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.storage.BuildDataManager");
private static final String SRC_TO_FORM_STORAGE = "src-form";
private static final String OUT_TARGET_STORAGE = "out-target";
diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/JavacFileEncodingTest.groovy b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/JavacFileEncodingTest.kt
index 80770ee36359..a3017b2bc2dd 100644
--- a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/JavacFileEncodingTest.groovy
+++ b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/JavacFileEncodingTest.kt
@@ -16,13 +16,14 @@
package org.jetbrains.jps.builders
import org.jetbrains.jps.builders.rebuild.JpsRebuildTestCase
+import org.jetbrains.jps.builders.rebuild.fs
/**
* @author nik
*/
-class JavacFileEncodingTest extends JpsRebuildTestCase {
- public void test() {
- doTest("javacFileEncoding/javacFileEncoding.ipr", {
+class JavacFileEncodingTest: JpsRebuildTestCase() {
+ fun test() {
+ doTest("javacFileEncoding/javacFileEncoding.ipr", fs {
dir("production") {
dir("javacFileEncoding") {
file("MyClass.class")
diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/JpsBuildTestCase.java b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/JpsBuildTestCase.java
index 2c3fca029cd9..eb9b42a3904d 100644
--- a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/JpsBuildTestCase.java
+++ b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/JpsBuildTestCase.java
@@ -225,7 +225,7 @@ public abstract class JpsBuildTestCase extends UsefulTestCase {
Map<String, String> allPathVariables = new HashMap<String, String>(pathVariables.size() + 1);
allPathVariables.putAll(pathVariables);
allPathVariables.put(PathMacroUtil.APPLICATION_HOME_DIR, PathManager.getHomePath());
- addPathVariables(allPathVariables);
+ allPathVariables.putAll(getAdditionalPathVariables());
JpsProjectLoader.loadProject(myProject, allPathVariables, fullProjectPath);
}
catch (IOException e) {
@@ -233,7 +233,9 @@ public abstract class JpsBuildTestCase extends UsefulTestCase {
}
}
- protected void addPathVariables(Map<String, String> pathVariables) {
+ @NotNull
+ protected Map<String, String> getAdditionalPathVariables() {
+ return Collections.emptyMap();
}
@Nullable
diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/ModuleClasspathTest.kt b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/ModuleClasspathTest.kt
index b76196eba947..cabb841db7f4 100644
--- a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/ModuleClasspathTest.kt
+++ b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/ModuleClasspathTest.kt
@@ -30,68 +30,68 @@ import org.junit.Assert
* @author nik
*/
public class ModuleClasspathTest(): JpsBuildTestCase() {
- override fun setUp() {
- super.setUp()
- addJdk("1.6", "/jdk.jar")
- addJdk("1.5", "/jdk15.jar")
- loadProject("moduleClasspath/moduleClasspath.ipr")
- }
+ override fun setUp() {
+ super.setUp()
+ addJdk("1.6", "/jdk.jar")
+ addJdk("1.5", "/jdk15.jar")
+ loadProject("moduleClasspath/moduleClasspath.ipr")
+ }
- private fun getProjectPath(): String {
- return FileUtil.toSystemIndependentName(getTestDataRootPath()) + "/moduleClasspath/moduleClasspath.ipr"
- }
+ private fun getProjectPath(): String {
+ return FileUtil.toSystemIndependentName(getTestDataRootPath()) + "/moduleClasspath/moduleClasspath.ipr"
+ }
- override fun getTestDataRootPath(): String {
- return FileUtil.toCanonicalPath(PathManagerEx.findFileUnderCommunityHome("jps/jps-builders/testData/output")!!.getAbsolutePath(), '/')!!
- }
+ override fun getTestDataRootPath(): String {
+ return FileUtil.toCanonicalPath(PathManagerEx.findFileUnderCommunityHome("jps/jps-builders/testData/output")!!.getAbsolutePath(), '/')!!
+ }
- public fun testSimpleClasspath() {
- assertClasspath("util", false, listOf("util/lib/exported.jar", "/jdk15.jar"))
- }
+ public fun testSimpleClasspath() {
+ assertClasspath("util", false, listOf("util/lib/exported.jar", "/jdk15.jar"))
+ }
- public fun testScopes() {
- assertClasspath("test-util", false, listOf("/jdk.jar", "test-util/lib/provided.jar"))
- assertClasspath("test-util", true, listOf("/jdk.jar", "test-util/lib/provided.jar", "test-util/lib/test.jar", "out/production/test-util"))
- }
+ public fun testScopes() {
+ assertClasspath("test-util", false, listOf("/jdk.jar", "test-util/lib/provided.jar"))
+ assertClasspath("test-util", true, listOf("/jdk.jar", "test-util/lib/provided.jar", "test-util/lib/test.jar", "out/production/test-util"))
+ }
- public fun testDepModules() {
- assertClasspath("main", false, listOf("util/lib/exported.jar", "out/production/util", "/jdk.jar", "main/lib/service.jar"))
- assertClasspath("main", true, listOf("out/production/main", "util/lib/exported.jar", "out/test/util", "out/production/util", "/jdk.jar", "out/test/test-util", "out/production/test-util", "main/lib/service.jar"))
- }
+ public fun testDepModules() {
+ assertClasspath("main", false, listOf("util/lib/exported.jar", "out/production/util", "/jdk.jar", "main/lib/service.jar"))
+ assertClasspath("main", true, listOf("out/production/main", "util/lib/exported.jar", "out/test/util", "out/production/util", "/jdk.jar", "out/test/test-util", "out/production/test-util", "main/lib/service.jar"))
+ }
- public fun testCompilationClasspath() {
- val chunk = createChunk("main")
- assertClasspath(listOf("util/lib/exported.jar", "out/production/util", "/jdk.jar"), getPathsList(ProjectPaths.getPlatformCompilationClasspath(chunk, true)))
- assertClasspath(listOf("main/lib/service.jar"), getPathsList(ProjectPaths.getCompilationClasspath(chunk, true)))
- }
+ public fun testCompilationClasspath() {
+ val chunk = createChunk("main")
+ assertClasspath(listOf("util/lib/exported.jar", "out/production/util", "/jdk.jar"), getPathsList(ProjectPaths.getPlatformCompilationClasspath(chunk, true)))
+ assertClasspath(listOf("main/lib/service.jar"), getPathsList(ProjectPaths.getCompilationClasspath(chunk, true)))
+ }
- private fun assertClasspath(moduleName: String, includeTests: Boolean, expected: List<String>) {
- val classpath = getPathsList(ProjectPaths.getCompilationClasspathFiles(createChunk(moduleName), includeTests, true, true))
- assertClasspath(expected, toSystemIndependentPaths(classpath))
- }
+ private fun assertClasspath(moduleName: String, includeTests: Boolean, expected: List<String>) {
+ val classpath = getPathsList(ProjectPaths.getCompilationClasspathFiles(createChunk(moduleName), includeTests, true, true))
+ assertClasspath(expected, toSystemIndependentPaths(classpath))
+ }
- private fun createChunk(moduleName: String): ModuleChunk {
- val module = myProject.getModules().firstOrNull { it.getName() == moduleName }
- return ModuleChunk(setOf(ModuleBuildTarget(module!!, JavaModuleBuildTargetType.PRODUCTION)))
- }
+ private fun createChunk(moduleName: String): ModuleChunk {
+ val module = myProject.getModules().first { it.getName() == moduleName }
+ return ModuleChunk(setOf(ModuleBuildTarget(module, JavaModuleBuildTargetType.PRODUCTION)))
+ }
- private fun assertClasspath(expected: List<String>, classpath: List<String>) {
- val basePath = FileUtil.toSystemIndependentName(File(getProjectPath()).getParentFile()!!.getAbsolutePath()) + "/"
- val actual = toSystemIndependentPaths(classpath).map { StringUtil.trimStart(it, basePath) }
- Assert.assertEquals(expected.join("\n"), actual.join("\n"))
- }
+ private fun assertClasspath(expected: List<String>, classpath: List<String>) {
+ val basePath = FileUtil.toSystemIndependentName(File(getProjectPath()).getParentFile()!!.getAbsolutePath()) + "/"
+ val actual = toSystemIndependentPaths(classpath).map { StringUtil.trimStart(it, basePath) }
+ Assert.assertEquals(expected.join("\n"), actual.join("\n"))
+ }
- private fun toSystemIndependentPaths(classpath: List<String>): List<String> {
- return classpath.map(FileUtil::toSystemIndependentName)
- }
+ private fun toSystemIndependentPaths(classpath: List<String>): List<String> {
+ return classpath.map(FileUtil::toSystemIndependentName)
+ }
- public fun getPathsList(files: Collection<File>): List<String> {
- return files.map(::getCanonicalPath)
- }
+ public fun getPathsList(files: Collection<File>): List<String> {
+ return files.map(::getCanonicalPath)
+ }
}
private fun getCanonicalPath(file: File): String {
- val path = file.getPath()
- return if (path.contains(".")) FileUtil.toCanonicalPath(path)!! else FileUtil.toSystemIndependentName(path)
+ val path = file.getPath()
+ return if (path.contains(".")) FileUtil.toCanonicalPath(path)!! else FileUtil.toSystemIndependentName(path)
}
diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/ArtifactRebuildTest.groovy b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/ArtifactRebuildTest.kt
index 5f4de621d724..0a3a49d559e4 100644
--- a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/ArtifactRebuildTest.groovy
+++ b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/ArtifactRebuildTest.kt
@@ -20,14 +20,19 @@ import com.intellij.util.io.ZipUtil
import java.util.jar.Attributes
import java.util.jar.Manifest
+import java.io.File
+import java.io.FileInputStream
+import kotlin.test.assertTrue
+import kotlin.test.assertEquals
+
/**
* @author nik
*/
-class ArtifactRebuildTest extends JpsRebuildTestCase {
- public void testArtifactIncludesArchiveArtifact() {
- def name = "artifactIncludesArchiveArtifact"
+class ArtifactRebuildTest: JpsRebuildTestCase() {
+ fun testArtifactIncludesArchiveArtifact() {
+ val name = "artifactIncludesArchiveArtifact"
try {
- doTest("$name/${name}.ipr", {
+ doTest("$name/${name}.ipr", fs {
dir("artifacts") {
dir("data") {
archive("a.jar") {
@@ -38,16 +43,16 @@ class ArtifactRebuildTest extends JpsRebuildTestCase {
})
}
finally {
- FileUtil.delete(new File(FileUtil.toSystemDependentName(getTestDataRootPath() + "/$name/data/a.jar")))
+ FileUtil.delete(File(FileUtil.toSystemDependentName(getTestDataRootPath() + "/$name/data/a.jar")))
}
}
- public void testArtifactWithoutOutput() {
- def outDir = FileUtil.createTempDirectory("output", "").absolutePath
- loadProject("artifactWithoutOutput/artifactWithoutOutput.ipr", ["OUTPUT_DIR":outDir])
+ fun testArtifactWithoutOutput() {
+ val outDir = FileUtil.createTempDirectory("output", "").getAbsolutePath()
+ loadProject("artifactWithoutOutput/artifactWithoutOutput.ipr", mapOf("OUTPUT_DIR" to outDir))
rebuild()
- assertOutput(outDir, {
+ assertOutput(outDir, fs {
dir("artifacts") {
dir("main") {
file("data.txt")
@@ -57,8 +62,8 @@ class ArtifactRebuildTest extends JpsRebuildTestCase {
})
}
- public void testExtractDir() {
- doTest("extractDirTest/extractDirTest.ipr", {
+ fun testExtractDir() {
+ doTest("extractDirTest/extractDirTest.ipr", fs {
dir("artifacts") {
dir("extractDir") {
file("b.txt", "b")
@@ -88,20 +93,20 @@ class ArtifactRebuildTest extends JpsRebuildTestCase {
})
}
- public void testManifestInArtifact() {
- loadAndRebuild("manifestInArtifact/manifest.ipr", [:])
- File jarFile = new File(myOutputDirectory, "artifacts/simple/simple.jar")
- junit.framework.Assert.assertTrue(jarFile.exists())
- File extracted = FileUtil.createTempDirectory("build-manifest", "")
+ fun testManifestInArtifact() {
+ loadAndRebuild("manifestInArtifact/manifest.ipr", mapOf())
+ val jarFile = File(myOutputDirectory, "artifacts/simple/simple.jar")
+ assertTrue(jarFile.exists())
+ val extracted = FileUtil.createTempDirectory("build-manifest", "")
ZipUtil.extract(jarFile, extracted, null)
- File manifestFile = new File(extracted, "META-INF/MANIFEST.MF")
- junit.framework.Assert.assertTrue(manifestFile.exists())
- Manifest manifest = new Manifest(new FileInputStream(manifestFile))
- junit.framework.Assert.assertEquals("MyClass", manifest.getMainAttributes().getValue(Attributes.Name.MAIN_CLASS))
+ val manifestFile = File(extracted, "META-INF/MANIFEST.MF")
+ assertTrue(manifestFile.exists())
+ val manifest = Manifest(FileInputStream(manifestFile))
+ assertEquals("MyClass", manifest.getMainAttributes()!!.getValue(Attributes.Name.MAIN_CLASS))
}
- public void testOverwriteArtifacts() {
- doTest("overwriteTest/overwriteTest.ipr", {
+ fun testOverwriteArtifacts() {
+ doTest("overwriteTest/overwriteTest.ipr", fs {
dir("artifacts") {
dir("classes") {
file("a.xml", "<root2/>")
@@ -128,9 +133,9 @@ class ArtifactRebuildTest extends JpsRebuildTestCase {
})
}
- public void testPathVariablesInArtifact() {
- String externalDir = "${getTestDataRootPath()}/pathVariables/external"
- doTest("pathVariables/pathVariables.ipr", ["EXTERNAL_DIR": externalDir], {
+ fun testPathVariablesInArtifact() {
+ val externalDir = "${getTestDataRootPath()}/pathVariables/external"
+ doTest("pathVariables/pathVariables.ipr", mapOf("EXTERNAL_DIR" to externalDir), fs {
dir("artifacts") {
dir("fileCopy") {
dir("dir") {
@@ -141,8 +146,8 @@ class ArtifactRebuildTest extends JpsRebuildTestCase {
})
}
- public void testModuleTestOutputElement() {
- doTest("moduleTestOutput/moduleTestOutput.ipr", {
+ fun testModuleTestOutputElement() {
+ doTest("moduleTestOutput/moduleTestOutput.ipr", fs {
dir("artifacts") {
dir("tests") {
file("MyTest.class")
@@ -160,15 +165,4 @@ class ArtifactRebuildTest extends JpsRebuildTestCase {
}
})
}
-
- //todo[nik] fix
- public void _testSourceRootUnderOutput() throws Exception {
- loadProject("sourceFolderUnderOutput/sourceFolderUnderOutput.ipr", [:])
- try {
- rebuild()
- junit.framework.Assert.fail("Cleaning should fail")
- }
- catch (Exception ignored) {
- }
- }
}
diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/JpsRebuildTestCase.groovy b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/JpsRebuildTestCase.groovy
deleted file mode 100644
index 7c102399e989..000000000000
--- a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/JpsRebuildTestCase.groovy
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright 2000-2012 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 org.jetbrains.jps.builders.rebuild
-import com.intellij.openapi.application.ex.PathManagerEx
-import com.intellij.openapi.util.io.FileUtil
-import com.intellij.util.io.TestFileSystemBuilder
-import org.jetbrains.annotations.NotNull
-import org.jetbrains.jps.util.JpsPathUtil
-import org.jetbrains.jps.builders.JpsBuildTestCase
-import org.jetbrains.jps.model.java.JpsJavaExtensionService
-/**
- * @author nik
- */
-abstract class JpsRebuildTestCase extends JpsBuildTestCase {
- protected File myOutputDirectory;
-
- @Override
- protected void setUp() {
- super.setUp()
- addJdk("1.6")
- }
-
- def doTest(String projectPath, Closure expectedOutput) {
- doTest(projectPath, [:], expectedOutput)
- }
-
- def doTest(String projectPath, Map<String, String> pathVariables, Closure expectedOutput) {
- loadAndRebuild(projectPath, pathVariables)
- assertOutput(getOrCreateOutputDirectory().getAbsolutePath(), expectedOutput);
- }
-
- def protected assertOutput(@NotNull String targetFolder, Closure expectedOutput) {
- def root = TestFileSystemBuilder.fs()
- initFileSystemItem(root, expectedOutput)
- root.build().assertDirectoryEqual(new File(FileUtil.toSystemDependentName(targetFolder)))
- }
-
- protected void loadAndRebuild(String projectPath, Map<String, String> pathVariables) {
- loadProject(projectPath, pathVariables)
- rebuild()
- }
-
- protected void rebuild() {
- JpsJavaExtensionService.getInstance().getOrCreateProjectExtension(myProject).outputUrl = JpsPathUtil.pathToUrl(FileUtil.toSystemIndependentName(getOrCreateOutputDirectory().getAbsolutePath()))
- rebuildAll()
- }
-
- private File getOrCreateOutputDirectory() {
- if (myOutputDirectory == null) {
- myOutputDirectory = FileUtil.createTempDirectory("jps-build-output", "")
- }
- myOutputDirectory
- }
-
- @Override
- protected void addPathVariables(Map<String, String> pathVariables) {
- pathVariables.put("ARTIFACTS_OUT", FileUtil.toSystemIndependentName(getOrCreateOutputDirectory().absolutePath) + "/artifacts")
- }
-
- @Override
- protected String getTestDataRootPath() {
- return PathManagerEx.findFileUnderCommunityHome("jps/jps-builders/testData/output").absolutePath
- }
-
- def initFileSystemItem(TestFileSystemBuilder item, Closure initializer) {
- def meta = new Expando()
- meta.dir = {String name, Closure content ->
- initFileSystemItem(item.dir(name), content)
- }
- meta.archive = {String name, Closure content ->
- initFileSystemItem(item.archive(name), content)
- }
- meta.file = {Object[] args ->
- item.file((String)args[0], (String)args.length > 1 ? args[1] : null)
- }
-
- initializer.delegate = meta
- initializer.setResolveStrategy Closure.DELEGATE_FIRST
- initializer()
- }
-
- def File createTempFile() {
- return FileUtil.createTempFile("jps-build-file", "");
- }
-}
diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/JpsRebuildTestCase.kt b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/JpsRebuildTestCase.kt
new file mode 100644
index 000000000000..dae4cb005e1d
--- /dev/null
+++ b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/JpsRebuildTestCase.kt
@@ -0,0 +1,86 @@
+package org.jetbrains.jps.builders.rebuild;
+
+import com.intellij.openapi.application.ex.PathManagerEx;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.util.io.TestFileSystemBuilder;
+import org.jetbrains.jps.builders.JpsBuildTestCase;
+import org.jetbrains.jps.model.java.JpsJavaExtensionService;
+import org.jetbrains.jps.util.JpsPathUtil;
+
+import java.io.File;
+import java.util.LinkedHashMap;
+import kotlin.properties.Delegates
+import com.intellij.util.io.TestFileSystemItem
+
+/**
+ * @author nik
+ */
+public abstract class JpsRebuildTestCase: JpsBuildTestCase() {
+ protected val myOutputDirectory: File by Delegates.lazy {
+ FileUtil.createTempDirectory("jps-build-output", "")
+ }
+
+ override fun setUp() {
+ super.setUp()
+ addJdk("1.6");
+ }
+
+ fun doTest(projectPath: String, expectedOutput: TestFileSystemItem) {
+ doTest(projectPath, LinkedHashMap<String, String>(), expectedOutput);
+ }
+
+ fun doTest(projectPath: String, pathVariables: Map<String, String>, expectedOutput: TestFileSystemItem) {
+ loadAndRebuild(projectPath, pathVariables);
+ assertOutput(myOutputDirectory.getAbsolutePath(), expectedOutput);
+ }
+
+ fun assertOutput(targetFolder: String, expectedOutput: TestFileSystemItem) {
+ expectedOutput.assertDirectoryEqual(File(FileUtil.toSystemDependentName(targetFolder)));
+ }
+
+ fun loadAndRebuild(projectPath: String, pathVariables: Map<String, String>) {
+ loadProject(projectPath, pathVariables);
+ rebuild();
+ }
+
+ fun rebuild() {
+ JpsJavaExtensionService.getInstance()!!.getOrCreateProjectExtension(myProject)
+ .setOutputUrl(JpsPathUtil.pathToUrl(FileUtil.toSystemIndependentName(myOutputDirectory.getAbsolutePath())));
+ rebuildAll();
+ }
+
+ override fun getAdditionalPathVariables(): MutableMap<String, String> =
+ hashMapOf("ARTIFACTS_OUT" to FileUtil.toSystemIndependentName(myOutputDirectory.getAbsolutePath()) + "/artifacts")
+
+ protected override fun getTestDataRootPath(): String {
+ return PathManagerEx.findFileUnderCommunityHome("jps/jps-builders/testData/output")!!.getAbsolutePath();
+ }
+}
+
+fun fs(init: TestFileSystemBuilderBuilder.() -> Unit): TestFileSystemItem {
+ val builder = TestFileSystemBuilder.fs()
+ TestFileSystemBuilderBuilder(builder).init()
+ return builder.build()
+}
+
+class TestFileSystemBuilderBuilder(private val current: TestFileSystemBuilder) {
+ fun file(name: String) {
+ current.file(name)
+ }
+
+ fun file(name: String, content: String) {
+ current.file(name, content)
+ }
+
+ fun dir(name: String, init: TestFileSystemBuilderBuilder.() -> Unit) {
+ val dir = current.dir(name)
+ TestFileSystemBuilderBuilder(dir).init()
+ dir.end()
+ }
+
+ fun archive(name: String, init: TestFileSystemBuilderBuilder.() -> Unit) {
+ val dir = current.archive(name)
+ TestFileSystemBuilderBuilder(dir).init()
+ dir.end()
+ }
+} \ No newline at end of file
diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/ModuleRebuildTest.groovy b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/ModuleRebuildTest.kt
index 36e03eb0890b..09e72b77cf2a 100644
--- a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/ModuleRebuildTest.groovy
+++ b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/ModuleRebuildTest.kt
@@ -17,9 +17,9 @@ package org.jetbrains.jps.builders.rebuild
/**
* @author nik
*/
-public class ModuleRebuildTest extends JpsRebuildTestCase {
- public void testModuleCycle() {
- doTest("moduleCycle/moduleCycle.ipr", {
+public class ModuleRebuildTest: JpsRebuildTestCase() {
+ fun testModuleCycle() {
+ doTest("moduleCycle/moduleCycle.ipr", fs {
dir("production") {
dir("module1") {
file("Bar1.class")
@@ -34,8 +34,8 @@ public class ModuleRebuildTest extends JpsRebuildTestCase {
})
}
- public void testOverlappingSourceRoots() {
- doTest("overlappingSourceRoots/overlappingSourceRoots.ipr", {
+ fun testOverlappingSourceRoots() {
+ doTest("overlappingSourceRoots/overlappingSourceRoots.ipr", fs {
dir("production") {
dir("inner") {
dir("y") {
@@ -52,8 +52,8 @@ public class ModuleRebuildTest extends JpsRebuildTestCase {
})
}
- public void testResourceCopying() {
- doTest("resourceCopying/resourceCopying.ipr", {
+ fun testResourceCopying() {
+ doTest("resourceCopying/resourceCopying.ipr", fs {
dir("production") {
dir("resourceCopying") {
dir("copy") {
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/PathMacroUtil.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/PathMacroUtil.java
index 6214412c4a52..cf87eb5744b3 100644
--- a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/PathMacroUtil.java
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/PathMacroUtil.java
@@ -16,16 +16,19 @@
package org.jetbrains.jps.model.serialization;
import com.intellij.openapi.application.PathManager;
-import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.ObjectUtils;
import com.intellij.util.SystemProperties;
-import com.intellij.util.containers.HashMap;
+import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.util.Map;
+import static com.intellij.openapi.util.io.FileUtil.toSystemIndependentName;
+
/**
* @author nik
*/
@@ -34,9 +37,16 @@ public class PathMacroUtil {
@NonNls public static final String MODULE_DIR_MACRO_NAME = "MODULE_DIR";
@NonNls public static final String DIRECTORY_STORE_NAME = ".idea";
@NonNls public static final String APPLICATION_HOME_DIR = "APPLICATION_HOME_DIR";
+ @NonNls public static final String APPLICATION_CONFIG_DIR = "APPLICATION_CONFIG_DIR";
@NonNls public static final String APPLICATION_PLUGINS_DIR = "APPLICATION_PLUGINS_DIR";
@NonNls public static final String USER_HOME_NAME = "USER_HOME";
+ private static final Map<String, String> ourGlobalMacros = ContainerUtil.<String, String>immutableMapBuilder()
+ .put(APPLICATION_HOME_DIR, toSystemIndependentName(PathManager.getHomePath()))
+ .put(APPLICATION_CONFIG_DIR, toSystemIndependentName(PathManager.getConfigPath()))
+ .put(APPLICATION_PLUGINS_DIR, toSystemIndependentName(PathManager.getPluginsPath()))
+ .put(USER_HOME_NAME, StringUtil.trimEnd(toSystemIndependentName(SystemProperties.getUserHome()), "/")).build();
+
@Nullable
public static String getModuleDir(String moduleFilePath) {
File moduleDirFile = new File(moduleFilePath).getParentFile();
@@ -57,31 +67,18 @@ public class PathMacroUtil {
return moduleDir;
}
+ @NotNull
public static String getUserHomePath() {
- return StringUtil.trimEnd(FileUtil.toSystemIndependentName(SystemProperties.getUserHome()), "/");
+ return ObjectUtils.assertNotNull(getGlobalSystemMacroValue(USER_HOME_NAME));
}
+ @NotNull
public static Map<String, String> getGlobalSystemMacros() {
- final Map<String, String> map = new HashMap<String, String>();
- map.put(APPLICATION_HOME_DIR, getApplicationHomeDirPath());
- map.put(APPLICATION_PLUGINS_DIR, getApplicationPluginsDirPath());
- map.put(USER_HOME_NAME, getUserHomePath());
- return map;
- }
-
- private static String getApplicationHomeDirPath() {
- return FileUtil.toSystemIndependentName(PathManager.getHomePath());
- }
-
- private static String getApplicationPluginsDirPath() {
- return FileUtil.toSystemIndependentName(PathManager.getPluginsPath());
+ return ourGlobalMacros;
}
@Nullable
public static String getGlobalSystemMacroValue(String name) {
- if (APPLICATION_HOME_DIR.equals(name)) return getApplicationHomeDirPath();
- if (APPLICATION_PLUGINS_DIR.equals(name)) return getApplicationPluginsDirPath();
- if (USER_HOME_NAME.equals(name)) return getUserHomePath();
- return null;
+ return ourGlobalMacros.get(name);
}
}
diff --git a/jps/standalone-builder/src/org/jetbrains/jps/idea/IdeaProjectLoader.java b/jps/standalone-builder/src/org/jetbrains/jps/idea/IdeaProjectLoader.java
new file mode 100644
index 000000000000..b392dcf15081
--- /dev/null
+++ b/jps/standalone-builder/src/org/jetbrains/jps/idea/IdeaProjectLoader.java
@@ -0,0 +1,30 @@
+package org.jetbrains.jps.idea;
+
+import groovy.lang.Script;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+/**
+ * @author max
+ */
+public class IdeaProjectLoader {
+ public static String guessHome(Script script) throws IOException, URISyntaxException {
+ String uri = (String)script.getProperty("gant.file");
+ File home = new File(new URI(uri).getSchemeSpecificPart());
+
+ while (home != null) {
+ if (home.isDirectory() && new File(home, ".idea").exists()) {
+ return home.getCanonicalPath();
+ }
+
+
+ home = home.getParentFile();
+ }
+
+
+ throw new IllegalArgumentException("Cannot guess project home from '" + uri + "'");
+ }
+}
diff --git a/native/runner/runnerw/.gitignore b/native/runner/runnerw/.gitignore
index 998f2ddef2dc..560bd1aaa0c7 100644
--- a/native/runner/runnerw/.gitignore
+++ b/native/runner/runnerw/.gitignore
@@ -1,5 +1,6 @@
*.aps
*.vcxproj.user
+Debug
Release
*.suo
*.opensdf
diff --git a/native/runner/runnerw/runnerw.cpp b/native/runner/runnerw/runnerw.cpp
index 8936b28f53e8..03e975ef81a1 100644
--- a/native/runner/runnerw/runnerw.cpp
+++ b/native/runner/runnerw/runnerw.cpp
@@ -18,16 +18,25 @@ void PrintUsage() {
exit(0);
}
-void ErrorMessage(char *str) {
-
+void ErrorMessage(char *operationName) {
LPVOID msg;
-
- FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
- NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPTSTR) &msg, 0, NULL);
-
- printf("%s: %s\n", str, msg);
- LocalFree(msg);
+ DWORD lastError = GetLastError();
+ FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ lastError,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPSTR)&msg,
+ 0,
+ NULL);
+ if (msg) {
+ fprintf(stderr, "%s failed with error %d: %s\n", operationName, lastError, msg);
+ LocalFree(msg);
+ }
+ else {
+ fprintf(stderr, "%s failed with error %d (no message available)\n", operationName, lastError);
+ }
+ fflush(stderr);
}
void CtrlBreak() {
@@ -126,6 +135,33 @@ bool hasEnding(std::string const &fullString, std::string const &ending) {
}
}
+BOOL attachChildConsole(PROCESS_INFORMATION const &childProcessInfo) {
+ if (!FreeConsole()) {
+ ErrorMessage("FreeConsole");
+ return FALSE;
+ }
+ int attempts = 20;
+ for (int i = 0; i < attempts; i++) {
+ DWORD sleepMillis = i < 5 ? 30 : (i < 10 ? 100 : 500);
+ // sleep to let child process initialize itself
+ Sleep(sleepMillis);
+ if (WaitForSingleObject(childProcessInfo.hProcess, 0) != WAIT_TIMEOUT) {
+ // child process has been terminated, no console to attach to
+ return FALSE;
+ }
+ if (AttachConsole(childProcessInfo.dwProcessId)) {
+ return TRUE;
+ }
+ // ERROR_GEN_FAILURE means "the specified process does not exist"
+ // Seems it also means that the console hasn't been fully initialized.
+ if (GetLastError() != ERROR_GEN_FAILURE) {
+ break;
+ }
+ }
+ ErrorMessage("AttachConsole");
+ return FALSE;
+}
+
int main(int argc, char * argv[]) {
if (argc < 2) {
PrintUsage();
@@ -195,18 +231,34 @@ int main(int argc, char * argv[]) {
char* c_args = new char[args.size() + 1];
strcpy(c_args, args.c_str());
- if (!SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlHandler, TRUE)) {
- ErrorMessage("SetConsoleCtrlHandler");
+ DWORD processFlag = CREATE_DEFAULT_ERROR_MODE;
+ BOOL hasConsoleWindow = GetConsoleWindow() != NULL;
+ if (hasConsoleWindow) {
+ processFlag |= CREATE_NO_WINDOW;
}
- if (!CreateProcess(c_app, // Application name
- c_args, // Application arguments
- NULL, NULL, TRUE, CREATE_DEFAULT_ERROR_MODE, NULL, NULL, &si, &pi)) {
+ if (!CreateProcess(
+ c_app,
+ c_args,
+ NULL,
+ NULL,
+ TRUE,
+ processFlag,
+ NULL,
+ NULL,
+ &si,
+ &pi)) {
ErrorMessage("CreateProcess");
CloseHandle(newstdin);
CloseHandle(write_stdin);
exit(0);
}
+ if (hasConsoleWindow) {
+ attachChildConsole(pi);
+ }
+ if (!SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlHandler, TRUE)) {
+ ErrorMessage("SetConsoleCtrlHandler");
+ }
CreateThread(NULL, 0, &scanStdinThread, &write_stdin, 0, NULL);
diff --git a/platform/analysis-api/src/com/intellij/codeInspection/ex/ScopeToolState.java b/platform/analysis-api/src/com/intellij/codeInspection/ex/ScopeToolState.java
index 3a75f1738ead..81e340679a50 100644
--- a/platform/analysis-api/src/com/intellij/codeInspection/ex/ScopeToolState.java
+++ b/platform/analysis-api/src/com/intellij/codeInspection/ex/ScopeToolState.java
@@ -42,6 +42,7 @@ public class ScopeToolState {
private boolean myEnabled;
private HighlightDisplayLevel myLevel;
+ private boolean myAdditionalConfigPanelCreated = false;
private JComponent myAdditionalConfigPanel;
private static final Logger LOG = Logger.getInstance("#" + ScopeToolState.class.getName());
@@ -98,13 +99,11 @@ public class ScopeToolState {
myLevel = level;
}
- @NotNull
+ @Nullable
public JComponent getAdditionalConfigPanel() {
- if (myAdditionalConfigPanel == null) {
+ if (!myAdditionalConfigPanelCreated) {
myAdditionalConfigPanel = myToolWrapper.getTool().createOptionsPanel();
- if (myAdditionalConfigPanel == null){
- myAdditionalConfigPanel = new JPanel();
- }
+ myAdditionalConfigPanelCreated = true;
}
return myAdditionalConfigPanel;
}
diff --git a/platform/analysis-api/src/com/intellij/codeInspection/reference/RefManager.java b/platform/analysis-api/src/com/intellij/codeInspection/reference/RefManager.java
index 6f0a3c24e523..b46352670030 100644
--- a/platform/analysis-api/src/com/intellij/codeInspection/reference/RefManager.java
+++ b/platform/analysis-api/src/com/intellij/codeInspection/reference/RefManager.java
@@ -47,6 +47,7 @@ public abstract class RefManager {
*
* @return the analysis scope.
*/
+ @Nullable
public abstract AnalysisScope getScope();
/**
diff --git a/platform/analysis-api/src/com/intellij/codeInspection/ui/OptionAccessor.java b/platform/analysis-api/src/com/intellij/codeInspection/ui/OptionAccessor.java
index 0c32f60dadd0..5e23b224920f 100644
--- a/platform/analysis-api/src/com/intellij/codeInspection/ui/OptionAccessor.java
+++ b/platform/analysis-api/src/com/intellij/codeInspection/ui/OptionAccessor.java
@@ -43,15 +43,7 @@ public interface OptionAccessor {
@Override
public void setOption(final String optionName, boolean optionValue) {
- try {
- ReflectionUtil.findField(myInspection.getClass(), boolean.class, optionName).setBoolean(myInspection, optionValue);
- }
- catch (IllegalAccessException e) {
- LOG.warn(e);
- }
- catch (NoSuchFieldException e) {
- LOG.warn(e);
- }
+ ReflectionUtil.setField(myInspection.getClass(), myInspection, boolean.class, optionName, optionValue);
}
}
}
diff --git a/platform/analysis-api/src/com/intellij/problems/WolfTheProblemSolver.java b/platform/analysis-api/src/com/intellij/problems/WolfTheProblemSolver.java
index c4580e082fb4..cc72d479daec 100644
--- a/platform/analysis-api/src/com/intellij/problems/WolfTheProblemSolver.java
+++ b/platform/analysis-api/src/com/intellij/problems/WolfTheProblemSolver.java
@@ -40,6 +40,7 @@ public abstract class WolfTheProblemSolver {
public abstract boolean isProblemFile(VirtualFile virtualFile);
public abstract void weHaveGotProblems(@NotNull VirtualFile virtualFile, @NotNull List<Problem> problems);
+ public abstract void weHaveGotNonIgnorableProblems(@NotNull VirtualFile virtualFile, @NotNull List<Problem> problems);
public abstract void clearProblems(@NotNull VirtualFile virtualFile);
public abstract boolean hasProblemFilesBeneath(@NotNull Condition<VirtualFile> condition);
diff --git a/platform/analysis-api/src/com/intellij/psi/search/GlobalSearchScopesCore.java b/platform/analysis-api/src/com/intellij/psi/search/GlobalSearchScopesCore.java
index 647cd728c6ac..76db4a7cc765 100644
--- a/platform/analysis-api/src/com/intellij/psi/search/GlobalSearchScopesCore.java
+++ b/platform/analysis-api/src/com/intellij/psi/search/GlobalSearchScopesCore.java
@@ -189,10 +189,10 @@ public class GlobalSearchScopesCore {
private final VirtualFile myDirectory;
private final boolean myWithSubdirectories;
- private DirectoryScope(@NotNull PsiDirectory directory, final boolean withSubdirectories) {
- super(directory.getProject());
+ private DirectoryScope(@NotNull PsiDirectory psiDirectory, final boolean withSubdirectories) {
+ super(psiDirectory.getProject());
myWithSubdirectories = withSubdirectories;
- myDirectory = directory.getVirtualFile();
+ myDirectory = psiDirectory.getVirtualFile();
}
private DirectoryScope(@NotNull Project project, @NotNull VirtualFile directory, final boolean withSubdirectories) {
@@ -221,6 +221,7 @@ public class GlobalSearchScopesCore {
return false;
}
+ @Override
public String toString() {
//noinspection HardCodedStringLiteral
return "directory scope: " + myDirectory + "; withSubdirs:"+myWithSubdirectories;
@@ -296,6 +297,7 @@ public class GlobalSearchScopesCore {
return false;
}
+ @Override
public String toString() {
//noinspection HardCodedStringLiteral
return "Directories scope: " + Arrays.asList(myDirectories);
diff --git a/platform/analysis-api/src/com/intellij/util/ui/CheckBox.java b/platform/analysis-api/src/com/intellij/util/ui/CheckBox.java
index d6e4101c6086..d00655a66768 100644
--- a/platform/analysis-api/src/com/intellij/util/ui/CheckBox.java
+++ b/platform/analysis-api/src/com/intellij/util/ui/CheckBox.java
@@ -16,14 +16,13 @@
package com.intellij.util.ui;
import com.intellij.codeInspection.InspectionProfileEntry;
+import com.intellij.util.ReflectionUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
-import javax.swing.ButtonModel;
-import javax.swing.JCheckBox;
+import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
-import java.lang.reflect.Field;
public class CheckBox extends JCheckBox {
@@ -39,30 +38,8 @@ public class CheckBox extends JCheckBox {
private static boolean getPropertyValue(InspectionProfileEntry owner,
String property) {
- try {
- final Class<? extends InspectionProfileEntry> aClass = owner.getClass();
- final Field field = getField(aClass, property);
- field.setAccessible(true);
- return field.getBoolean(owner);
- } catch (IllegalAccessException ignore) {
- return false;
- } catch (NoSuchFieldException ignore) {
- return false;
- }
- }
-
- static Field getField(Class clazz, String fieldName) throws NoSuchFieldException {
- try {
- return clazz.getDeclaredField(fieldName);
- } catch (NoSuchFieldException e) {
- final Class superClass = clazz.getSuperclass();
- if (superClass == null) {
- throw e;
- } else {
- return getField(superClass, fieldName);
- }
+ return ReflectionUtil.getField(owner.getClass(), owner, boolean.class, property);
}
- }
private static class SingleCheckboxChangeListener
implements ChangeListener {
@@ -85,16 +62,7 @@ public class CheckBox extends JCheckBox {
private static void setPropertyValue(InspectionProfileEntry owner,
String property,
boolean selected) {
- try {
- final Class<? extends InspectionProfileEntry> aClass = owner.getClass();
- final Field field = getField(aClass, property);
- field.setAccessible(true);
- field.setBoolean(owner, selected);
- } catch (IllegalAccessException ignore) {
- // do nothing
- } catch (NoSuchFieldException ignore) {
- // do nothing
- }
+ ReflectionUtil.setField(owner.getClass(), owner, boolean.class, property, selected);
}
}
} \ No newline at end of file
diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/ex/InspectionProfileImpl.java b/platform/analysis-impl/src/com/intellij/codeInspection/ex/InspectionProfileImpl.java
index d8dc5d00656a..0a1861e8000e 100644
--- a/platform/analysis-impl/src/com/intellij/codeInspection/ex/InspectionProfileImpl.java
+++ b/platform/analysis-impl/src/com/intellij/codeInspection/ex/InspectionProfileImpl.java
@@ -39,9 +39,13 @@ import com.intellij.profile.codeInspection.InspectionProfileManager;
import com.intellij.profile.codeInspection.SeverityProvider;
import com.intellij.psi.PsiElement;
import com.intellij.psi.search.scope.packageSet.NamedScope;
+import com.intellij.util.ArrayUtil;
import com.intellij.util.Consumer;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.graph.CachingSemiGraph;
+import com.intellij.util.graph.DFSTBuilder;
+import com.intellij.util.graph.GraphGenerator;
import gnu.trove.THashMap;
import org.jdom.Document;
import org.jdom.Element;
@@ -85,7 +89,7 @@ public class InspectionProfileImpl extends ProfileEx implements ModifiableModel,
private final ExternalInfo myExternalInfo = new ExternalInfo();
@TestOnly
public static boolean INIT_INSPECTIONS = false;
- private List<NamedScope> myScopes = Collections.emptyList();
+ private String[] myScopesOrder = null;
@Override
public void setModified(final boolean modified) {
@@ -509,6 +513,7 @@ public class InspectionProfileImpl extends ProfileEx implements ModifiableModel,
catch (ProcessCanceledException e) {
return false;
}
+ final Map<String, List<String>> dependencies = new HashMap<String, List<String>>();
for (InspectionToolWrapper toolWrapper : tools) {
final String shortName = toolWrapper.getShortName();
HighlightDisplayKey key = HighlightDisplayKey.find(shortName);
@@ -536,7 +541,7 @@ public class InspectionProfileImpl extends ProfileEx implements ModifiableModel,
final Element element = myDeinstalledInspectionsSettings.remove(toolWrapper.getShortName());
if (element != null) {
try {
- toolsList.readExternal(element, this);
+ toolsList.readExternal(element, this, dependencies);
}
catch (InvalidDataException e) {
LOG.error("Can't read settings for " + toolWrapper, e);
@@ -544,12 +549,39 @@ public class InspectionProfileImpl extends ProfileEx implements ModifiableModel,
}
myTools.put(toolWrapper.getShortName(), toolsList);
}
+ final GraphGenerator<String> graphGenerator = GraphGenerator.create(CachingSemiGraph.create(new GraphGenerator.SemiGraph<String>() {
+ @Override
+ public Collection<String> getNodes() {
+ return dependencies.keySet();
+ }
+
+ @Override
+ public Iterator<String> getIn(String n) {
+ return dependencies.get(n).iterator();
+ }
+ }));
+
+ DFSTBuilder<String> builder = new DFSTBuilder<String>(graphGenerator);
+ if (builder.isAcyclic()) {
+ final List<String> scopes = builder.getSortedNodes();
+ myScopesOrder = ArrayUtil.toStringArray(scopes);
+ }
+
if (mySource != null) {
copyToolsConfigurations(mySource, project);
}
return true;
}
+ @Nullable
+ public String[] getScopesOrder() {
+ return myScopesOrder;
+ }
+
+ public void setScopesOrder(String[] scopesOrder) {
+ myScopesOrder = scopesOrder;
+ }
+
@NotNull
private List<InspectionToolWrapper> createTools(Project project) {
if (mySource != null) {
@@ -907,13 +939,13 @@ public class InspectionProfileImpl extends ProfileEx implements ModifiableModel,
return getTools(toolWrapper.getShortName(), project).prependTool(scope, toolWrapper, enabled, level);
}
- public void setErrorLevel(@NotNull HighlightDisplayKey key, @NotNull HighlightDisplayLevel level, int scopeIdx, Project project) {
- getTools(key.toString(), project).setLevel(level, scopeIdx, project);
+ public void setErrorLevel(@NotNull HighlightDisplayKey key, @NotNull HighlightDisplayLevel level, String scopeName, Project project) {
+ getTools(key.toString(), project).setLevel(level, scopeName, project);
}
- public void setErrorLevel(@NotNull List<HighlightDisplayKey> keys, @NotNull HighlightDisplayLevel level, int scopeIdx, Project project) {
+ public void setErrorLevel(@NotNull List<HighlightDisplayKey> keys, @NotNull HighlightDisplayLevel level, String scopeName, Project project) {
for (HighlightDisplayKey key : keys) {
- getTools(key.toString(), project).setLevel(level, scopeIdx, project);
+ setErrorLevel(key, level, scopeName, project);
}
}
@@ -944,10 +976,4 @@ public class InspectionProfileImpl extends ProfileEx implements ModifiableModel,
return super.equals(o) && ((InspectionProfileImpl)o).getProfileManager() == getProfileManager();
}
- /**
- * @return list of used scopes for all inspections
- */
- public List<NamedScope> getUsedScopes() {
- return myScopes;
- }
}
diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/ex/ToolsImpl.java b/platform/analysis-impl/src/com/intellij/codeInspection/ex/ToolsImpl.java
index b28dad40f094..267c0ee67fc3 100644
--- a/platform/analysis-impl/src/com/intellij/codeInspection/ex/ToolsImpl.java
+++ b/platform/analysis-impl/src/com/intellij/codeInspection/ex/ToolsImpl.java
@@ -46,6 +46,7 @@ import org.jetbrains.annotations.TestOnly;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Map;
public class ToolsImpl implements Tools {
@NonNls private static final String ENABLED_BY_DEFAULT_ATTRIBUTE = "enabled_by_default";
@@ -170,7 +171,7 @@ public class ToolsImpl implements Tools {
}
}
- void readExternal(@NotNull Element toolElement, @NotNull InspectionProfile profile) throws InvalidDataException {
+ void readExternal(@NotNull Element toolElement, @NotNull InspectionProfile profile, Map<String, List<String>> dependencies) throws InvalidDataException {
final String levelName = toolElement.getAttributeValue(LEVEL_ATTRIBUTE);
final ProfileManager profileManager = profile.getProfileManager();
final SeverityRegistrar registrar = ((SeverityProvider)profileManager).getOwnSeverityRegistrar();
@@ -187,6 +188,7 @@ public class ToolsImpl implements Tools {
final InspectionToolWrapper toolWrapper = myDefaultState.getTool();
final List scopeElements = toolElement.getChildren(ProfileEx.SCOPE);
+ final List<String> scopeNames = new ArrayList<String>();
for (Object sO : scopeElements) {
final Element scopeElement = (Element)sO;
final String scopeName = scopeElement.getAttributeValue(ProfileEx.NAME);
@@ -216,6 +218,20 @@ public class ToolsImpl implements Tools {
else {
addTool(scopeName, copyToolWrapper, enabledInScope != null && Boolean.parseBoolean(enabledInScope), scopeLevel);
}
+
+ scopeNames.add(scopeName);
+ }
+
+ for (int i = 0; i < scopeNames.size(); i++) {
+ String scopeName = scopeNames.get(i);
+ List<String> order = dependencies.get(scopeName);
+ if (order == null) {
+ order = new ArrayList<String>();
+ dependencies.put(scopeName, order);
+ }
+ for (int j = i + 1; j < scopeNames.size(); j++) {
+ order.add(scopeNames.get(j));
+ }
}
// check if unknown children exists
@@ -445,22 +461,36 @@ public class ToolsImpl implements Tools {
}
- public void setLevel(@NotNull HighlightDisplayLevel level, int idx, Project project) {
- if (myTools != null && myTools.size() > idx && idx >= 0) {
- final ScopeToolState scopeToolState = myTools.get(idx);
- myTools.remove(idx);
+ public void setLevel(@NotNull HighlightDisplayLevel level, @Nullable String scopeName, Project project) {
+ if (scopeName == null) {
+ myDefaultState.setLevel(level);
+ } else {
+ if (myTools == null) {
+ return;
+ }
+ ScopeToolState scopeToolState = null;
+ int index = -1;
+ for (int i = 0; i < myTools.size(); i++) {
+ ScopeToolState tool = myTools.get(i);
+ if (scopeName.equals(tool.getScopeName())) {
+ scopeToolState = tool;
+ myTools.remove(tool);
+ index = i;
+ break;
+ }
+ }
+ if (index < 0) {
+ throw new IllegalStateException("Scope " + scopeName + " not found");
+ }
+ final InspectionToolWrapper toolWrapper = scopeToolState.getTool();
final NamedScope scope = scopeToolState.getScope(project);
- InspectionToolWrapper toolWrapper = scopeToolState.getTool();
if (scope != null) {
- myTools.add(idx, new ScopeToolState(scope, toolWrapper, scopeToolState.isEnabled(), level));
+ myTools.add(index, new ScopeToolState(scope, toolWrapper, scopeToolState.isEnabled(), level));
}
else {
- myTools.add(idx, new ScopeToolState(scopeToolState.getScopeName(), toolWrapper, scopeToolState.isEnabled(), level));
+ myTools.add(index, new ScopeToolState(scopeToolState.getScopeName(), toolWrapper, scopeToolState.isEnabled(), level));
}
}
- else if (idx == -1) {
- myDefaultState.setLevel(level);
- }
}
public void setDefaultState(@NotNull InspectionToolWrapper toolWrapper, boolean enabled, @NotNull HighlightDisplayLevel level) {
diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/reference/RefManagerImpl.java b/platform/analysis-impl/src/com/intellij/codeInspection/reference/RefManagerImpl.java
index 0fbd048f4929..f31e44e96e2c 100644
--- a/platform/analysis-impl/src/com/intellij/codeInspection/reference/RefManagerImpl.java
+++ b/platform/analysis-impl/src/com/intellij/codeInspection/reference/RefManagerImpl.java
@@ -149,6 +149,7 @@ public class RefManagerImpl extends RefManager {
}
}
+ @Nullable
@Override
public AnalysisScope getScope() {
return myScope;
@@ -304,7 +305,9 @@ public class RefManagerImpl extends RefManager {
if (!myDeclarationsFound) {
long before = System.currentTimeMillis();
final AnalysisScope scope = getScope();
- scope.accept(myProjectIterator);
+ if (scope != null) {
+ scope.accept(myProjectIterator);
+ }
myDeclarationsFound = true;
LOG.info("Total duration of processing project usages:" + (System.currentTimeMillis() - before));
diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/ui/ConventionOptionsPanel.java b/platform/analysis-impl/src/com/intellij/codeInspection/ui/ConventionOptionsPanel.java
index 0afe259bd018..ba9125f3808a 100644
--- a/platform/analysis-impl/src/com/intellij/codeInspection/ui/ConventionOptionsPanel.java
+++ b/platform/analysis-impl/src/com/intellij/codeInspection/ui/ConventionOptionsPanel.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@ package com.intellij.codeInspection.ui;
import com.intellij.codeInspection.InspectionProfileEntry;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.ui.DocumentAdapter;
+import com.intellij.util.ReflectionUtil;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -28,7 +29,6 @@ import javax.swing.event.DocumentListener;
import javax.swing.text.Document;
import javax.swing.text.InternationalFormatter;
import java.awt.*;
-import java.lang.reflect.Field;
import java.text.NumberFormat;
import java.util.regex.Pattern;
@@ -150,58 +150,18 @@ public class ConventionOptionsPanel extends JPanel {
}
private static void setPropertyIntegerValue(InspectionProfileEntry owner, String property, Integer value) {
- try {
- final Field field = getField(owner.getClass(), property);
- field.setAccessible(true);
- field.setInt(owner, value.intValue());
- } catch (Exception e) {
- LOG.error(e);
- }
+ setPropertyValue(owner, property, value);
}
private static Integer getPropertyIntegerValue(InspectionProfileEntry owner, String property) {
- try {
- final Field field = getField(owner.getClass(), property);
- field.setAccessible(true);
- return Integer.valueOf(field.getInt(owner));
- } catch (Exception e) {
- LOG.error(e);
- return 0;
- }
+ return (Integer)getPropertyValue(owner, property);
}
- private static void setPropertyValue(InspectionProfileEntry owner, String property, Object value) {
- try {
- final Field field = getField(owner.getClass(), property);
- field.setAccessible(true);
- field.set(owner, value);
- } catch (Exception e) {
- LOG.error(e);
- }
+ private static void setPropertyValue(@NotNull InspectionProfileEntry owner, String property, Object value) {
+ ReflectionUtil.setField(owner.getClass(), owner, null, property, value);
}
private static Object getPropertyValue(InspectionProfileEntry owner, String property) {
- try {
- final Field field = getField(owner.getClass(), property);
- field.setAccessible(true);
- return field.get(owner);
- }
- catch (Exception e) {
- LOG.error(e);
- return null;
- }
- }
-
- private static Field getField(Class clazz, String fieldName) throws NoSuchFieldException {
- try {
- return clazz.getDeclaredField(fieldName);
- } catch (NoSuchFieldException e) {
- Class superClass = clazz.getSuperclass();
- if (superClass == null) {
- throw e;
- } else {
- return getField(superClass, fieldName);
- }
- }
+ return ReflectionUtil.getField(owner.getClass(), owner, null, property);
}
}
diff --git a/platform/core-api/src/com/intellij/ide/caches/FileContent.java b/platform/core-api/src/com/intellij/ide/caches/FileContent.java
index 0933b7f19005..c4c6d61c4513 100644
--- a/platform/core-api/src/com/intellij/ide/caches/FileContent.java
+++ b/platform/core-api/src/com/intellij/ide/caches/FileContent.java
@@ -47,7 +47,7 @@ public class FileContent extends UserDataHolderBase {
@NotNull
public byte[] getBytes() throws IOException {
if (myCachedBytes == null) {
- myCachedBytes = myVirtualFile.contentsToByteArray(false);
+ myCachedBytes = myVirtualFile.isValid() ? myVirtualFile.contentsToByteArray(false) : ArrayUtil.EMPTY_BYTE_ARRAY;
}
return myCachedBytes;
diff --git a/platform/core-api/src/com/intellij/ide/util/PropertiesComponent.java b/platform/core-api/src/com/intellij/ide/util/PropertiesComponent.java
index f3b883d0b60f..f733cd04f4a6 100644
--- a/platform/core-api/src/com/intellij/ide/util/PropertiesComponent.java
+++ b/platform/core-api/src/com/intellij/ide/util/PropertiesComponent.java
@@ -17,8 +17,10 @@ package com.intellij.ide.util;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.project.Project;
+import com.intellij.util.ObjectUtils;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.lang.reflect.Field;
@@ -31,6 +33,7 @@ public abstract class PropertiesComponent {
public abstract boolean isValueSet(String name);
+ @Nullable
public abstract String getValue(@NonNls String name);
public abstract void setValue(@NonNls String name, String value);
@@ -62,7 +65,10 @@ public abstract class PropertiesComponent {
@NotNull
public String getValue(@NonNls String name, @NotNull String defaultValue) {
- return isValueSet(name) ? getValue(name) : defaultValue;
+ if (!isValueSet(name)) {
+ return defaultValue;
+ }
+ return ObjectUtils.notNull(getValue(name), defaultValue);
}
public final int getOrInitInt(@NonNls String name, int defaultValue) {
diff --git a/platform/core-api/src/com/intellij/lexer/DelegateLexer.java b/platform/core-api/src/com/intellij/lexer/DelegateLexer.java
index ce8bbbc18748..102256b60160 100644
--- a/platform/core-api/src/com/intellij/lexer/DelegateLexer.java
+++ b/platform/core-api/src/com/intellij/lexer/DelegateLexer.java
@@ -26,7 +26,7 @@ import org.jetbrains.annotations.Nullable;
public class DelegateLexer extends LexerBase {
protected final Lexer myDelegate;
- public DelegateLexer(Lexer delegate) {
+ public DelegateLexer(@NotNull Lexer delegate) {
myDelegate = delegate;
}
diff --git a/platform/core-api/src/com/intellij/openapi/progress/ProgressManager.java b/platform/core-api/src/com/intellij/openapi/progress/ProgressManager.java
index a319700b4be2..e99b8e6bebf0 100644
--- a/platform/core-api/src/com/intellij/openapi/progress/ProgressManager.java
+++ b/platform/core-api/src/com/intellij/openapi/progress/ProgressManager.java
@@ -79,7 +79,7 @@ public abstract class ProgressManager {
}
}
- public static void progress(final String text) throws ProcessCanceledException {
+ public static void progress(@NotNull String text) throws ProcessCanceledException {
progress(text, "");
}
@@ -91,7 +91,7 @@ public abstract class ProgressManager {
}
}
- public static void progress(final String text, @Nullable String text2) throws ProcessCanceledException {
+ public static void progress(@NotNull String text, @Nullable String text2) throws ProcessCanceledException {
final ProgressIndicator pi = getInstance().getProgressIndicator();
if (pi != null) {
pi.checkCanceled();
@@ -103,6 +103,7 @@ public abstract class ProgressManager {
protected abstract void doCheckCanceled() throws ProcessCanceledException;
public abstract void executeNonCancelableSection(@NotNull Runnable runnable);
+ @NotNull
public abstract NonCancelableSection startNonCancelableSection();
public abstract void setCancelButtonText(String cancelButtonText);
@@ -135,9 +136,9 @@ public abstract class ProgressManager {
* @throws E exception thrown by process
*/
public abstract <T, E extends Exception> T runProcessWithProgressSynchronously(@NotNull ThrowableComputable<T, E> process,
- @NotNull @Nls String progressTitle,
- boolean canBeCanceled,
- @Nullable Project project) throws E;
+ @NotNull @Nls String progressTitle,
+ boolean canBeCanceled,
+ @Nullable Project project) throws E;
/**
* Runs the specified operation in a background thread and shows a modal progress dialog in the
@@ -206,7 +207,10 @@ public abstract class ProgressManager {
public abstract void runProcessWithProgressAsynchronously(@NotNull Task.Backgroundable task, @NotNull ProgressIndicator progressIndicator);
protected static final ThreadLocal<ProgressIndicator> myThreadIndicator = new ThreadLocal<ProgressIndicator>();
- public void executeProcessUnderProgress(@NotNull Runnable process, ProgressIndicator progress) throws ProcessCanceledException {
+
+ public void executeProcessUnderProgress(@NotNull Runnable process,
+ @Nullable("null means reuse current progress") ProgressIndicator progress)
+ throws ProcessCanceledException {
ProgressIndicator oldIndicator = null;
boolean set = progress != null && progress != (oldIndicator = myThreadIndicator.get());
diff --git a/platform/core-api/src/com/intellij/openapi/roots/FileIndexFacade.java b/platform/core-api/src/com/intellij/openapi/roots/FileIndexFacade.java
index cc7dddd3c848..96dde81c6a80 100644
--- a/platform/core-api/src/com/intellij/openapi/roots/FileIndexFacade.java
+++ b/platform/core-api/src/com/intellij/openapi/roots/FileIndexFacade.java
@@ -45,6 +45,7 @@ public abstract class FileIndexFacade {
public abstract boolean isInLibrarySource(@NotNull VirtualFile file);
public abstract boolean isExcludedFile(@NotNull VirtualFile file);
+ public abstract boolean isUnderIgnored(@NotNull VirtualFile file);
@Nullable
public abstract Module getModuleForFile(@NotNull VirtualFile file);
diff --git a/platform/core-api/src/com/intellij/openapi/vfs/JarFile.java b/platform/core-api/src/com/intellij/openapi/vfs/JarFile.java
index c363a815577a..f8ddc7630e23 100644
--- a/platform/core-api/src/com/intellij/openapi/vfs/JarFile.java
+++ b/platform/core-api/src/com/intellij/openapi/vfs/JarFile.java
@@ -22,7 +22,7 @@ import java.io.InputStream;
import java.util.Enumeration;
import java.util.zip.ZipFile;
-/** @deprecated causes ZipFile leaks, do not use (to be removed in IDEA 15) */
+/** @deprecated causes ZipFile leaks, do not use (to be removed in IDEA 15) + can lead to crashes (IDEA-126550) */
public interface JarFile {
interface JarEntry {
String getName();
diff --git a/platform/core-api/src/com/intellij/openapi/vfs/VfsUtilCore.java b/platform/core-api/src/com/intellij/openapi/vfs/VfsUtilCore.java
index cd0f15f3796c..9e8c37880589 100644
--- a/platform/core-api/src/com/intellij/openapi/vfs/VfsUtilCore.java
+++ b/platform/core-api/src/com/intellij/openapi/vfs/VfsUtilCore.java
@@ -84,6 +84,20 @@ public class VfsUtilCore {
return false;
}
+ /**
+ * @return {@code true} if {@code url} is located under one of {@code rootUrls} or equal to one of them
+ */
+ public static boolean isUnder(@NotNull String url, @Nullable Collection<String> rootUrls) {
+ if (rootUrls == null || rootUrls.isEmpty()) return false;
+
+ for (String excludesUrl : rootUrls) {
+ if (isEqualOrAncestor(excludesUrl, url)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
public static boolean isEqualOrAncestor(@NotNull String ancestorUrl, @NotNull String fileUrl) {
if (ancestorUrl.equals(fileUrl)) return true;
if (StringUtil.endsWithChar(ancestorUrl, '/')) {
diff --git a/platform/core-api/src/com/intellij/psi/PsiInvalidElementAccessException.java b/platform/core-api/src/com/intellij/psi/PsiInvalidElementAccessException.java
index fb2ae2ce4d21..f24556fe5c25 100644
--- a/platform/core-api/src/com/intellij/psi/PsiInvalidElementAccessException.java
+++ b/platform/core-api/src/com/intellij/psi/PsiInvalidElementAccessException.java
@@ -164,7 +164,7 @@ public class PsiInvalidElementAccessException extends RuntimeException implement
}
public static boolean isTrackingInvalidation() {
- return Registry.is("psi.track.invalidation", true);
+ return Registry.is("psi.track.invalidation");
}
@Nullable
diff --git a/platform/core-impl/src/com/intellij/core/CoreApplicationEnvironment.java b/platform/core-impl/src/com/intellij/core/CoreApplicationEnvironment.java
index 7f04b192c640..633c25a0145a 100644
--- a/platform/core-impl/src/com/intellij/core/CoreApplicationEnvironment.java
+++ b/platform/core-impl/src/com/intellij/core/CoreApplicationEnvironment.java
@@ -68,10 +68,8 @@ import org.picocontainer.MutablePicoContainer;
import java.lang.reflect.Modifier;
import java.util.List;
-import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
/**
* @author yole
@@ -210,12 +208,12 @@ public class CoreApplicationEnvironment {
}
@Override
- public Object get() throws InterruptedException, ExecutionException {
+ public Object get() {
return null;
}
@Override
- public Object get(long timeout, @NotNull TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
+ public Object get(long timeout, @NotNull TimeUnit unit) {
return null;
}
});
diff --git a/platform/core-impl/src/com/intellij/ide/plugins/PluginDescriptorComparator.java b/platform/core-impl/src/com/intellij/ide/plugins/PluginDescriptorComparator.java
deleted file mode 100644
index a6b957c0c508..000000000000
--- a/platform/core-impl/src/com/intellij/ide/plugins/PluginDescriptorComparator.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright 2000-2009 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.ide.plugins;
-
-import com.intellij.openapi.extensions.PluginId;
-import com.intellij.util.containers.HashMap;
-import gnu.trove.TObjectIntHashMap;
-
-import java.util.Comparator;
-import java.util.Map;
-import java.util.Stack;
-
-/**
- * @author Eugene Zhuravlev
- * Date: Aug 3, 2004
- */
-public class PluginDescriptorComparator implements Comparator<IdeaPluginDescriptor>{
- private final TObjectIntHashMap<PluginId> myIdToNumberMap = new TObjectIntHashMap<PluginId>();
- private int myAvailableNumber = 1;
-
- public PluginDescriptorComparator(IdeaPluginDescriptor[] descriptors){
- final Map<PluginId, IdeaPluginDescriptor> idToDescriptorMap = new HashMap<PluginId, IdeaPluginDescriptor>();
- for (final IdeaPluginDescriptor descriptor : descriptors) {
- idToDescriptorMap.put(descriptor.getPluginId(), descriptor);
- }
- myIdToNumberMap.put(PluginId.getId(PluginManagerCore.CORE_PLUGIN_ID), 0);
-
- final Stack<PluginId> visited = new Stack<PluginId>();
- for (int idx = 0; idx < descriptors.length && myIdToNumberMap.size() != descriptors.length; idx++) {
- assignNumbers(descriptors[idx].getPluginId(), idToDescriptorMap, visited);
- visited.clear();
- }
- }
-
- private void assignNumbers(PluginId id, Map<PluginId, IdeaPluginDescriptor> idToDescriptorMap, Stack<PluginId> visited){
- visited.push(id);
- try {
- final IdeaPluginDescriptor ideaPluginDescriptor = idToDescriptorMap.get(id);
- if (ideaPluginDescriptor == null || !ideaPluginDescriptor.isEnabled()) {
- // missing optional dependency or already disabled due to cycles
- return;
- }
- final PluginId[] parentIds = ideaPluginDescriptor.getDependentPluginIds();
- for (final PluginId parentId : parentIds) {
- if (visited.contains(parentId)) {
- //disable plugins in the cycle
- ideaPluginDescriptor.setEnabled(false);
- break;
- }
- }
- for (PluginId parentId1 : parentIds) {
- assignNumbers(parentId1, idToDescriptorMap, visited);
- }
- if (!myIdToNumberMap.contains(id)) {
- myIdToNumberMap.put(id, myAvailableNumber++);
- }
- }
- finally {
- visited.pop();
- }
- }
-
- public int compare(IdeaPluginDescriptor d1, IdeaPluginDescriptor d2) {
- return myIdToNumberMap.get(d1.getPluginId()) - myIdToNumberMap.get(d2.getPluginId());
- }
-}
diff --git a/platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java b/platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java
index 8f4fd771ebdd..e834e33f0f42 100644
--- a/platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java
+++ b/platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java
@@ -30,10 +30,7 @@ import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.io.StreamUtil;
import com.intellij.openapi.util.io.ZipFileCache;
import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.util.ArrayUtil;
-import com.intellij.util.Function;
-import com.intellij.util.PlatformUtilsCore;
-import com.intellij.util.ReflectionUtil;
+import com.intellij.util.*;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import com.intellij.util.execution.ParametersListUtil;
@@ -43,6 +40,7 @@ import com.intellij.util.graph.Graph;
import com.intellij.util.graph.GraphGenerator;
import com.intellij.util.xmlb.XmlSerializationException;
import gnu.trove.THashMap;
+import gnu.trove.TIntProcedure;
import org.jdom.Document;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -498,26 +496,38 @@ public class PluginManagerCore {
}
}
- @Deprecated
- static Comparator<IdeaPluginDescriptor> getPluginDescriptorComparator(Map<PluginId, IdeaPluginDescriptorImpl> idToDescriptorMap) {
+ static Comparator<IdeaPluginDescriptor> getPluginDescriptorComparator(final Map<PluginId, ? extends IdeaPluginDescriptor> idToDescriptorMap) {
final Graph<PluginId> graph = createPluginIdGraph(idToDescriptorMap);
final DFSTBuilder<PluginId> builder = new DFSTBuilder<PluginId>(graph);
- /*
if (!builder.isAcyclic()) {
- final Pair<String,String> circularDependency = builder.getCircularDependency();
- throw new Exception("Cyclic dependencies between plugins are not allowed: \"" + circularDependency.getFirst() + "\" and \"" + circularDependency.getSecond() + "");
+ builder.getSCCs().forEach(new TIntProcedure() {
+ int myTNumber = 0;
+ public boolean execute(int size) {
+ if (size > 1) {
+ for (int j = 0; j < size; j++) {
+ idToDescriptorMap.get(builder.getNodeByTNumber(myTNumber + j)).setEnabled(false);
+ }
+ }
+ myTNumber += size;
+ return true;
+ }
+ });
}
- */
+
final Comparator<PluginId> idComparator = builder.comparator();
return new Comparator<IdeaPluginDescriptor>() {
@Override
public int compare(IdeaPluginDescriptor o1, IdeaPluginDescriptor o2) {
- return idComparator.compare(o1.getPluginId(), o2.getPluginId());
+ final PluginId pluginId1 = o1.getPluginId();
+ final PluginId pluginId2 = o2.getPluginId();
+ if (pluginId1.getIdString().equals(CORE_PLUGIN_ID)) return -1;
+ if (pluginId2.getIdString().equals(CORE_PLUGIN_ID)) return 1;
+ return idComparator.compare(pluginId1, pluginId2);
}
};
}
- private static Graph<PluginId> createPluginIdGraph(final Map<PluginId, IdeaPluginDescriptorImpl> idToDescriptorMap) {
+ private static Graph<PluginId> createPluginIdGraph(final Map<PluginId, ? extends IdeaPluginDescriptor> idToDescriptorMap) {
final List<PluginId> ids = new ArrayList<PluginId>(idToDescriptorMap.keySet());
// this magic ensures that the dependent plugins always follow their dependencies in lexicographic order
// needed to make sure that extensions are always in the same order
@@ -539,7 +549,7 @@ public class PluginManagerCore {
ArrayList<PluginId> plugins = new ArrayList<PluginId>();
for (PluginId dependentPluginId : descriptor.getDependentPluginIds()) {
// check for missing optional dependency
- IdeaPluginDescriptorImpl dep = idToDescriptorMap.get(dependentPluginId);
+ IdeaPluginDescriptor dep = idToDescriptorMap.get(dependentPluginId);
if (dep != null) {
plugins.add(dep.getPluginId());
}
@@ -901,7 +911,12 @@ public class PluginManagerCore {
loadDescriptorsFromClassPath(result, fromSources ? progress : null);
IdeaPluginDescriptorImpl[] pluginDescriptors = result.toArray(new IdeaPluginDescriptorImpl[result.size()]);
- Arrays.sort(pluginDescriptors, new PluginDescriptorComparator(pluginDescriptors));
+ final Map<PluginId, IdeaPluginDescriptorImpl> idToDescriptorMap = new com.intellij.util.containers.HashMap<PluginId, IdeaPluginDescriptorImpl>();
+ for (final IdeaPluginDescriptorImpl descriptor : pluginDescriptors) {
+ idToDescriptorMap.put(descriptor.getPluginId(), descriptor);
+ }
+
+ Arrays.sort(pluginDescriptors, getPluginDescriptorComparator(idToDescriptorMap));
return pluginDescriptors;
}
@@ -1110,13 +1125,35 @@ public class PluginManagerCore {
final Graph<PluginId> graph = createPluginIdGraph(idToDescriptorMap);
final DFSTBuilder<PluginId> builder = new DFSTBuilder<PluginId>(graph);
if (!builder.isAcyclic()) {
- final Couple<PluginId> circularDependency = builder.getCircularDependency();
- final PluginId id = circularDependency.getFirst();
- final PluginId parentId = circularDependency.getSecond();
if (!StringUtil.isEmptyOrSpaces(errorMessage)) {
errorMessage += "<br>";
}
- errorMessage += IdeBundle.message("error.plugins.should.not.have.cyclic.dependencies") + id + "->" + parentId + "->...->" + id;
+
+ final String cyclePresentation;
+ if (ApplicationManager.getApplication().isInternal()) {
+ final List<String> cycles = new ArrayList<String>();
+ builder.getSCCs().forEach(new TIntProcedure() {
+ int myTNumber = 0;
+ public boolean execute(int size) {
+ if (size > 1) {
+ String cycle = "";
+ for (int j = 0; j < size; j++) {
+ cycle += builder.getNodeByTNumber(myTNumber + j).getIdString() + " ";
+ }
+ cycles.add(cycle);
+ }
+ myTNumber += size;
+ return true;
+ }
+ });
+ cyclePresentation = ": " + StringUtil.join(cycles, ";");
+ } else {
+ final Couple<PluginId> circularDependency = builder.getCircularDependency();
+ final PluginId id = circularDependency.getFirst();
+ final PluginId parentId = circularDependency.getSecond();
+ cyclePresentation = id + "->" + parentId + "->...->" + id;
+ }
+ errorMessage += IdeBundle.message("error.plugins.should.not.have.cyclic.dependencies") + cyclePresentation;
}
prepareLoadingPluginsErrorMessage(errorMessage);
diff --git a/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java b/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java
index 3338241e705a..b68fa936af23 100644
--- a/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java
+++ b/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java
@@ -1152,64 +1152,66 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder {
}
private void balanceWhiteSpaces() {
- RelativeTokenTypesView wsTokens = null;
- RelativeTokenTextView tokenTextGetter = null;
+ RelativeTokenTypesView wsTokens = new RelativeTokenTypesView();
+ RelativeTokenTextView tokenTextGetter = new RelativeTokenTextView();
+ int lastIndex = 0;
for (int i = 1, size = myProduction.size() - 1; i < size; i++) {
- final ProductionMarker item = myProduction.get(i);
-
+ ProductionMarker item = myProduction.get(i);
if (item instanceof StartMarker && ((StartMarker)item).myDoneMarker == null) {
LOG.error(UNBALANCED_MESSAGE);
}
- final int prevProductionLexIndex = myProduction.get(i - 1).myLexemeIndex;
- int idx = item.myLexemeIndex;
- while (idx > prevProductionLexIndex && whitespaceOrComment(myLexTypes[idx - 1])) idx--;
- final int wsStartIndex = idx;
-
+ int prevProductionLexIndex = myProduction.get(i - 1).myLexemeIndex;
+ int wsStartIndex = Math.max(item.myLexemeIndex, lastIndex);
+ while (wsStartIndex > prevProductionLexIndex && whitespaceOrComment(myLexTypes[wsStartIndex - 1])) wsStartIndex--;
int wsEndIndex = item.myLexemeIndex;
while (wsEndIndex < myLexemeCount && whitespaceOrComment(myLexTypes[wsEndIndex])) wsEndIndex++;
- if (wsTokens == null) wsTokens = new RelativeTokenTypesView();
- wsTokens.configure(wsStartIndex, wsEndIndex);
- final boolean atEnd = wsStartIndex == 0 || wsEndIndex == myLexemeCount;
- if (tokenTextGetter == null) tokenTextGetter = new RelativeTokenTextView();
- tokenTextGetter.configure(wsStartIndex);
+ if (wsStartIndex != wsEndIndex) {
+ wsTokens.configure(wsStartIndex, wsEndIndex);
+ tokenTextGetter.configure(wsStartIndex);
+ boolean atEnd = wsStartIndex == 0 || wsEndIndex == myLexemeCount;
+ item.myLexemeIndex = wsStartIndex + item.myEdgeTokenBinder.getEdgePosition(wsTokens, atEnd, tokenTextGetter);
+ }
+ else if (item.myLexemeIndex < wsStartIndex) {
+ item.myLexemeIndex = wsStartIndex;
+ }
- item.myLexemeIndex = wsStartIndex + item.myEdgeTokenBinder.getEdgePosition(wsTokens, atEnd, tokenTextGetter);
+ lastIndex = item.myLexemeIndex;
}
}
private final class RelativeTokenTypesView extends AbstractList<IElementType> {
- private int start;
- private int size;
+ private int myStart;
+ private int mySize;
- private void configure(int _start, int _end) {
- size = _end - _start;
- start = _start;
+ private void configure(int start, int end) {
+ myStart = start;
+ mySize = end - start;
}
@Override
- public IElementType get(final int index) {
- return myLexTypes[start + index];
+ public IElementType get(int index) {
+ return myLexTypes[myStart + index];
}
@Override
public int size() {
- return size;
+ return mySize;
}
}
private final class RelativeTokenTextView implements WhitespacesAndCommentsBinder.TokenTextGetter {
- private int start;
+ private int myStart;
- private void configure(int _start) {
- start = _start;
+ private void configure(int start) {
+ myStart = start;
}
@Override
- public CharSequence get(final int i) {
- return myText.subSequence(myLexStarts[start + i], myLexStarts[start + i + 1]);
+ public CharSequence get(int i) {
+ return myText.subSequence(myLexStarts[myStart + i], myLexStarts[myStart + i + 1]);
}
}
diff --git a/platform/core-impl/src/com/intellij/mock/MockFileIndexFacade.java b/platform/core-impl/src/com/intellij/mock/MockFileIndexFacade.java
index dd6d73f11b99..6df23d8edba0 100644
--- a/platform/core-impl/src/com/intellij/mock/MockFileIndexFacade.java
+++ b/platform/core-impl/src/com/intellij/mock/MockFileIndexFacade.java
@@ -74,6 +74,11 @@ public class MockFileIndexFacade extends FileIndexFacade {
}
@Override
+ public boolean isUnderIgnored(@NotNull VirtualFile file) {
+ return false;
+ }
+
+ @Override
public Module getModuleForFile(@NotNull VirtualFile file) {
return myModule;
}
diff --git a/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java b/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java
index fa234e109d49..918ebaa22425 100644
--- a/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java
+++ b/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java
@@ -75,6 +75,9 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx {
private final List<EditReadOnlyListener> myReadOnlyListeners = ContainerUtil.createLockFreeCopyOnWriteList();
+ private volatile boolean myMightContainTabs = true; // optimisation flag: when document contains no tabs it is dramatically easier to calculate positions in editor
+ private int myTabTrackingRequestors = 0;
+
private int myCheckGuardedBlocks = 0;
private boolean myGuardsSuppressed = false;
private boolean myEventsHandling = false;
@@ -171,14 +174,14 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx {
/**
* @return true if stripping was completed successfully, false if the document prevented stripping by e.g. caret being in the way
*
- * @deprecated should be replaced with {@link #stripTrailingSpaces(com.intellij.openapi.project.Project, boolean, boolean, java.util.List)}
+ * @deprecated should be replaced with {@link #stripTrailingSpaces(com.intellij.openapi.project.Project, boolean, boolean, int[])}
* once multicaret logic will become unconditional (not controlled by configuration flag)
*/
- public boolean stripTrailingSpaces(@Nullable final Project project,
- boolean inChangedLinesOnly,
- boolean virtualSpaceEnabled,
- int caretLine,
- int caretOffset) {
+ boolean stripTrailingSpaces(@Nullable final Project project,
+ boolean inChangedLinesOnly,
+ boolean virtualSpaceEnabled,
+ int caretLine,
+ int caretOffset) {
if (!isStripTrailingSpacesEnabled) {
return true;
}
@@ -230,24 +233,24 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx {
/**
* @return true if stripping was completed successfully, false if the document prevented stripping by e.g. caret(s) being in the way
*/
- public boolean stripTrailingSpaces(@Nullable final Project project,
- boolean inChangedLinesOnly,
- boolean virtualSpaceEnabled,
- @NotNull List<Integer> caretOffsets) {
+ boolean stripTrailingSpaces(@Nullable final Project project,
+ boolean inChangedLinesOnly,
+ boolean virtualSpaceEnabled,
+ @NotNull int[] caretOffsets) {
if (!isStripTrailingSpacesEnabled) {
return true;
}
boolean markAsNeedsStrippingLater = false;
CharSequence text = myText;
- TIntObjectHashMap<List<RangeMarker>> caretMarkers = new TIntObjectHashMap<List<RangeMarker>>(caretOffsets.size());
+ TIntObjectHashMap<List<RangeMarker>> caretMarkers = new TIntObjectHashMap<List<RangeMarker>>(caretOffsets.length);
try {
if (!virtualSpaceEnabled) {
- for (Integer caretOffset : caretOffsets) {
- if (caretOffset == null || caretOffset < 0 || caretOffset > getTextLength()) {
+ for (int caretOffset : caretOffsets) {
+ if (caretOffset < 0 || caretOffset > getTextLength()) {
continue;
}
- Integer line = getLineNumber(caretOffset);
+ int line = getLineNumber(caretOffset);
List<RangeMarker> markers = caretMarkers.get(line);
if (markers == null) {
markers = new ArrayList<RangeMarker>();
@@ -763,6 +766,9 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx {
if (LOG.isDebugEnabled()) LOG.debug(event.toString());
getLineSet().changedUpdate(event);
+ if (myTabTrackingRequestors > 0) {
+ updateMightContainTabs(event.getNewFragment());
+ }
setModificationStamp(newModificationStamp);
if (!ShutDownTracker.isShutdownHookRunning()) {
@@ -1051,4 +1057,29 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx {
public String toString() {
return "DocumentImpl[" + FileDocumentManager.getInstance().getFile(this) + "]";
}
+
+ public void requestTabTracking() {
+ ApplicationManager.getApplication().assertIsDispatchThread();
+ if (myTabTrackingRequestors++ == 0) {
+ myMightContainTabs = false;
+ updateMightContainTabs(myText);
+ }
+ }
+
+ public void giveUpTabTracking() {
+ ApplicationManager.getApplication().assertIsDispatchThread();
+ if (--myTabTrackingRequestors == 0) {
+ myMightContainTabs = true;
+ }
+ }
+
+ public boolean mightContainTabs() {
+ return myMightContainTabs;
+ }
+
+ private void updateMightContainTabs(CharSequence text) {
+ if (!myMightContainTabs) {
+ myMightContainTabs = StringUtil.contains(text, 0, text.length(), '\t');
+ }
+ }
}
diff --git a/platform/core-impl/src/com/intellij/openapi/editor/impl/RangeMarkerTree.java b/platform/core-impl/src/com/intellij/openapi/editor/impl/RangeMarkerTree.java
index 975add0847a9..5ce1e2c2167b 100644
--- a/platform/core-impl/src/com/intellij/openapi/editor/impl/RangeMarkerTree.java
+++ b/platform/core-impl/src/com/intellij/openapi/editor/impl/RangeMarkerTree.java
@@ -123,7 +123,7 @@ public class RangeMarkerTree<T extends RangeMarkerEx> extends IntervalTreeImpl<T
}
});
if (alive.get() > DUPLICATE_LIMIT) {
- return "Too many range markers (" + alive + ") registered in "+this+"\n";
+ return "Too many range markers (" + alive + ") registered for interval "+node+"\n";
}
return null;
diff --git a/platform/core-impl/src/com/intellij/pom/core/impl/PomModelImpl.java b/platform/core-impl/src/com/intellij/pom/core/impl/PomModelImpl.java
index ba5858c52993..2ca35e4227e9 100644
--- a/platform/core-impl/src/com/intellij/pom/core/impl/PomModelImpl.java
+++ b/platform/core-impl/src/com/intellij/pom/core/impl/PomModelImpl.java
@@ -301,15 +301,30 @@ public class PomModelImpl extends UserDataHolderBase implements PomModel {
final PsiToDocumentSynchronizer synchronizer = manager.getSynchronizer();
final PsiElement changeScope = transaction.getChangeScope();
LOG.assertTrue(changeScope != null);
- BlockSupportImpl.sendBeforeChildrenChangeEvent((PsiManagerImpl)PsiManager.getInstance(myProject), changeScope, true);
+
final PsiFile containingFileByTree = getContainingFileByTree(changeScope);
+ if (changeScope.isPhysical() && synchronizer.toProcessPsiEvent() && isDocumentUncommitted(containingFileByTree)) {
+ // fail-fast to prevent any psi modifications that would cause psi/document text mismatch
+ // PsiToDocumentSynchronizer assertions happen inside event processing and are logged by PsiManagerImpl.fireEvent instead of being rethrown
+ // so it's important to throw something outside event processing
+ throw new IllegalStateException("Attempt to modify PSI for non-committed Document!");
+ }
+ BlockSupportImpl.sendBeforeChildrenChangeEvent((PsiManagerImpl)PsiManager.getInstance(myProject), changeScope, true);
Document document = containingFileByTree == null ? null : manager.getCachedDocument(containingFileByTree);
if(document != null) {
synchronizer.startTransaction(myProject, document, changeScope);
}
}
+ private boolean isDocumentUncommitted(@Nullable PsiFile file) {
+ if (file == null) return false;
+
+ PsiDocumentManager manager = PsiDocumentManager.getInstance(myProject);
+ Document cachedDocument = manager.getCachedDocument(file);
+ return cachedDocument != null && manager.isUncommited(cachedDocument);
+ }
+
@Nullable
private static PsiFile getContainingFileByTree(@NotNull final PsiElement changeScope) {
// there could be pseudo physical trees (JSPX/JSP/etc.) which must not translate
diff --git a/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java b/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java
index 3583af212528..8a8f7221d962 100644
--- a/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java
+++ b/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java
@@ -699,7 +699,7 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen
}
// we can end up outside write action here if the document has forUseInNonAWTThread=true
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ ApplicationManager.getApplication().runWriteAction(new ExternalChangeAction() {
@Override
public void run() {
psiFile.getViewProvider().beforeContentsSynchronized();
diff --git a/platform/core-impl/src/com/intellij/psi/impl/PsiToDocumentSynchronizer.java b/platform/core-impl/src/com/intellij/psi/impl/PsiToDocumentSynchronizer.java
index 7611dd11162a..13c43571decb 100644
--- a/platform/core-impl/src/com/intellij/psi/impl/PsiToDocumentSynchronizer.java
+++ b/platform/core-impl/src/com/intellij/psi/impl/PsiToDocumentSynchronizer.java
@@ -74,10 +74,8 @@ public class PsiToDocumentSynchronizer extends PsiTreeChangeAdapter {
final PsiFile psiFile = event.getFile();
if (psiFile == null || psiFile.getNode() == null) return;
- final Document document = getCachedDocument(psiFile, force);
- if (document == null) return;
-
- if (myPsiDocumentManager.isUncommited(document)) {
+ final Document document = myPsiDocumentManager.getCachedDocument(psiFile);
+ if (document != null && myPsiDocumentManager.isUncommited(document)) {
throw new IllegalStateException("Attempt to modify PSI for non-committed Document!");
}
}
@@ -207,7 +205,7 @@ public class PsiToDocumentSynchronizer extends PsiTreeChangeAdapter {
return myIgnorePsiEvents;
}
- private boolean toProcessPsiEvent() {
+ public boolean toProcessPsiEvent() {
return !myIgnorePsiEvents && !ApplicationManager.getApplication().hasWriteAction(IgnorePsiEventsMarker.class);
}
diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/text/DiffLog.java b/platform/core-impl/src/com/intellij/psi/impl/source/text/DiffLog.java
index d41138043e95..386fb2dea0e9 100644
--- a/platform/core-impl/src/com/intellij/psi/impl/source/text/DiffLog.java
+++ b/platform/core-impl/src/com/intellij/psi/impl/source/text/DiffLog.java
@@ -39,8 +39,7 @@ import java.util.List;
* User: cdr
*/
public class DiffLog implements DiffTreeChangeBuilder<ASTNode,ASTNode> {
- public DiffLog() {
- }
+ public DiffLog() { }
private abstract static class LogEntry {
protected LogEntry() {
@@ -58,7 +57,6 @@ public class DiffLog implements DiffTreeChangeBuilder<ASTNode,ASTNode> {
entry.doActualPsiChange(file, astDiffBuilder);
}
file.subtreeChanged();
-
return astDiffBuilder.getEvent();
}
@@ -83,7 +81,6 @@ public class DiffLog implements DiffTreeChangeBuilder<ASTNode,ASTNode> {
@Override
public void nodeDeleted(@NotNull ASTNode oldParent, @NotNull ASTNode oldNode) {
myEntries.add(new DeleteEntry(oldParent, oldNode));
-
}
@Override
@@ -126,14 +123,12 @@ public class DiffLog implements DiffTreeChangeBuilder<ASTNode,ASTNode> {
astDiffBuilder.nodeReplaced(oldNode, newNode);
- /////////////////
((TreeElement)newNode).clearCaches();
if (!(newNode instanceof FileElement)) {
((CompositeElement)newNode.getTreeParent()).subtreeChanged();
}
DebugUtil.checkTreeStructure(parent);
-
}
}
@@ -168,7 +163,6 @@ public class DiffLog implements DiffTreeChangeBuilder<ASTNode,ASTNode> {
((CompositeElement)parent).subtreeChanged();
DebugUtil.checkTreeStructure(parent);
-
}
}
@@ -222,7 +216,6 @@ public class DiffLog implements DiffTreeChangeBuilder<ASTNode,ASTNode> {
DebugUtil.checkTreeStructure(myOldParent);
}
-
}
private static PsiElement getPsi(ASTNode node, PsiFile file) {
diff --git a/platform/core-impl/src/com/intellij/psi/search/ProjectScopeImpl.java b/platform/core-impl/src/com/intellij/psi/search/ProjectScopeImpl.java
index 115b91a050fd..f21c241e966a 100644
--- a/platform/core-impl/src/com/intellij/psi/search/ProjectScopeImpl.java
+++ b/platform/core-impl/src/com/intellij/psi/search/ProjectScopeImpl.java
@@ -26,7 +26,7 @@ import org.jetbrains.annotations.NotNull;
public class ProjectScopeImpl extends GlobalSearchScope {
private final FileIndexFacade myFileIndex;
- public ProjectScopeImpl(Project project, FileIndexFacade fileIndex) {
+ public ProjectScopeImpl(@NotNull Project project, @NotNull FileIndexFacade fileIndex) {
super(project);
myFileIndex = fileIndex;
}
@@ -61,6 +61,7 @@ public class ProjectScopeImpl extends GlobalSearchScope {
return PsiBundle.message("psi.search.scope.project");
}
+ @Override
public String toString() {
return getDisplayName();
}
diff --git a/platform/core-impl/src/com/intellij/psi/text/BlockSupport.java b/platform/core-impl/src/com/intellij/psi/text/BlockSupport.java
index c94921b7eaeb..581352cea35f 100644
--- a/platform/core-impl/src/com/intellij/psi/text/BlockSupport.java
+++ b/platform/core-impl/src/com/intellij/psi/text/BlockSupport.java
@@ -66,7 +66,7 @@ public abstract class BlockSupport {
// maximal tree depth for which incremental reparse is allowed
// if tree is deeper then it will be replaced completely - to avoid SOEs
- public static final int INCREMENTAL_REPARSE_DEPTH_LIMIT = Registry.intValue("psi.incremental.reparse.depth.limit", 1000);
+ public static final int INCREMENTAL_REPARSE_DEPTH_LIMIT = Registry.intValue("psi.incremental.reparse.depth.limit");
public static final Key<Boolean> TREE_DEPTH_LIMIT_EXCEEDED = Key.create("TREE_IS_TOO_DEEP");
diff --git a/platform/dvcs/src/com/intellij/dvcs/repo/Repository.java b/platform/dvcs/src/com/intellij/dvcs/repo/Repository.java
index 3650b99ce200..c12cf4ff0407 100644
--- a/platform/dvcs/src/com/intellij/dvcs/repo/Repository.java
+++ b/platform/dvcs/src/com/intellij/dvcs/repo/Repository.java
@@ -15,6 +15,7 @@
*/
package com.intellij.dvcs.repo;
+import com.intellij.openapi.Disposable;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
@@ -49,7 +50,7 @@ import org.jetbrains.annotations.Nullable;
*
* @author Nadya Zabrodina
*/
-public interface Repository {
+public interface Repository extends Disposable {
/**
diff --git a/platform/dvcs/src/com/intellij/dvcs/repo/RepositoryImpl.java b/platform/dvcs/src/com/intellij/dvcs/repo/RepositoryImpl.java
index a7de8f97cb8a..5a605c566710 100644
--- a/platform/dvcs/src/com/intellij/dvcs/repo/RepositoryImpl.java
+++ b/platform/dvcs/src/com/intellij/dvcs/repo/RepositoryImpl.java
@@ -25,7 +25,7 @@ import org.jetbrains.annotations.Nullable;
/**
* @author Nadya Zabrodina
*/
-public abstract class RepositoryImpl implements Repository, Disposable {
+public abstract class RepositoryImpl implements Repository {
@NotNull private final Project myProject;
@NotNull private final VirtualFile myRootDir;
@@ -82,7 +82,6 @@ public abstract class RepositoryImpl implements Repository, Disposable {
public void dispose() {
}
-
@Override
public boolean equals(Object o) {
if (this == o) return true;
diff --git a/platform/dvcs/src/com/intellij/dvcs/repo/RepositoryUtil.java b/platform/dvcs/src/com/intellij/dvcs/repo/RepositoryUtil.java
index fa2e9a8bebe8..5a5a555768ba 100644
--- a/platform/dvcs/src/com/intellij/dvcs/repo/RepositoryUtil.java
+++ b/platform/dvcs/src/com/intellij/dvcs/repo/RepositoryUtil.java
@@ -17,6 +17,7 @@ package com.intellij.dvcs.repo;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VfsUtil;
@@ -29,7 +30,10 @@ import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
-import java.util.*;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
import java.util.concurrent.Callable;
/**
@@ -117,7 +121,9 @@ public class RepositoryUtil {
@Override
public void consume(Object dummy) {
- myRepository.update();
+ if (!Disposer.isDisposed(myRepository)) {
+ myRepository.update();
+ }
}
}
diff --git a/platform/dvcs/src/com/intellij/dvcs/ui/VcsLogAction.java b/platform/dvcs/src/com/intellij/dvcs/ui/VcsLogAction.java
new file mode 100644
index 000000000000..bb7f64f9b24c
--- /dev/null
+++ b/platform/dvcs/src/com/intellij/dvcs/ui/VcsLogAction.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.dvcs.ui;
+
+import com.intellij.dvcs.repo.Repository;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.actionSystem.CommonDataKeys;
+import com.intellij.openapi.project.DumbAwareAction;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.containers.MultiMap;
+import com.intellij.vcs.log.VcsFullCommitDetails;
+import com.intellij.vcs.log.VcsLog;
+import com.intellij.vcs.log.VcsLogDataKeys;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+public abstract class VcsLogAction<Repo extends Repository> extends DumbAwareAction {
+
+ @Override
+ public void actionPerformed(AnActionEvent e) {
+ Project project = e.getRequiredData(CommonDataKeys.PROJECT);
+ VcsLog log = e.getRequiredData(VcsLogDataKeys.VSC_LOG);
+ List<VcsFullCommitDetails> details = log.getSelectedDetails();
+ MultiMap<Repo, VcsFullCommitDetails> grouped = groupByRootWithCheck(project, details);
+ assert grouped != null;
+ actionPerformed(project, grouped);
+ }
+
+ @Override
+ public void update(AnActionEvent e) {
+ Project project = e.getProject();
+ VcsLog log = e.getData(VcsLogDataKeys.VSC_LOG);
+ if (project == null || log == null) {
+ e.getPresentation().setEnabledAndVisible(false);
+ return;
+ }
+
+ List<VcsFullCommitDetails> details = log.getSelectedDetails();
+ MultiMap<Repo, VcsFullCommitDetails> grouped = groupByRootWithCheck(project, details);
+ if (grouped == null) {
+ e.getPresentation().setEnabledAndVisible(false);
+ }
+ else {
+ e.getPresentation().setVisible(true);
+ e.getPresentation().setEnabled(!grouped.isEmpty() && isEnabled(grouped));
+ }
+ }
+
+ protected abstract void actionPerformed(@NotNull Project project, @NotNull MultiMap<Repo, VcsFullCommitDetails> grouped);
+
+ protected abstract boolean isEnabled(@NotNull MultiMap<Repo, VcsFullCommitDetails> grouped);
+
+ @Nullable
+ protected abstract Repo getRepositoryForRoot(@NotNull Project project, @NotNull VirtualFile root);
+
+ @Nullable
+ private MultiMap<Repo, VcsFullCommitDetails> groupByRootWithCheck(@NotNull Project project, @NotNull List<VcsFullCommitDetails> commits) {
+ MultiMap<Repo, VcsFullCommitDetails> map = MultiMap.create();
+ for (VcsFullCommitDetails commit : commits) {
+ Repo root = getRepositoryForRoot(project, commit.getRoot());
+ if (root == null) { // commit from some other VCS
+ return null;
+ }
+ map.putValue(root, commit);
+ }
+ return map;
+ }
+
+}
diff --git a/platform/dvcs/src/com/intellij/dvcs/ui/VcsLogOneCommitPerRepoAction.java b/platform/dvcs/src/com/intellij/dvcs/ui/VcsLogOneCommitPerRepoAction.java
new file mode 100644
index 000000000000..1b4be918a3e1
--- /dev/null
+++ b/platform/dvcs/src/com/intellij/dvcs/ui/VcsLogOneCommitPerRepoAction.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.dvcs.ui;
+
+import com.intellij.dvcs.repo.Repository;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Condition;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.MultiMap;
+import com.intellij.vcs.log.VcsFullCommitDetails;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collection;
+import java.util.Map;
+
+public abstract class VcsLogOneCommitPerRepoAction<Repo extends Repository> extends VcsLogAction<Repo> {
+
+ @Override
+ protected void actionPerformed(@NotNull Project project, @NotNull MultiMap<Repo, VcsFullCommitDetails> grouped) {
+ Map<Repo, VcsFullCommitDetails> singleElementMap = convertToSingleElementMap(grouped);
+ assert singleElementMap != null;
+ actionPerformed(project, singleElementMap);
+ }
+
+ @Override
+ protected boolean isEnabled(@NotNull MultiMap<Repo, VcsFullCommitDetails> grouped) {
+ return allValuesAreSingletons(grouped);
+ }
+
+ protected abstract void actionPerformed(@NotNull Project project, @NotNull Map<Repo, VcsFullCommitDetails> commits);
+
+ private boolean allValuesAreSingletons(@NotNull MultiMap<Repo, VcsFullCommitDetails> grouped) {
+ return !ContainerUtil.exists(grouped.entrySet(), new Condition<Map.Entry<Repo, Collection<VcsFullCommitDetails>>>() {
+ @Override
+ public boolean value(Map.Entry<Repo, Collection<VcsFullCommitDetails>> entry) {
+ return entry.getValue().size() != 1;
+ }
+ });
+ }
+
+ @Nullable
+ private Map<Repo, VcsFullCommitDetails> convertToSingleElementMap(@NotNull MultiMap<Repo, VcsFullCommitDetails> groupedCommits) {
+ Map<Repo, VcsFullCommitDetails> map = ContainerUtil.newHashMap();
+ for (Map.Entry<Repo, Collection<VcsFullCommitDetails>> entry : groupedCommits.entrySet()) {
+ Collection<VcsFullCommitDetails> commits = entry.getValue();
+ if (commits.size() != 1) {
+ return null;
+ }
+ map.put(entry.getKey(), commits.iterator().next());
+ }
+ return map;
+ }
+
+
+}
diff --git a/platform/dvcs/src/com/intellij/dvcs/ui/VcsLogSingleCommitAction.java b/platform/dvcs/src/com/intellij/dvcs/ui/VcsLogSingleCommitAction.java
new file mode 100644
index 000000000000..4b43380ea9eb
--- /dev/null
+++ b/platform/dvcs/src/com/intellij/dvcs/ui/VcsLogSingleCommitAction.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.dvcs.ui;
+
+import com.intellij.dvcs.repo.Repository;
+import com.intellij.openapi.project.Project;
+import com.intellij.util.containers.MultiMap;
+import com.intellij.vcs.log.VcsFullCommitDetails;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collection;
+import java.util.Map;
+
+public abstract class VcsLogSingleCommitAction<Repo extends Repository> extends VcsLogAction<Repo> {
+
+ @Override
+ protected boolean isEnabled(@NotNull MultiMap<Repo, VcsFullCommitDetails> grouped) {
+ return grouped.size() == 1;
+ }
+
+ @Override
+ protected void actionPerformed(@NotNull Project project, @NotNull MultiMap<Repo, VcsFullCommitDetails> grouped) {
+ assert grouped.size() == 1;
+ Map.Entry<Repo, Collection<VcsFullCommitDetails>> entry = grouped.entrySet().iterator().next();
+ Repo repository = entry.getKey();
+ Collection<VcsFullCommitDetails> commits = entry.getValue();
+ assert commits.size() == 1;
+ actionPerformed(repository, commits.iterator().next());
+ }
+
+ protected abstract void actionPerformed(@NotNull Repo repository, @NotNull VcsFullCommitDetails commit);
+
+}
diff --git a/platform/editor-ui-api/src/com/intellij/ide/ui/UISettings.java b/platform/editor-ui-api/src/com/intellij/ide/ui/UISettings.java
index cb0e1a298c9c..e6b2553085a8 100644
--- a/platform/editor-ui-api/src/com/intellij/ide/ui/UISettings.java
+++ b/platform/editor-ui-api/src/com/intellij/ide/ui/UISettings.java
@@ -72,6 +72,7 @@ public class UISettings implements PersistentStateComponent<UISettings>, Exporta
public int RECENT_FILES_LIMIT = 50;
public int CONSOLE_COMMAND_HISTORY_LIMIT = 300;
public int EDITOR_TAB_LIMIT = 10;
+ public int EDITOR_TAB_TITLE_LIMIT = 100;
public boolean ANIMATE_WINDOWS = true;
public int ANIMATION_SPEED = 2000; // Pixels per second
public boolean SHOW_TOOL_WINDOW_NUMBERS = true;
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/search/LexerEditorHighlighterLexer.java b/platform/editor-ui-ex/src/com/intellij/psi/impl/search/LexerEditorHighlighterLexer.java
index 2add3ed1b3c5..a966d831b71a 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/search/LexerEditorHighlighterLexer.java
+++ b/platform/editor-ui-ex/src/com/intellij/psi/impl/search/LexerEditorHighlighterLexer.java
@@ -15,23 +15,12 @@
*/
package com.intellij.psi.impl.search;
-import com.intellij.lexer.Lexer;
import com.intellij.lexer.LexerBase;
-import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.highlighter.EditorHighlighter;
-import com.intellij.openapi.editor.highlighter.EditorHighlighterFactory;
import com.intellij.openapi.editor.highlighter.HighlighterIterator;
-import com.intellij.openapi.editor.impl.EditorHighlighterCache;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.PsiDocumentManager;
-import com.intellij.psi.PsiFile;
-import com.intellij.psi.PsiManager;
-import com.intellij.psi.impl.cache.impl.id.PlatformIdTableBuilding;
import com.intellij.psi.tree.IElementType;
import com.intellij.util.text.CharSequenceSubSequence;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
/**
* @author Sergey Evdokimov
@@ -49,31 +38,6 @@ public class LexerEditorHighlighterLexer extends LexerBase {
myAlreadyInitializedHighlighter = alreadyInitializedHighlighter;
}
- @Nullable
- public static Lexer getLexerBasedOnLexerHighlighter(CharSequence text, VirtualFile virtualFile, Project project) {
- EditorHighlighter highlighter = null;
-
- PsiFile psiFile = virtualFile != null ? PsiManager.getInstance(project).findFile(virtualFile) : null;
- final Document document = psiFile != null ? PsiDocumentManager.getInstance(project).getDocument(psiFile) : null;
- final EditorHighlighter cachedEditorHighlighter;
- boolean alreadyInitializedHighlighter = false;
-
- if (document != null &&
- (cachedEditorHighlighter = EditorHighlighterCache.getEditorHighlighterForCachesBuilding(document)) != null &&
- PlatformIdTableBuilding.checkCanUseCachedEditorHighlighter(text, cachedEditorHighlighter)) {
- highlighter = cachedEditorHighlighter;
- alreadyInitializedHighlighter = true;
- }
- else if (virtualFile != null) {
- highlighter = EditorHighlighterFactory.getInstance().createEditorHighlighter(project, virtualFile);
- }
-
- if (highlighter != null) {
- return new LexerEditorHighlighterLexer(highlighter, alreadyInitializedHighlighter);
- }
- return null;
- }
-
@Override
public void start(@NotNull CharSequence buffer, int startOffset, int endOffset, int state) {
if (myAlreadyInitializedHighlighter) {
diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DataNode.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DataNode.java
index 4efac184c2ee..10fc11acbf5f 100644
--- a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DataNode.java
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DataNode.java
@@ -69,6 +69,18 @@ public class DataNode<T> implements Serializable {
}
@NotNull
+ public <T> DataNode<T> createOrReplaceChild(@NotNull Key<T> key, @NotNull T data) {
+ for (Iterator<DataNode<?>> iterator = myChildren.iterator(); iterator.hasNext(); ) {
+ DataNode<?> child = iterator.next();
+ if (child.getKey().equals(key)) {
+ iterator.remove();
+ break;
+ }
+ }
+ return createChild(key, data);
+ }
+
+ @NotNull
public Key<T> getKey() {
return myKey;
}
diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DefaultExternalFilter.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DefaultExternalFilter.java
new file mode 100644
index 000000000000..6bc9cf9aed94
--- /dev/null
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DefaultExternalFilter.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.externalSystem.model;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/22/2014
+ */
+public class DefaultExternalFilter implements ExternalFilter {
+ private static final long serialVersionUID = 1L;
+
+ @NotNull
+ private String myFilterType;
+ @NotNull
+ private String myPropertiesAsJsonMap;
+
+ public DefaultExternalFilter() {
+ myPropertiesAsJsonMap = "";
+ myFilterType = "";
+ }
+
+
+ public DefaultExternalFilter(ExternalFilter filter) {
+ myPropertiesAsJsonMap = filter.getPropertiesAsJsonMap();
+ myFilterType = filter.getFilterType();
+ }
+
+ @NotNull
+ @Override
+ public String getFilterType() {
+ return myFilterType;
+ }
+
+ public void setFilterType(@NotNull String filterType) {
+ myFilterType = filterType;
+ }
+
+ @Override
+ @NotNull
+ public String getPropertiesAsJsonMap() {
+ return myPropertiesAsJsonMap;
+ }
+
+ public void setPropertiesAsJsonMap(@NotNull String propertiesAsJsonMap) {
+ myPropertiesAsJsonMap = propertiesAsJsonMap;
+ }
+}
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/SteppingConfigurable.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DefaultExternalPlugin.java
index 5f16424c1790..8b7991b1d88c 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/SteppingConfigurable.java
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DefaultExternalPlugin.java
@@ -13,29 +13,34 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.intellij.xdebugger.impl.settings;
+package com.intellij.openapi.externalSystem.model;
-import com.intellij.openapi.options.Configurable;
-import com.intellij.xdebugger.XDebuggerBundle;
-import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
-import java.util.List;
+/**
+ * @author Vladislav.Soroka
+ * @since 7/16/2014
+ */
+public class DefaultExternalPlugin implements ExternalPlugin {
+ private static final long serialVersionUID = 1L;
+
+ @NotNull
+ private String myId;
-class SteppingConfigurable extends MergedCompositeConfigurable {
- public SteppingConfigurable(@NotNull List<Configurable> configurables) {
- super(configurables.toArray(new Configurable[configurables.size()]));
+ public DefaultExternalPlugin() {
+ }
+
+ public DefaultExternalPlugin(ExternalPlugin plugin) {
+ myId = plugin.getId();
}
@NotNull
@Override
public String getId() {
- return "debugger.stepping";
+ return myId;
}
- @Nls
- @Override
- public String getDisplayName() {
- return XDebuggerBundle.message("debugger.stepping.display.name");
+ public void setId(@NotNull String id) {
+ myId = id;
}
-} \ No newline at end of file
+}
diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DefaultExternalProject.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DefaultExternalProject.java
new file mode 100644
index 000000000000..cecb9ad33c12
--- /dev/null
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DefaultExternalProject.java
@@ -0,0 +1,243 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.externalSystem.model;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/14/2014
+ */
+public class DefaultExternalProject implements ExternalProject {
+
+ private static final long serialVersionUID = 1L;
+
+ @NotNull
+ private String myName;
+ @NotNull
+ private String myQName;
+ @Nullable
+ private String myDescription;
+ @NotNull
+ private String myGroup;
+ @NotNull
+ private String myVersion;
+ @NotNull
+ private Map<String, ExternalProject> myChildProjects;
+ @NotNull
+ private File myProjectDir;
+ @NotNull
+ private File myBuildDir;
+ @Nullable
+ private File myBuildFile;
+ @NotNull
+ private Map<String, ExternalTask> myTasks;
+ @NotNull
+ private Map<String, ?> myProperties;
+ @NotNull
+ private Map<String, ExternalSourceSet> mySourceSets;
+ @NotNull
+ private String myExternalSystemId;
+ @NotNull
+ private Map<String, ExternalPlugin> myPlugins;
+
+ public DefaultExternalProject() {
+ myChildProjects = new HashMap<String, ExternalProject>();
+ myTasks = new HashMap<String, ExternalTask>();
+ myProperties = new HashMap<String, Object>();
+ mySourceSets = new HashMap<String, ExternalSourceSet>();
+ myPlugins = new HashMap<String, ExternalPlugin>();
+ }
+
+ public DefaultExternalProject(@NotNull ExternalProject externalProject) {
+ this();
+ myName = externalProject.getName();
+ myQName = externalProject.getQName();
+ myVersion = externalProject.getVersion();
+ myGroup = externalProject.getGroup();
+ myDescription = externalProject.getDescription();
+ myProjectDir = externalProject.getProjectDir();
+ myBuildDir = externalProject.getBuildDir();
+ myBuildFile = externalProject.getBuildFile();
+ myExternalSystemId = externalProject.getExternalSystemId();
+
+ for (Map.Entry<String, ExternalProject> entry : externalProject.getChildProjects().entrySet()) {
+ myChildProjects.put(entry.getKey(), new DefaultExternalProject(entry.getValue()));
+ }
+
+ for (Map.Entry<String, ExternalTask> entry : externalProject.getTasks().entrySet()) {
+ myTasks.put(entry.getKey(), new DefaultExternalTask(entry.getValue()));
+ }
+ for (Map.Entry<String, ExternalSourceSet> entry : externalProject.getSourceSets().entrySet()) {
+ mySourceSets.put(entry.getKey(), new DefaultExternalSourceSet(entry.getValue()));
+ }
+ for (Map.Entry<String, ExternalPlugin> entry : externalProject.getPlugins().entrySet()) {
+ myPlugins.put(entry.getKey(), new DefaultExternalPlugin(entry.getValue()));
+ }
+ }
+
+
+ @NotNull
+ @Override
+ public String getExternalSystemId() {
+ return myExternalSystemId;
+ }
+
+ public void setExternalSystemId(@NotNull String externalSystemId) {
+ myExternalSystemId = externalSystemId;
+ }
+
+ @NotNull
+ @Override
+ public String getName() {
+ return myName;
+ }
+
+ public void setName(@NotNull String name) {
+ myName = name;
+ }
+
+ @NotNull
+ @Override
+ public String getQName() {
+ return myQName;
+ }
+
+ public void setQName(@NotNull String QName) {
+ myQName = QName;
+ }
+
+ @Nullable
+ @Override
+ public String getDescription() {
+ return myDescription;
+ }
+
+ public void setDescription(@Nullable String description) {
+ myDescription = description;
+ }
+
+ @NotNull
+ @Override
+ public String getGroup() {
+ return myGroup;
+ }
+
+ public void setGroup(@NotNull String group) {
+ myGroup = group;
+ }
+
+ @NotNull
+ @Override
+ public String getVersion() {
+ return myVersion;
+ }
+
+ public void setVersion(@NotNull String version) {
+ myVersion = version;
+ }
+
+ @NotNull
+ @Override
+ public Map<String, ExternalProject> getChildProjects() {
+ return myChildProjects;
+ }
+
+ public void setChildProjects(@NotNull Map<String, ExternalProject> childProjects) {
+ myChildProjects = childProjects;
+ }
+
+ @NotNull
+ @Override
+ public File getProjectDir() {
+ return myProjectDir;
+ }
+
+ public void setProjectDir(@NotNull File projectDir) {
+ myProjectDir = projectDir;
+ }
+
+ @NotNull
+ @Override
+ public File getBuildDir() {
+ return myBuildDir;
+ }
+
+ public void setBuildDir(@NotNull File buildDir) {
+ myBuildDir = buildDir;
+ }
+
+ @Nullable
+ @Override
+ public File getBuildFile() {
+ return myBuildFile;
+ }
+
+ public void setBuildFile(@Nullable File buildFile) {
+ myBuildFile = buildFile;
+ }
+
+ @NotNull
+ @Override
+ public Map<String, ExternalTask> getTasks() {
+ return myTasks;
+ }
+
+ public void setTasks(@NotNull Map<String, ExternalTask> tasks) {
+ myTasks = tasks;
+ }
+
+ @NotNull
+ @Override
+ public Map<String, ExternalPlugin> getPlugins() {
+ return myPlugins;
+ }
+
+ public void setPlugins(@NotNull Map<String, ExternalPlugin> plugins) {
+ myPlugins = plugins;
+ }
+
+ @NotNull
+ @Override
+ public Map<String, ?> getProperties() {
+ return myProperties;
+ }
+
+ public void setProperties(@NotNull Map<String, ?> properties) {
+ myProperties = properties;
+ }
+
+ @Nullable
+ @Override
+ public Object getProperty(String name) {
+ return myProperties.get(name);
+ }
+
+ @NotNull
+ @Override
+ public Map<String, ExternalSourceSet> getSourceSets() {
+ return mySourceSets;
+ }
+
+ public void setSourceSets(@NotNull Map<String, ExternalSourceSet> sourceSets) {
+ mySourceSets = sourceSets;
+ }
+}
diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DefaultExternalSourceDirectorySet.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DefaultExternalSourceDirectorySet.java
new file mode 100644
index 000000000000..d6a8d7aa6291
--- /dev/null
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DefaultExternalSourceDirectorySet.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.externalSystem.model;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/14/2014
+ */
+public class DefaultExternalSourceDirectorySet implements ExternalSourceDirectorySet {
+ private static final long serialVersionUID = 1L;
+
+ @NotNull
+ private String myName;
+ @NotNull
+ private Set<File> mySrcDirs;
+ @NotNull
+ private File myOutputDir;
+ @NotNull
+ private Set<String> myExcludes;
+ @NotNull
+ private Set<String> myIncludes;
+ @NotNull
+ private List<ExternalFilter> myFilters;
+
+ public DefaultExternalSourceDirectorySet() {
+ mySrcDirs = new HashSet<File>();
+ myExcludes = new HashSet<String>();
+ myIncludes = new HashSet<String>();
+ myFilters = new ArrayList<ExternalFilter>();
+ }
+
+ public DefaultExternalSourceDirectorySet(ExternalSourceDirectorySet sourceDirectorySet) {
+ this();
+ myName = sourceDirectorySet.getName();
+ mySrcDirs = new HashSet<File>(sourceDirectorySet.getSrcDirs());
+ myOutputDir = sourceDirectorySet.getOutputDir();
+ myExcludes = new HashSet<String>(sourceDirectorySet.getExcludes());
+ myIncludes = new HashSet<String>(sourceDirectorySet.getIncludes());
+ for (ExternalFilter filter : sourceDirectorySet.getFilters()) {
+ myFilters.add(new DefaultExternalFilter(filter));
+ }
+ }
+
+ @NotNull
+ @Override
+ public String getName() {
+ return myName;
+ }
+
+ public void setName(@NotNull String name) {
+ myName = name;
+ }
+
+ @NotNull
+ @Override
+ public Set<File> getSrcDirs() {
+ return mySrcDirs;
+ }
+
+ public void setSrcDirs(@NotNull Set<File> srcDirs) {
+ mySrcDirs = srcDirs;
+ }
+
+ @NotNull
+ @Override
+ public File getOutputDir() {
+ return myOutputDir;
+ }
+
+ @NotNull
+ @Override
+ public Set<String> getIncludes() {
+ return myIncludes;
+ }
+
+ public void setIncludes(@NotNull Set<String> includes) {
+ myIncludes = includes;
+ }
+
+ @NotNull
+ @Override
+ public Set<String> getExcludes() {
+ return myExcludes;
+ }
+
+ public void setExcludes(@NotNull Set<String> excludes) {
+ myExcludes = excludes;
+ }
+
+ @NotNull
+ @Override
+ public List<ExternalFilter> getFilters() {
+ return myFilters;
+ }
+
+ public void setFilters(@NotNull List<ExternalFilter> filters) {
+ myFilters = filters;
+ }
+
+ public void setOutputDir(@NotNull File outputDir) {
+ myOutputDir = outputDir;
+ }
+}
diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DefaultExternalSourceSet.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DefaultExternalSourceSet.java
new file mode 100644
index 000000000000..19d692dd1985
--- /dev/null
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DefaultExternalSourceSet.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.externalSystem.model;
+
+import com.intellij.openapi.externalSystem.model.project.ExternalSystemSourceType;
+import com.intellij.openapi.externalSystem.model.project.IExternalSystemSourceType;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/14/2014
+ */
+public class DefaultExternalSourceSet implements ExternalSourceSet {
+ private static final long serialVersionUID = 1L;
+
+ private String myName;
+ private Map<IExternalSystemSourceType, ExternalSourceDirectorySet> mySources;
+
+ public DefaultExternalSourceSet() {
+ mySources = new HashMap<IExternalSystemSourceType, ExternalSourceDirectorySet>();
+ }
+
+ public DefaultExternalSourceSet(ExternalSourceSet sourceSet) {
+ this();
+ myName = sourceSet.getName();
+ for (Map.Entry<IExternalSystemSourceType, ExternalSourceDirectorySet> entry : sourceSet.getSources().entrySet()) {
+ mySources.put(ExternalSystemSourceType.from(entry.getKey()), new DefaultExternalSourceDirectorySet(entry.getValue()));
+ }
+ }
+
+ @NotNull
+ @Override
+ public String getName() {
+ return myName;
+ }
+
+ public void setName(String name) {
+ myName = name;
+ }
+
+ @NotNull
+ @Override
+ public Map<IExternalSystemSourceType, ExternalSourceDirectorySet> getSources() {
+ return mySources;
+ }
+
+ public void setSources(Map<IExternalSystemSourceType, ExternalSourceDirectorySet> sources) {
+ mySources = sources;
+ }
+}
diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DefaultExternalTask.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DefaultExternalTask.java
new file mode 100644
index 000000000000..e9392eb52e84
--- /dev/null
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/DefaultExternalTask.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.externalSystem.model;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/14/2014
+ */
+public class DefaultExternalTask implements ExternalTask {
+ private static final long serialVersionUID = 1L;
+
+ @NotNull
+ private String myName;
+ @NotNull
+ private String myQName;
+ @Nullable
+ private String myDescription;
+ @Nullable
+ private String myGroup;
+
+ public DefaultExternalTask() {
+ }
+
+ public DefaultExternalTask(ExternalTask externalTask) {
+ myName = externalTask.getName();
+ myQName = externalTask.getQName();
+ myDescription = externalTask.getDescription();
+ myGroup = externalTask.getGroup();
+ }
+
+ @NotNull
+ @Override
+ public String getName() {
+ return myName;
+ }
+
+ public void setName(@NotNull String name) {
+ myName = name;
+ }
+
+ @NotNull
+ @Override
+ public String getQName() {
+ return myQName;
+ }
+
+ public void setQName(@NotNull String QName) {
+ myQName = QName;
+ }
+
+ @Nullable
+ @Override
+ public String getDescription() {
+ return myDescription;
+ }
+
+ public void setDescription(@Nullable String description) {
+ myDescription = description;
+ }
+
+ @Nullable
+ @Override
+ public String getGroup() {
+ return myGroup;
+ }
+
+ public void setGroup(@Nullable String group) {
+ myGroup = group;
+ }
+}
diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/ExternalFilter.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/ExternalFilter.java
new file mode 100644
index 000000000000..98fc003cb645
--- /dev/null
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/ExternalFilter.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.externalSystem.model;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.Serializable;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/14/2014
+ */
+public interface ExternalFilter extends Serializable {
+ @NotNull
+ String getFilterType();
+ @NotNull
+ String getPropertiesAsJsonMap();
+}
diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/ExternalPlugin.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/ExternalPlugin.java
new file mode 100644
index 000000000000..edd3db771b3f
--- /dev/null
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/ExternalPlugin.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.externalSystem.model;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.Serializable;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/14/2014
+ */
+public interface ExternalPlugin extends Serializable {
+ @NotNull
+ String getId();
+}
diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/ExternalProject.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/ExternalProject.java
new file mode 100644
index 000000000000..6df2d413d0fd
--- /dev/null
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/ExternalProject.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.externalSystem.model;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.File;
+import java.io.Serializable;
+import java.util.Map;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/14/2014
+ */
+public interface ExternalProject extends Serializable {
+
+ @NotNull
+ String getExternalSystemId();
+
+ @NotNull
+ String getName();
+
+ @NotNull
+ String getQName();
+
+ @Nullable
+ String getDescription();
+
+ @NotNull
+ String getGroup();
+
+ @NotNull
+ String getVersion();
+
+ @NotNull
+ Map<String, ExternalProject> getChildProjects();
+
+ @NotNull
+ File getProjectDir();
+
+ @NotNull
+ File getBuildDir();
+
+ @Nullable
+ File getBuildFile();
+
+ @NotNull
+ Map<String, ExternalTask> getTasks();
+
+ //@NotNull
+ //Map<String, ExternalConfiguration> getConfigurations();
+
+ //@NotNull
+ //List<ExternalRepository> getRepositories();
+
+ //@NotNull
+ //List<ExternalDependency> getDependencies();
+
+ @NotNull
+ Map<String, ExternalPlugin> getPlugins();
+
+ //@NotNull
+ //ExternalProjectBuild getBuild();
+
+ @NotNull
+ Map<String, ?> getProperties();
+
+ @Nullable
+ Object getProperty(String name);
+
+ @NotNull
+ Map<String, ExternalSourceSet> getSourceSets();
+}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatePsiInfoBase.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/ExternalSourceDirectorySet.java
index 7254e651ce41..70f0bed3d177 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatePsiInfoBase.java
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/ExternalSourceDirectorySet.java
@@ -13,27 +13,34 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.intellij.codeInsight.template.postfix.templates;
+package com.intellij.openapi.externalSystem.model;
-import com.intellij.openapi.editor.Document;
-import com.intellij.psi.PsiElement;
-import com.intellij.util.Function;
import org.jetbrains.annotations.NotNull;
+import java.io.File;
+import java.io.Serializable;
import java.util.List;
+import java.util.Set;
-public abstract class PostfixTemplatePsiInfoBase implements PostfixTemplatePsiInfo {
+/**
+ * @author Vladislav.Soroka
+ * @since 7/14/2014
+ */
+public interface ExternalSourceDirectorySet extends Serializable {
+ @NotNull
+ String getName();
+
+ @NotNull
+ Set<File> getSrcDirs();
@NotNull
- public abstract List<PsiElement> getExpressions(@NotNull PsiElement context, @NotNull Document document, int newOffset);
+ File getOutputDir();
+
+ @NotNull
+ Set<String> getExcludes();
+ @NotNull
+ Set<String> getIncludes();
@NotNull
- public Function<PsiElement, String> getRenderer() {
- return new Function<PsiElement, String>() {
- @Override
- public String fun(@NotNull PsiElement element) {
- return element.getText();
- }
- };
- }
+ List<ExternalFilter> getFilters();
}
diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/ExternalSourceSet.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/ExternalSourceSet.java
new file mode 100644
index 000000000000..b23c07bbafa6
--- /dev/null
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/ExternalSourceSet.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.externalSystem.model;
+
+import com.intellij.openapi.externalSystem.model.project.IExternalSystemSourceType;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.Serializable;
+import java.util.Map;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/14/2014
+ */
+public interface ExternalSourceSet extends Serializable {
+ @NotNull
+ String getName();
+ //@NotNull
+ //ClasspathContainer getCompileClasspath();
+
+ //@NotNull
+ //ClasspathContainer getRuntimeClasspath();
+
+ @NotNull
+ Map<IExternalSystemSourceType, ExternalSourceDirectorySet> getSources();
+}
diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/ExternalTask.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/ExternalTask.java
new file mode 100644
index 000000000000..b4c61c662acc
--- /dev/null
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/ExternalTask.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.externalSystem.model;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.Serializable;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/14/2014
+ */
+public interface ExternalTask extends Serializable {
+ @NotNull
+ String getName();
+ @NotNull
+ String getQName();
+ @Nullable
+ String getDescription();
+ @Nullable
+ String getGroup();
+}
diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/ExternalSystemSourceType.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/ExternalSystemSourceType.java
index ffe8a52d4a06..0e112b1c2b14 100644
--- a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/ExternalSystemSourceType.java
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/ExternalSystemSourceType.java
@@ -1,52 +1,62 @@
package com.intellij.openapi.externalSystem.model.project;
-import org.jetbrains.annotations.NotNull;
-
-import java.io.Serializable;
-
/**
* Enumerates module source types.
*
* @author Denis Zhdanov
* @since 8/10/11 5:21 PM
*/
-public class ExternalSystemSourceType implements Serializable {
-
- @NotNull public static final ExternalSystemSourceType SOURCE = new ExternalSystemSourceType("SOURCE");
- @NotNull public static final ExternalSystemSourceType TEST = new ExternalSystemSourceType("TEST");
- @NotNull public static final ExternalSystemSourceType EXCLUDED = new ExternalSystemSourceType("EXCLUDED");
- @NotNull public static final ExternalSystemSourceType SOURCE_GENERATED = new ExternalSystemSourceType("SOURCE_GENERATED");
- @NotNull public static final ExternalSystemSourceType TEST_GENERATED = new ExternalSystemSourceType("TEST_GENERATED");
- @NotNull public static final ExternalSystemSourceType RESOURCE = new ExternalSystemSourceType("RESOURCE");
- @NotNull public static final ExternalSystemSourceType TEST_RESOURCE = new ExternalSystemSourceType("TEST_RESOURCE");
-
- private static final long serialVersionUID = 1L;
-
- @NotNull private final String myId;
-
- public ExternalSystemSourceType(@NotNull String id) {
- myId = id;
+public enum ExternalSystemSourceType implements IExternalSystemSourceType {
+
+ SOURCE(false, false, false, false),
+ TEST(true, false, false, false),
+ EXCLUDED(false, false, false, true),
+ SOURCE_GENERATED(true, true, false, false),
+ TEST_GENERATED(true, true, false, false),
+ RESOURCE(false, false, true, false),
+ TEST_RESOURCE(true, false, true, false);
+
+ private final boolean isTest;
+ private final boolean isGenerated;
+ private final boolean isResource;
+ private final boolean isExcluded;
+
+ ExternalSystemSourceType(boolean test, boolean generated, boolean resource, boolean excluded) {
+ isTest = test;
+ isGenerated = generated;
+ isResource = resource;
+ isExcluded = excluded;
}
@Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
- ExternalSystemSourceType type = (ExternalSystemSourceType)o;
-
- if (!myId.equals(type.myId)) return false;
+ public boolean isTest() {
+ return isTest;
+ }
- return true;
+ @Override
+ public boolean isGenerated() {
+ return isGenerated;
}
@Override
- public int hashCode() {
- return myId.hashCode();
+ public boolean isResource() {
+ return isResource;
}
@Override
- public String toString() {
- return myId;
+ public boolean isExcluded() {
+ return isExcluded;
+ }
+
+ public static ExternalSystemSourceType from(IExternalSystemSourceType sourceType) {
+ for (ExternalSystemSourceType systemSourceType : ExternalSystemSourceType.values()) {
+ if (systemSourceType.isGenerated == sourceType.isGenerated() &&
+ systemSourceType.isResource == sourceType.isResource() &&
+ systemSourceType.isTest == sourceType.isTest() &&
+ systemSourceType.isExcluded == sourceType.isExcluded()) {
+ return systemSourceType;
+ }
+ }
+ throw new IllegalArgumentException("Invalid source type: " + sourceType);
}
}
diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/IExternalSystemSourceType.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/IExternalSystemSourceType.java
new file mode 100644
index 000000000000..2ad8821b06cd
--- /dev/null
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/IExternalSystemSourceType.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.externalSystem.model.project;
+
+import java.io.Serializable;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/17/2014
+ */
+public interface IExternalSystemSourceType extends Serializable {
+ boolean isTest();
+
+ boolean isGenerated();
+
+ boolean isResource();
+
+ boolean isExcluded();
+}
diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/util/ExternalSystemApiUtil.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/util/ExternalSystemApiUtil.java
index a6cfc65eb759..fd3493447ced 100644
--- a/platform/external-system-api/src/com/intellij/openapi/externalSystem/util/ExternalSystemApiUtil.java
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/util/ExternalSystemApiUtil.java
@@ -681,4 +681,9 @@ public class ExternalSystemApiUtil {
public static String getExternalProjectPath(@Nullable Module module) {
return module != null ? module.getOptionValue(ExternalSystemConstants.LINKED_PROJECT_PATH_KEY) : null;
}
+
+ @Nullable
+ public static String getExternalProjectId(@Nullable Module module) {
+ return module != null ? module.getOptionValue(ExternalSystemConstants.LINKED_PROJECT_ID_KEY) : null;
+ }
}
diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/util/ExternalSystemConstants.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/util/ExternalSystemConstants.java
index 283067810bb0..160c95938378 100644
--- a/platform/external-system-api/src/com/intellij/openapi/externalSystem/util/ExternalSystemConstants.java
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/util/ExternalSystemConstants.java
@@ -27,6 +27,7 @@ public class ExternalSystemConstants {
@NonNls @NotNull public static final String EXTERNAL_SYSTEM_ID_KEY = "external.system.id";
@NonNls @NotNull public static final String LINKED_PROJECT_PATH_KEY = "external.linked.project.path";
@NonNls @NotNull public static final String ROOT_PROJECT_PATH_KEY = "external.root.project.path";
+ @NonNls @NotNull public static final String LINKED_PROJECT_ID_KEY = "external.linked.project.id";
@NonNls @NotNull public static final String EXTERNAL_SYSTEM_MODULE_GROUP_KEY = "external.system.module.group";
@NonNls @NotNull public static final String EXTERNAL_SYSTEM_MODULE_VERSION_KEY = "external.system.module.version";
diff --git a/platform/external-system-impl/external-system-impl.iml b/platform/external-system-impl/external-system-impl.iml
index aa68fdc4d7b6..1cbf68f907f9 100644
--- a/platform/external-system-impl/external-system-impl.iml
+++ b/platform/external-system-impl/external-system-impl.iml
@@ -24,6 +24,7 @@
<orderEntry type="library" scope="TEST" name="JUnit4" level="project" />
<orderEntry type="module" module-name="testFramework" scope="TEST" />
<orderEntry type="module" module-name="testFramework-java" scope="TEST" />
+ <orderEntry type="module" module-name="compiler-impl" scope="TEST" />
</component>
</module>
diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/ProjectStructureServices.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/ProjectStructureServices.java
deleted file mode 100644
index 1e6dadd0d3b8..000000000000
--- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/ProjectStructureServices.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package com.intellij.openapi.externalSystem.service.project;
-
-import org.jetbrains.annotations.NotNull;
-
-/**
- * Facades all services necessary for the 'sync project changes' processing.
- * <p/>
- * Thread-safe.
- *
- * @author Denis Zhdanov
- * @since 2/14/12 1:26 PM
- */
-public class ProjectStructureServices {
-
- @NotNull private final ProjectStructureHelper myProjectStructureHelper;
- @NotNull private final PlatformFacade myPlatformFacade;
- @NotNull private final ExternalLibraryPathTypeMapper myLibraryPathTypeMapper;
-
- public ProjectStructureServices(@NotNull ProjectStructureHelper projectStructureHelper,
- @NotNull PlatformFacade platformFacade,
- @NotNull ExternalLibraryPathTypeMapper mapper)
- {
- myProjectStructureHelper = projectStructureHelper;
- myPlatformFacade = platformFacade;
- myLibraryPathTypeMapper = mapper;
- }
-
- @NotNull
- public ProjectStructureHelper getProjectStructureHelper() {
- return myProjectStructureHelper;
- }
-
- @NotNull
- public PlatformFacade getPlatformFacade() {
- return myPlatformFacade;
- }
-
- @NotNull
- public ExternalLibraryPathTypeMapper getLibraryPathTypeMapper() {
- return myLibraryPathTypeMapper;
- }
-}
diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ContentRootDataService.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ContentRootDataService.java
index 7e7483869728..3e1c95ad3766 100644
--- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ContentRootDataService.java
+++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ContentRootDataService.java
@@ -33,8 +33,13 @@ import com.intellij.openapi.externalSystem.util.ExternalSystemConstants;
import com.intellij.openapi.externalSystem.util.Order;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.roots.*;
+import com.intellij.openapi.roots.ContentEntry;
+import com.intellij.openapi.roots.ModifiableRootModel;
+import com.intellij.openapi.roots.ModuleRootModificationUtil;
+import com.intellij.openapi.roots.SourceFolder;
+import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vcs.changes.ChangeListManager;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
@@ -151,7 +156,7 @@ public class ContentRootDataService implements ProjectDataService<ContentRootDat
createSourceRootIfAbsent(contentEntry, path, module.getName(), JavaSourceRootType.TEST_SOURCE, true, createEmptyContentRootDirectories);
}
for (SourceRoot path : contentRoot.getPaths(ExternalSystemSourceType.EXCLUDED)) {
- createExcludedRootIfAbsent(contentEntry, path, module.getName());
+ createExcludedRootIfAbsent(contentEntry, path, module.getName(), module.getProject());
}
contentEntriesMap.remove(contentEntry.getUrl());
}
@@ -214,14 +219,18 @@ public class ContentRootDataService implements ProjectDataService<ContentRootDat
}
}
- private static void createExcludedRootIfAbsent(@NotNull ContentEntry entry, @NotNull SourceRoot root, @NotNull String moduleName) {
+ private static void createExcludedRootIfAbsent(@NotNull ContentEntry entry, @NotNull SourceRoot root, @NotNull String moduleName, @NotNull Project project) {
+ String rootPath = root.getPath();
for (VirtualFile file : entry.getExcludeFolderFiles()) {
- if (ExternalSystemApiUtil.getLocalFileSystemPath(file).equals(root.getPath())) {
+ if (ExternalSystemApiUtil.getLocalFileSystemPath(file).equals(rootPath)) {
return;
}
}
LOG.info(String.format("Importing excluded root '%s' for content root '%s' of module '%s'", root, entry.getUrl(), moduleName));
- entry.addExcludeFolder(toVfsUrl(root.getPath()));
+ entry.addExcludeFolder(toVfsUrl(rootPath));
+ if (!Registry.is("ide.hide.excluded.files")) {
+ ChangeListManager.getInstance(project).addDirectoryToIgnoreImplicitly(rootPath);
+ }
}
@Override
diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ModuleDataService.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ModuleDataService.java
index 4b1e3b13a22f..32919794eca4 100644
--- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ModuleDataService.java
+++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ModuleDataService.java
@@ -274,6 +274,7 @@ public class ModuleDataService implements ProjectDataService<ModuleData, Module>
module.putUserData(MODULE_DATA_KEY, moduleData);
module.setOption(ExternalSystemConstants.EXTERNAL_SYSTEM_ID_KEY, moduleData.getOwner().toString());
+ module.setOption(ExternalSystemConstants.LINKED_PROJECT_ID_KEY, moduleData.getId());
module.setOption(ExternalSystemConstants.LINKED_PROJECT_PATH_KEY, moduleData.getLinkedExternalProjectPath());
final ProjectData projectData = moduleDataNode.getData(ProjectKeys.PROJECT);
module.setOption(ExternalSystemConstants.ROOT_PROJECT_PATH_KEY, projectData != null ? projectData.getLinkedExternalProjectPath() : "");
diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ProjectDataManager.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ProjectDataManager.java
index 6575ffb107f0..c2dcfe57b010 100644
--- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ProjectDataManager.java
+++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ProjectDataManager.java
@@ -25,6 +25,7 @@ import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.ContainerUtilRt;
import com.intellij.util.containers.Stack;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.List;
@@ -40,8 +41,10 @@ public class ProjectDataManager {
private static final Logger LOG = Logger.getInstance("#" + ProjectDataManager.class.getName());
- @NotNull private final NotNullLazyValue<Map<Key<?>, List<ProjectDataService<?, ?>>>> myServices =
- new NotNullLazyValue<Map<Key<?>, List<ProjectDataService<?, ?>>>>() {
+ @NotNull private final NotNullLazyValue<Map<Key<?>, List<ProjectDataService<?, ?>>>> myServices;
+
+ public ProjectDataManager() {
+ myServices = new NotNullLazyValue<Map<Key<?>, List<ProjectDataService<?, ?>>>>() {
@NotNull
@Override
protected Map<Key<?>, List<ProjectDataService<?, ?>>> compute() {
@@ -57,10 +60,22 @@ public class ProjectDataManager {
for (List<ProjectDataService<?, ?>> services : result.values()) {
ExternalSystemApiUtil.orderAwareSort(services);
}
-
return result;
}
};
+ }
+
+ @Nullable
+ public List<ProjectDataService<?, ?>> getDataServices(Key<?> key) {
+ return myServices.getValue().get(key);
+ }
+
+ @Nullable
+ public ProjectDataService<?, ?> getDataService(Key<?> key) {
+ final List<ProjectDataService<?, ?>> dataServices = myServices.getValue().get(key);
+ assert dataServices == null || dataServices.isEmpty() || dataServices.size() == 1;
+ return ContainerUtil.getFirstItem(dataServices);
+ }
@SuppressWarnings("unchecked")
public <T> void importData(@NotNull Collection<DataNode<?>> nodes, @NotNull Project project, boolean synchronous) {
diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/settings/AbstractImportFromExternalSystemControl.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/settings/AbstractImportFromExternalSystemControl.java
index 5dcb5ef71e3b..deb9a9044ea6 100644
--- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/settings/AbstractImportFromExternalSystemControl.java
+++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/settings/AbstractImportFromExternalSystemControl.java
@@ -193,6 +193,11 @@ public abstract class AbstractImportFromExternalSystemControl<
return myProjectSettingsControl;
}
+ @Nullable
+ public ExternalSystemSettingsControl<SystemSettings> getSystemSettingsControl() {
+ return mySystemSettingsControl;
+ }
+
public void setLinkedProjectPath(@NotNull String path) {
myProjectSettings.setExternalProjectPath(path);
myLinkedProjectPathField.setText(path);
diff --git a/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/test/ExternalSystemTestCase.java b/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/test/ExternalSystemTestCase.java
index 22ec927eb30d..449de84f4627 100644
--- a/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/test/ExternalSystemTestCase.java
+++ b/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/test/ExternalSystemTestCase.java
@@ -15,24 +15,42 @@
*/
package com.intellij.openapi.externalSystem.test;
+import com.intellij.compiler.CompilerTestUtil;
+import com.intellij.compiler.CompilerWorkspaceConfiguration;
+import com.intellij.compiler.artifacts.ArtifactsTestUtil;
+import com.intellij.compiler.impl.ModuleCompileScope;
+import com.intellij.openapi.application.AccessToken;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.command.WriteCommandAction;
+import com.intellij.openapi.compiler.CompileContext;
+import com.intellij.openapi.compiler.CompileScope;
+import com.intellij.openapi.compiler.CompileStatusNotification;
+import com.intellij.openapi.compiler.CompilerManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.module.StdModuleTypes;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.projectRoots.Sdk;
+import com.intellij.openapi.projectRoots.impl.JavaAwareProjectJdkTableImpl;
+import com.intellij.openapi.roots.ModuleRootModificationUtil;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
+import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.packaging.artifacts.Artifact;
+import com.intellij.packaging.impl.compiler.ArtifactCompileScope;
import com.intellij.testFramework.IdeaTestCase;
+import com.intellij.testFramework.IdeaTestUtil;
import com.intellij.testFramework.PsiTestUtil;
import com.intellij.testFramework.UsefulTestCase;
import com.intellij.testFramework.fixtures.IdeaProjectTestFixture;
import com.intellij.testFramework.fixtures.IdeaTestFixtureFactory;
+import com.intellij.util.concurrency.Semaphore;
+import com.intellij.util.io.TestFileSystemItem;
import com.intellij.util.ui.UIUtil;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NonNls;
@@ -40,6 +58,7 @@ import org.jetbrains.annotations.NotNull;
import org.junit.After;
import org.junit.Before;
+import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.io.IOException;
@@ -129,11 +148,11 @@ public abstract class ExternalSystemTestCase extends UsefulTestCase {
@Override
public void tearDown() throws Exception {
try {
- myProject = null;
- UIUtil.invokeAndWaitIfNeeded(new Runnable() {
+ edt(new Runnable() {
@Override
public void run() {
try {
+ CompilerTestUtil.disableExternalCompiler(myProject);
tearDownFixtures();
}
catch (Exception e) {
@@ -141,6 +160,7 @@ public abstract class ExternalSystemTestCase extends UsefulTestCase {
}
}
});
+ myProject = null;
if (!FileUtil.delete(myTestDir) && myTestDir.exists()) {
System.err.println("Cannot delete " + myTestDir);
//printDirectoryContent(myDir);
@@ -319,7 +339,11 @@ public abstract class ExternalSystemTestCase extends UsefulTestCase {
protected VirtualFile createProjectSubFile(String relativePath) throws IOException {
File f = new File(getProjectPath(), relativePath);
FileUtil.ensureExists(f.getParentFile());
- f.createNewFile();
+ FileUtil.ensureCanCreateFile(f);
+ final boolean created = f.createNewFile();
+ if(!created) {
+ throw new AssertionError("Unable to create the project sub file: " + f.getAbsolutePath());
+ }
return LocalFileSystem.getInstance().refreshAndFindFileByIoFile(f);
}
@@ -329,6 +353,116 @@ public abstract class ExternalSystemTestCase extends UsefulTestCase {
return file;
}
+
+ protected void compileModules(final String... moduleNames) {
+ compile(createModulesCompileScope(moduleNames));
+ }
+
+ protected void buildArtifacts(String... artifactNames) {
+ compile(createArtifactsScope(artifactNames));
+ }
+
+ private void compile(final CompileScope scope) {
+ edt(new Runnable() {
+ @Override
+ public void run() {
+ for (Module module : scope.getAffectedModules()) {
+ setupJdkForModule(module.getName());
+ }
+ }
+ });
+
+ CompilerWorkspaceConfiguration.getInstance(myProject).CLEAR_OUTPUT_DIRECTORY = true;
+
+ final Semaphore semaphore = new Semaphore();
+ semaphore.down();
+ edt(new Runnable() {
+ @Override
+ public void run() {
+ CompilerTestUtil.enableExternalCompiler();
+ CompilerManager.getInstance(myProject).make(scope, new CompileStatusNotification() {
+ @Override
+ public void finished(boolean aborted, int errors, int warnings, CompileContext compileContext) {
+ //assertFalse(aborted);
+ //assertEquals(collectMessages(compileContext, CompilerMessageCategory.ERROR), 0, errors);
+ //assertEquals(collectMessages(compileContext, CompilerMessageCategory.WARNING), 0, warnings);
+ semaphore.up();
+ }
+ });
+ }
+ });
+ while (!semaphore.waitFor(100)) {
+ if (SwingUtilities.isEventDispatchThread()) {
+ UIUtil.dispatchAllInvocationEvents();
+ }
+ }
+ if (SwingUtilities.isEventDispatchThread()) {
+ UIUtil.dispatchAllInvocationEvents();
+ }
+ }
+
+ private CompileScope createModulesCompileScope(final String[] moduleNames) {
+ final List<Module> modules = new ArrayList<Module>();
+ for (String name : moduleNames) {
+ modules.add(getModule(name));
+ }
+ return new ModuleCompileScope(myProject, modules.toArray(new Module[modules.size()]), false);
+ }
+
+ private CompileScope createArtifactsScope(String[] artifactNames) {
+ List<Artifact> artifacts = new ArrayList<Artifact>();
+ for (String name : artifactNames) {
+ artifacts.add(ArtifactsTestUtil.findArtifact(myProject, name));
+ }
+ return ArtifactCompileScope.createArtifactsScope(myProject, artifacts);
+ }
+
+ protected Sdk setupJdkForModule(final String moduleName) {
+ final Sdk sdk = true ? JavaAwareProjectJdkTableImpl.getInstanceEx().getInternalJdk() : createJdk("Java 1.5");
+ ModuleRootModificationUtil.setModuleSdk(getModule(moduleName), sdk);
+ return sdk;
+ }
+
+ protected static Sdk createJdk(String versionName) {
+ return IdeaTestUtil.getMockJdk17(versionName);
+ }
+
+ protected Module getModule(final String name) {
+ AccessToken accessToken = ApplicationManager.getApplication().acquireReadActionLock();
+ try {
+ Module m = ModuleManager.getInstance(myProject).findModuleByName(name);
+ assertNotNull("Module " + name + " not found", m);
+ return m;
+ }
+ finally {
+ accessToken.finish();
+ }
+ }
+
+ protected void assertExplodedLayout(String artifactName, String expected) {
+ assertJarLayout(artifactName + " exploded", expected);
+ }
+
+ protected void assertJarLayout(String artifactName, String expected) {
+ ArtifactsTestUtil.assertLayout(myProject, artifactName, expected);
+ }
+
+ protected void assertArtifactOutputPath(final String artifactName, final String expected) {
+ ArtifactsTestUtil.assertOutputPath(myProject, artifactName, expected);
+ }
+
+ protected void assertArtifactOutputFileName(final String artifactName, final String expected) {
+ ArtifactsTestUtil.assertOutputFileName(myProject, artifactName, expected);
+ }
+
+ protected void assertArtifactOutput(String artifactName, TestFileSystemItem fs) {
+ final Artifact artifact = ArtifactsTestUtil.findArtifact(myProject, artifactName);
+ final VirtualFile outputFile = artifact.getOutputFile();
+ assert outputFile != null;
+ final File file = VfsUtilCore.virtualToIoFile(outputFile);
+ fs.assertFileEqual(file);
+ }
+
private static void setFileContent(final VirtualFile file, final String content, final boolean advanceStamps) throws IOException {
new WriteAction<VirtualFile>() {
@Override
diff --git a/platform/icons/src/actions/GroupByFile.png b/platform/icons/src/actions/GroupByFile.png
new file mode 100644
index 000000000000..b79988d3f0ed
--- /dev/null
+++ b/platform/icons/src/actions/GroupByFile.png
Binary files differ
diff --git a/platform/icons/src/actions/GroupByFile@2x.png b/platform/icons/src/actions/GroupByFile@2x.png
new file mode 100644
index 000000000000..5342abe8ad2c
--- /dev/null
+++ b/platform/icons/src/actions/GroupByFile@2x.png
Binary files differ
diff --git a/platform/icons/src/actions/GroupByFile@2x_dark.png b/platform/icons/src/actions/GroupByFile@2x_dark.png
new file mode 100644
index 000000000000..809d342a1266
--- /dev/null
+++ b/platform/icons/src/actions/GroupByFile@2x_dark.png
Binary files differ
diff --git a/platform/icons/src/actions/GroupByFile_dark.png b/platform/icons/src/actions/GroupByFile_dark.png
new file mode 100644
index 000000000000..f5db91f950fc
--- /dev/null
+++ b/platform/icons/src/actions/GroupByFile_dark.png
Binary files differ
diff --git a/platform/icons/src/general/projectConfigurableBanner.png b/platform/icons/src/general/projectConfigurableBanner.png
new file mode 100644
index 000000000000..b655f59be352
--- /dev/null
+++ b/platform/icons/src/general/projectConfigurableBanner.png
Binary files differ
diff --git a/platform/icons/src/general/projectConfigurableBanner@2x.png b/platform/icons/src/general/projectConfigurableBanner@2x.png
new file mode 100644
index 000000000000..04495ec5073e
--- /dev/null
+++ b/platform/icons/src/general/projectConfigurableBanner@2x.png
Binary files differ
diff --git a/platform/icons/src/general/projectConfigurableSelected.png b/platform/icons/src/general/projectConfigurableSelected.png
new file mode 100644
index 000000000000..dcbb64a75390
--- /dev/null
+++ b/platform/icons/src/general/projectConfigurableSelected.png
Binary files differ
diff --git a/platform/icons/src/general/projectConfigurableSelected@2x.png b/platform/icons/src/general/projectConfigurableSelected@2x.png
new file mode 100644
index 000000000000..3550d5fbf390
--- /dev/null
+++ b/platform/icons/src/general/projectConfigurableSelected@2x.png
Binary files differ
diff --git a/platform/indexing-impl/src/com/intellij/openapi/module/impl/scopes/ModuleWithDependentsScope.java b/platform/indexing-impl/src/com/intellij/openapi/module/impl/scopes/ModuleWithDependentsScope.java
index 259ea3936934..c773402b27e3 100644
--- a/platform/indexing-impl/src/com/intellij/openapi/module/impl/scopes/ModuleWithDependentsScope.java
+++ b/platform/indexing-impl/src/com/intellij/openapi/module/impl/scopes/ModuleWithDependentsScope.java
@@ -56,6 +56,8 @@ class ModuleWithDependentsScope extends GlobalSearchScope {
private static Set<Module> buildDependents(Module module) {
Set<Module> result = new THashSet<Module>();
result.add(module);
+
+ Set<Module> processedExporting = new THashSet<Module>();
ModuleIndex index = getModuleIndex(module.getProject());
@@ -64,9 +66,11 @@ class ModuleWithDependentsScope extends GlobalSearchScope {
while (!walkingQueue.isEmpty()) {
Module current = walkingQueue.pullFirst();
+ processedExporting.add(current);
result.addAll(index.plainUsages.get(current));
for (Module dependent : index.exportingUsages.get(current)) {
- if (result.add(dependent)) {
+ result.add(dependent);
+ if (processedExporting.add(dependent)) {
walkingQueue.addLast(dependent);
}
}
diff --git a/platform/indexing-impl/src/com/intellij/psi/impl/cache/impl/id/IdTableBuilding.java b/platform/indexing-impl/src/com/intellij/psi/impl/cache/impl/id/IdTableBuilding.java
index 3e6571405a91..8519453e3e6c 100644
--- a/platform/indexing-impl/src/com/intellij/psi/impl/cache/impl/id/IdTableBuilding.java
+++ b/platform/indexing-impl/src/com/intellij/psi/impl/cache/impl/id/IdTableBuilding.java
@@ -149,7 +149,9 @@ public class IdTableBuilding {
}
private int convertToMask(final WordOccurrence.Kind kind) {
- if (kind == null) return UsageSearchContext.ANY;
+ if (kind == null) {
+ return UsageSearchContext.ANY;
+ }
if (kind == WordOccurrence.Kind.CODE) return UsageSearchContext.IN_CODE;
if (kind == WordOccurrence.Kind.COMMENTS) return UsageSearchContext.IN_COMMENTS;
if (kind == WordOccurrence.Kind.LITERALS) return UsageSearchContext.IN_STRINGS;
diff --git a/platform/indexing-impl/src/com/intellij/psi/impl/file/impl/ResolveScopeManagerImpl.java b/platform/indexing-impl/src/com/intellij/psi/impl/file/impl/ResolveScopeManagerImpl.java
index 6f904bae5d54..b89042b68257 100644
--- a/platform/indexing-impl/src/com/intellij/psi/impl/file/impl/ResolveScopeManagerImpl.java
+++ b/platform/indexing-impl/src/com/intellij/psi/impl/file/impl/ResolveScopeManagerImpl.java
@@ -76,7 +76,7 @@ public class ResolveScopeManagerImpl extends ResolveScopeManager {
}
- private GlobalSearchScope getDefaultResolveScope(@NotNull PsiFile psiFile, @NotNull final VirtualFile vFile) {
+ private GlobalSearchScope getResolveScopeFromProviders(@NotNull final VirtualFile vFile) {
return myDefaultResolveScopesCache.get(vFile);
}
@@ -85,8 +85,6 @@ public class ResolveScopeManagerImpl extends ResolveScopeManager {
Module module = projectFileIndex.getModuleForFile(vFile);
if (module != null) {
boolean includeTests = projectFileIndex.isInTestSourceContent(vFile);
- // TODO: dmitrylomov: removed this line to see what fails.
- //!(vFile.getFileType() == StdFileTypes.JAVA && projectFileIndex.isContentSourceFile(vFile));
return GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module, includeTests);
}
else {
@@ -167,7 +165,7 @@ public class ResolveScopeManagerImpl extends ResolveScopeManager {
return GlobalSearchScope.allScope(myProject);
}
- return getDefaultResolveScope(contextFile, vFile);
+ return getResolveScopeFromProviders(vFile);
}
@@ -175,7 +173,7 @@ public class ResolveScopeManagerImpl extends ResolveScopeManager {
public GlobalSearchScope getDefaultResolveScope(final VirtualFile vFile) {
final PsiFile psiFile = myManager.findFile(vFile);
assert psiFile != null;
- return getDefaultResolveScope(psiFile, vFile);
+ return getResolveScopeFromProviders(vFile);
}
diff --git a/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionInitializationContext.java b/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionInitializationContext.java
index 624d60fd8688..2c152b595421 100644
--- a/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionInitializationContext.java
+++ b/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionInitializationContext.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2010 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,8 +16,8 @@
package com.intellij.codeInsight.completion;
import com.intellij.lang.Language;
+import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.editor.SelectionModel;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiFile;
import com.intellij.psi.util.PsiUtilBase;
@@ -45,26 +45,24 @@ public class CompletionInitializationContext {
private final OffsetMap myOffsetMap;
private String myDummyIdentifier = DUMMY_IDENTIFIER;
- public CompletionInitializationContext(final Editor editor, final PsiFile file, final CompletionType completionType, int invocationCount) {
+ public CompletionInitializationContext(final Editor editor, final Caret caret, final PsiFile file, final CompletionType completionType, int invocationCount) {
myEditor = editor;
myFile = file;
myCompletionType = completionType;
myInvocationCount = invocationCount;
myOffsetMap = new OffsetMap(editor.getDocument());
- myOffsetMap.addOffset(START_OFFSET, calcStartOffset(editor));
- myOffsetMap.addOffset(SELECTION_END_OFFSET, calcSelectionEnd(editor));
- myOffsetMap.addOffset(IDENTIFIER_END_OFFSET, calcDefaultIdentifierEnd(editor, calcSelectionEnd(editor)));
+ myOffsetMap.addOffset(START_OFFSET, calcStartOffset(caret));
+ myOffsetMap.addOffset(SELECTION_END_OFFSET, calcSelectionEnd(caret));
+ myOffsetMap.addOffset(IDENTIFIER_END_OFFSET, calcDefaultIdentifierEnd(editor, calcSelectionEnd(caret)));
}
- private static int calcSelectionEnd(Editor editor) {
- final SelectionModel selectionModel = editor.getSelectionModel();
- return selectionModel.hasSelection() ? selectionModel.getSelectionEnd() : editor.getCaretModel().getOffset();
+ private static int calcSelectionEnd(Caret caret) {
+ return caret.hasSelection() ? caret.getSelectionEnd() : caret.getOffset();
}
- public static int calcStartOffset(Editor editor) {
- final SelectionModel selectionModel = editor.getSelectionModel();
- return selectionModel.hasSelection() ? selectionModel.getSelectionStart() : editor.getCaretModel().getOffset();
+ public static int calcStartOffset(Caret caret) {
+ return caret.hasSelection() ? caret.getSelectionStart() : caret.getOffset();
}
static int calcDefaultIdentifierEnd(Editor editor, int startFrom) {
diff --git a/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionResultSet.java b/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionResultSet.java
index 8a7feb2109fe..6cccc06dacf2 100644
--- a/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionResultSet.java
+++ b/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionResultSet.java
@@ -19,6 +19,7 @@ import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.patterns.ElementPattern;
import com.intellij.patterns.StandardPatterns;
import com.intellij.util.Consumer;
+import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import java.util.LinkedHashSet;
@@ -61,7 +62,6 @@ public abstract class CompletionResultSet implements Consumer<LookupElement> {
/**
* If a given element matches the prefix, give it for further processing (which may eventually result in its appearing in the completion list)
- * @param element
*/
public abstract void addElement(@NotNull final LookupElement element);
@@ -75,15 +75,17 @@ public abstract class CompletionResultSet implements Consumer<LookupElement> {
}
}
+ @Contract(value="", pure=true)
@NotNull public abstract CompletionResultSet withPrefixMatcher(@NotNull PrefixMatcher matcher);
/**
* Creates a default camel-hump prefix matcher based on given prefix
- * @param prefix
*/
+ @Contract(value="", pure=true)
@NotNull public abstract CompletionResultSet withPrefixMatcher(@NotNull String prefix);
@NotNull
+ @Contract(value="", pure=true)
public abstract CompletionResultSet withRelevanceSorter(@NotNull CompletionSorter sorter);
public abstract void addLookupAdvertisement(@NotNull String text);
@@ -92,6 +94,7 @@ public abstract class CompletionResultSet implements Consumer<LookupElement> {
* @return A result set with the same prefix, but the lookup strings will be matched case-insensitively. Their lookup strings will
* remain as they are though, so upon insertion the prefix case will be changed.
*/
+ @Contract(value="", pure=true)
@NotNull public abstract CompletionResultSet caseInsensitive();
@NotNull
diff --git a/platform/lang-api/src/com/intellij/codeInsight/lookup/LookupElementBuilder.java b/platform/lang-api/src/com/intellij/codeInsight/lookup/LookupElementBuilder.java
index 189e6581d171..771ca526b5fe 100644
--- a/platform/lang-api/src/com/intellij/codeInsight/lookup/LookupElementBuilder.java
+++ b/platform/lang-api/src/com/intellij/codeInsight/lookup/LookupElementBuilder.java
@@ -23,6 +23,7 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiNamedElement;
import com.intellij.psi.util.PsiUtilCore;
import gnu.trove.THashSet;
+import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -85,10 +86,12 @@ public final class LookupElementBuilder extends LookupElement {
/**
* @deprecated use {@link #withInsertHandler(com.intellij.codeInsight.completion.InsertHandler)}
*/
+ @Contract(value="", pure=true)
public LookupElementBuilder setInsertHandler(@Nullable InsertHandler<LookupElement> insertHandler) {
return withInsertHandler(insertHandler);
}
+ @Contract(value="", pure=true)
public LookupElementBuilder withInsertHandler(@Nullable InsertHandler<LookupElement> insertHandler) {
return new LookupElementBuilder(myLookupString, myObject, insertHandler, myRenderer, myHardcodedPresentation,
myAllLookupStrings, myCaseSensitive);
@@ -97,9 +100,11 @@ public final class LookupElementBuilder extends LookupElement {
/**
* @deprecated use {@link #withRenderer(LookupElementRenderer)}
*/
+ @Contract(value="", pure=true)
public LookupElementBuilder setRenderer(@Nullable LookupElementRenderer<LookupElement> renderer) {
return withRenderer(renderer);
}
+ @Contract(value="", pure=true)
public LookupElementBuilder withRenderer(@Nullable LookupElementRenderer<LookupElement> renderer) {
return new LookupElementBuilder(myLookupString, myObject, myInsertHandler, renderer, myHardcodedPresentation,
myAllLookupStrings, myCaseSensitive);
@@ -114,10 +119,12 @@ public final class LookupElementBuilder extends LookupElement {
/**
* @deprecated use {@link #withIcon(javax.swing.Icon)}
*/
+ @Contract(value="", pure=true)
public LookupElementBuilder setIcon(@Nullable Icon icon) {
return withIcon(icon);
}
+ @Contract(value="", pure=true)
public LookupElementBuilder withIcon(@Nullable Icon icon) {
final LookupElementPresentation presentation = copyPresentation();
presentation.setIcon(icon);
@@ -139,9 +146,11 @@ public final class LookupElementBuilder extends LookupElement {
/**
* @deprecated use {@link #withLookupString(String)}
*/
+ @Contract(value="", pure=true)
public LookupElementBuilder addLookupString(@NotNull String another) {
return withLookupString(another);
}
+ @Contract(value="", pure=true)
public LookupElementBuilder withLookupString(@NotNull String another) {
final THashSet<String> set = new THashSet<String>(myAllLookupStrings);
set.add(another);
@@ -157,6 +166,7 @@ public final class LookupElementBuilder extends LookupElement {
/**
* @deprecated use {@link #withCaseSensitivity(boolean)}
*/
+ @Contract(value="", pure=true)
public LookupElementBuilder setCaseSensitive(boolean caseSensitive) {
return withCaseSensitivity(caseSensitive);
}
@@ -165,6 +175,7 @@ public final class LookupElementBuilder extends LookupElement {
* @return modified builder
* @see com.intellij.codeInsight.completion.CompletionResultSet#caseInsensitive()
*/
+ @Contract(value="", pure=true)
public LookupElementBuilder withCaseSensitivity(boolean caseSensitive) {
return new LookupElementBuilder(myLookupString, myObject, myInsertHandler, myRenderer, myHardcodedPresentation,
myAllLookupStrings, caseSensitive);
@@ -173,9 +184,11 @@ public final class LookupElementBuilder extends LookupElement {
/**
* @deprecated use {@link #withItemTextForeground(java.awt.Color)}
*/
+ @Contract(value="", pure=true)
public LookupElementBuilder setItemTextForeground(@NotNull Color itemTextForeground) {
return withItemTextForeground(itemTextForeground);
}
+ @Contract(value="", pure=true)
public LookupElementBuilder withItemTextForeground(@NotNull Color itemTextForeground) {
final LookupElementPresentation presentation = copyPresentation();
presentation.setItemTextForeground(itemTextForeground);
@@ -185,9 +198,11 @@ public final class LookupElementBuilder extends LookupElement {
/**
* @deprecated use {@link #withItemTextUnderlined(boolean)}
*/
+ @Contract(value="", pure=true)
public LookupElementBuilder setItemTextUnderlined(boolean underlined) {
return withItemTextUnderlined(underlined);
}
+ @Contract(value="", pure=true)
public LookupElementBuilder withItemTextUnderlined(boolean underlined) {
final LookupElementPresentation presentation = copyPresentation();
presentation.setItemTextUnderlined(underlined);
@@ -197,9 +212,11 @@ public final class LookupElementBuilder extends LookupElement {
/**
* @deprecated use {@link #withTypeText(String)}
*/
+ @Contract(value="", pure=true)
public LookupElementBuilder setTypeText(@Nullable String typeText) {
return withTypeText(typeText);
}
+ @Contract(value="", pure=true)
public LookupElementBuilder withTypeText(@Nullable String typeText) {
return withTypeText(typeText, false);
}
@@ -207,14 +224,17 @@ public final class LookupElementBuilder extends LookupElement {
/**
* @deprecated use {@link #withTypeText(String, boolean)}
*/
+ @Contract(value="", pure=true)
public LookupElementBuilder setTypeText(@Nullable String typeText, boolean grayed) {
return withTypeText(typeText, grayed);
}
+ @Contract(value="", pure=true)
public LookupElementBuilder withTypeText(@Nullable String typeText, boolean grayed) {
return withTypeText(typeText, null, grayed);
}
+ @Contract(value="", pure=true)
public LookupElementBuilder withTypeText(@Nullable String typeText, @Nullable Icon typeIcon, boolean grayed) {
final LookupElementPresentation presentation = copyPresentation();
presentation.setTypeText(typeText, typeIcon);
@@ -226,9 +246,11 @@ public final class LookupElementBuilder extends LookupElement {
/**
* @deprecated use {@link #withPresentableText(String)}
*/
+ @Contract(value="", pure=true)
public LookupElementBuilder setPresentableText(@NotNull String presentableText) {
return withPresentableText(presentableText);
}
+ @Contract(value="", pure=true)
public LookupElementBuilder withPresentableText(@NotNull String presentableText) {
final LookupElementPresentation presentation = copyPresentation();
presentation.setItemText(presentableText);
@@ -239,9 +261,11 @@ public final class LookupElementBuilder extends LookupElement {
/**
* @deprecated use {@link #bold()}
*/
+ @Contract(value="", pure=true)
public LookupElementBuilder setBold() {
return bold();
}
+ @Contract(value="", pure=true)
public LookupElementBuilder bold() {
return withBoldness(true);
}
@@ -249,9 +273,11 @@ public final class LookupElementBuilder extends LookupElement {
/**
* @deprecated use {@link #withBoldness(boolean)}
*/
+ @Contract(value="", pure=true)
public LookupElementBuilder setBold(boolean bold) {
return withBoldness(bold);
}
+ @Contract(value="", pure=true)
public LookupElementBuilder withBoldness(boolean bold) {
final LookupElementPresentation presentation = copyPresentation();
presentation.setItemTextBold(bold);
@@ -262,9 +288,11 @@ public final class LookupElementBuilder extends LookupElement {
/**
* @deprecated use {@link #strikeout()}
*/
+ @Contract(value="", pure=true)
public LookupElementBuilder setStrikeout() {
return strikeout();
}
+ @Contract(value="", pure=true)
public LookupElementBuilder strikeout() {
return withStrikeoutness(true);
}
@@ -272,9 +300,11 @@ public final class LookupElementBuilder extends LookupElement {
/**
* @deprecated use {@link #withStrikeoutness(boolean)}
*/
+ @Contract(value="", pure=true)
public LookupElementBuilder setStrikeout(boolean strikeout) {
return withStrikeoutness(strikeout);
}
+ @Contract(value="", pure=true)
public LookupElementBuilder withStrikeoutness(boolean strikeout) {
final LookupElementPresentation presentation = copyPresentation();
presentation.setStrikeout(strikeout);
@@ -285,9 +315,11 @@ public final class LookupElementBuilder extends LookupElement {
/**
* @deprecated use {@link #withTailText(String)}
*/
+ @Contract(value="", pure=true)
public LookupElementBuilder setTailText(@Nullable String tailText) {
return withTailText(tailText);
}
+ @Contract(value="", pure=true)
public LookupElementBuilder withTailText(@Nullable String tailText) {
return withTailText(tailText, false);
}
@@ -295,9 +327,11 @@ public final class LookupElementBuilder extends LookupElement {
/**
* @deprecated use {@link #withTailText(String, boolean)}
*/
+ @Contract(value="", pure=true)
public LookupElementBuilder setTailText(@Nullable String tailText, boolean grayed) {
return withTailText(tailText, grayed);
}
+ @Contract(value="", pure=true)
public LookupElementBuilder withTailText(@Nullable String tailText, boolean grayed) {
final LookupElementPresentation presentation = copyPresentation();
presentation.setTailText(tailText, grayed);
@@ -305,12 +339,14 @@ public final class LookupElementBuilder extends LookupElement {
myAllLookupStrings, myCaseSensitive);
}
+ @Contract(value="", pure=true)
public LookupElementBuilder appendTailText(@NotNull String tailText, boolean grayed) {
final LookupElementPresentation presentation = copyPresentation();
presentation.appendTailText(tailText, grayed);
return new LookupElementBuilder(myLookupString, myObject, myInsertHandler, null, presentation, myAllLookupStrings, myCaseSensitive);
}
+ @Contract(value="", pure=true)
public LookupElement withAutoCompletionPolicy(AutoCompletionPolicy policy) {
return policy.applyPolicy(this);
}
diff --git a/platform/lang-api/src/com/intellij/execution/ui/RunContentDescriptor.java b/platform/lang-api/src/com/intellij/execution/ui/RunContentDescriptor.java
index efee74b807da..8d4d3b29b088 100644
--- a/platform/lang-api/src/com/intellij/execution/ui/RunContentDescriptor.java
+++ b/platform/lang-api/src/com/intellij/execution/ui/RunContentDescriptor.java
@@ -142,14 +142,15 @@ public class RunContentDescriptor implements Disposable {
return myContent;
}
- public void setRestarter(Runnable runnable) {
- myRestarter = runnable;
- }
-
+ @Nullable
public Runnable getRestarter() {
return myRestarter;
}
+ public void setRestarter(@Nullable Runnable runnable) {
+ myRestarter = runnable;
+ }
+
public boolean isActivateToolWindowWhenAdded() {
return myActivateToolWindowWhenAdded;
}
diff --git a/platform/lang-api/src/com/intellij/find/FindManager.java b/platform/lang-api/src/com/intellij/find/FindManager.java
index 56339d116e14..abf90bb4f0b7 100644
--- a/platform/lang-api/src/com/intellij/find/FindManager.java
+++ b/platform/lang-api/src/com/intellij/find/FindManager.java
@@ -172,6 +172,18 @@ public abstract class FindManager {
public abstract void setFindWasPerformed();
/**
+ * Gets the flag indicating that 'Add Selection for Next Occurrence' action was performed recently,
+ * so "Find Next" and "Find Previous" actions should work in its context.
+ */
+ public abstract boolean selectNextOccurrenceWasPerformed();
+
+ /**
+ * Sets the flag indicating that 'Add Selection for Next Occurrence' action was performed recently,
+ * so "Find Next" and "Find Previous" actions should work in its context.
+ */
+ public abstract void setSelectNextOccurrenceWasPerformed();
+
+ /**
* Explicitly tell FindManager that "Find Next" and "Find Previous" actions should not use
* find usages previous results.
*/
diff --git a/platform/lang-api/src/com/intellij/find/FindModel.java b/platform/lang-api/src/com/intellij/find/FindModel.java
index a09070c1ed24..5dafc2db8acf 100644
--- a/platform/lang-api/src/com/intellij/find/FindModel.java
+++ b/platform/lang-api/src/com/intellij/find/FindModel.java
@@ -19,6 +19,7 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.UserDataHolderBase;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.search.SearchScope;
+import com.intellij.util.PatternUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -72,8 +73,7 @@ public class FindModel extends UserDataHolderBase implements Cloneable {
private boolean isSearchHighlighters = false;
private boolean isReplaceState = false;
private boolean isWholeWordsOnly = false;
- private boolean isInCommentsOnly;
- private boolean isInStringLiteralsOnly;
+ private SearchContext searchContext = SearchContext.ANY;
private boolean isFromCursor = true;
private boolean isForward = true;
private boolean isGlobal = true;
@@ -96,6 +96,7 @@ public class FindModel extends UserDataHolderBase implements Cloneable {
private SearchScope customScope;
private boolean isCustomScope = false;
private boolean isMultiline = false;
+ private boolean mySearchInProjectFiles;
public boolean isMultiline() {
return isMultiline;
@@ -170,8 +171,7 @@ public class FindModel extends UserDataHolderBase implements Cloneable {
isCustomScope = model.isCustomScope;
isFindAll = model.isFindAll;
- isInCommentsOnly = model.isInCommentsOnly;
- isInStringLiteralsOnly = model.isInStringLiteralsOnly;
+ searchContext = model.searchContext;
isMultiline = model.isMultiline;
}
@@ -190,8 +190,8 @@ public class FindModel extends UserDataHolderBase implements Cloneable {
if (isForward != findModel.isForward) return false;
if (isFromCursor != findModel.isFromCursor) return false;
if (isGlobal != findModel.isGlobal) return false;
- if (isInCommentsOnly != findModel.isInCommentsOnly) return false;
- if (isInStringLiteralsOnly != findModel.isInStringLiteralsOnly) return false;
+ if (searchContext != findModel.searchContext) return false;
+
if (isMultiline != findModel.isMultiline) return false;
if (isMultipleFiles != findModel.isMultipleFiles) return false;
if (isOpenInNewTabEnabled != findModel.isOpenInNewTabEnabled) return false;
@@ -215,6 +215,7 @@ public class FindModel extends UserDataHolderBase implements Cloneable {
if (myStringToReplace != null ? !myStringToReplace.equals(findModel.myStringToReplace) : findModel.myStringToReplace != null) {
return false;
}
+ if (mySearchInProjectFiles != findModel.mySearchInProjectFiles) return false;
return true;
}
@@ -227,8 +228,7 @@ public class FindModel extends UserDataHolderBase implements Cloneable {
result = 31 * result + (isSearchHighlighters ? 1 : 0);
result = 31 * result + (isReplaceState ? 1 : 0);
result = 31 * result + (isWholeWordsOnly ? 1 : 0);
- result = 31 * result + (isInCommentsOnly ? 1 : 0);
- result = 31 * result + (isInStringLiteralsOnly ? 1 : 0);
+ result = 31 * result + (searchContext.ordinal());
result = 31 * result + (isFromCursor ? 1 : 0);
result = 31 * result + (isForward ? 1 : 0);
result = 31 * result + (isGlobal ? 1 : 0);
@@ -252,6 +252,7 @@ public class FindModel extends UserDataHolderBase implements Cloneable {
result = 31 * result + (isCustomScope ? 1 : 0);
result = 31 * result + (isMultiline ? 1 : 0);
result = 31 * result + (isPreserveCase ? 1 : 0);
+ result = 31 * result + (mySearchInProjectFiles ? 1 : 0);
result = 31 * result + (myPattern != null ? myPattern.hashCode() : 0);
return result;
}
@@ -274,7 +275,7 @@ public class FindModel extends UserDataHolderBase implements Cloneable {
public void setStringToFind(@NotNull String s) {
boolean changed = !StringUtil.equals(s, myStringToFind);
myStringToFind = s;
- myPattern = NO_PATTERN;
+ myPattern = PatternUtil.NOTHING;
if (changed) {
notifyObservers();
}
@@ -409,7 +410,7 @@ public class FindModel extends UserDataHolderBase implements Cloneable {
boolean changed = val != isCaseSensitive;
isCaseSensitive = val;
if (changed) {
- myPattern = NO_PATTERN;
+ myPattern = PatternUtil.NOTHING;
notifyObservers();
}
}
@@ -658,8 +659,8 @@ public class FindModel extends UserDataHolderBase implements Cloneable {
}
@Override
- public Object clone() {
- return super.clone();
+ public FindModel clone() {
+ return (FindModel)super.clone();
}
@@ -670,8 +671,7 @@ public class FindModel extends UserDataHolderBase implements Cloneable {
buffer.append("myStringToReplace =").append(myStringToReplace).append("\n");
buffer.append("isReplaceState =").append(isReplaceState).append("\n");
buffer.append("isWholeWordsOnly =").append(isWholeWordsOnly).append("\n");
- buffer.append("isInStringLiterals =").append(isInStringLiteralsOnly).append("\n");
- buffer.append("isInComments =").append(isInCommentsOnly).append("\n");
+ buffer.append("searchContext =").append(searchContext).append("\n");
buffer.append("isFromCursor =").append(isFromCursor).append("\n");
buffer.append("isForward =").append(isForward).append("\n");
buffer.append("isGlobal =").append(isGlobal).append("\n");
@@ -689,6 +689,7 @@ public class FindModel extends UserDataHolderBase implements Cloneable {
buffer.append("fileFilter =").append(fileFilter).append("\n");
buffer.append("moduleName =").append(moduleName).append("\n");
buffer.append("customScopeName =").append(customScopeName).append("\n");
+ buffer.append("searchInProjectFiles =").append(mySearchInProjectFiles).append("\n");
return buffer.toString();
}
@@ -849,45 +850,95 @@ public class FindModel extends UserDataHolderBase implements Cloneable {
}
}
+ public enum SearchContext {
+ ANY, IN_STRING_LITERALS, IN_COMMENTS, EXCEPT_STRING_LITERALS, EXCEPT_COMMENTS, EXCEPT_COMMENTS_AND_STRING_LITERALS
+ }
+
public boolean isInStringLiteralsOnly() {
- return isInStringLiteralsOnly;
+ return searchContext == SearchContext.IN_STRING_LITERALS;
+ }
+
+ public boolean isExceptComments() {
+ return searchContext == SearchContext.EXCEPT_COMMENTS;
+ }
+
+ public boolean isExceptStringLiterals() {
+ return searchContext == SearchContext.EXCEPT_STRING_LITERALS;
+ }
+
+ public boolean isInCommentsOnly() {
+ return searchContext == SearchContext.IN_COMMENTS;
+ }
+
+ public boolean isExceptCommentsAndStringLiterals() {
+ return searchContext == SearchContext.EXCEPT_COMMENTS_AND_STRING_LITERALS;
+ }
+
+ @Deprecated
+ public void setInCommentsOnly(boolean inCommentsOnly) {
+ doApplyContextChange(inCommentsOnly, SearchContext.IN_COMMENTS);
}
+ @Deprecated
public void setInStringLiteralsOnly(boolean inStringLiteralsOnly) {
- boolean changed = isInStringLiteralsOnly != inStringLiteralsOnly;
- isInStringLiteralsOnly = inStringLiteralsOnly;
+ doApplyContextChange(inStringLiteralsOnly, SearchContext.IN_STRING_LITERALS);
+ }
+
+ private void doApplyContextChange(boolean newOptionValue, SearchContext option) {
+ boolean changed = false;
+ if (newOptionValue) {
+ changed = searchContext != option;
+ searchContext = option;
+ } else if (searchContext == option) { // do not reset unrelated value
+ changed = true;
+ searchContext = SearchContext.ANY;
+ }
+
if (changed) {
notifyObservers();
}
}
- public boolean isInCommentsOnly() {
- return isInCommentsOnly;
+ public @NotNull SearchContext getSearchContext() {
+ return searchContext;
}
- public void setInCommentsOnly(boolean inCommentsOnly) {
- boolean changed = isInCommentsOnly != inCommentsOnly;
- isInCommentsOnly = inCommentsOnly;
+ public void setSearchContext(@NotNull SearchContext _searchContext) {
+ doSetContext(_searchContext);
+ }
+
+ private void doSetContext(SearchContext newSearchContext) {
+ boolean changed = newSearchContext != searchContext;
+ searchContext = newSearchContext;
+ if (changed) {
+ notifyObservers();
+ }
+ }
+
+ public boolean isSearchInProjectFiles() {
+ return mySearchInProjectFiles;
+ }
+
+ public void setSearchInProjectFiles(boolean searchInProjectFiles) {
+ boolean changed = mySearchInProjectFiles != searchInProjectFiles;
+ mySearchInProjectFiles = searchInProjectFiles;
if (changed) {
notifyObservers();
}
}
- private static final Pattern NO_PATTERN = Pattern.compile("");
- private Pattern myPattern = NO_PATTERN;
+ private Pattern myPattern = PatternUtil.NOTHING;
public Pattern compileRegExp() {
String toFind = getStringToFind();
Pattern pattern = myPattern;
- if (pattern == NO_PATTERN) {
+ if (pattern == PatternUtil.NOTHING) {
try {
myPattern = pattern = Pattern.compile(toFind, isCaseSensitive() ? Pattern.MULTILINE : Pattern.MULTILINE | Pattern.CASE_INSENSITIVE);
}
catch (PatternSyntaxException e) {
- LOG.error("Regexp:'" + toFind + "'", e);
- myPattern = null;
- return null;
+ myPattern = pattern = null;
}
}
diff --git a/platform/lang-api/src/com/intellij/ide/util/projectWizard/WizardContext.java b/platform/lang-api/src/com/intellij/ide/util/projectWizard/WizardContext.java
index bb8a60c83479..6f23ac69f745 100644
--- a/platform/lang-api/src/com/intellij/ide/util/projectWizard/WizardContext.java
+++ b/platform/lang-api/src/com/intellij/ide/util/projectWizard/WizardContext.java
@@ -22,6 +22,7 @@ import com.intellij.openapi.components.StorageScheme;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.ProjectRootManager;
+import com.intellij.openapi.roots.ui.configuration.ModulesProvider;
import com.intellij.openapi.util.UserDataHolderBase;
import com.intellij.platform.ProjectTemplate;
import com.intellij.util.SystemProperties;
@@ -48,6 +49,7 @@ public class WizardContext extends UserDataHolderBase {
private final List<Listener> myListeners = ContainerUtil.createLockFreeCopyOnWriteList();
private StorageScheme myProjectStorageFormat = StorageScheme.DIRECTORY_BASED;
private boolean myNewWizard;
+ private ModulesProvider myModulesProvider;
public void setProjectStorageFormat(StorageScheme format) {
myProjectStorageFormat = format;
@@ -61,6 +63,14 @@ public class WizardContext extends UserDataHolderBase {
myNewWizard = newWizard;
}
+ public ModulesProvider getModulesProvider() {
+ return myModulesProvider;
+ }
+
+ public void setModulesProvider(ModulesProvider modulesProvider) {
+ myModulesProvider = modulesProvider;
+ }
+
public interface Listener {
void buttonsUpdateRequested();
void nextStepRequested();
diff --git a/platform/lang-api/src/com/intellij/lexer/LexerUtil.java b/platform/lang-api/src/com/intellij/lexer/LexerUtil.java
index 7623248e60d1..8abdfa5e79af 100644
--- a/platform/lang-api/src/com/intellij/lexer/LexerUtil.java
+++ b/platform/lang-api/src/com/intellij/lexer/LexerUtil.java
@@ -16,6 +16,8 @@
package com.intellij.lexer;
import com.intellij.util.CharTable;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.Nullable;
/**
* @author max
@@ -30,4 +32,12 @@ public class LexerUtil {
public static CharSequence internToken(Lexer lexer, CharTable table) {
return table.intern(getTokenText(lexer));
}
+
+ @Contract("!null->!null")
+ public static Lexer getRootLexer(@Nullable Lexer lexer) {
+ while (lexer instanceof DelegateLexer) {
+ lexer = ((DelegateLexer)lexer).getDelegate();
+ }
+ return lexer;
+ }
}
diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettings.java b/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettings.java
index 2c44a32d9ace..d858bfc01fcb 100644
--- a/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettings.java
+++ b/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettings.java
@@ -56,7 +56,6 @@ public class CodeStyleSettings extends CommonCodeStyleSettings implements Clonea
public CodeStyleSettings(boolean loadExtensions) {
super(null);
- RIGHT_MARGIN = DEFAULT_RIGHT_MARGIN;
initTypeToName();
initImportsByDefault();
@@ -108,12 +107,16 @@ public class CodeStyleSettings extends CommonCodeStyleSettings implements Clonea
private void addCustomSettings(CustomCodeStyleSettings settings) {
if (settings != null) {
- myCustomSettings.put(settings.getClass(), settings);
+ synchronized (myCustomSettings) {
+ myCustomSettings.put(settings.getClass(), settings);
+ }
}
}
public <T extends CustomCodeStyleSettings> T getCustomSettings(Class<T> aClass) {
- return (T)myCustomSettings.get(aClass);
+ synchronized (myCustomSettings) {
+ return (T)myCustomSettings.get(aClass);
+ }
}
@Override
@@ -125,7 +128,7 @@ public class CodeStyleSettings extends CommonCodeStyleSettings implements Clonea
private void copyCustomSettingsFrom(@NotNull CodeStyleSettings from) {
myCustomSettings.clear();
- for (final CustomCodeStyleSettings settings : from.myCustomSettings.values()) {
+ for (final CustomCodeStyleSettings settings : from.getCustomSettingsValues()) {
addCustomSettings((CustomCodeStyleSettings) settings.clone());
}
@@ -244,6 +247,7 @@ public class CodeStyleSettings extends CommonCodeStyleSettings implements Clonea
public int INNER_CLASSES_ORDER_WEIGHT = 7;
//----------------- WRAPPING ---------------------------
+ public int RIGHT_MARGIN = 120;
public boolean WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN = false;
@@ -431,6 +435,12 @@ public class CodeStyleSettings extends CommonCodeStyleSettings implements Clonea
private CodeStyleSettings myParentSettings;
private boolean myLoadedAdditionalIndentOptions;
+ private Collection<CustomCodeStyleSettings> getCustomSettingsValues() {
+ synchronized (myCustomSettings) {
+ return Collections.unmodifiableCollection(myCustomSettings.values());
+ }
+ }
+
@Override
public void readExternal(Element element) throws InvalidDataException {
DefaultJDOMExternalizer.readExternal(this, element);
@@ -452,7 +462,7 @@ public class CodeStyleSettings extends CommonCodeStyleSettings implements Clonea
}
}
boolean oldOptionsImported = importOldIndentOptions(element);
- for (final CustomCodeStyleSettings settings : myCustomSettings.values()) {
+ for (final CustomCodeStyleSettings settings : getCustomSettingsValues()) {
settings.readExternal(element);
settings.importLegacySettings();
}
@@ -564,7 +574,7 @@ public class CodeStyleSettings extends CommonCodeStyleSettings implements Clonea
public void writeExternal(Element element) throws WriteExternalException {
final CodeStyleSettings parentSettings = new CodeStyleSettings();
DefaultJDOMExternalizer.writeExternal(this, element, new DifferenceFilter<CodeStyleSettings>(this, parentSettings));
- List<CustomCodeStyleSettings> customSettings = new ArrayList<CustomCodeStyleSettings>(myCustomSettings.values());
+ List<CustomCodeStyleSettings> customSettings = new ArrayList<CustomCodeStyleSettings>(getCustomSettingsValues());
Collections.sort(customSettings, new Comparator<CustomCodeStyleSettings>(){
@Override
diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java b/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java
index 20b96cac3920..299d17215fdf 100644
--- a/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java
+++ b/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java
@@ -287,7 +287,6 @@ public class CommonCodeStyleSettings {
//----------------- GENERAL --------------------
public int RIGHT_MARGIN = -1;
- public final static int DEFAULT_RIGHT_MARGIN = 120;
public boolean LINE_COMMENT_AT_FIRST_COLUMN = true;
public boolean BLOCK_COMMENT_AT_FIRST_COLUMN = true;
diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/OptionTableWithPreviewPanel.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/OptionTableWithPreviewPanel.java
index f978d5f6dcdb..59736bc0e4b2 100644
--- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/OptionTableWithPreviewPanel.java
+++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/OptionTableWithPreviewPanel.java
@@ -18,6 +18,7 @@ package com.intellij.application.options.codeStyle;
import com.intellij.lang.Language;
import com.intellij.openapi.application.ApplicationBundle;
import com.intellij.psi.codeStyle.CodeStyleSettings;
+import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import com.intellij.psi.codeStyle.CustomCodeStyleSettings;
import com.intellij.ui.SpeedSearchComparator;
import com.intellij.ui.TreeTableSpeedSearch;
@@ -378,7 +379,7 @@ public abstract class OptionTableWithPreviewPanel extends MultilanguageCodeStyle
this.groupName = groupName;
try {
- Class styleSettingsClass = clazz == null ? CodeStyleSettings.class : clazz;
+ Class styleSettingsClass = clazz == null ? CommonCodeStyleSettings.class : clazz;
this.field = styleSettingsClass.getField(fieldName);
}
catch (NoSuchFieldException e) {
diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/RightMarginForm.form b/platform/lang-impl/src/com/intellij/application/options/codeStyle/RightMarginForm.form
new file mode 100644
index 000000000000..67f579a77ff5
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/RightMarginForm.form
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.application.options.codeStyle.RightMarginForm">
+ <grid id="27dc6" binding="myTopPanel" layout-manager="GridLayoutManager" row-count="2" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <xy x="20" y="20" width="500" height="400"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="12cf8" class="com.intellij.ui.components.JBLabel">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <text resource-bundle="messages/ApplicationBundle" key="editbox.right.margin.columns"/>
+ </properties>
+ </component>
+ <vspacer id="1265c">
+ <constraints>
+ <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
+ </constraints>
+ </vspacer>
+ <component id="78fe" class="javax.swing.JTextField" binding="myRightMarginField">
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
+ <preferred-size width="50" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <horizontalAlignment value="2"/>
+ </properties>
+ </component>
+ <component id="5ef52" class="javax.swing.JCheckBox" binding="myDefaultGeneralCheckBox" default-binding="true">
+ <constraints>
+ <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <text resource-bundle="messages/ApplicationBundle" key="settings.code.style.default.general"/>
+ </properties>
+ </component>
+ </children>
+ </grid>
+</form>
diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/RightMarginForm.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/RightMarginForm.java
new file mode 100644
index 000000000000..70c747dc11ca
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/RightMarginForm.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.application.options.codeStyle;
+
+import com.intellij.lang.Language;
+import com.intellij.psi.codeStyle.CodeStyleSettings;
+import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+
+/**
+ * Can be used for languages which do not use standard "Wrapping and Braces" panel.
+ * <p>
+ * <strong>Note</strong>: besides adding the panel to UI it is necessary to make sure that language's own
+ * <code>LanguageCodeStyleSettingsProvider</code> explicitly supports RIGHT_MARGIN field in <code>customizeSettings()</code>
+ * method as shown below:
+ * <pre>
+ * public void customizeSettings(...) {
+ * if (settingsType == SettingsType.WRAPPING_AND_BRACES_SETTINGS) {
+ * consumer.showStandardOptions("RIGHT_MARGIN");
+ * }
+ * }
+ * </pre>
+ * @author Rustam Vishnyakov
+ */
+public class RightMarginForm {
+ private JTextField myRightMarginField;
+ private JCheckBox myDefaultGeneralCheckBox;
+ private JPanel myTopPanel;
+ private final Language myLanguage;
+ private final int myDefaultRightMargin;
+
+ public RightMarginForm(@NotNull Language language, @NotNull CodeStyleSettings settings) {
+ myLanguage = language;
+ myDefaultRightMargin = settings.RIGHT_MARGIN;
+ myDefaultGeneralCheckBox.addChangeListener(new ChangeListener() {
+ @Override
+ public void stateChanged(ChangeEvent e) {
+ if (myDefaultGeneralCheckBox.isSelected()) {
+ myRightMarginField.setText(Integer.toString(myDefaultRightMargin));
+ myRightMarginField.setEnabled(false);
+ }
+ else {
+ myRightMarginField.setEnabled(true);
+ }
+ }
+ });
+ }
+
+ public void reset(@NotNull CodeStyleSettings settings) {
+ CommonCodeStyleSettings langSettings = settings.getCommonSettings(myLanguage);
+ if (langSettings != settings && langSettings.RIGHT_MARGIN >= 0) {
+ myDefaultGeneralCheckBox.setSelected(false);
+ myRightMarginField.setText(Integer.toString(langSettings.RIGHT_MARGIN));
+ }
+ else {
+ myDefaultGeneralCheckBox.setSelected(true);
+ myRightMarginField.setText(Integer.toString(settings.RIGHT_MARGIN));
+ if (langSettings == settings) {
+ myDefaultGeneralCheckBox.setEnabled(false);
+ myRightMarginField.setEnabled(false);
+ }
+ }
+ }
+
+ public void apply(@NotNull CodeStyleSettings settings) {
+ CommonCodeStyleSettings langSettings = settings.getCommonSettings(myLanguage);
+ if (langSettings != settings) {
+ if (myDefaultGeneralCheckBox.isSelected()) {
+ langSettings.RIGHT_MARGIN = -1;
+ }
+ else {
+ langSettings.RIGHT_MARGIN = getFieldRightMargin(settings.RIGHT_MARGIN);
+ }
+ }
+ }
+
+ public boolean isModified(@NotNull CodeStyleSettings settings) {
+ CommonCodeStyleSettings langSettings = settings.getCommonSettings(myLanguage);
+ if (myDefaultGeneralCheckBox.isSelected()) {
+ return langSettings.RIGHT_MARGIN >= 0;
+ }
+ else {
+ return langSettings.RIGHT_MARGIN != getFieldRightMargin(settings.RIGHT_MARGIN);
+ }
+ }
+
+ private int getFieldRightMargin(int fallBackValue) {
+ String strValue = myRightMarginField.getText();
+ if (!strValue.trim().isEmpty()) {
+ try {
+ return Integer.parseInt(strValue);
+ }
+ catch (NumberFormatException e) {
+ myRightMarginField.setText(Integer.toString(fallBackValue));
+ }
+ }
+ return fallBackValue;
+ }
+
+ public JPanel getTopPanel() {
+ return myTopPanel;
+ }
+}
diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRulesControl.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRulesControl.java
index fa14958132d0..145ae1094e0b 100644
--- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRulesControl.java
+++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRulesControl.java
@@ -165,7 +165,7 @@ public class ArrangementMatchingRulesControl extends JBTable {
}
final List<ArrangementSectionRule> result = ContainerUtil.newArrayList();
- final List<StdArrangementMatchRule> currentRules = ContainerUtil.newArrayList();
+ final List<StdArrangementMatchRule> buffer = ContainerUtil.newArrayList();
String currentSectionStart = null;
for (int i = 0; i < getModel().getSize(); i++) {
Object element = getModel().getElementAt(i);
@@ -174,15 +174,12 @@ public class ArrangementMatchingRulesControl extends JBTable {
mySectionRuleManager == null ? null : mySectionRuleManager.getSectionRuleData((StdArrangementMatchRule)element);
if (sectionRule != null) {
if (sectionRule.isSectionStart()) {
- if (currentSectionStart != null) {
- result.add(ArrangementSectionRule.create(currentSectionStart, null, currentRules));
- currentRules.clear();
- }
+ appendBufferedSectionRules(result, buffer, currentSectionStart);
currentSectionStart = sectionRule.getText();
}
else {
- result.add(ArrangementSectionRule.create(StringUtil.notNullize(currentSectionStart), sectionRule.getText(), currentRules));
- currentRules.clear();
+ result.add(ArrangementSectionRule.create(StringUtil.notNullize(currentSectionStart), sectionRule.getText(), buffer));
+ buffer.clear();
currentSectionStart = null;
}
}
@@ -190,17 +187,34 @@ public class ArrangementMatchingRulesControl extends JBTable {
result.add(ArrangementSectionRule.create((StdArrangementMatchRule)element));
}
else {
- currentRules.add((StdArrangementMatchRule)element);
+ buffer.add((StdArrangementMatchRule)element);
}
}
}
- if (currentSectionStart != null) {
- result.add(ArrangementSectionRule.create(currentSectionStart, null, currentRules));
- }
+ appendBufferedSectionRules(result, buffer, currentSectionStart);
return result;
}
+ private static void appendBufferedSectionRules(@NotNull List<ArrangementSectionRule> result,
+ @NotNull List<StdArrangementMatchRule> buffer,
+ @Nullable String currentSectionStart) {
+ if (currentSectionStart == null) {
+ return;
+ }
+
+ if (buffer.isEmpty()) {
+ result.add(ArrangementSectionRule.create(currentSectionStart, null));
+ }
+ else {
+ result.add(ArrangementSectionRule.create(currentSectionStart, null, buffer.get(0)));
+ for (int j = 1; j < buffer.size(); j++) {
+ result.add(ArrangementSectionRule.create(buffer.get(j)));
+ }
+ buffer.clear();
+ }
+ }
+
@Override
protected void processMouseEvent(MouseEvent e) {
int id = e.getID();
diff --git a/platform/lang-impl/src/com/intellij/application/options/editor/EditorTabsConfigurable.form b/platform/lang-impl/src/com/intellij/application/options/editor/EditorTabsConfigurable.form
index 9872c7c624aa..db23ce17b2c3 100644
--- a/platform/lang-impl/src/com/intellij/application/options/editor/EditorTabsConfigurable.form
+++ b/platform/lang-impl/src/com/intellij/application/options/editor/EditorTabsConfigurable.form
@@ -3,7 +3,7 @@
<grid id="27dc6" binding="myRootPanel" layout-manager="GridLayoutManager" row-count="3" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
- <xy x="20" y="20" width="500" height="527"/>
+ <xy x="20" y="20" width="500" height="585"/>
</constraints>
<properties/>
<border type="none"/>
@@ -108,7 +108,7 @@
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
- <grid id="eb8d0" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="10">
+ <grid id="eb8d0" layout-manager="GridLayoutManager" row-count="4" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="10">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
@@ -119,7 +119,7 @@
</clientProperties>
<border type="none" title-resource-bundle="messages/ApplicationBundle" title-key="group.tab.closing.policy"/>
<children>
- <grid id="5a5a7" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <grid id="5a5a7" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
@@ -129,7 +129,9 @@
<children>
<component id="527a6" class="javax.swing.JLabel">
<constraints>
- <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
+ <preferred-size width="60" height="27"/>
+ </grid>
</constraints>
<properties>
<text resource-bundle="messages/ApplicationBundle" key="editbox.tab.limit"/>
@@ -138,19 +140,38 @@
<component id="16477" class="javax.swing.JTextField" binding="myEditorTabLimitField">
<constraints>
<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">
- <preferred-size width="30" height="-1"/>
+ <preferred-size width="30" height="27"/>
</grid>
</constraints>
<properties>
<text value="15"/>
</properties>
</component>
+ <component id="2479d" class="javax.swing.JLabel">
+ <constraints>
+ <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="4" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <text resource-bundle="messages/ApplicationBundle" key="editbox.tab.title.limit"/>
+ </properties>
+ </component>
+ <component id="3499c" class="javax.swing.JTextField" binding="myTabTitleLimitField">
+ <constraints>
+ <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">
+ <preferred-size width="30" height="27"/>
+ </grid>
+ </constraints>
+ <properties>
+ <columns value="2"/>
+ <text value="30"/>
+ </properties>
+ </component>
</children>
</grid>
<grid id="9b723" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="2">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
- <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
@@ -184,7 +205,7 @@
<grid id="611cc" layout-manager="GridLayoutManager" row-count="4" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="2">
<margin top="10" left="0" bottom="0" right="0"/>
<constraints>
- <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ <grid row="3" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
diff --git a/platform/lang-impl/src/com/intellij/application/options/editor/EditorTabsConfigurable.java b/platform/lang-impl/src/com/intellij/application/options/editor/EditorTabsConfigurable.java
index 4e1de817255a..35a34085d035 100644
--- a/platform/lang-impl/src/com/intellij/application/options/editor/EditorTabsConfigurable.java
+++ b/platform/lang-impl/src/com/intellij/application/options/editor/EditorTabsConfigurable.java
@@ -45,6 +45,7 @@ public class EditorTabsConfigurable implements EditorOptionsProvider {
private JCheckBox myShowCloseButtonOnCheckBox;
private JCheckBox myShowDirectoryInTabCheckBox;
private JRadioButton myActivateRightNeighbouringTabRadioButton;
+ private JTextField myTabTitleLimitField;
public EditorTabsConfigurable() {
myEditorTabPlacement.setModel(new DefaultComboBoxModel(new Object[]{
@@ -119,6 +120,7 @@ public class EditorTabsConfigurable implements EditorOptionsProvider {
myHideKnownExtensions.setSelected(uiSettings.HIDE_KNOWN_EXTENSION_IN_TABS);
myShowDirectoryInTabCheckBox.setSelected(uiSettings.SHOW_DIRECTORY_FOR_NON_UNIQUE_FILENAMES);
myEditorTabLimitField.setText(Integer.toString(uiSettings.EDITOR_TAB_LIMIT));
+ myTabTitleLimitField.setText(Integer.toString(uiSettings.EDITOR_TAB_TITLE_LIMIT));
myShowCloseButtonOnCheckBox.setSelected(uiSettings.SHOW_CLOSE_BUTTON);
if (uiSettings.CLOSE_NON_MODIFIED_FILES_FIRST) {
@@ -171,14 +173,29 @@ public class EditorTabsConfigurable implements EditorOptionsProvider {
uiSettings.ACTIVATE_RIGHT_EDITOR_ON_CLOSE = myActivateRightNeighbouringTabRadioButton.isSelected();
String temp = myEditorTabLimitField.getText();
- if(temp.trim().length() > 0){
+ if (temp.trim().length() > 0) {
try {
int newEditorTabLimit = Integer.parseInt(temp);
- if(newEditorTabLimit>0&&newEditorTabLimit!=uiSettings.EDITOR_TAB_LIMIT){
- uiSettings.EDITOR_TAB_LIMIT=newEditorTabLimit;
+ if (newEditorTabLimit > 0 && newEditorTabLimit != uiSettings.EDITOR_TAB_LIMIT) {
+ uiSettings.EDITOR_TAB_LIMIT = newEditorTabLimit;
uiSettingsChanged = true;
}
- }catch (NumberFormatException ignored){}
+ }
+ catch (NumberFormatException ignored) {
+ }
+ }
+ temp = myTabTitleLimitField.getText();
+ if (temp.trim().length() > 0) {
+ try {
+ int newTabTitleLimit = Integer.parseInt(temp);
+ newTabTitleLimit = Math.max(25, Math.min(100, newTabTitleLimit));
+ if (newTabTitleLimit != uiSettings.EDITOR_TAB_TITLE_LIMIT){
+ uiSettings.EDITOR_TAB_TITLE_LIMIT = newTabTitleLimit;
+ uiSettingsChanged = true;
+ }
+ }
+ catch (NumberFormatException ignored) {
+ }
}
if(uiSettingsChanged){
uiSettings.fireUISettingsChanged();
@@ -191,6 +208,7 @@ public class EditorTabsConfigurable implements EditorOptionsProvider {
boolean isModified = isModified(myCbModifiedTabsMarkedWithAsterisk, uiSettings.MARK_MODIFIED_TABS_WITH_ASTERISK);
isModified |= isModified(myShowTabsTooltipsCheckBox, uiSettings.SHOW_TABS_TOOLTIPS);
isModified |= isModified(myEditorTabLimitField, uiSettings.EDITOR_TAB_LIMIT);
+ isModified |= isModified(myTabTitleLimitField, uiSettings.EDITOR_TAB_TITLE_LIMIT);
int tabPlacement = ((Integer)myEditorTabPlacement.getSelectedItem()).intValue();
isModified |= tabPlacement != uiSettings.EDITOR_TAB_PLACEMENT;
isModified |= myHideKnownExtensions.isSelected() != uiSettings.HIDE_KNOWN_EXTENSION_IN_TABS;
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java
index bf77a3022a0e..af6bbdc931ca 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java
@@ -289,7 +289,16 @@ public class FormatChangedTextUtil {
}
try {
- List<Range> changedRanges = new RangesBuilder(document, documentFromVcs).getRanges();
+ List<Range> changedRanges;
+
+ LineStatusTracker tracker = LineStatusTrackerManager.getInstance(project).getLineStatusTracker(document);
+ if (tracker != null) {
+ changedRanges = tracker.getRanges();
+ }
+ else {
+ changedRanges = new RangesBuilder(document, documentFromVcs).getRanges();
+ }
+
return getChangedTextRanges(document, changedRanges);
}
catch (FilesTooBigForDiffException e) {
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java
index 4966a9466a26..8ec833e8258b 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java
@@ -79,9 +79,6 @@ public class ReformatCodeAction extends AnAction implements DumbAware {
PsiDocumentManager.getInstance(project).commitAllDocuments();
final Editor editor = CommonDataKeys.EDITOR.getData(dataContext);
final VirtualFile[] files = CommonDataKeys.VIRTUAL_FILE_ARRAY.getData(dataContext);
- if (files == null) {
- return;
- }
PsiFile file = null;
final PsiDirectory dir;
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java
index e0a3be5f423d..fcb080dcd277 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java
@@ -71,6 +71,8 @@ import java.util.concurrent.atomic.AtomicReference;
public class CodeCompletionHandlerBase {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.completion.CodeCompletionHandlerBase");
+ private static final Key<Boolean> CARET_PROCESSED = Key.create("CodeCompletionHandlerBase.caretProcessed");
+
@NotNull private final CompletionType myCompletionType;
final boolean invokedExplicitly;
final boolean synchronous;
@@ -108,6 +110,13 @@ public class CodeCompletionHandlerBase {
}
public final void invokeCompletion(@NotNull final Project project, @NotNull final Editor editor, int time, boolean hasModifiers, boolean restarted) {
+ clearCaretMarkers(editor);
+ invokeCompletion(project, editor, time, hasModifiers, restarted, editor.getCaretModel().getPrimaryCaret());
+ }
+
+ public final void invokeCompletion(@NotNull final Project project, @NotNull final Editor editor, int time, boolean hasModifiers, boolean restarted, @NotNull final Caret caret) {
+ markCaretAsProcessed(caret);
+
if (invokedExplicitly) {
CompletionLookupArranger.applyLastCompletionStatisticsUpdate();
}
@@ -162,12 +171,12 @@ public class CodeCompletionHandlerBase {
PsiDocumentManager.getInstance(project).commitAllDocuments();
CompletionAssertions.checkEditorValid(editor);
- final PsiFile psiFile = PsiUtilBase.getPsiFileInEditor(editor, project);
+ final PsiFile psiFile = PsiUtilBase.getPsiFileInEditor(caret, project);
assert psiFile != null : "no PSI file: " + FileDocumentManager.getInstance().getFile(editor.getDocument());
psiFile.putUserData(PsiFileEx.BATCH_REFERENCE_PROCESSING, Boolean.TRUE);
CompletionAssertions.assertCommitSuccessful(editor, psiFile);
- initializationContext[0] = runContributorsBeforeCompletion(editor, psiFile, invocationCount);
+ initializationContext[0] = runContributorsBeforeCompletion(editor, psiFile, invocationCount, caret);
}
};
ApplicationManager.getApplication().runWriteAction(runnable);
@@ -186,9 +195,9 @@ public class CodeCompletionHandlerBase {
insertDummyIdentifier(initializationContext[0], hasModifiers, invocationCount);
}
- private CompletionInitializationContext runContributorsBeforeCompletion(Editor editor, PsiFile psiFile, int invocationCount) {
+ private CompletionInitializationContext runContributorsBeforeCompletion(Editor editor, PsiFile psiFile, int invocationCount, Caret caret) {
final Ref<CompletionContributor> current = Ref.create(null);
- CompletionInitializationContext context = new CompletionInitializationContext(editor, psiFile, myCompletionType, invocationCount) {
+ CompletionInitializationContext context = new CompletionInitializationContext(editor, caret, psiFile, myCompletionType, invocationCount) {
CompletionContributor dummyIdentifierChanger;
@Override
@@ -400,8 +409,15 @@ public class CodeCompletionHandlerBase {
final LookupElement[] items, boolean hasModifiers) {
if (items.length == 0) {
LookupManager.getInstance(indicator.getProject()).hideActiveLookup();
- indicator.handleEmptyLookup(true);
- checkNotSync(indicator, items);
+
+ Caret nextCaret = getNextCaretToProcess(indicator.getEditor());
+ if (nextCaret != null) {
+ invokeCompletion(indicator.getProject(), indicator.getEditor(), indicator.getParameters().getInvocationCount(), hasModifiers, false, nextCaret);
+ }
+ else {
+ indicator.handleEmptyLookup(true);
+ checkNotSync(indicator, items);
+ }
return;
}
@@ -866,4 +882,23 @@ public class CodeCompletionHandlerBase {
}
};
}
+
+ private static void clearCaretMarkers(@NotNull Editor editor) {
+ for (Caret caret : editor.getCaretModel().getAllCarets()) {
+ caret.putUserData(CARET_PROCESSED, null);
+ }
+ }
+
+ private static void markCaretAsProcessed(@NotNull Caret caret) {
+ caret.putUserData(CARET_PROCESSED, Boolean.TRUE);
+ }
+
+ private static Caret getNextCaretToProcess(@NotNull Editor editor) {
+ for (Caret caret : editor.getCaretModel().getAllCarets()) {
+ if (caret.getUserData(CARET_PROCESSED) == null) {
+ return caret;
+ }
+ }
+ return null;
+ }
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/InjectedGeneralHighlightingPass.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/InjectedGeneralHighlightingPass.java
index 8560129194f1..0321191294c5 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/InjectedGeneralHighlightingPass.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/InjectedGeneralHighlightingPass.java
@@ -73,7 +73,7 @@ public class InjectedGeneralHighlightingPass extends GeneralHighlightingPass imp
@Override
protected void collectInformationWithProgress(@NotNull final ProgressIndicator progress) {
- if (!Registry.is("editor.injected.highlighting.enabled", true)) return;
+ if (!Registry.is("editor.injected.highlighting.enabled")) return;
final Set<HighlightInfo> gotHighlights = new THashSet<HighlightInfo>(100);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/WolfHighlightingPass.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/WolfHighlightingPass.java
index 9211bead784b..6ff242108eed 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/WolfHighlightingPass.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/WolfHighlightingPass.java
@@ -38,7 +38,7 @@ class WolfHighlightingPass extends ProgressableTextEditorHighlightingPass implem
@Override
protected void collectInformationWithProgress(@NotNull final ProgressIndicator progress) {
- if (!Registry.is("wolf.the.problem.solver", true)) return;
+ if (!Registry.is("wolf.the.problem.solver")) return;
final WolfTheProblemSolver solver = WolfTheProblemSolver.getInstance(myProject);
if (solver instanceof WolfTheProblemSolverImpl) {
((WolfTheProblemSolverImpl)solver).startCheckingIfVincentSolvedProblemsYet(progress, this);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java
index c27ce400049e..05a1e01c6aa1 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java
@@ -261,10 +261,20 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
}
public void showJavaDocInfo(final Editor editor, @Nullable final PsiFile file, boolean requestFocus) {
- showJavaDocInfo(editor, file, requestFocus, true);
+ showJavaDocInfo(editor, file, requestFocus, null);
}
- private void showJavaDocInfo(final Editor editor, @Nullable final PsiFile file, boolean requestFocus, final boolean autoupdate) {
+ public void showJavaDocInfo(final Editor editor,
+ @Nullable final PsiFile file,
+ boolean requestFocus,
+ final Runnable closeCallback) {
+ showJavaDocInfo(editor, file, requestFocus, true, closeCallback);
+ }
+
+ private void showJavaDocInfo(final Editor editor,
+ @Nullable final PsiFile file,
+ boolean requestFocus,
+ final boolean autoupdate, @Nullable final Runnable closeCallback) {
myEditor = editor;
final Project project = getProject(file);
PsiDocumentManager.getInstance(project).commitAllDocuments();
@@ -314,7 +324,7 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
return;
}
if (lookupIteObject instanceof PsiElement) {
- doShowJavaDocInfo((PsiElement)lookupIteObject, false, this, originalElement, autoupdate);
+ doShowJavaDocInfo((PsiElement)lookupIteObject, false, this, originalElement, autoupdate, closeCallback);
return;
}
@@ -337,12 +347,12 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
}
}
else {
- doShowJavaDocInfo(element, false, this, originalElement, autoupdate);
+ doShowJavaDocInfo(element, false, this, originalElement, autoupdate, closeCallback);
}
}
};
- doShowJavaDocInfo(element, requestFocus, updateProcessor, originalElement, autoupdate);
+ doShowJavaDocInfo(element, requestFocus, updateProcessor, originalElement, autoupdate, closeCallback);
}
public PsiElement findTargetElement(Editor editor, PsiFile file) {
@@ -969,7 +979,7 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
@Override
protected void doUpdateComponent(Editor editor, PsiFile psiFile) {
- showJavaDocInfo(editor, psiFile, false, true);
+ showJavaDocInfo(editor, psiFile, false, true, null);
}
@Override
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CopyHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CopyHandler.java
index 2a46c08fc2dd..b738bafb038a 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CopyHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CopyHandler.java
@@ -19,12 +19,12 @@ package com.intellij.codeInsight.editorActions;
import com.intellij.ide.DataManager;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
import com.intellij.openapi.editor.actions.CopyAction;
import com.intellij.openapi.editor.actions.EditorActionUtil;
import com.intellij.openapi.editor.ex.EditorEx;
+import com.intellij.openapi.editor.impl.EditorCopyPasteHelperImpl;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.ide.CopyPasteManager;
import com.intellij.openapi.project.Project;
@@ -92,7 +92,7 @@ public class CopyHandler extends EditorActionHandler {
}
String text = editor.getCaretModel().supportsMultipleCarets()
- ? CopyPasteSupport.getSelectedTextForClipboard(editor, transferableDatas)
+ ? EditorCopyPasteHelperImpl.getSelectedTextForClipboard(editor, transferableDatas)
: selectionModel.getSelectedText();
String rawText = TextBlockTransferable.convertLineSeparators(text, "\n", transferableDatas);
String escapedText = null;
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/IndentingBackspaceHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/IndentingBackspaceHandler.java
index 345cb80bae69..17916e008501 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/IndentingBackspaceHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/IndentingBackspaceHandler.java
@@ -17,15 +17,22 @@ package com.intellij.codeInsight.editorActions;
import com.intellij.codeInsight.CodeInsightSettings;
import com.intellij.codeStyle.CodeStyleFacade;
+import com.intellij.formatting.*;
+import com.intellij.lang.LanguageFormatting;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.CaretModel;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.LogicalPosition;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
+import com.intellij.psi.codeStyle.CodeStyleSettings;
+import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.codeStyle.LanguageCodeStyleSettingsProvider;
import com.intellij.util.text.CharArrayUtil;
import org.jetbrains.annotations.NotNull;
@@ -36,40 +43,75 @@ import org.jetbrains.annotations.NotNull;
public class IndentingBackspaceHandler extends BackspaceHandlerDelegate {
private static final Logger LOG = Logger.getInstance(IndentingBackspaceHandler.class);
+ private boolean isApplicable;
private boolean caretWasAtLineStart;
+ private String precalculatedSpacing;
@Override
public void beforeCharDeleted(char c, PsiFile file, Editor editor) {
- caretWasAtLineStart = editor.getCaretModel().getLogicalPosition().column == 0;
- }
-
- @Override
- public boolean charDeleted(char c, PsiFile file, Editor editor) {
if (CodeInsightSettings.getInstance().SMART_BACKSPACE != CodeInsightSettings.AUTOINDENT || !StringUtil.isWhiteSpace(c)) {
- return false;
+ isApplicable = false;
+ return;
}
LanguageCodeStyleSettingsProvider codeStyleSettingsProvider = LanguageCodeStyleSettingsProvider.forLanguage(file.getLanguage());
if (codeStyleSettingsProvider != null && codeStyleSettingsProvider.isIndentBasedLanguageSemantics()) {
+ isApplicable = false;
+ return;
+ }
+ Document document = editor.getDocument();
+ CharSequence charSequence = document.getCharsSequence();
+ CaretModel caretModel = editor.getCaretModel();
+ int caretOffset = caretModel.getOffset();
+ LogicalPosition pos = caretModel.getLogicalPosition();
+ isApplicable = true;
+ caretWasAtLineStart = pos.column == 0;
+ precalculatedSpacing = null;
+ if (caretWasAtLineStart && pos.line > 0 && caretOffset < charSequence.length() && !StringUtil.isWhiteSpace(charSequence.charAt(caretOffset))) {
+ int prevLineEnd = document.getLineEndOffset(pos.line - 1);
+ if (prevLineEnd > 0 && !StringUtil.isWhiteSpace(charSequence.charAt(prevLineEnd - 1))) {
+ PsiDocumentManager.getInstance(file.getProject()).commitDocument(document);
+ precalculatedSpacing = getSpacing(file, caretOffset);
+ }
+ }
+ }
+
+ @Override
+ public boolean charDeleted(char c, PsiFile file, Editor editor) {
+ if (!isApplicable) {
return false;
}
+ Project project = file.getProject();
Document document = editor.getDocument();
+ CaretModel caretModel = editor.getCaretModel();
- int caretOffset = editor.getCaretModel().getOffset();
+ int caretOffset = caretModel.getOffset();
int offset = CharArrayUtil.shiftForward(document.getCharsSequence(), caretOffset, " \t");
int beforeWhitespaceOffset = CharArrayUtil.shiftBackward(document.getCharsSequence(), offset - 1, " \t") + 1;
- LogicalPosition logicalPosition = caretOffset < offset ? editor.offsetToLogicalPosition(offset) : editor.getCaretModel().getLogicalPosition();
+ LogicalPosition logicalPosition = caretOffset < offset ? editor.offsetToLogicalPosition(offset) : caretModel.getLogicalPosition();
int lineStartOffset = document.getLineStartOffset(logicalPosition.line);
if (lineStartOffset < beforeWhitespaceOffset) {
- if (caretWasAtLineStart && beforeWhitespaceOffset < offset) {
- document.deleteString(beforeWhitespaceOffset, offset);
- return true;
+ if (caretWasAtLineStart && beforeWhitespaceOffset <= offset) {
+ String spacing;
+ if (precalculatedSpacing == null) {
+ PsiDocumentManager.getInstance(project).commitDocument(document);
+ spacing = getSpacing(file, offset);
+ }
+ else {
+ spacing = precalculatedSpacing;
+ }
+ if (beforeWhitespaceOffset < offset || !spacing.isEmpty()) {
+ document.replaceString(beforeWhitespaceOffset, offset, spacing);
+ caretModel.moveToOffset(beforeWhitespaceOffset + spacing.length());
+ return true;
+ }
}
return false;
}
- CodeStyleFacade codeStyleFacade = CodeStyleFacade.getInstance(editor.getProject());
- String indent = codeStyleFacade.getLineIndent(document, lineStartOffset);
+ PsiDocumentManager.getInstance(project).commitDocument(document);
+ CodeStyleFacade codeStyleFacade = CodeStyleFacade.getInstance(project);
+ String indent = codeStyleFacade.getLineIndent(document, offset);
if (indent == null) {
return false;
}
@@ -79,7 +121,7 @@ public class IndentingBackspaceHandler extends BackspaceHandlerDelegate {
if (logicalPosition.column == targetColumn) {
if (caretOffset < offset) {
- editor.getCaretModel().moveToLogicalPosition(logicalPosition);
+ caretModel.moveToLogicalPosition(logicalPosition);
return true;
}
return false;
@@ -87,7 +129,7 @@ public class IndentingBackspaceHandler extends BackspaceHandlerDelegate {
if (caretWasAtLineStart || logicalPosition.column > targetColumn) {
document.replaceString(lineStartOffset, offset, indent);
- editor.getCaretModel().moveToLogicalPosition(new LogicalPosition(logicalPosition.line, targetColumn));
+ caretModel.moveToLogicalPosition(new LogicalPosition(logicalPosition.line, targetColumn));
return true;
}
@@ -100,12 +142,13 @@ public class IndentingBackspaceHandler extends BackspaceHandlerDelegate {
int targetOffset = CharArrayUtil.shiftBackward(document.getCharsSequence(), prevLineEndOffset - 1, " \t") + 1;
if (prevLineStartOffset < targetOffset) {
- document.deleteString(targetOffset, offset);
- editor.getCaretModel().moveToOffset(targetOffset);
+ String spacing = getSpacing(file, offset);
+ document.replaceString(targetOffset, offset, spacing);
+ caretModel.moveToOffset(targetOffset + spacing.length());
}
else {
document.replaceString(prevLineStartOffset, offset, indent);
- editor.getCaretModel().moveToLogicalPosition(new LogicalPosition(logicalPosition.line - 1, targetColumn));
+ caretModel.moveToLogicalPosition(new LogicalPosition(logicalPosition.line - 1, targetColumn));
}
return true;
}
@@ -132,4 +175,15 @@ public class IndentingBackspaceHandler extends BackspaceHandlerDelegate {
}
return width;
}
+
+ private static String getSpacing(PsiFile file, int offset) {
+ FormattingModelBuilder builder = LanguageFormatting.INSTANCE.forContext(file);
+ if (builder == null) {
+ return "";
+ }
+ CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(file.getProject());
+ FormattingModel model = builder.createModel(file, settings);
+ int spacing = FormatterEx.getInstance().getSpacingForBlockAtOffset(model, offset);
+ return StringUtil.repeatSymbol(' ', spacing);
+ }
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/TypedHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/TypedHandler.java
index bb21eac69ecd..ba4768f73099 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/TypedHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/TypedHandler.java
@@ -148,14 +148,17 @@ public class TypedHandler extends TypedActionHandlerBase {
return;
}
+ final PsiDocumentManager psiDocumentManager = PsiDocumentManager.getInstance(project);
+ final Document originalDocument = originalEditor.getDocument();
originalEditor.getCaretModel().runForEachCaret(new CaretAction() {
@Override
public void perform(Caret caret) {
- PsiDocumentManager.getInstance(project)
- .doPostponedOperationsAndUnblockDocument(originalEditor.getDocument()); // to clean up after previous caret processing
+ if (psiDocumentManager.isDocumentBlockedByPsi(originalDocument)) {
+ psiDocumentManager.doPostponedOperationsAndUnblockDocument(originalDocument); // to clean up after previous caret processing
+ }
Editor editor = injectedEditorIfCharTypedIsSignificant(charTyped, originalEditor, originalFile);
- PsiFile file = editor == originalEditor ? originalFile : PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
+ PsiFile file = editor == originalEditor ? originalFile : psiDocumentManager.getPsiFile(editor.getDocument());
final TypedHandlerDelegate[] delegates = Extensions.getExtensions(TypedHandlerDelegate.EP_NAME);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java
index 3a1f04b80414..9a71909fcca8 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java
@@ -372,31 +372,34 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable,
checkValid();
CollectionListModel<LookupElement> listModel = getListModel();
- synchronized (myList) {
- Pair<List<LookupElement>, Integer> pair = myPresentableArranger.arrangeItems(this, onExplicitAction || reused);
- List<LookupElement> items = pair.first;
- Integer toSelect = pair.second;
- if (toSelect == null || toSelect < 0 || items.size() > 0 && toSelect >= items.size()) {
- LOG.error("Arranger " + myPresentableArranger + " returned invalid selection index=" + toSelect + "; items=" + items);
- }
-
- myOffsets.checkMinPrefixLengthChanges(items, this);
- List<LookupElement> oldModel = listModel.toList();
- listModel.removeAll();
- if (!items.isEmpty()) {
- listModel.add(items);
- }
- else {
- addEmptyItem(listModel);
- }
+ Pair<List<LookupElement>, Integer> pair;
+ synchronized (myList) {
+ pair = myPresentableArranger.arrangeItems(this, onExplicitAction || reused);
+ }
+
+ List<LookupElement> items = pair.first;
+ Integer toSelect = pair.second;
+ if (toSelect == null || toSelect < 0 || items.size() > 0 && toSelect >= items.size()) {
+ LOG.error("Arranger " + myPresentableArranger + " returned invalid selection index=" + toSelect + "; items=" + items);
+ toSelect = 0;
+ }
- updateListHeight(listModel);
+ myOffsets.checkMinPrefixLengthChanges(items, this);
+ List<LookupElement> oldModel = listModel.toList();
- myList.setSelectedIndex(toSelect);
- return !ContainerUtil.equalsIdentity(oldModel, items);
+ listModel.removeAll();
+ if (!items.isEmpty()) {
+ listModel.add(items);
}
+ else {
+ addEmptyItem(listModel);
+ }
+
+ updateListHeight(listModel);
+ myList.setSelectedIndex(toSelect);
+ return !ContainerUtil.equalsIdentity(oldModel, items);
}
private boolean isSelectionVisible() {
@@ -566,7 +569,7 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable,
public void perform(Caret caret) {
EditorModificationUtil.deleteSelectedText(hostEditor);
final int caretOffset = hostEditor.getCaretModel().getOffset();
- int lookupStart = caretOffset - prefix;
+ int lookupStart = Math.max(caretOffset - prefix, 0);
int len = hostEditor.getDocument().getTextLength();
LOG.assertTrue(lookupStart >= 0 && lookupStart <= len,
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/NavigationUtil.java b/platform/lang-impl/src/com/intellij/codeInsight/navigation/NavigationUtil.java
index 3c0e84a11656..3617c944e888 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/NavigationUtil.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/NavigationUtil.java
@@ -19,30 +19,46 @@ package com.intellij.codeInsight.navigation;
import com.intellij.ide.util.DefaultPsiElementCellRenderer;
import com.intellij.ide.util.EditSourceUtil;
import com.intellij.ide.util.PsiElementListCellRenderer;
+import com.intellij.navigation.GotoRelatedItem;
+import com.intellij.navigation.GotoRelatedProvider;
import com.intellij.navigation.NavigationItem;
+import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.markup.HighlighterTargetArea;
import com.intellij.openapi.editor.markup.RangeHighlighter;
import com.intellij.openapi.editor.markup.TextAttributes;
+import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.TextEditor;
import com.intellij.openapi.fileEditor.impl.EditorHistoryManager;
import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.openapi.ui.popup.PopupChooserBuilder;
+import com.intellij.openapi.ui.popup.PopupStep;
+import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
+import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.Navigatable;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.impl.ElementBase;
import com.intellij.psi.search.PsiElementProcessor;
-import com.intellij.ui.JBListWithHintProvider;
+import com.intellij.ui.*;
+import com.intellij.ui.popup.list.ListPopupImpl;
+import com.intellij.ui.popup.list.PopupListElementRenderer;
+import com.intellij.util.Processor;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.util.*;
+import java.util.List;
/**
* @author ven
@@ -220,4 +236,242 @@ public final class NavigationUtil {
}
return attributes;
}
+
+ @NotNull
+ public static JBPopup getRelatedItemsPopup(final List<? extends GotoRelatedItem> items, String title) {
+ Object[] elements = new Object[items.size()];
+ //todo[nik] move presentation logic to GotoRelatedItem class
+ final Map<PsiElement, GotoRelatedItem> itemsMap = new HashMap<PsiElement, GotoRelatedItem>();
+ for (int i = 0; i < items.size(); i++) {
+ GotoRelatedItem item = items.get(i);
+ elements[i] = item.getElement() != null ? item.getElement() : item;
+ itemsMap.put(item.getElement(), item);
+ }
+
+ return getPsiElementPopup(elements, itemsMap, title, new Processor<Object>() {
+ @Override
+ public boolean process(Object element) {
+ if (element instanceof PsiElement) {
+ //noinspection SuspiciousMethodCalls
+ itemsMap.get(element).navigate();
+ }
+ else {
+ ((GotoRelatedItem)element).navigate();
+ }
+ return true;
+ }
+ }
+ );
+ }
+
+ private static JBPopup getPsiElementPopup(final Object[] elements, final Map<PsiElement, GotoRelatedItem> itemsMap,
+ final String title, final Processor<Object> processor) {
+
+ final Ref<Boolean> hasMnemonic = Ref.create(false);
+ final DefaultPsiElementCellRenderer renderer = new DefaultPsiElementCellRenderer() {
+ {
+ setFocusBorderEnabled(false);
+ }
+
+ @Override
+ public String getElementText(PsiElement element) {
+ String customName = itemsMap.get(element).getCustomName();
+ return (customName != null ? customName : super.getElementText(element));
+ }
+
+ @Override
+ protected Icon getIcon(PsiElement element) {
+ Icon customIcon = itemsMap.get(element).getCustomIcon();
+ return customIcon != null ? customIcon : super.getIcon(element);
+ }
+
+ @Override
+ public String getContainerText(PsiElement element, String name) {
+ String customContainerName = itemsMap.get(element).getCustomContainerName();
+
+ if (customContainerName != null) {
+ return customContainerName;
+ }
+ PsiFile file = element.getContainingFile();
+ return file != null && !getElementText(element).equals(file.getName())
+ ? "(" + file.getName() + ")"
+ : null;
+ }
+
+ @Override
+ protected DefaultListCellRenderer getRightCellRenderer(Object value) {
+ return null;
+ }
+
+ @Override
+ protected boolean customizeNonPsiElementLeftRenderer(ColoredListCellRenderer renderer,
+ JList list,
+ Object value,
+ int index,
+ boolean selected,
+ boolean hasFocus) {
+ final GotoRelatedItem item = (GotoRelatedItem)value;
+ Color color = list.getForeground();
+ final SimpleTextAttributes nameAttributes = new SimpleTextAttributes(Font.PLAIN, color);
+ final String name = item.getCustomName();
+ if (name == null) return false;
+ renderer.append(name, nameAttributes);
+ renderer.setIcon(item.getCustomIcon());
+ return true;
+ }
+
+ @Override
+ public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
+ final JPanel component = (JPanel)super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
+ if (!hasMnemonic.get()) return component;
+
+ final JPanel panelWithMnemonic = new JPanel(new BorderLayout());
+ final int mnemonic = getMnemonic(value, itemsMap);
+ final JLabel label = new JLabel("");
+ if (mnemonic != -1) {
+ label.setText(mnemonic + ".");
+ label.setDisplayedMnemonicIndex(0);
+ }
+ label.setPreferredSize(new JLabel("8.").getPreferredSize());
+
+ final JComponent leftRenderer = (JComponent)component.getComponents()[0];
+ component.remove(leftRenderer);
+ panelWithMnemonic.setBorder(BorderFactory.createEmptyBorder(0, 7, 0, 0));
+ panelWithMnemonic.setBackground(leftRenderer.getBackground());
+ label.setBackground(leftRenderer.getBackground());
+ panelWithMnemonic.add(label, BorderLayout.WEST);
+ panelWithMnemonic.add(leftRenderer, BorderLayout.CENTER);
+ component.add(panelWithMnemonic);
+ return component;
+ }
+ };
+ final ListPopupImpl popup = new ListPopupImpl(new BaseListPopupStep<Object>(title, Arrays.asList(elements)) {
+ @Override
+ public boolean isSpeedSearchEnabled() {
+ return true;
+ }
+
+ @Override
+ public String getIndexedString(Object value) {
+ if (value instanceof GotoRelatedItem) {
+ //noinspection ConstantConditions
+ return ((GotoRelatedItem)value).getCustomName();
+ }
+ final PsiElement element = (PsiElement)value;
+ return renderer.getElementText(element) + " " + renderer.getContainerText(element, null);
+ }
+
+ @Override
+ public PopupStep onChosen(Object selectedValue, boolean finalChoice) {
+ processor.process(selectedValue);
+ return super.onChosen(selectedValue, finalChoice);
+ }
+ }) {
+ };
+ popup.getList().setCellRenderer(new PopupListElementRenderer(popup) {
+ Map<Object, String> separators = new HashMap<Object, String>();
+ {
+ final ListModel model = popup.getList().getModel();
+ String current = null;
+ boolean hasTitle = false;
+ for (int i = 0; i < model.getSize(); i++) {
+ final Object element = model.getElementAt(i);
+ final GotoRelatedItem item = itemsMap.get(element);
+ if (item != null && !StringUtil.equals(current, item.getGroup())) {
+ current = item.getGroup();
+ separators.put(element, current);
+ if (!hasTitle && !StringUtil.isEmpty(current)) {
+ hasTitle = true;
+ }
+ }
+ }
+
+ if (!hasTitle) {
+ separators.remove(model.getElementAt(0));
+ }
+ }
+ @Override
+ public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
+ final Component component = renderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
+ final String separator = separators.get(value);
+
+ if (separator != null) {
+ JPanel panel = new JPanel(new BorderLayout());
+ panel.add(component, BorderLayout.CENTER);
+ final SeparatorWithText sep = new SeparatorWithText() {
+ @Override
+ protected void paintComponent(Graphics g) {
+ g.setColor(new JBColor(Color.WHITE, UIUtil.getSeparatorColor()));
+ g.fillRect(0,0,getWidth(), getHeight());
+ super.paintComponent(g);
+ }
+ };
+ sep.setCaption(separator);
+ panel.add(sep, BorderLayout.NORTH);
+ return panel;
+ }
+ return component;
+ }
+ });
+
+ popup.setMinimumSize(new Dimension(200, -1));
+
+ for (Object item : elements) {
+ final int mnemonic = getMnemonic(item, itemsMap);
+ if (mnemonic != -1) {
+ final Action action = createNumberAction(mnemonic, popup, itemsMap, processor);
+ popup.registerAction(mnemonic + "Action", KeyStroke.getKeyStroke(String.valueOf(mnemonic)), action);
+ popup.registerAction(mnemonic + "Action", KeyStroke.getKeyStroke("NUMPAD" + String.valueOf(mnemonic)), action);
+ hasMnemonic.set(true);
+ }
+ }
+ return popup;
+ }
+
+ private static Action createNumberAction(final int mnemonic,
+ final ListPopupImpl listPopup,
+ final Map<PsiElement, GotoRelatedItem> itemsMap,
+ final Processor<Object> processor) {
+ return new AbstractAction() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ for (final Object item : listPopup.getListStep().getValues()) {
+ if (getMnemonic(item, itemsMap) == mnemonic) {
+ listPopup.setFinalRunnable(new Runnable() {
+ @Override
+ public void run() {
+ processor.process(item);
+ }
+ });
+ listPopup.closeOk(null);
+ }
+ }
+ }
+ };
+ }
+
+ private static int getMnemonic(Object item, Map<PsiElement, GotoRelatedItem> itemsMap) {
+ return (item instanceof GotoRelatedItem ? (GotoRelatedItem)item : itemsMap.get((PsiElement)item)).getMnemonic();
+ }
+
+ @NotNull
+ public static List<GotoRelatedItem> collectRelatedItems(@NotNull PsiElement contextElement, @Nullable DataContext dataContext) {
+ Set<GotoRelatedItem> items = ContainerUtil.newLinkedHashSet();
+ for (GotoRelatedProvider provider : Extensions.getExtensions(GotoRelatedProvider.EP_NAME)) {
+ items.addAll(provider.getItems(contextElement));
+ if (dataContext != null) {
+ items.addAll(provider.getItems(dataContext));
+ }
+ }
+ GotoRelatedItem[] result = items.toArray(new GotoRelatedItem[items.size()]);
+ Arrays.sort(result, new Comparator<GotoRelatedItem>() {
+ @Override
+ public int compare(GotoRelatedItem i1, GotoRelatedItem i2) {
+ String o1 = i1.getGroup();
+ String o2 = i2.getGroup();
+ return StringUtil.isEmpty(o1) ? 1 : StringUtil.isEmpty(o2) ? -1 : o1.compareTo(o2);
+ }
+ });
+ return Arrays.asList(result);
+ }
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/problems/MockWolfTheProblemSolver.java b/platform/lang-impl/src/com/intellij/codeInsight/problems/MockWolfTheProblemSolver.java
index eeb5e04b8aab..4ea365f34b0c 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/problems/MockWolfTheProblemSolver.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/problems/MockWolfTheProblemSolver.java
@@ -44,6 +44,11 @@ public class MockWolfTheProblemSolver extends WolfTheProblemSolver {
}
@Override
+ public void weHaveGotNonIgnorableProblems(@NotNull VirtualFile virtualFile, @NotNull List<Problem> problems) {
+ if (myDelegate != null) myDelegate.weHaveGotNonIgnorableProblems(virtualFile, problems);
+ }
+
+ @Override
public boolean hasProblemFilesBeneath(@NotNull final Condition<VirtualFile> condition) {
return false;
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/problems/WolfTheProblemSolverImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/problems/WolfTheProblemSolverImpl.java
index 45b4532713c4..fab185e6ddc0 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/problems/WolfTheProblemSolverImpl.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/problems/WolfTheProblemSolverImpl.java
@@ -413,6 +413,12 @@ public class WolfTheProblemSolverImpl extends WolfTheProblemSolver {
public void weHaveGotProblems(@NotNull final VirtualFile virtualFile, @NotNull List<Problem> problems) {
if (problems.isEmpty()) return;
if (!isToBeHighlighted(virtualFile)) return;
+ weHaveGotNonIgnorableProblems(virtualFile, problems);
+ }
+
+ @Override
+ public void weHaveGotNonIgnorableProblems(@NotNull VirtualFile virtualFile, @NotNull List<Problem> problems) {
+ if (problems.isEmpty()) return;
boolean fireListener = false;
synchronized (myProblems) {
ProblemFileInfo storedProblems = myProblems.get(virtualFile);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java
index 516ed9118c8c..0c838cd05ec5 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java
@@ -212,8 +212,11 @@ public class TemplateState implements Disposable {
if (variableName.equals(TemplateImpl.END)) {
return new TextResult("");
}
- if (myPredefinedVariableValues != null && myPredefinedVariableValues.containsKey(variableName)) {
- return new TextResult(myPredefinedVariableValues.get(variableName));
+ if (myPredefinedVariableValues != null) {
+ String text = myPredefinedVariableValues.get(variableName);
+ if (text != null) {
+ return new TextResult(text);
+ }
}
CharSequence text = myDocument.getCharsSequence();
int segmentNumber = myTemplate.getVariableSegmentNumber(variableName);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/ExpressionPostfixTemplateWithChooser.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/ChooserExpressionSelector.java
index f6b0cedae31e..2989f0d0c97c 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/ExpressionPostfixTemplateWithChooser.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/ChooserExpressionSelector.java
@@ -15,6 +15,7 @@
*/
package com.intellij.codeInsight.template.postfix.templates;
+
import com.intellij.codeInsight.unwrap.ScopeHighlighter;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
@@ -30,45 +31,43 @@ import org.jetbrains.annotations.NotNull;
import java.util.List;
/**
- * @author ignatov
+ * See {@link PostfixTemplateExpressionSelector} for description
*/
-public abstract class ExpressionPostfixTemplateWithChooser extends PostfixTemplate {
+public class ChooserExpressionSelector implements PostfixTemplateExpressionSelector {
@NotNull
- protected final PostfixTemplatePsiInfoBase myInfo;
+ private final Condition<PsiElement> myCondition;
- protected ExpressionPostfixTemplateWithChooser(@NotNull String name, @NotNull String example, @NotNull PostfixTemplatePsiInfoBase info) {
- super(name, example);
- myInfo = info;
+ public ChooserExpressionSelector(@NotNull Condition<PsiElement> condition) {
+ myCondition = condition;
}
- protected ExpressionPostfixTemplateWithChooser(@NotNull String name,
- @NotNull String key,
- @NotNull String example,
- @NotNull PostfixTemplatePsiInfoBase info) {
- super(name, key, example);
- myInfo = info;
- }
- @Override
- public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) {
- return !getExpressions(context, copyDocument, newOffset).isEmpty();
+ public boolean hasExpression(@NotNull final PostfixTemplateWithExpressionSelector postfixTemplate,
+ @NotNull PsiElement context,
+ @NotNull Document copyDocument,
+ int newOffset) {
+ return !getExpressions(postfixTemplate, context, copyDocument, newOffset).isEmpty();
}
- @Override
- public void expand(@NotNull PsiElement context, @NotNull final Editor editor) {
- List<PsiElement> expressions = getExpressions(context, editor.getDocument(), editor.getCaretModel().getOffset());
+ public void expandTemplate(@NotNull final PostfixTemplateWithExpressionSelector postfixTemplate,
+ @NotNull PsiElement context,
+ @NotNull final Editor editor) {
+ List<PsiElement> expressions =
+ getExpressions(postfixTemplate, context, editor.getDocument(), editor.getCaretModel().getOffset());
if (expressions.isEmpty()) {
PostfixTemplatesUtils.showErrorHint(context.getProject(), editor);
}
else if (expressions.size() == 1) {
- doIt(editor, expressions.get(0));
+ postfixTemplate.expandForChooseExpression(expressions.get(0), editor);
}
else {
if (ApplicationManager.getApplication().isUnitTestMode()) {
- doIt(editor, expressions.get(expressions.size() - 1));
+ PsiElement item = ContainerUtil.getLastItem(expressions);
+ assert item != null;
+ postfixTemplate.expandForChooseExpression(item, editor);
return;
}
@@ -81,22 +80,25 @@ public abstract class ExpressionPostfixTemplateWithChooser extends PostfixTempla
public void run() {
CommandProcessor.getInstance().executeCommand(e.getProject(), new Runnable() {
public void run() {
- doIt(editor, e);
+ postfixTemplate.expandForChooseExpression(e, editor);
}
}, "Expand postfix template", PostfixLiveTemplate.POSTFIX_TEMPLATE_ID);
}
});
}
},
- myInfo.getRenderer(),
+ postfixTemplate.getPsiInfo().getRenderer(),
"Expressions", 0, ScopeHighlighter.NATURAL_RANGER
);
}
}
@NotNull
- protected List<PsiElement> getExpressions(@NotNull PsiElement context, @NotNull Document document, final int offset) {
- List<PsiElement> possibleExpressions = myInfo.getExpressions(context, document, offset);
+ private List<PsiElement> getExpressions(@NotNull PostfixTemplateWithExpressionSelector postfixTemplate,
+ @NotNull PsiElement context,
+ @NotNull Document document,
+ final int offset) {
+ List<PsiElement> possibleExpressions = postfixTemplate.getPsiInfo().getExpressions(context, document, offset);
List<PsiElement> expressions = ContainerUtil.filter(possibleExpressions,
new Condition<PsiElement>() {
@Override
@@ -105,19 +107,13 @@ public abstract class ExpressionPostfixTemplateWithChooser extends PostfixTempla
}
}
);
- return ContainerUtil.filter(expressions.isEmpty() ? maybeTopmostExpression(context) : expressions, getTypeCondition());
+ return ContainerUtil
+ .filter(expressions.isEmpty() ? maybeTopmostExpression(postfixTemplate, context) : expressions, myCondition);
}
- @NotNull
- @SuppressWarnings("unchecked")
- protected Condition<PsiElement> getTypeCondition() {
- return Condition.TRUE;
- }
@NotNull
- private List<PsiElement> maybeTopmostExpression(@NotNull PsiElement context) {
- return ContainerUtil.createMaybeSingletonList(myInfo.getTopmostExpression(context));
+ private static List<PsiElement> maybeTopmostExpression(@NotNull PostfixTemplateWithExpressionSelector postfixTemplate, @NotNull PsiElement context) {
+ return ContainerUtil.createMaybeSingletonList(postfixTemplate.getPsiInfo().getTopmostExpression(context));
}
-
- protected abstract void doIt(@NotNull Editor editor, @NotNull PsiElement expression);
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/NotPostfixTemplate.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/NotPostfixTemplate.java
index 9c1d9c66b94d..3944cd930af0 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/NotPostfixTemplate.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/NotPostfixTemplate.java
@@ -16,26 +16,34 @@
package com.intellij.codeInsight.template.postfix.templates;
import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.util.Condition;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
-public class NotPostfixTemplate extends ExpressionPostfixTemplateWithChooser {
+import static com.intellij.codeInsight.template.postfix.templates.PostfixTemplatesUtils.selectorWithChooser;
- public NotPostfixTemplate(@NotNull PostfixTemplatePsiInfoBase info) {
- super("not", "!expr", info);
+public class NotPostfixTemplate extends PostfixTemplateWithExpressionSelector {
+
+ public NotPostfixTemplate(@NotNull PostfixTemplatePsiInfo info, @NotNull Condition<PsiElement> typeChecker) {
+ super("not", "!expr", info, selectorWithChooser(typeChecker));
}
+ public NotPostfixTemplate(@NotNull PostfixTemplatePsiInfo info) {
+ super("not", "!expr", info, selectorWithChooser());
+ }
public NotPostfixTemplate(@NotNull String name,
@NotNull String key,
@NotNull String example,
- @NotNull PostfixTemplatePsiInfoBase info) {
- super(name, key, example, info);
+ @NotNull PostfixTemplatePsiInfo info,
+ @NotNull Condition<PsiElement> typeChecker
+ ) {
+ super(name, key, example, info, selectorWithChooser(typeChecker));
}
@Override
- protected void doIt(@NotNull Editor editor, @NotNull PsiElement expression) {
- PsiElement element = myInfo.getNegatedExpression(expression);
+ protected void expandForChooseExpression(@NotNull PsiElement expression, @NotNull Editor editor) {
+ PsiElement element = myPsiInfo.getNegatedExpression(expression);
expression.replace(element);
}
} \ No newline at end of file
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/ParenthesizedPostfixTemplate.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/ParenthesizedPostfixTemplate.java
index 9a5d03a9359c..3f1dd1143348 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/ParenthesizedPostfixTemplate.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/ParenthesizedPostfixTemplate.java
@@ -16,16 +16,25 @@
package com.intellij.codeInsight.template.postfix.templates;
import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.util.Condition;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
-public class ParenthesizedPostfixTemplate extends ExpressionPostfixTemplateWithChooser {
- public ParenthesizedPostfixTemplate(PostfixTemplatePsiInfoBase psiInfo) {
- super("par", "(expr)", psiInfo);
+import static com.intellij.codeInsight.template.postfix.templates.PostfixTemplatesUtils.selectorWithChooser;
+
+public class ParenthesizedPostfixTemplate extends PostfixTemplateWithExpressionSelector {
+
+ public ParenthesizedPostfixTemplate(PostfixTemplatePsiInfo psiInfo, Condition<PsiElement> condition) {
+ super("par", "(expr)", psiInfo, selectorWithChooser(condition));
+ }
+
+
+ public ParenthesizedPostfixTemplate(PostfixTemplatePsiInfo psiInfo) {
+ super("par", "(expr)", psiInfo, selectorWithChooser());
}
@Override
- protected void doIt(@NotNull Editor editor, @NotNull PsiElement expression) {
- expression.replace(myInfo.createExpression(expression, "(", ")"));
+ protected void expandForChooseExpression(@NotNull PsiElement expression, @NotNull Editor editor) {
+ expression.replace(myPsiInfo.createExpression(expression, "(", ")"));
}
} \ No newline at end of file
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateExpressionSelector.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateExpressionSelector.java
new file mode 100644
index 000000000000..6b5d559da1de
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateExpressionSelector.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.template.postfix.templates;
+
+
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.psi.PsiElement;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Interface provides method used in {@link com.intellij.codeInsight.template.postfix.templates.PostfixTemplateWithExpressionSelector}
+ *
+ * You should implement the interface if you have non-trivial logic how to determine expression for next processing in postfix template
+ * Otherwise, you can use one of existing simple implementations:
+ *
+ * 1) {@link com.intellij.codeInsight.template.postfix.templates.ChooserExpressionSelector} - The selector get all expression
+ * in the current position and show to user chooser for these expressions.
+ *
+ * 2) {@link com.intellij.codeInsight.template.postfix.templates.TopmostExpressionSelector} - The selector pass to postfix template
+ * top most expression in the current position
+ *
+ *
+ */
+public interface PostfixTemplateExpressionSelector {
+
+ /**
+ * Check that we can select not-null expression(PsiElement) in current context
+ */
+ boolean hasExpression(@NotNull final PostfixTemplateWithExpressionSelector postfixTemplate,
+ @NotNull PsiElement context,
+ @NotNull Document copyDocument,
+ int newOffset);
+
+ /**
+ * Select expression(PsiElement) and call postfixTemplate.expandForChooseExpression for selected expression
+ */
+ void expandTemplate(@NotNull final PostfixTemplateWithExpressionSelector postfixTemplate,
+ @NotNull PsiElement context,
+ @NotNull final Editor editor);
+}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatePsiInfo.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatePsiInfo.java
index 8f4716787453..6664d6404d64 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatePsiInfo.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatePsiInfo.java
@@ -16,25 +16,42 @@
package com.intellij.codeInsight.template.postfix.templates;
+import com.intellij.openapi.editor.Document;
import com.intellij.psi.PsiElement;
+import com.intellij.util.Function;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-public interface PostfixTemplatePsiInfo {
+import java.util.List;
+
+public abstract class PostfixTemplatePsiInfo {
@NotNull
- PsiElement createStatement(@NotNull PsiElement context,
- @NotNull String prefix,
- @NotNull String suffix);
+ public abstract PsiElement createStatement(@NotNull PsiElement context,
+ @NotNull String prefix,
+ @NotNull String suffix);
@NotNull
- PsiElement createExpression(@NotNull PsiElement context,
- @NotNull String prefix,
- @NotNull String suffix);
+ public abstract PsiElement createExpression(@NotNull PsiElement context,
+ @NotNull String prefix,
+ @NotNull String suffix);
@Nullable
- PsiElement getTopmostExpression(@NotNull PsiElement element);
+ public abstract PsiElement getTopmostExpression(@NotNull PsiElement element);
+
+ @NotNull
+ public abstract PsiElement getNegatedExpression(@NotNull PsiElement element);
+
+ @NotNull
+ public abstract List<PsiElement> getExpressions(@NotNull PsiElement context, @NotNull Document document, int offset);
@NotNull
- PsiElement getNegatedExpression(@NotNull PsiElement element);
+ public Function<PsiElement, String> getRenderer() {
+ return new Function<PsiElement, String>() {
+ @Override
+ public String fun(@NotNull PsiElement element) {
+ return element.getText();
+ }
+ };
+ }
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateWithExpressionSelector.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateWithExpressionSelector.java
new file mode 100644
index 000000000000..d7cfbafdf7a8
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateWithExpressionSelector.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.template.postfix.templates;
+
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.util.Condition;
+import com.intellij.psi.PsiElement;
+import org.jetbrains.annotations.NotNull;
+
+import static com.intellij.codeInsight.template.postfix.templates.PostfixTemplatesUtils.selectorTopmost;
+
+public abstract class PostfixTemplateWithExpressionSelector extends PostfixTemplate {
+
+ @NotNull
+ protected final PostfixTemplatePsiInfo myPsiInfo;
+ @NotNull
+ private final PostfixTemplateExpressionSelector mySelector;
+
+ protected PostfixTemplateWithExpressionSelector(@NotNull String name,
+ @NotNull String key,
+ @NotNull String example,
+ @NotNull PostfixTemplatePsiInfo psiInfo,
+ @NotNull PostfixTemplateExpressionSelector selector) {
+ super(name, key, example);
+ myPsiInfo = psiInfo;
+ mySelector = selector;
+ }
+
+
+ protected PostfixTemplateWithExpressionSelector(@NotNull String name,
+ @NotNull String example,
+ @NotNull PostfixTemplatePsiInfo psiInfo,
+ @NotNull PostfixTemplateExpressionSelector selector) {
+ super(name, example);
+ myPsiInfo = psiInfo;
+ mySelector = selector;
+ }
+
+ protected PostfixTemplateWithExpressionSelector(@NotNull String name,
+ @NotNull String example,
+ @NotNull PostfixTemplatePsiInfo psiInfo,
+ @NotNull Condition<PsiElement> typeChecker) {
+ this(name, example, psiInfo, selectorTopmost(typeChecker));
+ }
+
+ protected PostfixTemplateWithExpressionSelector(@NotNull String name,
+ @NotNull String example,
+ @NotNull PostfixTemplatePsiInfo psiInfo) {
+ this(name, example, psiInfo, selectorTopmost());
+ }
+
+
+ @Override
+ public final boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) {
+ return mySelector.hasExpression(this, context, copyDocument, newOffset);
+ }
+
+ @Override
+ public final void expand(@NotNull PsiElement context, @NotNull Editor editor) {
+ mySelector.expandTemplate(this, context, editor);
+ }
+
+ protected abstract void expandForChooseExpression(@NotNull PsiElement expression, @NotNull Editor editor);
+
+ @NotNull
+ PostfixTemplatePsiInfo getPsiInfo() {
+ return myPsiInfo;
+ }
+}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatesUtils.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatesUtils.java
index 877e10b53490..5ff744e3d72a 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatesUtils.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatesUtils.java
@@ -21,6 +21,8 @@ import com.intellij.lang.surroundWith.Surrounder;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.Conditions;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.refactoring.util.CommonRefactoringUtil;
@@ -31,6 +33,22 @@ public abstract class PostfixTemplatesUtils {
private PostfixTemplatesUtils() {
}
+ public static PostfixTemplateExpressionSelector selectorWithChooser() {
+ return selectorWithChooser(Conditions.<PsiElement>alwaysTrue());
+ }
+
+ public static PostfixTemplateExpressionSelector selectorTopmost() {
+ return selectorTopmost(Conditions.<PsiElement>alwaysTrue());
+ }
+
+ public static PostfixTemplateExpressionSelector selectorWithChooser(Condition<PsiElement> condition) {
+ return new ChooserExpressionSelector(condition);
+ }
+
+ public static PostfixTemplateExpressionSelector selectorTopmost(Condition<PsiElement> condition) {
+ return new TopmostExpressionSelector(condition);
+ }
+
@Nullable
public static TextRange surround(@NotNull Surrounder surrounder,
@NotNull Editor editor,
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/StatementWrapPostfixTemplate.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/StatementWrapPostfixTemplate.java
index ed1605d3a9fb..5b5c3624f33b 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/StatementWrapPostfixTemplate.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/StatementWrapPostfixTemplate.java
@@ -22,7 +22,7 @@ import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
-public abstract class StatementWrapPostfixTemplate extends TypedPostfixTemplate {
+public abstract class StatementWrapPostfixTemplate extends PostfixTemplateWithExpressionSelector {
@SuppressWarnings("unchecked")
protected StatementWrapPostfixTemplate(@NotNull String name,
@@ -39,9 +39,7 @@ public abstract class StatementWrapPostfixTemplate extends TypedPostfixTemplate
}
@Override
- public void expand(@NotNull PsiElement context, @NotNull Editor editor) {
- PsiElement topmostExpression = myPsiInfo.getTopmostExpression(context);
- assert topmostExpression != null;
+ public void expandForChooseExpression(@NotNull PsiElement topmostExpression, @NotNull Editor editor) {
PsiElement parent = topmostExpression.getParent();
PsiElement expression = getWrappedExpression(topmostExpression);
PsiElement replace = parent.replace(expression);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/StringBasedPostfixTemplate.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/StringBasedPostfixTemplate.java
index 4d6582f071de..9f19b2011a49 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/StringBasedPostfixTemplate.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/StringBasedPostfixTemplate.java
@@ -26,7 +26,7 @@ import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-public abstract class StringBasedPostfixTemplate extends TypedPostfixTemplate {
+public abstract class StringBasedPostfixTemplate extends PostfixTemplateWithExpressionSelector {
public StringBasedPostfixTemplate(@NotNull String name,
@NotNull String example,
@@ -36,10 +36,8 @@ public abstract class StringBasedPostfixTemplate extends TypedPostfixTemplate {
}
@Override
- public final void expand(@NotNull PsiElement context, @NotNull Editor editor) {
- PsiElement expr = myPsiInfo.getTopmostExpression(context);
- assert expr != null;
- Project project = context.getProject();
+ public final void expandForChooseExpression(@NotNull PsiElement expr, @NotNull Editor editor) {
+ Project project = expr.getProject();
Document document = editor.getDocument();
PsiElement elementForRemoving = shouldRemoveParent() ? expr.getParent() : expr;
document.deleteString(elementForRemoving.getTextRange().getStartOffset(), elementForRemoving.getTextRange().getEndOffset());
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/SurroundPostfixTemplateBase.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/SurroundPostfixTemplateBase.java
index 52ad0c4cdde8..29ea4d39ac64 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/SurroundPostfixTemplateBase.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/SurroundPostfixTemplateBase.java
@@ -40,11 +40,9 @@ public abstract class SurroundPostfixTemplateBase extends StatementWrapPostfixTe
@Override
- public void expand(@NotNull PsiElement context, @NotNull final Editor editor) {
+ public final void expandForChooseExpression(@NotNull PsiElement context, @NotNull final Editor editor) {
PsiElement topmostExpression = myPsiInfo.getTopmostExpression(context);
- PsiElement expression = getWrappedExpression(topmostExpression);
- assert topmostExpression != null;
- PsiElement replace = topmostExpression.replace(expression);
+ PsiElement replace = getReplacedExpression(topmostExpression);
TextRange range = PostfixTemplatesUtils.surround(getSurrounder(), editor, replace);
if (range != null) {
@@ -52,6 +50,12 @@ public abstract class SurroundPostfixTemplateBase extends StatementWrapPostfixTe
}
}
+ protected PsiElement getReplacedExpression(PsiElement topmostExpression) {
+ PsiElement expression = getWrappedExpression(topmostExpression);
+ assert topmostExpression != null;
+ return topmostExpression.replace(expression);
+ }
+
public boolean isStatement() {
return false;
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/TopmostExpressionSelector.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/TopmostExpressionSelector.java
new file mode 100644
index 000000000000..bd6028d2d8d2
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/TopmostExpressionSelector.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.template.postfix.templates;
+
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.util.Condition;
+import com.intellij.psi.PsiElement;
+import org.jetbrains.annotations.NotNull;
+
+
+/**
+ * See {@link PostfixTemplateExpressionSelector} for description
+ */
+public class TopmostExpressionSelector implements PostfixTemplateExpressionSelector {
+
+ @NotNull
+ private final Condition<PsiElement> myCondition;
+
+ public TopmostExpressionSelector(@NotNull Condition<PsiElement> condition) {
+
+ myCondition = condition;
+ }
+
+ @Override
+ public boolean hasExpression(@NotNull PostfixTemplateWithExpressionSelector template,
+ @NotNull PsiElement context,
+ @NotNull Document copyDocument,
+ int newOffset) {
+ PsiElement topmostExpression = template.getPsiInfo().getTopmostExpression(context);
+ return topmostExpression != null && myCondition.value(topmostExpression);
+ }
+
+ @Override
+ public void expandTemplate(@NotNull PostfixTemplateWithExpressionSelector template,
+ @NotNull PsiElement context,
+ @NotNull Editor editor) {
+ PostfixTemplatePsiInfo info = template.getPsiInfo();
+ PsiElement expression = info.getTopmostExpression(context);
+ if (expression == null) {
+ return;
+ }
+ template.expandForChooseExpression(expression, editor);
+ }
+}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/TypedPostfixTemplate.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/TypedPostfixTemplate.java
deleted file mode 100644
index 0d7d424d99a8..000000000000
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/TypedPostfixTemplate.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 2000-2014 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.codeInsight.template.postfix.templates;
-
-import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.util.Condition;
-import com.intellij.psi.PsiElement;
-import org.jetbrains.annotations.NotNull;
-
-public abstract class TypedPostfixTemplate extends PostfixTemplate {
-
- protected final PostfixTemplatePsiInfo myPsiInfo;
- protected final Condition<PsiElement> myTypeChecker;
-
- protected TypedPostfixTemplate(@NotNull String name,
- @NotNull String example,
- @NotNull PostfixTemplatePsiInfo psiInfo,
- @NotNull Condition<PsiElement> typeChecker) {
- super(name, example);
- this.myPsiInfo = psiInfo;
- this.myTypeChecker = typeChecker;
- }
-
- @Override
- public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) {
- PsiElement topmostExpression = myPsiInfo.getTopmostExpression(context);
- return topmostExpression != null && myTypeChecker.value(topmostExpression);
- }
-}
diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionManagerEx.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionManagerEx.java
index 2c934d76bbd5..7ae94888c90d 100644
--- a/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionManagerEx.java
+++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionManagerEx.java
@@ -64,6 +64,8 @@ public class InspectionManagerEx extends InspectionManagerBase {
@NotNull
@Override
protected ContentManager compute() {
+ ToolWindowManager toolWindowManager = ToolWindowManager.getInstance(project);
+ toolWindowManager.registerToolWindow(ToolWindowId.INSPECTION, true, ToolWindowAnchor.BOTTOM, project);
return ContentFactory.SERVICE.getInstance().createContentManager(new TabbedPaneContentUI(), true, project);
}
};
diff --git a/platform/lang-impl/src/com/intellij/execution/ProgramRunnerUtil.java b/platform/lang-impl/src/com/intellij/execution/ProgramRunnerUtil.java
index f19d92f76bcf..b27a939dd57c 100644
--- a/platform/lang-impl/src/com/intellij/execution/ProgramRunnerUtil.java
+++ b/platform/lang-impl/src/com/intellij/execution/ProgramRunnerUtil.java
@@ -74,7 +74,7 @@ public class ProgramRunnerUtil {
}
public static void executeConfiguration(Project project,
- DataContext context,
+ @Nullable DataContext context,
@Nullable RunnerAndConfigurationSettings configuration,
Executor executor,
ExecutionTarget target,
diff --git a/platform/lang-impl/src/com/intellij/execution/console/ConsoleHistoryController.java b/platform/lang-impl/src/com/intellij/execution/console/ConsoleHistoryController.java
index 6c0bfffd450e..9aab415d5e70 100644
--- a/platform/lang-impl/src/com/intellij/execution/console/ConsoleHistoryController.java
+++ b/platform/lang-impl/src/com/intellij/execution/console/ConsoleHistoryController.java
@@ -45,7 +45,9 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiFileFactory;
import com.intellij.testFramework.LightVirtualFile;
+import com.intellij.util.ExceptionUtil;
import com.intellij.util.ObjectUtils;
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.io.SafeFileOutputStream;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.xml.XppReader;
@@ -56,7 +58,6 @@ import org.xmlpull.v1.XmlSerializer;
import java.awt.event.KeyEvent;
import java.io.*;
-import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
@@ -65,6 +66,8 @@ import java.util.ListIterator;
*/
public class ConsoleHistoryController {
+ private static final int VERSION = 1;
+
private static final Logger LOG = Logger.getInstance("com.intellij.execution.console.ConsoleHistoryController");
private final LanguageConsoleImpl myConsole;
@@ -394,7 +397,15 @@ public class ConsoleHistoryController {
}
}
catch (Exception ex) {
- LOG.error(ex);
+ //noinspection ThrowableResultOfMethodCallIgnored
+ Throwable cause = ExceptionUtil.getRootCause(ex);
+ if (cause instanceof EOFException) {
+ LOG.warn("Failed to load " + myType + " console history from: " + file.getPath(), ex);
+ return false;
+ }
+ else {
+ LOG.error(ex);
+ }
}
finally {
if (xmlReader != null) {
@@ -423,6 +434,7 @@ public class ConsoleHistoryController {
}
serializer.setOutput(os = new SafeFileOutputStream(file), CharsetToolkit.UTF8);
saveHistory(serializer);
+ serializer.flush();
}
catch (Exception ex) {
LOG.error(ex);
@@ -439,47 +451,58 @@ public class ConsoleHistoryController {
}
@Nullable
- private String loadHistory(final HierarchicalStreamReader in, final String expectedId) {
+ private String loadHistory(HierarchicalStreamReader in, String expectedId) {
if (!in.getNodeName().equals("console-history")) return null;
- final String id = in.getAttribute("id");
+ int version = StringUtil.parseInt(in.getAttribute("version"), 0);
+ String id = in.getAttribute("id");
if (!expectedId.equals(id)) return null;
- final ArrayList<String> entries = new ArrayList<String>();
+ List<String> entries = ContainerUtil.newArrayList();
String consoleContent = null;
while (in.hasMoreChildren()) {
in.moveDown();
if ("history-entry".equals(in.getNodeName())) {
- entries.add(in.getValue());
+ entries.add(StringUtil.notNullize(in.getValue()));
}
else if ("console-content".equals(in.getNodeName())) {
- consoleContent = in.getValue();
+ consoleContent = StringUtil.notNullize(in.getValue());
}
in.moveUp();
}
for (ListIterator<String> iterator = entries.listIterator(entries.size()); iterator.hasPrevious(); ) {
- final String entry = iterator.previous();
+ String entry = iterator.previous();
getModel().addToHistory(entry);
}
return consoleContent;
}
- private void saveHistory(final XmlSerializer out) throws IOException {
+ private void saveHistory(XmlSerializer out) throws IOException {
out.startDocument(CharsetToolkit.UTF8, null);
out.startTag(null, "console-history");
+ out.attribute(null, "version", String.valueOf(VERSION));
out.attribute(null, "id", myId);
- for (String s : getModel().getHistory()) {
- out.startTag(null, "history-entry");
- out.text(s);
- out.endTag(null, "history-entry");
+ try {
+ for (String s : getModel().getHistory()) {
+ textTag(out, "history-entry", s);
+ }
+ String current = myContent;
+ if (StringUtil.isNotEmpty(current)) {
+ textTag(out, "console-content", current);
+ }
}
- String current = myContent;
- if (StringUtil.isNotEmpty(current)) {
- out.startTag(null, "console-content");
- out.text(current);
- out.endTag(null, "console-content");
+ finally {
+ out.endTag(null, "console-history");
+ out.endDocument();
}
- out.endTag(null, "console-history");
- out.endDocument();
}
}
+ private static void textTag(@NotNull XmlSerializer out, @NotNull String tag, @NotNull String text) throws IOException {
+ out.startTag(null, tag);
+ try {
+ out.cdsect(text);
+ }
+ finally {
+ out.endTag(null, tag);
+ }
+ }
}
diff --git a/platform/lang-impl/src/com/intellij/execution/console/DuplexConsoleView.java b/platform/lang-impl/src/com/intellij/execution/console/DuplexConsoleView.java
index c760310cd391..87e1323fe607 100644
--- a/platform/lang-impl/src/com/intellij/execution/console/DuplexConsoleView.java
+++ b/platform/lang-impl/src/com/intellij/execution/console/DuplexConsoleView.java
@@ -9,6 +9,7 @@ import com.intellij.execution.ui.ConsoleView;
import com.intellij.execution.ui.ConsoleViewContentType;
import com.intellij.execution.ui.ObservableConsoleView;
import com.intellij.icons.AllIcons;
+import com.intellij.ide.util.PropertiesComponent;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
@@ -34,6 +35,8 @@ public class DuplexConsoleView<S extends ConsoleView, T extends ConsoleView> ext
private final S myPrimaryConsoleView;
@NotNull
private final T mySecondaryConsoleView;
+ @Nullable
+ private final String myStateStorageKey;
private boolean myPrimary;
@Nullable
@@ -41,25 +44,46 @@ public class DuplexConsoleView<S extends ConsoleView, T extends ConsoleView> ext
@NotNull
private final SwitchDuplexConsoleViewAction mySwitchConsoleAction;
+
public DuplexConsoleView(@NotNull S primaryConsoleView, @NotNull T secondaryConsoleView) {
+ this(primaryConsoleView, secondaryConsoleView, null);
+ }
+
+ public DuplexConsoleView(@NotNull S primaryConsoleView, @NotNull T secondaryConsoleView, @Nullable String stateStorageKey) {
super(new CardLayout());
myPrimaryConsoleView = primaryConsoleView;
mySecondaryConsoleView = secondaryConsoleView;
+ myStateStorageKey = stateStorageKey;
add(myPrimaryConsoleView.getComponent(), PRIMARY_CONSOLE_PANEL);
add(mySecondaryConsoleView.getComponent(), SECONDARY_CONSOLE_PANEL);
- mySwitchConsoleAction = new SwitchDuplexConsoleViewAction(this);
+ mySwitchConsoleAction = new SwitchDuplexConsoleViewAction();
myPrimary = true;
- enableConsole(false);
+ enableConsole(getStoredState());
Disposer.register(this, myPrimaryConsoleView);
Disposer.register(this, mySecondaryConsoleView);
}
- public static <S extends ConsoleView, T extends ConsoleView> DuplexConsoleView<S, T> create(S primary, T secondary) {
- return new DuplexConsoleView<S, T>(primary, secondary);
+ public static <S extends ConsoleView, T extends ConsoleView> DuplexConsoleView<S, T> create(@NotNull S primary,
+ @NotNull T secondary,
+ @Nullable String stateStorageKey) {
+ return new DuplexConsoleView<S, T>(primary, secondary, stateStorageKey);
+ }
+
+ private void setStoredState(boolean primary) {
+ if (myStateStorageKey != null) {
+ PropertiesComponent.getInstance().setValue(myStateStorageKey, String.valueOf(primary));
+ }
+ }
+
+ private boolean getStoredState() {
+ if (myStateStorageKey == null) {
+ return false;
+ }
+ return PropertiesComponent.getInstance().getBoolean(myStateStorageKey, false);
}
public void enableConsole(boolean primary) {
@@ -215,23 +239,22 @@ public class DuplexConsoleView<S extends ConsoleView, T extends ConsoleView> ext
return mySwitchConsoleAction.getTemplatePresentation();
}
- private static class SwitchDuplexConsoleViewAction extends ToggleAction implements DumbAware {
- private final DuplexConsoleView myConsole;
+ private class SwitchDuplexConsoleViewAction extends ToggleAction implements DumbAware {
- public SwitchDuplexConsoleViewAction(final DuplexConsoleView console) {
+ public SwitchDuplexConsoleViewAction() {
super(ExecutionBundle.message("run.configuration.show.command.line.action.name"), null,
AllIcons.Debugger.ToolConsole);
- myConsole = console;
}
@Override
public boolean isSelected(final AnActionEvent event) {
- return !myConsole.isPrimaryConsoleEnabled();
+ return !isPrimaryConsoleEnabled();
}
@Override
public void setSelected(final AnActionEvent event, final boolean flag) {
- myConsole.enableConsole(!flag);
+ enableConsole(!flag);
+ setStoredState(!flag);
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
@@ -244,12 +267,12 @@ public class DuplexConsoleView<S extends ConsoleView, T extends ConsoleView> ext
public void update(final AnActionEvent event) {
super.update(event);
final Presentation presentation = event.getPresentation();
- final boolean isRunning = myConsole.myProcessHandler != null && !myConsole.myProcessHandler.isProcessTerminated();
+ final boolean isRunning = myProcessHandler != null && !myProcessHandler.isProcessTerminated();
if (isRunning) {
presentation.setEnabled(true);
}
else {
- myConsole.enableConsole(true);
+ enableConsole(true);
presentation.putClientProperty(SELECTED_PROPERTY, false);
presentation.setEnabled(false);
}
diff --git a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java
index 9cb57be6ad9d..1a9afd1e25e5 100644
--- a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java
+++ b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java
@@ -670,12 +670,14 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider {
}
}
+ @NotNull
public Editor getCurrentEditor() {
- return ObjectUtils.chooseNotNull(myCurrentEditor, myConsoleEditor);
+ return ObjectUtils.notNull(myCurrentEditor, myConsoleEditor);
}
+ @NotNull
public Language getLanguage() {
- return myVirtualFile.getLanguage();
+ return ObjectUtils.assertNotNull(myVirtualFile.getLanguage());
}
public void setLanguage(@NotNull Language language) {
diff --git a/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationBeforeRunProvider.java b/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationBeforeRunProvider.java
index ae6af9d1064e..edf1352a760c 100644
--- a/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationBeforeRunProvider.java
+++ b/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationBeforeRunProvider.java
@@ -49,6 +49,8 @@ import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
import java.util.*;
import java.util.List;
@@ -345,6 +347,14 @@ extends BeforeRunTaskProvider<RunConfigurationBeforeRunProvider.RunConfigurableB
mySettings = settings;
init();
myJBList.setSelectedValue(mySelectedSettings, true);
+ myJBList.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ if (SwingUtilities.isLeftMouseButton(e) && e.getClickCount() ==2) {
+ doOKAction();
+ }
+ }
+ });
FontMetrics fontMetrics = myJBList.getFontMetrics(myJBList.getFont());
int maxWidth = fontMetrics.stringWidth("m") * 30;
for (RunnerAndConfigurationSettings setting : settings) {
diff --git a/platform/lang-impl/src/com/intellij/execution/runners/AbstractConsoleRunnerWithHistory.java b/platform/lang-impl/src/com/intellij/execution/runners/AbstractConsoleRunnerWithHistory.java
index df7f7e1b2e1c..b4b3cd919ec4 100644
--- a/platform/lang-impl/src/com/intellij/execution/runners/AbstractConsoleRunnerWithHistory.java
+++ b/platform/lang-impl/src/com/intellij/execution/runners/AbstractConsoleRunnerWithHistory.java
@@ -15,6 +15,9 @@
*/
package com.intellij.execution.runners;
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.collect.FluentIterable;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.ExecutionHelper;
import com.intellij.execution.ExecutionManager;
@@ -129,38 +132,30 @@ public abstract class AbstractConsoleRunnerWithHistory<T extends LanguageConsole
registerActionShortcuts(actions, getLanguageConsole().getConsoleEditor().getComponent());
registerActionShortcuts(actions, panel);
panel.updateUI();
+
showConsole(defaultExecutor, contentDescriptor);
// Run
myProcessHandler.startNotify();
}
- private String constructConsoleTitle(final @NotNull String consoleTitle) {
+ protected String constructConsoleTitle(final @NotNull String consoleTitle) {
if (shouldAddNumberToTitle()) {
- List<RunContentDescriptor> consoles = ExecutionHelper.collectConsolesByDisplayName(myProject, new NotNullFunction<String, Boolean>() {
- @NotNull
- @Override
- public Boolean fun(String dom) {
- return dom.contains(consoleTitle);
- }
- });
+ List<String> activeConsoleNames = getActiveConsoleNames(consoleTitle);
int max = 0;
- for (RunContentDescriptor dsc : consoles) {
- ProcessHandler handler = dsc.getProcessHandler();
- if (handler != null && !handler.isProcessTerminated()) {
- if (max == 0) {
- max = 1;
- }
- try {
- int num = Integer.parseInt(dsc.getDisplayName().substring(consoleTitle.length() + 1, dsc.getDisplayName().length() - 1));
- if (num > max) {
- max = num;
- }
- }
- catch (Exception ignored) {
- //skip
+ for (String name : activeConsoleNames) {
+ if (max == 0) {
+ max = 1;
+ }
+ try {
+ int num = Integer.parseInt(name.substring(consoleTitle.length() + 1, name.length() - 1));
+ if (num > max) {
+ max = num;
}
}
+ catch (Exception ignored) {
+ //skip
+ }
}
if (max >= 1) {
return consoleTitle + "(" + (max + 1) + ")";
@@ -178,9 +173,9 @@ public abstract class AbstractConsoleRunnerWithHistory<T extends LanguageConsole
return false;
}
- protected void showConsole(Executor defaultExecutor, RunContentDescriptor myDescriptor) {
+ protected void showConsole(Executor defaultExecutor, RunContentDescriptor contentDescriptor) {
// Show in run toolwindow
- ExecutionManager.getInstance(myProject).getContentManager().showRunContent(defaultExecutor, myDescriptor);
+ ExecutionManager.getInstance(myProject).getContentManager().showRunContent(defaultExecutor, contentDescriptor);
}
protected void finishConsole() {
@@ -245,11 +240,13 @@ public abstract class AbstractConsoleRunnerWithHistory<T extends LanguageConsole
public static AnAction createConsoleExecAction(@NotNull LanguageConsoleView console,
@NotNull ProcessHandler processHandler,
@NotNull ProcessBackedConsoleExecuteActionHandler consoleExecuteActionHandler) {
- return new ConsoleExecuteAction(console, consoleExecuteActionHandler, consoleExecuteActionHandler.getEmptyExecuteAction(), consoleExecuteActionHandler);
+ return new ConsoleExecuteAction(console, consoleExecuteActionHandler, consoleExecuteActionHandler.getEmptyExecuteAction(),
+ consoleExecuteActionHandler);
}
protected AnAction createConsoleExecAction(@NotNull ProcessBackedConsoleExecuteActionHandler consoleExecuteActionHandler) {
- return new ConsoleExecuteAction(myConsoleView, consoleExecuteActionHandler, consoleExecuteActionHandler.getEmptyExecuteAction(), consoleExecuteActionHandler);
+ return new ConsoleExecuteAction(myConsoleView, consoleExecuteActionHandler, consoleExecuteActionHandler.getEmptyExecuteAction(),
+ consoleExecuteActionHandler);
}
@SuppressWarnings("UnusedDeclaration")
@@ -301,4 +298,31 @@ public abstract class AbstractConsoleRunnerWithHistory<T extends LanguageConsole
public ProcessBackedConsoleExecuteActionHandler getConsoleExecuteActionHandler() {
return myConsoleExecuteActionHandler;
}
+
+ protected List<String> getActiveConsoleNames(final String consoleTitle) {
+ return getActiveConsolesFromRunToolWindow(consoleTitle);
+ }
+
+ protected List<String> getActiveConsolesFromRunToolWindow(final String consoleTitle) {
+ List<RunContentDescriptor> consoles = ExecutionHelper.collectConsolesByDisplayName(myProject, new NotNullFunction<String, Boolean>() {
+ @NotNull
+ @Override
+ public Boolean fun(String dom) {
+ return dom.contains(consoleTitle);
+ }
+ });
+
+ return FluentIterable.from(consoles).filter(new Predicate<RunContentDescriptor>() {
+ @Override
+ public boolean apply(RunContentDescriptor input) {
+ ProcessHandler handler = input.getProcessHandler();
+ return handler != null && !handler.isProcessTerminated();
+ }
+ }).transform(new Function<RunContentDescriptor, String>() {
+ @Override
+ public String apply(RunContentDescriptor input) {
+ return input.getDisplayName();
+ }
+ }).toList();
+ }
}
diff --git a/platform/lang-impl/src/com/intellij/execution/runners/RestartAction.java b/platform/lang-impl/src/com/intellij/execution/runners/RestartAction.java
index 507864126430..20b29c2de994 100644
--- a/platform/lang-impl/src/com/intellij/execution/runners/RestartAction.java
+++ b/platform/lang-impl/src/com/intellij/execution/runners/RestartAction.java
@@ -61,6 +61,15 @@ public class RestartAction extends FakeRerunAction implements DumbAware, AnActio
myDescriptor = descriptor;
myExecutor = executor;
// see IDEADEV-698
+
+ if (descriptor.getRestarter() == null) {
+ descriptor.setRestarter(new Runnable() {
+ @Override
+ public void run() {
+ restart();
+ }
+ });
+ }
}
@Override
diff --git a/platform/lang-impl/src/com/intellij/execution/runners/RunContentBuilder.java b/platform/lang-impl/src/com/intellij/execution/runners/RunContentBuilder.java
index ab9433e66831..bb6d206f1eb9 100644
--- a/platform/lang-impl/src/com/intellij/execution/runners/RunContentBuilder.java
+++ b/platform/lang-impl/src/com/intellij/execution/runners/RunContentBuilder.java
@@ -206,12 +206,6 @@ public class RunContentBuilder extends LogConsoleManagerBase {
final RestartAction restartAction = new RestartAction(myExecutor, myRunner, contentDescriptor, getEnvironment());
restartAction.registerShortcut(component);
actionGroup.add(restartAction);
- contentDescriptor.setRestarter(new Runnable() {
- @Override
- public void run() {
- restartAction.restart();
- }
- });
if (myExecutionResult instanceof DefaultExecutionResult) {
final AnAction[] actions = ((DefaultExecutionResult)myExecutionResult).getRestartActions();
diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java
index 897d169e1845..821d9dbd6bc3 100644
--- a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java
+++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java
@@ -1271,6 +1271,17 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
return null;
}
+ @Nullable
+ public void restoreContent(final String key) {
+ for (AnAction action : myMinimizedViewActions.getChildren(null)) {
+ Content content = ((RestoreViewAction)action).getContent();
+ if (key.equals(content.getUserData(ViewImpl.ID))) {
+ action.actionPerformed(null);
+ return;
+ }
+ }
+ }
+
public void setToDisposeRemovedContent(final boolean toDispose) {
myToDisposeRemovedContent = toDispose;
}
diff --git a/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java b/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java
index 8a36638d993c..9613ac0dd33f 100644
--- a/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java
+++ b/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java
@@ -392,6 +392,9 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data
if (secondaryActionsAvailable()) {
actionGroup.addAction(new ToggleInCommentsAction(this)).setAsSecondary(true);
actionGroup.addAction(new ToggleInLiteralsOnlyAction(this)).setAsSecondary(true);
+ actionGroup.addAction(new ToggleExceptCommentsAction(this)).setAsSecondary(true);
+ actionGroup.addAction(new ToggleExceptLiteralsAction(this)).setAsSecondary(true);
+ actionGroup.addAction(new ToggleExceptCommentsAndLiteralsAction(this)).setAsSecondary(true);
}
actionGroup.addAction(new TogglePreserveCaseAction(this));
actionGroup.addAction(new ToggleSelectionOnlyAction(this));
@@ -473,8 +476,7 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data
to.setCaseSensitive(from.isCaseSensitive());
to.setWholeWordsOnly(from.isWholeWordsOnly());
to.setRegularExpressions(from.isRegularExpressions());
- to.setInCommentsOnly(from.isInCommentsOnly());
- to.setInStringLiteralsOnly(from.isInStringLiteralsOnly());
+ to.setSearchContext(from.getSearchContext());
if (from.isReplaceState()) {
to.setPreserveCase(from.isPreserveCase());
}
diff --git a/platform/lang-impl/src/com/intellij/find/FindSettings.java b/platform/lang-impl/src/com/intellij/find/FindSettings.java
index 964670a45723..d61fd395eadd 100644
--- a/platform/lang-impl/src/com/intellij/find/FindSettings.java
+++ b/platform/lang-impl/src/com/intellij/find/FindSettings.java
@@ -119,4 +119,13 @@ public abstract class FindSettings{
public abstract boolean isInCommentsOnly();
public abstract void setInCommentsOnly(boolean selected);
+
+ public abstract boolean isExceptStringLiterals();
+ public abstract void setExceptStringLiterals(boolean selected);
+
+ public abstract boolean isExceptComments();
+ public abstract void setExceptComments(boolean selected);
+
+ public abstract boolean isExceptCommentsAndLiterals();
+ public abstract void setExceptCommentsAndLiterals(boolean selected);
}
diff --git a/platform/lang-impl/src/com/intellij/find/FindUtil.java b/platform/lang-impl/src/com/intellij/find/FindUtil.java
index edc906481398..674358a49379 100644
--- a/platform/lang-impl/src/com/intellij/find/FindUtil.java
+++ b/platform/lang-impl/src/com/intellij/find/FindUtil.java
@@ -321,7 +321,7 @@ public class FindUtil {
public static void searchBack(final Project project, final Editor editor, @Nullable DataContext context) {
FindManager findManager = FindManager.getInstance(project);
- if (!findManager.findWasPerformed()) {
+ if (!findManager.findWasPerformed() && !findManager.selectNextOccurrenceWasPerformed()) {
new IncrementalFindAction().getHandler().execute(editor, context);
return;
}
@@ -363,7 +363,7 @@ public class FindUtil {
public static boolean searchAgain(final Project project, final Editor editor, @Nullable DataContext context) {
FindManager findManager = FindManager.getInstance(project);
- if (!findManager.findWasPerformed()) {
+ if (!findManager.findWasPerformed() && !findManager.selectNextOccurrenceWasPerformed()) {
new IncrementalFindAction().getHandler().execute(editor, context);
return false;
}
diff --git a/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleExceptCommentsAction.java b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleExceptCommentsAction.java
new file mode 100644
index 000000000000..ae60f31a70b7
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleExceptCommentsAction.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.find.editorHeaderActions;
+
+import com.intellij.find.EditorSearchComponent;
+import com.intellij.find.FindModel;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+
+public class ToggleExceptCommentsAction extends EditorHeaderToggleAction implements SecondaryHeaderAction {
+ private static final String TEXT = "Except C&omments";
+
+ public ToggleExceptCommentsAction(EditorSearchComponent editorSearchComponent) {
+ super(editorSearchComponent, TEXT);
+ }
+
+ @Override
+ public boolean isSelected(AnActionEvent e) {
+ return getEditorSearchComponent().getFindModel().isExceptComments();
+ }
+
+ @Override
+ public void setSelected(AnActionEvent e, boolean state) {
+ getEditorSearchComponent().getFindModel().setSearchContext(state ? FindModel.SearchContext.EXCEPT_COMMENTS : FindModel.SearchContext.ANY);
+ }
+}
diff --git a/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleExceptCommentsAndLiteralsAction.java b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleExceptCommentsAndLiteralsAction.java
new file mode 100644
index 000000000000..d3ff1015e610
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleExceptCommentsAndLiteralsAction.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.find.editorHeaderActions;
+
+import com.intellij.find.EditorSearchComponent;
+import com.intellij.find.FindModel;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+
+public class ToggleExceptCommentsAndLiteralsAction extends EditorHeaderToggleAction implements SecondaryHeaderAction {
+ private static final String TEXT = "Except Comments and Li&terals";
+
+ public ToggleExceptCommentsAndLiteralsAction(EditorSearchComponent editorSearchComponent) {
+ super(editorSearchComponent, TEXT);
+ }
+
+ @Override
+ public boolean isSelected(AnActionEvent e) {
+ return getEditorSearchComponent().getFindModel().isExceptCommentsAndStringLiterals();
+ }
+
+ @Override
+ public void setSelected(AnActionEvent e, boolean state) {
+ getEditorSearchComponent().getFindModel().setSearchContext(state ? FindModel.SearchContext.EXCEPT_COMMENTS_AND_STRING_LITERALS : FindModel.SearchContext.ANY);
+ }
+}
diff --git a/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleExceptLiteralsAction.java b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleExceptLiteralsAction.java
new file mode 100644
index 000000000000..4b7f09c2b211
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleExceptLiteralsAction.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.find.editorHeaderActions;
+
+import com.intellij.find.EditorSearchComponent;
+import com.intellij.find.FindModel;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+
+public class ToggleExceptLiteralsAction extends EditorHeaderToggleAction implements SecondaryHeaderAction {
+ private static final String TEXT = "Except L&iterals";
+
+ public ToggleExceptLiteralsAction(EditorSearchComponent editorSearchComponent) {
+ super(editorSearchComponent, TEXT);
+ }
+
+ @Override
+ public boolean isSelected(AnActionEvent e) {
+ return getEditorSearchComponent().getFindModel().isExceptStringLiterals();
+ }
+
+ @Override
+ public void setSelected(AnActionEvent e, boolean state) {
+ getEditorSearchComponent().getFindModel().setSearchContext(state ? FindModel.SearchContext.EXCEPT_STRING_LITERALS : FindModel.SearchContext.ANY);
+ }
+}
diff --git a/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleInCommentsAction.java b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleInCommentsAction.java
index e6cae36868af..4d9d5ad44cac 100644
--- a/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleInCommentsAction.java
+++ b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleInCommentsAction.java
@@ -18,8 +18,6 @@ public class ToggleInCommentsAction extends EditorHeaderToggleAction implements
@Override
public void setSelected(AnActionEvent e, boolean state) {
- FindModel findModel = getEditorSearchComponent().getFindModel();
- findModel.setInCommentsOnly(state);
- if (state) findModel.setInStringLiteralsOnly(false);
+ getEditorSearchComponent().getFindModel().setSearchContext(state ? FindModel.SearchContext.IN_COMMENTS : FindModel.SearchContext.ANY);
}
}
diff --git a/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleInLiteralsOnlyAction.java b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleInLiteralsOnlyAction.java
index c4d47e024f5e..d8fc5d530095 100644
--- a/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleInLiteralsOnlyAction.java
+++ b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleInLiteralsOnlyAction.java
@@ -18,8 +18,6 @@ public class ToggleInLiteralsOnlyAction extends EditorHeaderToggleAction implem
@Override
public void setSelected(AnActionEvent e, boolean state) {
- FindModel findModel = getEditorSearchComponent().getFindModel();
- findModel.setInStringLiteralsOnly(state);
- if (state) findModel.setInCommentsOnly(false);
+ getEditorSearchComponent().getFindModel().setSearchContext(state ? FindModel.SearchContext.IN_STRING_LITERALS : FindModel.SearchContext.ANY);
}
}
diff --git a/platform/lang-impl/src/com/intellij/find/findInProject/FindInProjectManager.java b/platform/lang-impl/src/com/intellij/find/findInProject/FindInProjectManager.java
index 7bc0e0c595f8..d7f7665a9299 100644
--- a/platform/lang-impl/src/com/intellij/find/findInProject/FindInProjectManager.java
+++ b/platform/lang-impl/src/com/intellij/find/findInProject/FindInProjectManager.java
@@ -25,6 +25,7 @@ import com.intellij.find.impl.FindManagerImpl;
import com.intellij.find.replaceInProject.ReplaceInProjectManager;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
@@ -71,8 +72,14 @@ public class FindInProjectManager {
findModel.setOpenInNewTab(toOpenInNewTab[0]);
FindInProjectUtil.setDirectoryName(findModel, dataContext);
- Editor editor = CommonDataKeys.EDITOR.getData(dataContext);
- FindUtil.initStringToFindWithSelection(findModel, editor);
+ String text = PlatformDataKeys.PREDEFINED_TEXT.getData(dataContext);
+ if (text != null) {
+ FindModel.initStringToFindNoMultiline(findModel, text);
+ }
+ else {
+ Editor editor = CommonDataKeys.EDITOR.getData(dataContext);
+ FindUtil.initStringToFindWithSelection(findModel, editor);
+ }
findManager.showFindDialog(findModel, new Runnable() {
@Override
diff --git a/platform/lang-impl/src/com/intellij/find/findUsages/CommonFindUsagesDialog.java b/platform/lang-impl/src/com/intellij/find/findUsages/CommonFindUsagesDialog.java
index fe47fb8558a6..3315eac0b979 100644
--- a/platform/lang-impl/src/com/intellij/find/findUsages/CommonFindUsagesDialog.java
+++ b/platform/lang-impl/src/com/intellij/find/findUsages/CommonFindUsagesDialog.java
@@ -16,8 +16,8 @@
package com.intellij.find.findUsages;
+import com.intellij.lang.HelpID;
import com.intellij.lang.findUsages.DescriptiveNameUtil;
-import com.intellij.openapi.help.HelpManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
@@ -26,7 +26,9 @@ import com.intellij.psi.search.PsiSearchHelper;
import com.intellij.ui.SimpleColoredComponent;
import com.intellij.ui.SimpleTextAttributes;
import com.intellij.usageView.UsageViewUtil;
+import com.intellij.util.ObjectUtils;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -35,6 +37,7 @@ import javax.swing.*;
*/
public class CommonFindUsagesDialog extends AbstractFindUsagesDialog {
@NotNull protected final PsiElement myPsiElement;
+ @Nullable private final String myHelpId;
public CommonFindUsagesDialog(@NotNull PsiElement element,
@NotNull Project project,
@@ -46,6 +49,7 @@ public class CommonFindUsagesDialog extends AbstractFindUsagesDialog {
super(project, findUsagesOptions, toShowInNewTab, mustOpenInNewTab, isSingleFile, isTextSearch(element, isSingleFile, handler),
!isSingleFile && !element.getManager().isInProject(element));
myPsiElement = element;
+ myHelpId = ObjectUtils.chooseNotNull(handler.getHelpId(), HelpID.FIND_OTHER_USAGES);
init();
}
@@ -71,8 +75,9 @@ public class CommonFindUsagesDialog extends AbstractFindUsagesDialog {
coloredComponent.append(DescriptiveNameUtil.getDescriptiveName(myPsiElement), SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES);
}
+ @Nullable
@Override
- protected void doHelpAction() {
- HelpManager.getInstance().invokeHelp(FindUsagesManager.getHelpID(myPsiElement));
+ protected String getHelpId() {
+ return myHelpId;
}
}
diff --git a/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesHandler.java b/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesHandler.java
index a9291cf612ba..b0dcc459d55b 100644
--- a/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesHandler.java
+++ b/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesHandler.java
@@ -83,6 +83,11 @@ public abstract class FindUsagesHandler {
return PsiElement.EMPTY_ARRAY;
}
+ @Nullable
+ protected String getHelpId() {
+ return FindUsagesManager.getHelpID(myPsiElement);
+ }
+
@NotNull
public static FindUsagesOptions createFindUsagesOptions(@NotNull Project project, @Nullable final DataContext dataContext) {
FindUsagesOptions findUsagesOptions = new FindUsagesOptions(project, dataContext);
diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindDialog.java b/platform/lang-impl/src/com/intellij/find/impl/FindDialog.java
index b6a6152b678b..c25456da1988 100644
--- a/platform/lang-impl/src/com/intellij/find/impl/FindDialog.java
+++ b/platform/lang-impl/src/com/intellij/find/impl/FindDialog.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,7 +35,6 @@ import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.*;
-import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
@@ -50,8 +49,6 @@ import com.intellij.ui.EditorComboBoxRenderer;
import com.intellij.ui.EditorTextField;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.StateRestoringCheckBox;
-import com.intellij.ui.components.labels.LinkLabel;
-import com.intellij.ui.components.labels.LinkListener;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Consumer;
import com.intellij.util.ui.UIUtil;
@@ -60,7 +57,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
-import javax.swing.text.BadLocationException;
import java.awt.*;
import java.awt.event.*;
import java.util.Arrays;
@@ -78,8 +74,7 @@ public class FindDialog extends DialogWrapper {
private StateRestoringCheckBox myCbCaseSensitive;
private StateRestoringCheckBox myCbPreserveCase;
private StateRestoringCheckBox myCbWholeWordsOnly;
- private StateRestoringCheckBox myCbInCommentsOnly;
- private StateRestoringCheckBox myCbInStringLiteralsOnly;
+ private ComboBox mySearchContext;
private StateRestoringCheckBox myCbRegularExpressions;
private JRadioButton myRbGlobal;
private JRadioButton myRbSelectedText;
@@ -223,7 +218,7 @@ public class FindDialog extends DialogWrapper {
myReplacePrompt.setVisible(myModel.isReplaceState());
myReplaceComboBox.setVisible(myModel.isReplaceState());
if (myCbToSkipResultsWhenOneUsage != null) {
- myCbToSkipResultsWhenOneUsage.setVisible(myModel.isReplaceState());
+ myCbToSkipResultsWhenOneUsage.setVisible(!myModel.isReplaceState());
}
myCbPreserveCase.setVisible(myModel.isReplaceState());
}
@@ -354,9 +349,9 @@ public class FindDialog extends DialogWrapper {
gbConstraints.gridwidth = GridBagConstraints.REMAINDER;
optionsPanel.add(createFilterPanel(),gbConstraints);
- myCbToSkipResultsWhenOneUsage = createCheckbox(FindSettings.getInstance().isSkipResultsWithOneUsage(), FindBundle.message("find.options.skip.results.tab.with.one.usage.checkbox"));
+ myCbToSkipResultsWhenOneUsage = createCheckbox(FindSettings.getInstance().isSkipResultsWithOneUsage(), FindBundle.message("find.options.skip.results.tab.with.one.occurrence.checkbox"));
optionsPanel.add(myCbToSkipResultsWhenOneUsage, gbConstraints);
- myCbToSkipResultsWhenOneUsage.setVisible(myModel.isReplaceState());
+ myCbToSkipResultsWhenOneUsage.setVisible(!myModel.isReplaceState());
}
else {
if (FindManagerImpl.ourHasSearchInCommentsAndLiterals) {
@@ -476,6 +471,9 @@ public class FindDialog extends DialogWrapper {
findSettings.setWholeWordsOnly(myModel.isWholeWordsOnly());
findSettings.setInStringLiteralsOnly(myModel.isInStringLiteralsOnly());
findSettings.setInCommentsOnly(myModel.isInCommentsOnly());
+ findSettings.setExceptComments(myModel.isExceptComments());
+ findSettings.setExceptStringLiterals(myModel.isExceptStringLiterals());
+ findSettings.setExceptCommentsAndLiterals(myModel.isExceptCommentsAndStringLiterals());
findSettings.setRegularExpressions(myModel.isRegularExpressions());
if (!myModel.isMultipleFiles()){
@@ -603,39 +601,26 @@ public class FindDialog extends DialogWrapper {
regExPanel.setLayout(new BoxLayout(regExPanel, BoxLayout.X_AXIS));
regExPanel.add(myCbRegularExpressions);
- regExPanel.add(new LinkLabel("[Help]", null, new LinkListener() {
- @Override
- public void linkSelected(LinkLabel aSource, Object aLinkData) {
- try {
- final JBPopup helpPopup = RegExHelpPopup.createRegExHelpPopup();
- helpPopup.showInCenterOf(regExPanel);
- }
- catch (BadLocationException e) {
- LOG.info(e);
- }
- }
- }));
+ regExPanel.add(RegExHelpPopup.createRegExLink("[Help]", regExPanel, LOG));
findOptionsPanel.add(regExPanel);
- myCbInCommentsOnly = createCheckbox(FindBundle.message("find.options.comments.only"));
- myCbInStringLiteralsOnly = createCheckbox(FindBundle.message("find.options.string.literals.only"));
- ItemListener itemListener = new ItemListener() {
- @Override
- public void itemStateChanged(ItemEvent e) {
- if (e.getSource() == myCbInCommentsOnly) {
- if (myCbInCommentsOnly.isSelected()) myCbInStringLiteralsOnly.setSelected(false);
- } else if (e.getSource() == myCbInStringLiteralsOnly) {
- if (myCbInStringLiteralsOnly.isSelected()) myCbInCommentsOnly.setSelected(false);
- }
- }
- };
- myCbInCommentsOnly.addItemListener(itemListener);
- myCbInStringLiteralsOnly.addItemListener(itemListener);
+ mySearchContext = new ComboBox(new Object[] {FindBundle.message("find.context.anywhere.scope.label", 200),
+ FindBundle.message("find.context.in.comments.scope.label"), FindBundle.message("find.context.in.literals.scope.label"),
+ FindBundle.message("find.context.except.comments.scope.label"),
+ FindBundle.message("find.context.except.literals.scope.label"),
+ FindBundle.message("find.context.except.comments.and.literals.scope.label")});
+ final JPanel searchContextPanel = new JPanel(new BorderLayout());
+ searchContextPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
+
+ JLabel searchContextLabel = new JLabel(FindBundle.message("find.context.combo.label"));
+ searchContextLabel.setLabelFor(mySearchContext);
+ searchContextPanel.add(searchContextLabel, BorderLayout.WEST);
+
+ searchContextPanel.add(mySearchContext, BorderLayout.CENTER);
if (FindManagerImpl.ourHasSearchInCommentsAndLiterals) {
- findOptionsPanel.add(myCbInCommentsOnly);
- findOptionsPanel.add(myCbInStringLiteralsOnly);
+ findOptionsPanel.add(searchContextPanel);
}
ActionListener actionListener = new ActionListener() {
@@ -1000,9 +985,25 @@ public class FindDialog extends DialogWrapper {
}
model.setWholeWordsOnly(myCbWholeWordsOnly.isSelected());
- model.setInStringLiteralsOnly(myCbInStringLiteralsOnly.isSelected());
- model.setInCommentsOnly(myCbInCommentsOnly.isSelected());
+ String selectedSearchContextInUi = (String)mySearchContext.getSelectedItem();
+ FindModel.SearchContext searchContext = FindModel.SearchContext.ANY;
+ if (FindBundle.message("find.context.in.literals.scope.label").equals(selectedSearchContextInUi)) {
+ searchContext = FindModel.SearchContext.IN_STRING_LITERALS;
+ }
+ else if (FindBundle.message("find.context.in.comments.scope.label").equals(selectedSearchContextInUi)) {
+ searchContext = FindModel.SearchContext.IN_COMMENTS;
+ }
+ else if (FindBundle.message("find.context.except.comments.scope.label").equals(selectedSearchContextInUi)) {
+ searchContext = FindModel.SearchContext.EXCEPT_COMMENTS;
+ }
+ else if (FindBundle.message("find.context.except.literals.scope.label").equals(selectedSearchContextInUi)) {
+ searchContext = FindModel.SearchContext.EXCEPT_STRING_LITERALS;
+ } else if (FindBundle.message("find.context.except.comments.and.literals.scope.label").equals(selectedSearchContextInUi)) {
+ searchContext = FindModel.SearchContext.EXCEPT_COMMENTS_AND_STRING_LITERALS;
+ }
+
+ model.setSearchContext(searchContext);
model.setRegularExpressions(myCbRegularExpressions.isSelected());
String stringToFind = getStringToFind();
@@ -1068,8 +1069,14 @@ public class FindDialog extends DialogWrapper {
private void initByModel() {
myCbCaseSensitive.setSelected(myModel.isCaseSensitive());
myCbWholeWordsOnly.setSelected(myModel.isWholeWordsOnly());
- myCbInStringLiteralsOnly.setSelected(myModel.isInStringLiteralsOnly());
- myCbInCommentsOnly.setSelected(myModel.isInCommentsOnly());
+ String searchContext = FindBundle.message("find.context.anywhere.scope.label");
+ if (myModel.isInCommentsOnly()) searchContext = FindBundle.message("find.context.in.comments.scope.label");
+ else if (myModel.isInStringLiteralsOnly()) searchContext = FindBundle.message("find.context.in.literals.scope.label");
+ else if (myModel.isExceptStringLiterals()) searchContext = FindBundle.message("find.context.except.literals.scope.label");
+ else if (myModel.isExceptComments()) searchContext = FindBundle.message("find.context.except.comments.scope.label");
+ else if (myModel.isExceptCommentsAndStringLiterals()) searchContext = FindBundle.message("find.context.except.comments.and.literals.scope.label");
+ mySearchContext.setSelectedItem(searchContext);
+
myCbRegularExpressions.setSelected(myModel.isRegularExpressions());
if (myModel.isMultipleFiles()) {
diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java
index 59adf1e62bd0..7e9e71d7a94d 100644
--- a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java
+++ b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java
@@ -19,6 +19,7 @@ import com.google.common.collect.HashMultiset;
import com.google.common.collect.Multiset;
import com.intellij.find.FindBundle;
import com.intellij.find.FindModel;
+import com.intellij.find.findInProject.FindInProjectManager;
import com.intellij.find.ngrams.TrigramIndex;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ApplicationNamesInfo;
@@ -182,7 +183,7 @@ class FindInProjectTask {
private void searchInFiles(@NotNull Collection<PsiFile> psiFiles,
@NotNull FindUsagesProcessPresentation processPresentation,
- @NotNull Processor<UsageInfo> consumer) {
+ @NotNull final Processor<UsageInfo> consumer) {
int i = 0;
long totalFilesSize = 0;
int count = 0;
@@ -195,7 +196,8 @@ class FindInProjectTask {
long fileLength = UsageViewManagerImpl.getFileLength(virtualFile);
if (fileLength == -1) continue; // Binary or invalid
- if (ProjectCoreUtil.isProjectOrWorkspaceFile(virtualFile) && !Registry.is("find.search.in.project.files")) continue;
+ final boolean skipProjectFile = ProjectCoreUtil.isProjectOrWorkspaceFile(virtualFile) && !myFindModel.isSearchInProjectFiles();
+ if (skipProjectFile && !Registry.is("find.search.in.project.files")) continue;
if (fileLength > SINGLE_FILE_SIZE_LIMIT) {
myLargeFiles.add(psiFile);
@@ -209,7 +211,24 @@ class FindInProjectTask {
myProgress.setText(text);
myProgress.setText2(FindBundle.message("find.searching.for.string.in.file.occurrences.progress", count));
- int countInFile = FindInProjectUtil.processUsagesInFile(psiFile, myFindModel, consumer);
+ int countInFile = FindInProjectUtil.processUsagesInFile(psiFile, myFindModel, new Processor<UsageInfo>() {
+ @Override
+ public boolean process(UsageInfo info) {
+ return skipProjectFile || consumer.process(info);
+ }
+ });
+
+ if (countInFile > 0 && skipProjectFile) {
+ processPresentation.projectFileUsagesFound(new Runnable() {
+ @Override
+ public void run() {
+ FindModel model = myFindModel.clone();
+ model.setSearchInProjectFiles(true);
+ FindInProjectManager.getInstance(myProject).startFindInProject(model);
+ }
+ });
+ continue;
+ }
count += countInFile;
if (countInFile > 0) {
@@ -231,6 +250,7 @@ class FindInProjectTask {
final GlobalSearchScope globalCustomScope = toGlobal(customScope);
final ProjectFileIndex fileIndex = ProjectFileIndex.SERVICE.getInstance(myProject);
+ final boolean hasTrigrams = hasTrigrams(myFindModel.getStringToFind());
class EnumContentIterator implements ContentIterator {
final Set<PsiFile> myFiles = new LinkedHashSet<PsiFile>();
@@ -238,8 +258,6 @@ class FindInProjectTask {
@Override
public boolean processFile(@NotNull final VirtualFile virtualFile) {
ApplicationManager.getApplication().runReadAction(new Runnable() {
- final boolean hasTrigrams = hasTrigrams(myFindModel.getStringToFind());
-
@Override
public void run() {
ProgressManager.checkCanceled();
@@ -249,9 +267,6 @@ class FindInProjectTask {
return;
}
- if (virtualFile.getFileType().isBinary()) {
- return;
- }
if (skipIndexed && isCoveredByIndex(virtualFile) &&
(fileIndex.isInContent(virtualFile) || fileIndex.isInLibraryClasses(virtualFile) || fileIndex.isInLibrarySource(virtualFile))) {
return;
@@ -261,7 +276,9 @@ class FindInProjectTask {
if (psiFile != null && !(psiFile instanceof PsiBinaryFile) && !alreadySearched.contains(psiFile)) {
PsiFile sourceFile = (PsiFile)psiFile.getNavigationElement();
if (sourceFile != null) psiFile = sourceFile;
- myFiles.add(psiFile);
+ if (!psiFile.getFileType().isBinary()) {
+ myFiles.add(psiFile);
+ }
}
}
@@ -290,7 +307,9 @@ class FindInProjectTask {
for (VirtualFile file : getLocalScopeFiles((LocalSearchScope)customScope)) {
iterator.processFile(file);
}
- } else if (customScope instanceof Iterable) { // GlobalSearchScope can span files out of project roots e.g. FileScope / FilesScope
+ }
+ else if (customScope instanceof Iterable) { // GlobalSearchScope can span files out of project roots e.g. FileScope / FilesScope
+ //noinspection unchecked
for (VirtualFile file : (Iterable<VirtualFile>)customScope) {
iterator.processFile(file);
}
@@ -382,16 +401,14 @@ class FindInProjectTask {
return myFindModel.isWholeWordsOnly() && text.indexOf('$') < 0 && !StringUtil.getWordsInStringLongestFirst(text).isEmpty();
}
- private static boolean hasTrigrams(String text) {
- if (TrigramIndex.ENABLED) {
- return !TrigramBuilder.processTrigrams(text, new TrigramBuilder.TrigramProcessor() {
- @Override
- public boolean execute(int value) {
- return false;
- }
- });
- }
- return false;
+ private static boolean hasTrigrams(@NotNull String text) {
+ return TrigramIndex.ENABLED &&
+ !TrigramBuilder.processTrigrams(text, new TrigramBuilder.TrigramProcessor() {
+ @Override
+ public boolean execute(int value) {
+ return false;
+ }
+ });
}
@@ -430,6 +447,7 @@ class FindInProjectTask {
final List<VirtualFile> hits = new ArrayList<VirtualFile>();
final GlobalSearchScope finalScope = scope;
ApplicationManager.getApplication().runReadAction(new Runnable() {
+ @Override
public void run() {
FileBasedIndex.getInstance().getFilesWithKey(TrigramIndex.INDEX_ID, keys, new CommonProcessors.CollectProcessor<VirtualFile>(hits),
finalScope);
diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java
index e4570b7379bf..23f14c5eb0b4 100644
--- a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java
+++ b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java
@@ -47,7 +47,6 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.openapi.vfs.ex.VirtualFileManagerEx;
import com.intellij.psi.*;
-import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.search.SearchScope;
import com.intellij.ui.content.Content;
@@ -55,7 +54,6 @@ import com.intellij.usageView.UsageInfo;
import com.intellij.usageView.UsageViewManager;
import com.intellij.usages.ConfigurableUsageTarget;
import com.intellij.usages.FindUsagesProcessPresentation;
-import com.intellij.usages.UsageView;
import com.intellij.usages.UsageViewPresentation;
import com.intellij.util.Function;
import com.intellij.util.PatternUtil;
@@ -326,7 +324,7 @@ public class FindInProjectUtil {
return processPresentation;
}
- public static class StringUsageTarget implements ConfigurableUsageTarget, ItemPresentation, TypeSafeDataProvider {
+ public static class StringUsageTarget implements ConfigurableUsageTarget, ItemPresentation {
@NotNull protected final Project myProject;
@NotNull protected final FindModel myFindModel;
@@ -425,12 +423,5 @@ public class FindInProjectUtil {
public KeyboardShortcut getShortcut() {
return ActionManager.getInstance().getKeyboardShortcut("FindInPath");
}
-
- @Override
- public void calcData(DataKey key, DataSink sink) {
- if (key == UsageView.USAGE_SCOPE) {
- sink.put(UsageView.USAGE_SCOPE, GlobalSearchScope.allScope(myProject));
- }
- }
}
}
diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindManagerImpl.java b/platform/lang-impl/src/com/intellij/find/impl/FindManagerImpl.java
index e327ec79c227..27e2b7215f25 100644
--- a/platform/lang-impl/src/com/intellij/find/impl/FindManagerImpl.java
+++ b/platform/lang-impl/src/com/intellij/find/impl/FindManagerImpl.java
@@ -27,7 +27,6 @@ import com.intellij.find.impl.livePreview.SearchResults;
import com.intellij.lang.Language;
import com.intellij.lang.LanguageParserDefinitions;
import com.intellij.lang.ParserDefinition;
-import com.intellij.lexer.LayeredLexer;
import com.intellij.lexer.Lexer;
import com.intellij.navigation.NavigationItem;
import com.intellij.openapi.actionSystem.ActionManager;
@@ -42,11 +41,6 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.colors.TextAttributesKey;
import com.intellij.openapi.editor.ex.FoldingModelEx;
-import com.intellij.openapi.editor.ex.util.LayeredHighlighterIterator;
-import com.intellij.openapi.editor.ex.util.LayeredLexerEditorHighlighter;
-import com.intellij.openapi.editor.highlighter.EditorHighlighter;
-import com.intellij.openapi.editor.highlighter.EditorHighlighterFactory;
-import com.intellij.openapi.editor.highlighter.HighlighterIterator;
import com.intellij.openapi.editor.markup.RangeHighlighter;
import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.fileEditor.TextEditor;
@@ -58,15 +52,17 @@ import com.intellij.openapi.util.*;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
-import com.intellij.psi.impl.search.LexerEditorHighlighterLexer;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
import com.intellij.ui.LightweightHint;
import com.intellij.ui.ReplacePromptDialog;
+import com.intellij.usages.ChunkExtractor;
import com.intellij.usages.UsageViewManager;
+import com.intellij.usages.impl.SyntaxHighlighterOverEditorHighlighter;
import com.intellij.util.Consumer;
import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.Predicate;
import com.intellij.util.messages.MessageBus;
import com.intellij.util.text.CharArrayUtil;
import com.intellij.util.text.StringSearcher;
@@ -96,6 +92,7 @@ public class FindManagerImpl extends FindManager implements PersistentStateCompo
private final FindUsagesManager myFindUsagesManager;
private boolean isFindWasPerformed = false;
+ private boolean isSelectNextOccurrenceWasPerformed = false;
private Point myReplaceInFilePromptPos = new Point(-1, -1);
private Point myReplaceInProjectPromptPos = new Point(-1, -1);
private final FindModel myFindInProjectModel = new FindModel();
@@ -257,7 +254,18 @@ public class FindManagerImpl extends FindManager implements PersistentStateCompo
@Override
public void setFindWasPerformed() {
isFindWasPerformed = true;
- //myFindUsagesManager.clearFindingNextUsageInFile();
+ isSelectNextOccurrenceWasPerformed = false;
+ }
+
+ @Override
+ public boolean selectNextOccurrenceWasPerformed() {
+ return isSelectNextOccurrenceWasPerformed;
+ }
+
+ @Override
+ public void setSelectNextOccurrenceWasPerformed() {
+ isSelectNextOccurrenceWasPerformed = true;
+ isFindWasPerformed = false;
}
@Override
@@ -270,7 +278,7 @@ public class FindManagerImpl extends FindManager implements PersistentStateCompo
if (myFindNextModel == null) return null;
final JComponent header = editor.getHeaderComponent();
- if (header instanceof EditorSearchComponent) {
+ if (header instanceof EditorSearchComponent && !isSelectNextOccurrenceWasPerformed) {
final EditorSearchComponent searchComponent = (EditorSearchComponent)header;
final String textInField = searchComponent.getTextInField();
if (!Comparing.equal(textInField, myFindInFileModel.getStringToFind()) && !textInField.isEmpty()) {
@@ -305,25 +313,103 @@ public class FindManagerImpl extends FindManager implements PersistentStateCompo
LOG.debug(model.toString());
}
- final char[] textArray = CharArrayUtil.fromSequenceWithoutCopying(text);
+ return findStringLoop(text, offset, model, file, getFindContextPredicate(model, file, text));
+ }
+ private FindResult findStringLoop(CharSequence text, int offset, FindModel model, VirtualFile file, @Nullable Predicate<FindResult> filter) {
+ final char[] textArray = CharArrayUtil.fromSequenceWithoutCopying(text);
while(true) {
FindResult result = doFindString(text, textArray, offset, model, file);
+ if (filter == null || filter.apply(result)) {
+ if (!model.isWholeWordsOnly()) {
+ return result;
+ }
+ if (!result.isStringFound()) {
+ return result;
+ }
+ if (isWholeWord(text, result.getStartOffset(), result.getEndOffset())) {
+ return result;
+ }
+ }
+
+ offset = model.isForward() ? result.getStartOffset() + 1 : result.getEndOffset() - 1;
+ if (offset > text.length() || offset < 0) return NOT_FOUND_RESULT;
+ }
+ }
+
+ private class FindExceptCommentsOrLiteralsData implements Predicate<FindResult> {
+ private final VirtualFile myFile;
+ private final FindModel myFindModel;
+ private final TreeMap<Integer, Integer> mySkipRangesSet;
+
+ private FindExceptCommentsOrLiteralsData(VirtualFile file, FindModel model, CharSequence text) {
+ myFile = file;
+ myFindModel = model.clone();
- if (!model.isWholeWordsOnly()) {
- return result;
+ TreeMap<Integer, Integer> result = new TreeMap<Integer, Integer>();
+
+ if (model.isExceptComments() || model.isExceptCommentsAndStringLiterals()) {
+ addRanges(file, model, text, result, FindModel.SearchContext.IN_COMMENTS);
}
- if (!result.isStringFound()){
- return result;
+
+ if (model.isExceptStringLiterals() || model.isExceptCommentsAndStringLiterals()) {
+ addRanges(file, model, text, result, FindModel.SearchContext.IN_STRING_LITERALS);
}
- if (isWholeWord(text, result.getStartOffset(), result.getEndOffset())){
- return result;
+
+ mySkipRangesSet = result;
+ }
+
+ private void addRanges(VirtualFile file,
+ FindModel model,
+ CharSequence text,
+ TreeMap<Integer, Integer> result,
+ FindModel.SearchContext searchContext) {
+ FindModel clonedModel = model.clone();
+ clonedModel.setSearchContext(searchContext);
+ clonedModel.setForward(true);
+ int offset = 0;
+
+ while(true) {
+ FindResult customResult = findStringLoop(text, offset, clonedModel, file, null);
+ if (!customResult.isStringFound()) break;
+ result.put(customResult.getStartOffset(), customResult.getEndOffset());
+ offset = Math.max(customResult.getEndOffset(), offset + 1); // avoid loop for zero size reg exps matches
+ if (offset >= text.length()) break;
}
+ }
- offset = model.isForward() ? result.getStartOffset() + 1 : result.getEndOffset() - 1;
- if (offset > text.length() || offset < 0) return NOT_FOUND_RESULT;
+ boolean isAcceptableFor(FindModel model, VirtualFile file) {
+ return Comparing.equal(myFile, file) && myFindModel.equals(model);
+ }
+
+ @Override
+ public boolean apply(@Nullable FindResult input) {
+ if (input == null || !input.isStringFound()) return true;
+ NavigableMap<Integer, Integer> map = mySkipRangesSet.headMap(input.getStartOffset(), true);
+ for(Map.Entry<Integer, Integer> e:map.descendingMap().entrySet()) {
+ if (e.getKey() <= input.getStartOffset() && e.getValue() >= input.getEndOffset()) return false;
+ if (e.getValue() <= input.getStartOffset()) break;
+ }
+ return true;
}
}
+ private static Key<FindExceptCommentsOrLiteralsData> ourExceptCommentsOrLiteralsDataKey = Key.create("except.comments.literals.search.data");
+
+ private Predicate<FindResult> getFindContextPredicate(@NotNull FindModel model, VirtualFile file, CharSequence text) {
+ if (file == null) return null;
+ FindModel.SearchContext context = model.getSearchContext();
+ if( context == FindModel.SearchContext.ANY || context == FindModel.SearchContext.IN_COMMENTS ||
+ context == FindModel.SearchContext.IN_STRING_LITERALS) {
+ return null;
+ }
+
+ FindExceptCommentsOrLiteralsData data = model.getUserData(ourExceptCommentsOrLiteralsDataKey);
+ if (data == null || !data.isAcceptableFor(model, file)) {
+ model.putUserData(ourExceptCommentsOrLiteralsDataKey, data = new FindExceptCommentsOrLiteralsData(file, model, text));
+ }
+
+ return data;
+ }
@Override
public int showMalformedReplacementPrompt(@NotNull FindModel model, String title, MalformedReplacementStringException exception) {
@@ -408,11 +494,15 @@ public class FindManagerImpl extends FindManager implements PersistentStateCompo
return new StringSearcher(model.getStringToFind(), model.isCaseSensitive(), model.isForward());
}
+ public static void clearPreviousFindData(FindModel model) {
+ model.putUserData(ourCommentsLiteralsSearchDataKey, null);
+ model.putUserData(ourExceptCommentsOrLiteralsDataKey, null);
+ }
+
private static class CommentsLiteralsSearchData {
final VirtualFile lastFile;
int startOffset = 0;
- final SyntaxHighlighter highlighter;
- final Lexer highlightingLexer;
+ final SyntaxHighlighterOverEditorHighlighter highlighter;
TokenSet tokensOfInterest;
final StringSearcher searcher;
@@ -420,8 +510,8 @@ public class FindManagerImpl extends FindManager implements PersistentStateCompo
final Set<Language> relevantLanguages;
final FindModel model;
- public CommentsLiteralsSearchData(VirtualFile lastFile, Set<Language> relevantLanguages, SyntaxHighlighter highlighter,
- Lexer lexer, TokenSet tokensOfInterest,
+ public CommentsLiteralsSearchData(VirtualFile lastFile, Set<Language> relevantLanguages,
+ SyntaxHighlighterOverEditorHighlighter highlighter, TokenSet tokensOfInterest,
StringSearcher searcher, Matcher matcher, FindModel model) {
this.lastFile = lastFile;
this.highlighter = highlighter;
@@ -429,12 +519,11 @@ public class FindManagerImpl extends FindManager implements PersistentStateCompo
this.searcher = searcher;
this.matcher = matcher;
this.relevantLanguages = relevantLanguages;
- highlightingLexer = lexer;
this.model = model;
}
}
- public static final Key<CommentsLiteralsSearchData> ourCommentsLiteralsSearchDataKey = Key.create("comments.literals.search.data");
+ private static final Key<CommentsLiteralsSearchData> ourCommentsLiteralsSearchDataKey = Key.create("comments.literals.search.data");
@NotNull
private FindResult findInCommentsAndLiterals(@NotNull CharSequence text,
@@ -512,38 +601,15 @@ public class FindManagerImpl extends FindManager implements PersistentStateCompo
Matcher matcher = model.isRegularExpressions() ? compileRegExp(model, ""):null;
StringSearcher searcher = matcher != null ? null: new StringSearcher(model.getStringToFind(), model.isCaseSensitive(), true);
- LayeredLexer.ourDisableLayersFlag.set(Boolean.TRUE);
- EditorHighlighter editorHighlighter = EditorHighlighterFactory.getInstance().createEditorHighlighter(myProject, file);
- Lexer lexer;
-
- try {
- if (editorHighlighter instanceof LayeredLexerEditorHighlighter) {
- lexer = new LexerEditorHighlighterLexer(editorHighlighter, false);
- } else {
- lexer = highlighter.getHighlightingLexer();
- }
- }
- finally {
- LayeredLexer.ourDisableLayersFlag.set(null);
- }
-
- data = new CommentsLiteralsSearchData(file, relevantLanguages, highlighter, lexer, tokensOfInterest, searcher, matcher, (FindModel)model.clone());
- lexer.start(text, 0, text.length(), 0);
+ SyntaxHighlighterOverEditorHighlighter highlighterAdapter = new SyntaxHighlighterOverEditorHighlighter(highlighter, file, myProject);
+ data = new CommentsLiteralsSearchData(file, relevantLanguages, highlighterAdapter, tokensOfInterest, searcher, matcher, model.clone());
+ data.highlighter.restart(text);
model.putUserData(ourCommentsLiteralsSearchDataKey, data);
}
int initialStartOffset = model.isForward() && data.startOffset < offset ? data.startOffset : 0;
- final Lexer lexer = data.highlightingLexer;
- LayeredHighlighterIterator layeredHighlighterIterator = null;
- if (lexer instanceof LexerEditorHighlighterLexer) {
- ((LexerEditorHighlighterLexer)lexer).resetPosition(initialStartOffset);
- HighlighterIterator iterator = ((LexerEditorHighlighterLexer)lexer).getHighlighterIterator();
- if (iterator instanceof LayeredHighlighterIterator) {
- layeredHighlighterIterator = (LayeredHighlighterIterator)iterator;
- }
- } else {
- lexer.start(text, initialStartOffset, text.length(), 0);
- }
+ data.highlighter.resetPosition(initialStartOffset);
+ final Lexer lexer = data.highlighter.getHighlightingLexer();
IElementType tokenType;
TokenSet tokens = data.tokensOfInterest;
@@ -555,13 +621,11 @@ public class FindManagerImpl extends FindManager implements PersistentStateCompo
while((tokenType = lexer.getTokenType()) != null) {
if (lexer.getState() == 0) lastGoodOffset = lexer.getTokenStart();
- final SyntaxHighlighter activeSyntaxHighlighter =
- layeredHighlighterIterator != null ? layeredHighlighterIterator.getActiveSyntaxHighlighter() : data.highlighter;
- final TextAttributesKey[] keys = activeSyntaxHighlighter.getTokenHighlights(tokenType);
+ final TextAttributesKey[] keys = data.highlighter.getTokenHighlights(tokenType);
if (tokens.contains(tokenType) ||
- (model.isInStringLiteralsOnly() && isHighlightedAsString(keys)) ||
- (model.isInCommentsOnly() && isHighlightedAsDocComment(keys))
+ (model.isInStringLiteralsOnly() && ChunkExtractor.isHighlightedAsString(keys)) ||
+ (model.isInCommentsOnly() && ChunkExtractor.isHighlightedAsComment(keys))
) {
int start = lexer.getTokenStart();
int end = lexer.getTokenEnd();
@@ -634,32 +698,6 @@ public class FindManagerImpl extends FindManager implements PersistentStateCompo
return prevFindResult;
}
- private static boolean isHighlightedAsDocComment(TextAttributesKey... keys) {
- for (TextAttributesKey key : keys) {
- if (key == DefaultLanguageHighlighterColors.DOC_COMMENT || key == SyntaxHighlighterColors.DOC_COMMENT) {
- return true;
- }
- final TextAttributesKey fallbackAttributeKey = key.getFallbackAttributeKey();
- if (fallbackAttributeKey != null && isHighlightedAsDocComment(fallbackAttributeKey)) {
- return true;
- }
- }
- return false;
- }
-
- private static boolean isHighlightedAsString(TextAttributesKey... keys) {
- for (TextAttributesKey key : keys) {
- if (key == DefaultLanguageHighlighterColors.STRING || key == SyntaxHighlighterColors.STRING) {
- return true;
- }
- final TextAttributesKey fallbackAttributeKey = key.getFallbackAttributeKey();
- if (fallbackAttributeKey != null && isHighlightedAsString(fallbackAttributeKey)) {
- return true;
- }
- }
- return false;
- }
-
private static TokenSet addTokenTypesForLanguage(FindModel model, Language lang, TokenSet tokensOfInterest) {
ParserDefinition definition = LanguageParserDefinitions.INSTANCE.forLanguage(lang);
if (definition != null) {
diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindResultUsageInfo.java b/platform/lang-impl/src/com/intellij/find/impl/FindResultUsageInfo.java
index 2c372795ea85..ee8d98422250 100644
--- a/platform/lang-impl/src/com/intellij/find/impl/FindResultUsageInfo.java
+++ b/platform/lang-impl/src/com/intellij/find/impl/FindResultUsageInfo.java
@@ -80,7 +80,7 @@ public class FindResultUsageInfo extends UsageInfo {
Long data = myFindModel.getUserData(ourDocumentTimestampKey);
if (data == null || data != myTimestamp) {
data = myTimestamp;
- myFindModel.putUserData(FindManagerImpl.ourCommentsLiteralsSearchDataKey, null);
+ FindManagerImpl.clearPreviousFindData(myFindModel);
}
myFindModel.putUserData(ourDocumentTimestampKey, data);
FindResult result;
@@ -110,7 +110,13 @@ public class FindResultUsageInfo extends UsageInfo {
assert result.isStringFound();
- if (myFindModel.isRegularExpressions() || myFindModel.isInCommentsOnly() || myFindModel.isInStringLiteralsOnly()) {
+ if (myFindModel.isRegularExpressions() ||
+ myFindModel.isInCommentsOnly() ||
+ myFindModel.isInStringLiteralsOnly() ||
+ myFindModel.isExceptStringLiterals() ||
+ myFindModel.isExceptCommentsAndStringLiterals() ||
+ myFindModel.isExceptComments()
+ ) {
myAnchor = SmartPointerManager.getInstance(getProject()).createSmartPsiFileRangePointer(file, TextRange.from(offset, 0));
}
diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindSettingsImpl.java b/platform/lang-impl/src/com/intellij/find/impl/FindSettingsImpl.java
index 5fb74f190ac0..c9c8e3492834 100644
--- a/platform/lang-impl/src/com/intellij/find/impl/FindSettingsImpl.java
+++ b/platform/lang-impl/src/com/intellij/find/impl/FindSettingsImpl.java
@@ -103,6 +103,9 @@ public class FindSettingsImpl extends FindSettings implements PersistentStateCom
@SuppressWarnings({"WeakerAccess"}) public boolean WHOLE_WORDS_ONLY = false;
@SuppressWarnings({"WeakerAccess"}) public boolean COMMENTS_ONLY = false;
@SuppressWarnings({"WeakerAccess"}) public boolean STRING_LITERALS_ONLY = false;
+ @SuppressWarnings({"WeakerAccess"}) public boolean EXCEPT_COMMENTS = false;
+ @SuppressWarnings({"WeakerAccess"}) public boolean EXCEPT_COMMENTS_AND_STRING_LITERALS = false;
+ @SuppressWarnings({"WeakerAccess"}) public boolean EXCEPT_STRING_LITERALS = false;
@SuppressWarnings({"WeakerAccess"}) public boolean LOCAL_WHOLE_WORDS_ONLY = false;
@SuppressWarnings({"WeakerAccess"}) public boolean REGULAR_EXPRESSIONS = false;
@SuppressWarnings({"WeakerAccess"}) public boolean LOCAL_REGULAR_EXPRESSIONS = false;
@@ -276,8 +279,18 @@ public class FindSettingsImpl extends FindSettings implements PersistentStateCom
model.setGlobal(isGlobal());
model.setRegularExpressions(isRegularExpressions());
model.setWholeWordsOnly(isWholeWordsOnly());
- model.setInCommentsOnly(isInCommentsOnly());
- model.setInStringLiteralsOnly(isInStringLiteralsOnly());
+ FindModel.SearchContext searchContext = isInCommentsOnly() ?
+ FindModel.SearchContext.IN_COMMENTS :
+ isInStringLiteralsOnly() ?
+ FindModel.SearchContext.IN_STRING_LITERALS :
+ isExceptComments() ?
+ FindModel.SearchContext.EXCEPT_COMMENTS :
+ isExceptStringLiterals() ?
+ FindModel.SearchContext.EXCEPT_STRING_LITERALS :
+ isExceptCommentsAndLiterals() ?
+ FindModel.SearchContext.EXCEPT_COMMENTS_AND_STRING_LITERALS :
+ FindModel.SearchContext.ANY;
+ model.setSearchContext(searchContext);
model.setWithSubdirectories(isWithSubdirectories());
model.setFileFilter(FILE_MASK);
@@ -384,4 +397,34 @@ public class FindSettingsImpl extends FindSettings implements PersistentStateCom
public void setCustomScope(final String SEARCH_SCOPE) {
this.SEARCH_SCOPE = SEARCH_SCOPE;
}
+
+ @Override
+ public boolean isExceptComments() {
+ return EXCEPT_COMMENTS;
+ }
+
+ @Override
+ public void setExceptCommentsAndLiterals(boolean selected) {
+ EXCEPT_COMMENTS_AND_STRING_LITERALS = selected;
+ }
+
+ @Override
+ public boolean isExceptCommentsAndLiterals() {
+ return EXCEPT_COMMENTS_AND_STRING_LITERALS;
+ }
+
+ @Override
+ public void setExceptComments(boolean selected) {
+ EXCEPT_COMMENTS = selected;
+ }
+
+ @Override
+ public boolean isExceptStringLiterals() {
+ return EXCEPT_STRING_LITERALS;
+ }
+
+ @Override
+ public void setExceptStringLiterals(boolean selected) {
+ EXCEPT_STRING_LITERALS = selected;
+ }
}
diff --git a/platform/lang-impl/src/com/intellij/find/impl/RegExHelpPopup.java b/platform/lang-impl/src/com/intellij/find/impl/RegExHelpPopup.java
index 23dee12e362f..0aace901a409 100644
--- a/platform/lang-impl/src/com/intellij/find/impl/RegExHelpPopup.java
+++ b/platform/lang-impl/src/com/intellij/find/impl/RegExHelpPopup.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,12 +17,19 @@ package com.intellij.find.impl;
import com.intellij.codeInsight.hint.HintUtil;
import com.intellij.ide.BrowserUtil;
+import com.intellij.openapi.Disposable;
+import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.ui.popup.ComponentPopupBuilder;
import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.ui.popup.util.MinimizeButton;
+import com.intellij.openapi.util.Disposer;
import com.intellij.ui.ScrollPaneFactory;
+import com.intellij.ui.components.labels.LinkLabel;
+import com.intellij.ui.components.labels.LinkListener;
import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.event.HyperlinkEvent;
@@ -331,6 +338,36 @@ public class RegExHelpPopup extends JPanel {
add(myScrollPane, BorderLayout.CENTER);
}
+ @NotNull
+ public static LinkLabel createRegExLink(@NotNull String title, @Nullable final Component owner, @Nullable final Logger logger) {
+ return new LinkLabel(title, null, new LinkListener() {
+ JBPopup helpPopup;
+ @Override
+ public void linkSelected(LinkLabel aSource, Object aLinkData) {
+ try {
+ if (helpPopup != null && !helpPopup.isDisposed() && helpPopup.isVisible()) {
+ return;
+ }
+ helpPopup = createRegExHelpPopup();
+ Disposer.register(helpPopup, new Disposable() {
+ @Override
+ public void dispose() {
+ destroyPopup();
+ }
+ });
+ helpPopup.showInCenterOf(owner);
+ }
+ catch (BadLocationException e) {
+ if (logger != null) logger.info(e);
+ }
+ }
+
+ private void destroyPopup() {
+ helpPopup = null;
+ }
+ });
+ }
+
@Override
public Dimension getPreferredSize() {
return new Dimension(600, 300);
diff --git a/platform/lang-impl/src/com/intellij/formatting/FormatterEx.java b/platform/lang-impl/src/com/intellij/formatting/FormatterEx.java
index e9e8c130a6f4..f5417dfb5a25 100644
--- a/platform/lang-impl/src/com/intellij/formatting/FormatterEx.java
+++ b/platform/lang-impl/src/com/intellij/formatting/FormatterEx.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -116,7 +116,14 @@ public abstract class FormatterEx{
TextRange affectedRange);
public abstract void setProgressTask(@NotNull FormattingProgressTask progressIndicator);
-
+
+ /**
+ * Calculates minimum spacing, allowed by formatting model (in columns) for a block starting at given offset,
+ * relative to its previous sibling block.
+ * Returns zero, if required block cannot be found at provided offset, or spacing cannot be calculated due to some other reason.
+ */
+ public abstract int getSpacingForBlockAtOffset(FormattingModel model, int offset);
+
public interface IndentInfoStorage {
void saveIndentInfo(@Nullable IndentInfo info, int startOffset);
diff --git a/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java b/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java
index e1366431efd0..7b40b786ff7a 100644
--- a/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java
+++ b/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java
@@ -25,6 +25,7 @@ import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.util.Couple;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
@@ -109,6 +110,58 @@ public class FormatterImpl extends FormatterEx
}
@Override
+ public int getSpacingForBlockAtOffset(FormattingModel model, int offset) {
+ Couple<Block> blockWithParent = getBlockAtOffset(null, model.getRootBlock(), offset);
+ if (blockWithParent == null) {
+ return 0;
+ }
+ Block parentBlock = blockWithParent.first;
+ Block targetBlock = blockWithParent.second;
+ if (parentBlock == null || targetBlock == null) {
+ return 0;
+ }
+ Block prevBlock = findPreviousSibling(parentBlock, targetBlock);
+ if (prevBlock == null) {
+ return 0;
+ }
+ SpacingImpl spacing = (SpacingImpl)parentBlock.getSpacing(prevBlock, targetBlock);
+ if (spacing == null) {
+ return 0;
+ }
+ return Math.max(spacing.getMinSpaces(), 0);
+ }
+
+ private static Couple<Block> getBlockAtOffset(Block parent, Block block, int offset) {
+ TextRange textRange = block.getTextRange();
+ int startOffset = textRange.getStartOffset();
+ int endOffset = textRange.getEndOffset();
+ if (startOffset == offset) {
+ return Couple.of(parent, block);
+ }
+ if (startOffset > offset || endOffset < offset || block.isLeaf()) {
+ return null;
+ }
+ for (Block subBlock : block.getSubBlocks()) {
+ Couple<Block> result = getBlockAtOffset(block, subBlock, offset);
+ if (result != null) {
+ return result;
+ }
+ }
+ return null;
+ }
+
+ private static Block findPreviousSibling(Block parent, Block block) {
+ Block result = null;
+ for (Block subBlock : parent.getSubBlocks()) {
+ if (subBlock == block) {
+ return result;
+ }
+ result = subBlock;
+ }
+ return null;
+ }
+
+ @Override
public void format(final FormattingModel model, final CodeStyleSettings settings,
final CommonCodeStyleSettings.IndentOptions indentOptions,
final CommonCodeStyleSettings.IndentOptions javaIndentOptions,
diff --git a/platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/DetectionExcludesConfigurable.java b/platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/DetectionExcludesConfigurable.java
index 88d675b168de..6239cbbab4ac 100644
--- a/platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/DetectionExcludesConfigurable.java
+++ b/platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/DetectionExcludesConfigurable.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,17 +28,21 @@ import com.intellij.openapi.ui.popup.ListPopup;
import com.intellij.openapi.ui.popup.PopupStep;
import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.ui.*;
import com.intellij.ui.awt.RelativePoint;
+import com.intellij.ui.border.CustomLineBorder;
import com.intellij.ui.components.JBList;
+import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
+import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
@@ -66,15 +70,33 @@ public class DetectionExcludesConfigurable implements Configurable {
@NotNull
public JComponent createComponent() {
myEnabledDetectionCheckBox = new JCheckBox("Enable framework detection");
+ myEnabledDetectionCheckBox.setBorder(new EmptyBorder(10, 10, 0, 0));
final JBList excludesList = new JBList(myModel);
- excludesList.setCellRenderer(new ColoredListCellRenderer() {
+ final ColoredListCellRenderer renderer = new ColoredListCellRenderer() {
+ JPanel panel = new JPanel(new BorderLayout());
+ {
+ panel.setBorder(new EmptyBorder(2, 10, 2, 0));
+ panel.add(this);
+ }
+
@Override
protected void customizeCellRenderer(JList list, Object value, int index, boolean selected, boolean hasFocus) {
+ setIconTextGap(4);
if (value instanceof ExcludeListItem) {
((ExcludeListItem)value).renderItem(this);
+ setBorder(new EmptyBorder(0, 10, 0, 0));
}
}
- });
+
+ @Override
+ public Component getListCellRendererComponent(JList list, Object value, int index, boolean selected, boolean hasFocus) {
+ super.getListCellRendererComponent(list, value, index, selected, hasFocus);
+ panel.setBackground(UIUtil.getListBackground(selected));
+ return panel;
+ }
+ };
+ renderer.setMyBorder(new EmptyBorder(0,0,0,0));
+ excludesList.setCellRenderer(renderer);
final ToolbarDecorator decorator = ToolbarDecorator.createDecorator(excludesList)
.disableUpAction().disableDownAction()
.setAddAction(new AnActionButtonRunnable() {
@@ -83,9 +105,12 @@ public class DetectionExcludesConfigurable implements Configurable {
doAddAction(button);
}
});
+ if (Registry.is("ide.new.project.settings")) {
+ decorator.setPanelBorder(new CustomLineBorder(1, 0, 0, 0));
+ }
myMainPanel = new JPanel(new BorderLayout(0, 5));
myMainPanel.add(myEnabledDetectionCheckBox, BorderLayout.NORTH);
- final LabeledComponent<JPanel> excludesComponent = LabeledComponent.create(decorator.createPanel(), "Exclude from detection:");
+ final LabeledComponent<JPanel> excludesComponent = LabeledComponent.create(decorator.createPanel(), " Exclude from detection:");
myMainPanel.add(excludesComponent);
myEnabledDetectionCheckBox.addActionListener(new ActionListener() {
@Override
diff --git a/platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/InvalidExcludeListItem.java b/platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/InvalidExcludeListItem.java
index 6848b039ceed..0dcdde7c6297 100644
--- a/platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/InvalidExcludeListItem.java
+++ b/platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/InvalidExcludeListItem.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@ package com.intellij.framework.detection.impl.exclude;
import com.intellij.ui.ColoredListCellRenderer;
import com.intellij.ui.SimpleTextAttributes;
+import com.intellij.util.ui.EmptyIcon;
/**
* @author nik
@@ -51,6 +52,7 @@ class InvalidExcludeListItem extends ExcludeListItem {
else {
renderer.append(myFileUrl, SimpleTextAttributes.ERROR_ATTRIBUTES);
}
+ renderer.setIcon(EmptyIcon.ICON_16);
}
@Override
diff --git a/platform/lang-impl/src/com/intellij/ide/actions/GotoRelatedFileAction.java b/platform/lang-impl/src/com/intellij/ide/actions/GotoRelatedFileAction.java
index 6d734d52a584..e86caec534f6 100644
--- a/platform/lang-impl/src/com/intellij/ide/actions/GotoRelatedFileAction.java
+++ b/platform/lang-impl/src/com/intellij/ide/actions/GotoRelatedFileAction.java
@@ -15,6 +15,7 @@
*/
package com.intellij.ide.actions;
+import com.intellij.codeInsight.navigation.NavigationUtil;
import com.intellij.navigation.GotoRelatedItem;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.ui.popup.JBPopup;
@@ -25,22 +26,25 @@ import org.jetbrains.annotations.Nullable;
import java.util.List;
/**
- * @deprecated API compatibility. Utility methods will be moved to NavigationUtil
+ * @deprecated API compatibility. Utility methods moved to NavigationUtil.
+ * todo [neuro] REMOVE-ME when September Ends..
* @author gregsh
*/
public class GotoRelatedFileAction {
/**
- * @deprecated This method will be moved to NavigationUtil
+ * @deprecated
+ * @see com.intellij.codeInsight.navigation.NavigationUtil#getRelatedItemsPopup(java.util.List, String)
*/
public static JBPopup createPopup(List<? extends GotoRelatedItem> items, final String title) {
- return GotoRelatedSymbolAction.createPopup(items, title);
+ return NavigationUtil.getRelatedItemsPopup(items, title);
}
/**
- * @deprecated This method will be moved to NavigationUtil
+ * @deprecated
+ * @see com.intellij.codeInsight.navigation.NavigationUtil#collectRelatedItems(com.intellij.psi.PsiElement, com.intellij.openapi.actionSystem.DataContext)
*/
public static List<GotoRelatedItem> getItems(@NotNull PsiElement contextElement, @Nullable DataContext dataContext) {
- return GotoRelatedSymbolAction.getItems(contextElement, dataContext);
+ return NavigationUtil.collectRelatedItems(contextElement, dataContext);
}
}
diff --git a/platform/lang-impl/src/com/intellij/ide/actions/GotoRelatedSymbolAction.java b/platform/lang-impl/src/com/intellij/ide/actions/GotoRelatedSymbolAction.java
index 2870f806ab8a..229531b3ef53 100644
--- a/platform/lang-impl/src/com/intellij/ide/actions/GotoRelatedSymbolAction.java
+++ b/platform/lang-impl/src/com/intellij/ide/actions/GotoRelatedSymbolAction.java
@@ -15,39 +15,19 @@
*/
package com.intellij.ide.actions;
-import com.intellij.ide.util.DefaultPsiElementCellRenderer;
+import com.intellij.codeInsight.navigation.NavigationUtil;
import com.intellij.navigation.GotoRelatedItem;
-import com.intellij.navigation.GotoRelatedProvider;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.extensions.Extensions;
-import com.intellij.openapi.ui.popup.JBPopup;
-import com.intellij.openapi.ui.popup.PopupStep;
-import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
-import com.intellij.openapi.util.Ref;
-import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
-import com.intellij.ui.ColoredListCellRenderer;
-import com.intellij.ui.JBColor;
-import com.intellij.ui.SeparatorWithText;
-import com.intellij.ui.SimpleTextAttributes;
-import com.intellij.ui.popup.list.ListPopupImpl;
-import com.intellij.ui.popup.list.PopupListElementRenderer;
-import com.intellij.util.Processor;
-import com.intellij.util.containers.ContainerUtil;
-import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
-import javax.swing.*;
-import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.util.*;
import java.util.List;
/**
@@ -66,210 +46,20 @@ public class GotoRelatedSymbolAction extends AnAction {
PsiElement element = getContextElement(e.getDataContext());
if (element == null) return;
- List<GotoRelatedItem> items = getItems(element, e.getDataContext());
+ List<GotoRelatedItem> items = NavigationUtil.collectRelatedItems(element, e.getDataContext());
if (items.isEmpty()) return;
if (items.size() == 1 && items.get(0).getElement() != null) {
items.get(0).navigate();
return;
}
- createPopup(items, "Choose Target").showInBestPositionFor(e.getDataContext());
- }
-
- public static JBPopup createPopup(final List<? extends GotoRelatedItem> items, final String title) {
- Object[] elements = new Object[items.size()];
- //todo[nik] move presentation logic to GotoRelatedItem class
- final Map<PsiElement, GotoRelatedItem> itemsMap = new HashMap<PsiElement, GotoRelatedItem>();
- for (int i = 0; i < items.size(); i++) {
- GotoRelatedItem item = items.get(i);
- elements[i] = item.getElement() != null ? item.getElement() : item;
- itemsMap.put(item.getElement(), item);
- }
-
- return getPsiElementPopup(elements, itemsMap, title, new Processor<Object>() {
- @Override
- public boolean process(Object element) {
- if (element instanceof PsiElement) {
- //noinspection SuspiciousMethodCalls
- itemsMap.get(element).navigate();
- }
- else {
- ((GotoRelatedItem)element).navigate();
- }
- return true;
- }
- }
- );
- }
-
- private static JBPopup getPsiElementPopup(final Object[] elements, final Map<PsiElement, GotoRelatedItem> itemsMap,
- final String title, final Processor<Object> processor) {
-
- final Ref<Boolean> hasMnemonic = Ref.create(false);
- final DefaultPsiElementCellRenderer renderer = new DefaultPsiElementCellRenderer() {
- {
- setFocusBorderEnabled(false);
- }
-
- @Override
- public String getElementText(PsiElement element) {
- String customName = itemsMap.get(element).getCustomName();
- return (customName != null ? customName : super.getElementText(element));
- }
-
- @Override
- protected Icon getIcon(PsiElement element) {
- Icon customIcon = itemsMap.get(element).getCustomIcon();
- return customIcon != null ? customIcon : super.getIcon(element);
- }
-
- @Override
- public String getContainerText(PsiElement element, String name) {
- String customContainerName = itemsMap.get(element).getCustomContainerName();
-
- if (customContainerName != null) {
- return customContainerName;
- }
- PsiFile file = element.getContainingFile();
- return file != null && !getElementText(element).equals(file.getName())
- ? "(" + file.getName() + ")"
- : null;
- }
-
- @Override
- protected DefaultListCellRenderer getRightCellRenderer(Object value) {
- return null;
- }
-
- @Override
- protected boolean customizeNonPsiElementLeftRenderer(ColoredListCellRenderer renderer,
- JList list,
- Object value,
- int index,
- boolean selected,
- boolean hasFocus) {
- final GotoRelatedItem item = (GotoRelatedItem)value;
- Color color = list.getForeground();
- final SimpleTextAttributes nameAttributes = new SimpleTextAttributes(Font.PLAIN, color);
- final String name = item.getCustomName();
- if (name == null) return false;
- renderer.append(name, nameAttributes);
- renderer.setIcon(item.getCustomIcon());
- return true;
- }
-
- @Override
- public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
- final JPanel component = (JPanel)super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
- if (!hasMnemonic.get()) return component;
-
- final JPanel panelWithMnemonic = new JPanel(new BorderLayout());
- final int mnemonic = getMnemonic(value, itemsMap);
- final JLabel label = new JLabel("");
- if (mnemonic != -1) {
- label.setText(mnemonic + ".");
- label.setDisplayedMnemonicIndex(0);
- }
- label.setPreferredSize(new JLabel("8.").getPreferredSize());
-
- final JComponent leftRenderer = (JComponent)component.getComponents()[0];
- component.remove(leftRenderer);
- panelWithMnemonic.setBorder(BorderFactory.createEmptyBorder(0, 7, 0, 0));
- panelWithMnemonic.setBackground(leftRenderer.getBackground());
- label.setBackground(leftRenderer.getBackground());
- panelWithMnemonic.add(label, BorderLayout.WEST);
- panelWithMnemonic.add(leftRenderer, BorderLayout.CENTER);
- component.add(panelWithMnemonic);
- return component;
- }
- };
- final ListPopupImpl popup = new ListPopupImpl(new BaseListPopupStep<Object>(title, Arrays.asList(elements)) {
- @Override
- public boolean isSpeedSearchEnabled() {
- return true;
- }
-
- @Override
- public String getIndexedString(Object value) {
- if (value instanceof GotoRelatedItem) {
- //noinspection ConstantConditions
- return ((GotoRelatedItem)value).getCustomName();
- }
- final PsiElement element = (PsiElement)value;
- return renderer.getElementText(element) + " " + renderer.getContainerText(element, null);
- }
-
- @Override
- public PopupStep onChosen(Object selectedValue, boolean finalChoice) {
- processor.process(selectedValue);
- return super.onChosen(selectedValue, finalChoice);
- }
- }) {
- };
- popup.getList().setCellRenderer(new PopupListElementRenderer(popup) {
- Map<Object, String> separators = new HashMap<Object, String>();
- {
- final ListModel model = popup.getList().getModel();
- String current = null;
- boolean hasTitle = false;
- for (int i = 0; i < model.getSize(); i++) {
- final Object element = model.getElementAt(i);
- final GotoRelatedItem item = itemsMap.get(element);
- if (item != null && !StringUtil.equals(current, item.getGroup())) {
- current = item.getGroup();
- separators.put(element, current);
- if (!hasTitle && !StringUtil.isEmpty(current)) {
- hasTitle = true;
- }
- }
- }
-
- if (!hasTitle) {
- separators.remove(model.getElementAt(0));
- }
- }
- @Override
- public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
- final Component component = renderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
- final String separator = separators.get(value);
-
- if (separator != null) {
- JPanel panel = new JPanel(new BorderLayout());
- panel.add(component, BorderLayout.CENTER);
- final SeparatorWithText sep = new SeparatorWithText() {
- @Override
- protected void paintComponent(Graphics g) {
- g.setColor(new JBColor(Color.WHITE, UIUtil.getSeparatorColor()));
- g.fillRect(0,0,getWidth(), getHeight());
- super.paintComponent(g);
- }
- };
- sep.setCaption(separator);
- panel.add(sep, BorderLayout.NORTH);
- return panel;
- }
- return component;
- }
- });
-
- popup.setMinimumSize(new Dimension(200, -1));
-
- for (Object item : elements) {
- final int mnemonic = getMnemonic(item, itemsMap);
- if (mnemonic != -1) {
- final Action action = createNumberAction(mnemonic, popup, itemsMap, processor);
- popup.registerAction(mnemonic + "Action", KeyStroke.getKeyStroke(String.valueOf(mnemonic)), action);
- popup.registerAction(mnemonic + "Action", KeyStroke.getKeyStroke("NUMPAD" + String.valueOf(mnemonic)), action);
- hasMnemonic.set(true);
- }
- }
- return popup;
+ NavigationUtil.getRelatedItemsPopup(items, "Choose Target").showInBestPositionFor(e.getDataContext());
}
@TestOnly
@NotNull
public static List<GotoRelatedItem> getItems(@NotNull PsiFile psiFile, @Nullable Editor editor, @Nullable DataContext dataContext) {
- return getItems(getContextElement(psiFile, editor), dataContext);
+ return NavigationUtil.collectRelatedItems(getContextElement(psiFile, editor), dataContext);
}
@Nullable
@@ -294,65 +84,4 @@ public class GotoRelatedSymbolAction extends AnAction {
}
return contextElement;
}
-
- @NotNull
- public static List<GotoRelatedItem> getItems(@NotNull PsiElement contextElement, @Nullable DataContext dataContext) {
- Set<GotoRelatedItem> items = ContainerUtil.newLinkedHashSet();
- for (GotoRelatedProvider provider : Extensions.getExtensions(GotoRelatedProvider.EP_NAME)) {
- items.addAll(provider.getItems(contextElement));
- if (dataContext != null) {
- items.addAll(provider.getItems(dataContext));
- }
- }
- sortByGroupNames(items);
- return new ArrayList<GotoRelatedItem>(items);
- }
-
- private static void sortByGroupNames(Set<GotoRelatedItem> items) {
- Map<String, List<GotoRelatedItem>> map = new HashMap<String, List<GotoRelatedItem>>();
- for (GotoRelatedItem item : items) {
- final String key = item.getGroup();
- if (!map.containsKey(key)) {
- map.put(key, new ArrayList<GotoRelatedItem>());
- }
- map.get(key).add(item);
- }
- final List<String> keys = new ArrayList<String>(map.keySet());
- Collections.sort(keys, new Comparator<String>() {
- @Override
- public int compare(String o1, String o2) {
- return StringUtil.isEmpty(o1) ? 1 : StringUtil.isEmpty(o2) ? -1 : o1.compareTo(o2);
- }
- });
- items.clear();
- for (String key : keys) {
- items.addAll(map.get(key));
- }
- }
-
- private static Action createNumberAction(final int mnemonic,
- final ListPopupImpl listPopup,
- final Map<PsiElement, GotoRelatedItem> itemsMap,
- final Processor<Object> processor) {
- return new AbstractAction() {
- @Override
- public void actionPerformed(ActionEvent e) {
- for (final Object item : listPopup.getListStep().getValues()) {
- if (getMnemonic(item, itemsMap) == mnemonic) {
- listPopup.setFinalRunnable(new Runnable() {
- @Override
- public void run() {
- processor.process(item);
- }
- });
- listPopup.closeOk(null);
- }
- }
- }
- };
- }
-
- private static int getMnemonic(Object item, Map<PsiElement, GotoRelatedItem> itemsMap) {
- return (item instanceof GotoRelatedItem ? (GotoRelatedItem)item : itemsMap.get((PsiElement)item)).getMnemonic();
- }
}
diff --git a/platform/lang-impl/src/com/intellij/ide/actions/SearchAgainAction.java b/platform/lang-impl/src/com/intellij/ide/actions/SearchAgainAction.java
index 3e28023a935c..531f3e52159f 100644
--- a/platform/lang-impl/src/com/intellij/ide/actions/SearchAgainAction.java
+++ b/platform/lang-impl/src/com/intellij/ide/actions/SearchAgainAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -49,7 +49,8 @@ public class SearchAgainAction extends AnAction implements DumbAware {
public void run() {
PsiDocumentManager.getInstance(project).commitAllDocuments();
IdeDocumentHistory.getInstance(project).includeCurrentCommandAsNavigation();
- if(FindManager.getInstance(project).findNextUsageInEditor(editor)) {
+ FindManager findManager = FindManager.getInstance(project);
+ if(!findManager.selectNextOccurrenceWasPerformed() && findManager.findNextUsageInEditor(editor)) {
return;
}
diff --git a/platform/lang-impl/src/com/intellij/ide/actions/SearchBackAction.java b/platform/lang-impl/src/com/intellij/ide/actions/SearchBackAction.java
index 4783205ae8c0..5f6e0d9959bd 100644
--- a/platform/lang-impl/src/com/intellij/ide/actions/SearchBackAction.java
+++ b/platform/lang-impl/src/com/intellij/ide/actions/SearchBackAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -46,7 +46,8 @@ public class SearchBackAction extends AnAction implements DumbAware {
@Override
public void run() {
PsiDocumentManager.getInstance(project).commitAllDocuments();
- if(FindManager.getInstance(project).findPreviousUsageInEditor(editor)) {
+ FindManager findManager = FindManager.getInstance(project);
+ if(!findManager.selectNextOccurrenceWasPerformed() && findManager.findPreviousUsageInEditor(editor)) {
return;
}
FindUtil.searchBack(project, editor, e.getDataContext());
diff --git a/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java b/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java
index ae7ee4363247..d704e738efa3 100644
--- a/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java
+++ b/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java
@@ -108,11 +108,9 @@ import javax.swing.border.EmptyBorder;
import javax.swing.event.DocumentEvent;
import java.awt.*;
import java.awt.event.*;
-import java.lang.reflect.Field;
import java.util.*;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicLong;
/**
* @author Konstantin Bulenkov
@@ -2120,13 +2118,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
private SearchListModel() {
super();
- try {
- final Field field = DefaultListModel.class.getDeclaredField("delegate");
- field.setAccessible(true);
- myDelegate = (Vector)field.get(this);
- }
- catch (NoSuchFieldException ignore) {}
- catch (IllegalAccessException ignore) {}
+ myDelegate = ReflectionUtil.getField(DefaultListModel.class, this, Vector.class, "delegate");
}
int next(int index) {
diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/AbstractProjectViewPane.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/AbstractProjectViewPane.java
index bb80f55237e5..c4708c48d19f 100644
--- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/AbstractProjectViewPane.java
+++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/AbstractProjectViewPane.java
@@ -29,6 +29,7 @@ import com.intellij.ide.projectView.ProjectView;
import com.intellij.ide.projectView.impl.nodes.AbstractModuleNode;
import com.intellij.ide.projectView.impl.nodes.AbstractProjectNode;
import com.intellij.ide.projectView.impl.nodes.ModuleGroupNode;
+import com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode;
import com.intellij.ide.util.treeView.*;
import com.intellij.injected.editor.VirtualFileWindow;
import com.intellij.openapi.Disposable;
@@ -54,6 +55,7 @@ import com.intellij.psi.util.PsiUtilCore;
import com.intellij.refactoring.move.MoveHandler;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ReflectionUtil;
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashMap;
import com.intellij.util.ui.UIUtil;
import com.intellij.util.ui.tree.TreeUtil;
@@ -481,6 +483,27 @@ public abstract class AbstractProjectViewPane implements DataProvider, Disposabl
}
public PsiDirectory[] getSelectedDirectories() {
+ List<PsiDirectory> directories = ContainerUtil.newArrayList();
+ for (PsiDirectoryNode node : getSelectedNodes(PsiDirectoryNode.class)) {
+ PsiDirectory directory = node.getValue();
+ if (directory != null) {
+ directories.add(directory);
+ Object parentValue = node.getParent().getValue();
+ if (parentValue instanceof PsiDirectory) {
+ while (true) {
+ directory = directory.getParentDirectory();
+ if (directory == null || directory.equals(parentValue)) {
+ break;
+ }
+ directories.add(directory);
+ }
+ }
+ }
+ }
+ if (!directories.isEmpty()) {
+ return directories.toArray(new PsiDirectory[directories.size()]);
+ }
+
final PsiElement[] elements = getSelectedPSIElements();
if (elements.length == 1) {
final PsiElement element = elements[0];
diff --git a/platform/lang-impl/src/com/intellij/ide/todo/ChangeListTodosPanel.java b/platform/lang-impl/src/com/intellij/ide/todo/ChangeListTodosPanel.java
index 2aa89adeb3b5..2a6c396e1e3e 100644
--- a/platform/lang-impl/src/com/intellij/ide/todo/ChangeListTodosPanel.java
+++ b/platform/lang-impl/src/com/intellij/ide/todo/ChangeListTodosPanel.java
@@ -65,7 +65,12 @@ public abstract class ChangeListTodosPanel extends TodoPanel{
@Override
public void changeListRenamed(final ChangeList list, final String oldName) {
- setDisplayName(IdeBundle.message("changelist.todo.title", list.getName()));
+ AppUIUtil.invokeOnEdt(new Runnable() {
+ @Override
+ public void run() {
+ setDisplayName(IdeBundle.message("changelist.todo.title", list.getName()));
+ }
+ });
}
@Override
diff --git a/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java b/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java
index f260c732adf5..35f7f658edfd 100644
--- a/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java
+++ b/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java
@@ -65,6 +65,7 @@ import com.intellij.ui.treeStructure.filtered.FilteringTreeBuilder;
import com.intellij.ui.treeStructure.filtered.FilteringTreeStructure;
import com.intellij.util.Alarm;
import com.intellij.util.ArrayUtil;
+import com.intellij.util.ReflectionUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.Convertor;
import com.intellij.util.containers.HashSet;
@@ -83,7 +84,6 @@ import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;
import java.awt.*;
import java.awt.event.*;
-import java.lang.reflect.Field;
import java.util.*;
import java.util.List;
@@ -1018,22 +1018,13 @@ public class FileStructurePopup implements Disposable {
public FileStructureTree(Object rootElement, boolean fastExpand) {
super(new DefaultMutableTreeNode(rootElement));
if (fastExpand) {
- boolean newValueIsSet;
- try {
- final Field field = JTree.class.getDeclaredField("expandedState");
- field.setAccessible(true);
- field.set(this, new Hashtable() {
- @Override
- public synchronized Object get(Object key) {
- return Boolean.TRUE;
- }
- });
- newValueIsSet = true;
- }
- catch (Exception e) {
- newValueIsSet = false;
- }
- fast = newValueIsSet;
+ Hashtable hashtable = new Hashtable() {
+ @Override
+ public synchronized Object get(Object key) {
+ return Boolean.TRUE;
+ }
+ };
+ fast = ReflectionUtil.setField(JTree.class, this, Hashtable.class, "expandedState", hashtable);
}
else {
fast = false;
diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java
index dcc1429c8bbd..3e90f2310884 100644
--- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java
+++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java
@@ -35,6 +35,7 @@ import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.ApplicationAdapter;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
+import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.fileTypes.UnknownFileType;
@@ -102,6 +103,7 @@ import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
public abstract class ChooseByNameBase {
+ private static final Logger LOG = Logger.getInstance("#com.intellij.ide.util.gotoByName.ChooseByNameBase");
protected final Project myProject;
protected final ChooseByNameModel myModel;
protected ChooseByNameItemProvider myProvider;
@@ -133,7 +135,6 @@ public abstract class ChooseByNameBase {
private final ListUpdater myListUpdater = new ListUpdater();
- private volatile boolean myListIsUpToDate = false;
private boolean myDisposedFlag = false;
private ActionCallback myPostponedOkAction;
@@ -278,7 +279,7 @@ public abstract class ChooseByNameBase {
if (PlatformDataKeys.HELP_ID.is(dataId)) {
return myModel.getHelpId();
}
- if (!myListIsUpToDate) {
+ if (myCalcElementsThread != null) {
return null;
}
if (CommonDataKeys.PSI_ELEMENT.is(dataId)) {
@@ -499,7 +500,7 @@ public abstract class ChooseByNameBase {
myTextField.addFocusListener(new FocusAdapter() {
@Override
public void focusLost(@NotNull final FocusEvent e) {
- cancelCalcElementsThread(); // cancel thread as early as possible
+ cancelListUpdater(); // cancel thread as early as possible
myHideAlarm.addRequest(new Runnable() {
@Override
public void run() {
@@ -531,7 +532,7 @@ public abstract class ChooseByNameBase {
if (queue instanceof IdeEventQueue) {
if (!((IdeEventQueue)queue).wasRootRecentlyClicked(oppositeComponent)) {
Component root = SwingUtilities.getRoot(myTextField);
- if (root != null) {
+ if (root != null && root.isShowing()) {
root.requestFocus();
myTextField.requestFocus();
return;
@@ -759,24 +760,29 @@ public abstract class ChooseByNameBase {
}
protected void doClose(final boolean ok) {
- try {
- if (checkDisposed()) return;
+ if (checkDisposed()) return;
- if (postponeCloseWhenListReady(ok)) return;
+ if (postponeCloseWhenListReady(ok)) return;
- cancelListUpdater();
- close(ok);
+ cancelListUpdater();
+ close(ok);
- clearPostponedOkAction(ok);
- }
- finally {
- myListModel.clear();
- cancelCalcElementsThread();
- }
+ clearPostponedOkAction(ok);
+ myListModel.clear();
}
protected void cancelListUpdater() {
- cancelCalcElementsThread();
+ final CalcElementsThread calcElementsThread = myCalcElementsThread;
+ if (calcElementsThread != null && calcElementsThread.cancel()) {
+ UIUtil.invokeLaterIfNeeded(new Runnable() {
+ @Override
+ public void run() {
+ if (!checkDisposed() && calcElementsThread == myCalcElementsThread) {
+ backgroundCalculationFinished(Collections.emptyList(), 0);
+ }
+ }
+ });
+ }
myListUpdater.cancelAll();
}
@@ -784,7 +790,7 @@ public abstract class ChooseByNameBase {
if (!isToFixLostTyping()) return false;
final String text = myTextField.getText();
- if (ok && !myListIsUpToDate && text != null && !text.trim().isEmpty()) {
+ if (ok && myCalcElementsThread != null && text != null && !text.trim().isEmpty()) {
myPostponedOkAction = new ActionCallback();
IdeFocusManager.getInstance(myProject).typeAheadUntil(myPostponedOkAction);
return true;
@@ -885,7 +891,7 @@ public abstract class ChooseByNameBase {
Disposer.register(myTextPopup, new Disposable() {
@Override
public void dispose() {
- cancelCalcElementsThread();
+ cancelListUpdater();
}
});
myTextPopup.show(layeredPane);
@@ -917,8 +923,6 @@ public abstract class ChooseByNameBase {
return layeredPane;
}
- private final Object myRebuildMutex = new Object();
-
protected void rebuildList(final int pos,
final int delay,
@NotNull final ModalityState modalityState,
@@ -928,11 +932,13 @@ public abstract class ChooseByNameBase {
return;
}
- myListIsUpToDate = false;
myAlarm.cancelAllRequests();
myListUpdater.cancelAll();
- cancelCalcElementsThread();
+ final CalcElementsThread calcElementsThread = myCalcElementsThread;
+ if (calcElementsThread != null) {
+ calcElementsThread.cancel();
+ }
final String text = myTextField.getText();
if (!canShowListForEmptyPattern() &&
@@ -960,24 +966,14 @@ public abstract class ChooseByNameBase {
scheduleCalcElements(text, myCheckBox.isSelected(), modalityState, new Consumer<Set<?>>() {
@Override
public void consume(Set<?> elements) {
- synchronized (myRebuildMutex) {
- ApplicationManager.getApplication().assertIsDispatchThread();
- if (checkDisposed()) {
- return;
- }
-
- myListIsUpToDate = true;
- setElementsToList(pos, elements);
- myList.repaint();
- chosenElementMightChange();
-
- if (elements.isEmpty()) {
- myTextFieldPanel.hideHint();
- }
+ ApplicationManager.getApplication().assertIsDispatchThread();
+ if (checkDisposed()) {
+ return;
+ }
+ backgroundCalculationFinished(elements, pos);
- if (postRunnable != null) {
- postRunnable.run();
- }
+ if (postRunnable != null) {
+ postRunnable.run();
}
}
});
@@ -992,6 +988,17 @@ public abstract class ChooseByNameBase {
}
}
+ private void backgroundCalculationFinished(Collection<?> result, int toSelect) {
+ myCalcElementsThread = null;
+ setElementsToList(toSelect, result);
+ myList.repaint();
+ chosenElementMightChange();
+
+ if (result.isEmpty()) {
+ myTextFieldPanel.hideHint();
+ }
+ }
+
public void scheduleCalcElements(String text,
boolean checkboxState,
ModalityState modalityState,
@@ -1008,16 +1015,7 @@ public abstract class ChooseByNameBase {
return myShowListAfterCompletionKeyStroke;
}
- private CalcElementsThread cancelCalcElementsThread() {
- CalcElementsThread calcElementsThread = myCalcElementsThread;
- if (calcElementsThread != null) {
- calcElementsThread.cancel();
- myCalcElementsThread = null;
- }
- return calcElementsThread;
- }
-
- private void setElementsToList(int pos, @NotNull Set<?> elements) {
+ private void setElementsToList(int pos, @NotNull Collection<?> elements) {
myListUpdater.cancelAll();
if (checkDisposed()) return;
if (elements.isEmpty()) {
@@ -1202,33 +1200,12 @@ public abstract class ChooseByNameBase {
}
protected List<Object> getChosenElements() {
-
- List<Object> values = new ArrayList<Object>(Arrays.asList(myList.getSelectedValues()));
- values.remove(EXTRA_ELEM);
- values.remove(NON_PREFIX_SEPARATOR);
-
- if (myListIsUpToDate || !values.isEmpty()) {
- return values;
- }
-
- final String text = myTextField.getText();
- if (text.length() == 0) return Collections.emptyList();
- final boolean checkBoxState = myCheckBox.isSelected();
- final String[] names = ourLoadNamesEachTime ? ensureNamesLoaded(checkBoxState) : getNamesSync(checkBoxState);
- if (names == null) return Collections.emptyList();
-
- Object uniqueElement = null;
-
- for (final String name : names) {
- if (text.equalsIgnoreCase(name)) {
- final Object[] elements = myModel.getElementsByName(name, checkBoxState, text);
- if (elements.length > 1) return Collections.emptyList();
- if (elements.length == 0) continue;
- if (uniqueElement != null) return Collections.emptyList();
- uniqueElement = elements[0];
+ return ContainerUtil.filter(myList.getSelectedValues(), new Condition<Object>() {
+ @Override
+ public boolean value(Object o) {
+ return o != EXTRA_ELEM && o != NON_PREFIX_SEPARATOR;
}
- }
- return uniqueElement == null ? Collections.emptyList() : Collections.singletonList(uniqueElement);
+ });
}
protected void chosenElementMightChange() {
@@ -1565,6 +1542,7 @@ public abstract class ChooseByNameBase {
@Override
public void run() {
if (!myCancelled.isCanceled()) {
+ LOG.assertTrue(myCalcElementsThread == CalcElementsThread.this);
myCallback.consume(edt ? filter(elements) : filtered);
}
}
@@ -1622,8 +1600,12 @@ public abstract class ChooseByNameBase {
return elementsArray.size() >= myMaximumListSizeLimit;
}
- private void cancel() {
+ private boolean cancel() {
+ if (myCancelled.isCanceled()) {
+ return false;
+ }
myCancelled.cancel();
+ return true;
}
}
@@ -1705,7 +1687,7 @@ public abstract class ChooseByNameBase {
final LinkedHashSet<Object> nonPrefixMatchElementsArray = new LinkedHashSet<Object>();
hideHint();
ProgressManager.getInstance().run(new Task.Modal(myProject, prefixPattern, true) {
- private ChooseByNameBase.CalcElementsThread myCalcElementsThread;
+ private ChooseByNameBase.CalcElementsThread myCalcUsagesThread;
@Override
public void run(@NotNull final ProgressIndicator indicator) {
@@ -1716,7 +1698,7 @@ public abstract class ChooseByNameBase {
@Override
public void run() {
final boolean[] overFlow = {false};
- myCalcElementsThread = new CalcElementsThread(text, everywhere, null, ModalityState.NON_MODAL, false) {
+ myCalcUsagesThread = new CalcElementsThread(text, everywhere, null, ModalityState.NON_MODAL, false) {
private final AtomicBoolean userAskedToAbort = new AtomicBoolean();
@Override
protected boolean isOverflow(@NotNull Set<Object> elementsArray) {
@@ -1734,11 +1716,11 @@ public abstract class ChooseByNameBase {
boolean anyPlace = isSearchInAnyPlace();
setSearchInAnyPlace(false);
- myCalcElementsThread.addElementsByPattern(text, prefixMatchElementsArray, indicator, everywhere);
+ myCalcUsagesThread.addElementsByPattern(text, prefixMatchElementsArray, indicator, everywhere);
setSearchInAnyPlace(anyPlace);
if (anyPlace && !overFlow[0]) {
- myCalcElementsThread.addElementsByPattern(text, nonPrefixMatchElementsArray, indicator, everywhere);
+ myCalcUsagesThread.addElementsByPattern(text, nonPrefixMatchElementsArray, indicator, everywhere);
nonPrefixMatchElementsArray.removeAll(prefixMatchElementsArray);
}
@@ -1756,7 +1738,7 @@ public abstract class ChooseByNameBase {
@Override
public void onCancel() {
- cancelCalcElementsThread();
+ myCalcUsagesThread.cancel();
}
});
}
diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNamePopup.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNamePopup.java
index cb03b68bfadb..86d9c1782b2a 100644
--- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNamePopup.java
+++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNamePopup.java
@@ -339,7 +339,7 @@ public class ChooseByNamePopup extends ChooseByNameBase implements ChooseByNameP
}
private static final Pattern patternToDetectLinesAndColumns = Pattern.compile("([^:]+)(?::|@|,|)\\[?(\\d+)?(?:(?:\\D)(\\d+)?)?\\]?");
- private static final Pattern patternToDetectAnonymousClasses = Pattern.compile("([\\.\\w]+)((\\$[\\d]+)*(\\$)?)");
+ public static final Pattern patternToDetectAnonymousClasses = Pattern.compile("([\\.\\w]+)((\\$[\\d]+)*(\\$)?)");
private static final Pattern patternToDetectMembers = Pattern.compile("(.+)(#)(.*)");
@Override
diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/DefaultChooseByNameItemProvider.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/DefaultChooseByNameItemProvider.java
index aa6a360c84e5..cc5915c26bb6 100644
--- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/DefaultChooseByNameItemProvider.java
+++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/DefaultChooseByNameItemProvider.java
@@ -189,6 +189,7 @@ public class DefaultChooseByNameItemProvider implements ChooseByNameItemProvider
@NotNull
private static String getQualifierPattern(@NotNull ChooseByNameBase base, @NotNull String pattern) {
+ pattern = base.transformPattern(pattern);
final String[] separators = base.getModel().getSeparators();
int lastSeparatorOccurrence = 0;
for (String separator : separators) {
diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionItemProvider.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionItemProvider.java
index a6e6c8fdf658..99d3c9b338ae 100644
--- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionItemProvider.java
+++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionItemProvider.java
@@ -26,6 +26,7 @@ import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.impl.ActionManagerImpl;
import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.ProgressManager;
import com.intellij.util.Function;
import com.intellij.util.Processor;
import com.intellij.util.containers.ContainerUtil;
@@ -128,17 +129,19 @@ public class GotoActionItemProvider implements ChooseByNameItemProvider {
List<AnAction> actions = ContainerUtil.newArrayList();
if (everywhere) {
for (String id : ((ActionManagerImpl)myActionManager).getActionIds()) {
+ ProgressManager.checkCanceled();
ContainerUtil.addIfNotNull(actions, myActionManager.getAction(id));
}
} else {
- actions.addAll(myModel.myActionsMap.keySet());
+ actions.addAll(myModel.myActionGroups.keySet());
}
List<ActionWrapper> actionWrappers = ContainerUtil.newArrayList();
for (AnAction action : actions) {
+ ProgressManager.checkCanceled();
MatchMode mode = myModel.actionMatches(pattern, action);
if (mode != MatchMode.NONE) {
- actionWrappers.add(new ActionWrapper(action, myModel.myActionsMap.get(action), mode, dataContext));
+ actionWrappers.add(new ActionWrapper(action, myModel.myActionGroups.get(action), mode, dataContext));
}
}
return processItems(pattern, actionWrappers, consumer);
diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java
index 91f0d3368521..348283dc3885 100644
--- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java
+++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java
@@ -66,16 +66,7 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C
private Pattern myCompiledPattern;
protected final SearchableOptionsRegistrar myIndex;
- protected final Map<AnAction, String> myActionsMap = new TreeMap<AnAction, String>(new Comparator<AnAction>() {
- @Override
- public int compare(@NotNull AnAction o1, @NotNull AnAction o2) {
- int compare = Comparing.compare(o1.getTemplatePresentation().getText(), o2.getTemplatePresentation().getText());
- if (compare == 0 && !o1.equals(o2)) {
- return o1.hashCode() - o2.hashCode();
- }
- return compare;
- }
- });
+ protected final Map<AnAction, String> myActionGroups = ContainerUtil.newHashMap();
protected final Map<String, ApplyIntentionAction> myIntentions = new TreeMap<String, ApplyIntentionAction>();
private final Map<String, String> myConfigurablesNames = ContainerUtil.newTroveMap();
@@ -88,7 +79,7 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C
myProject = project;
myContextComponent = component;
final ActionGroup mainMenu = (ActionGroup)myActionManager.getActionOrStub(IdeActions.GROUP_MAIN_MENU);
- collectActions(myActionsMap, mainMenu, mainMenu.getTemplatePresentation().getText());
+ collectActions(myActionGroups, mainMenu, mainMenu.getTemplatePresentation().getText());
if (project != null && editor != null && file != null) {
final ApplyIntentionAction[] children = ApplyIntentionAction.getAvailableIntentions(editor, file);
if (children != null) {
@@ -98,6 +89,9 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C
}
}
myIndex = SearchableOptionsRegistrar.getInstance();
+ if (!EventQueue.isDispatchThread()) {
+ return;
+ }
fillConfigurablesNames(ShowSettingsUtilImpl.getConfigurables(project, true));
}
@@ -457,11 +451,14 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C
else if (description != null && !description.equals(text) && matcher.matches(description, compiledPattern)) {
return MatchMode.DESCRIPTION;
}
- final String groupName = myActionsMap.get(anAction);
+ if (text == null) {
+ return MatchMode.NONE;
+ }
+ final String groupName = myActionGroups.get(anAction);
if (groupName == null) {
- return text != null && matcher.matches(text, compiledPattern) ? MatchMode.NON_MENU : MatchMode.NONE;
+ return matcher.matches(text, compiledPattern) ? MatchMode.NON_MENU : MatchMode.NONE;
}
- return text != null && matcher.matches(groupName + " " + text, compiledPattern) ? MatchMode.GROUP : MatchMode.NONE;
+ return matcher.matches(groupName + " " + text, compiledPattern) ? MatchMode.GROUP : MatchMode.NONE;
}
@Nullable
@@ -611,7 +608,7 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C
PatternMatcher getMatcher() {
return myMatcher.get();
}
-
+
public static class ActionWrapper implements Comparable<ActionWrapper>{
private final AnAction myAction;
private final MatchMode myMode;
diff --git a/platform/lang-impl/src/com/intellij/internal/DumpLookupElementWeights.java b/platform/lang-impl/src/com/intellij/internal/DumpLookupElementWeights.java
index 63d8a6038b6a..6350642c772e 100644
--- a/platform/lang-impl/src/com/intellij/internal/DumpLookupElementWeights.java
+++ b/platform/lang-impl/src/com/intellij/internal/DumpLookupElementWeights.java
@@ -22,7 +22,6 @@ import com.intellij.codeInsight.lookup.impl.LookupImpl;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
@@ -53,7 +52,12 @@ public class DumpLookupElementWeights extends AnAction implements DumbAware {
}
public static void dumpLookupElementWeights(final LookupImpl lookup) {
- String sb = StringUtil.join(getLookupElementWeights(lookup), "\n");
+ LookupElement selected = lookup.getCurrentItem();
+ String sb = "selected: " + selected;
+ if (selected != null) {
+ sb += "\nprefix: " + lookup.itemPattern(selected);
+ }
+ sb += "\nweights:\n" + StringUtil.join(getLookupElementWeights(lookup), "\n");
System.out.println(sb);
LOG.info(sb);
}
diff --git a/platform/lang-impl/src/com/intellij/lang/parser/GeneratedParserUtilBase.java b/platform/lang-impl/src/com/intellij/lang/parser/GeneratedParserUtilBase.java
index ad322c232fa0..ccf63a429346 100644
--- a/platform/lang-impl/src/com/intellij/lang/parser/GeneratedParserUtilBase.java
+++ b/platform/lang-impl/src/com/intellij/lang/parser/GeneratedParserUtilBase.java
@@ -100,8 +100,7 @@ public class GeneratedParserUtilBase {
if (!goodMarker) return false;
ErrorState state = ErrorState.get(builder_);
- Frame frame = state.frameStack.peekLast();
- return frame == null || frame.errorReportedAt <= builder_.rawTokenIndex();
+ return !state.frameStack.isEmpty();
}
public static TokenSet create_token_set_(IElementType... tokenTypes_) {
@@ -399,6 +398,11 @@ public class GeneratedParserUtilBase {
private static void enter_section_impl_(PsiBuilder builder_, int level, int modifiers, @Nullable String frameName) {
ErrorState state = ErrorState.get(builder_);
Frame frame = state.FRAMES.alloc().init(builder_, state, level, modifiers, frameName);
+ Frame prevFrame = state.frameStack.peekLast();
+ if (prevFrame != null && prevFrame.errorReportedAt > frame.position) {
+ // report error for previous unsuccessful frame
+ reportError(builder_, state, frame, true, false);
+ }
if (((frame.modifiers & _LEFT_) | (frame.modifiers & _LEFT_INNER_)) != 0) {
PsiBuilder.Marker left = (PsiBuilder.Marker)builder_.getLatestDoneMarker();
if (invalid_left_marker_guard_(builder_, left, frameName)) {
@@ -456,10 +460,10 @@ public class GeneratedParserUtilBase {
state.clearVariants(true, frame.variantCount);
addVariantInner(state, initialPos, frame.name);
}
+ int lastErrorPos = getLastVariantPos(state, initialPos);
if (!state.suppressErrors && eatMore != null) {
state.suppressErrors = true;
final boolean eatMoreFlagOnce = !builder_.eof() && eatMore.parse(builder_, frame.level + 1);
- final int lastErrorPos = getLastVariantPos(state, initialPos);
boolean eatMoreFlag = eatMoreFlagOnce || !result && frame.position == initialPos && lastErrorPos > frame.position;
PsiBuilderImpl.ProductionMarker latestDoneMarker =
@@ -497,7 +501,7 @@ public class GeneratedParserUtilBase {
errorReported = reportError(builder_, state, frame, true, true);
parseAsTree(state, builder_, frame.level + 1, DUMMY_BLOCK, true, TOKEN_ADVANCER, eatMore);
}
- else if (eatMoreFlagOnce || (!result && frame.position != builder_.rawTokenIndex())) {
+ else if (eatMoreFlagOnce || (!result && frame.position != builder_.rawTokenIndex()) || frame.errorReportedAt > initialPos) {
errorReported = reportError(builder_, state, frame, true, false);
}
if (extensionMarker != null) {
@@ -512,10 +516,14 @@ public class GeneratedParserUtilBase {
}
else if (!result && pinned && frame.errorReportedAt < 0) {
// do not report if there are errors beyond current position
- if (getLastVariantPos(state, initialPos) == initialPos) {
+ if (lastErrorPos == initialPos) {
// do not force, inner recoverRoot might have skipped some tokens
reportError(builder_, state, frame, false, false);
}
+ else if (lastErrorPos > initialPos) {
+ // set error pos here as if it is reported for future reference
+ frame.errorReportedAt = lastErrorPos;
+ }
}
// propagate errorReportedAt up the stack to avoid duplicate reporting
Frame prevFrame = willFail && eatMore == null ? null : state.frameStack.peekLast();
@@ -607,7 +615,7 @@ public class GeneratedParserUtilBase {
return;
}
int position = builder_.rawTokenIndex();
- if (frame.errorReportedAt < position && getLastVariantPos(state, position) <= position) {
+ if (frame.errorReportedAt < position && getLastVariantPos(state, position + 1) <= position) {
reportError(builder_, state, frame, true, advance);
}
}
@@ -865,7 +873,7 @@ public class GeneratedParserUtilBase {
((modifiers & _LEFT_INNER_) != 0? "_LEFT_INNER_, ": "") +
((modifiers & _AND_) != 0? "_AND_, ": "") +
((modifiers & _NOT_) != 0? "_NOT_, ": "");
- return "<" + offset + ", " + mod + level + (errorReportedAt > -1 ? ", [" + errorReportedAt + "]" : "") + ">";
+ return String.format("{%s:%s:%d, %d, %s%s}", offset, position, level, errorReportedAt, mod, name);
}
}
diff --git a/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectAllOccurrencesAction.java b/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectAllOccurrencesAction.java
index 3e284ff6b2cc..ae2a4dc0d53c 100644
--- a/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectAllOccurrencesAction.java
+++ b/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectAllOccurrencesAction.java
@@ -42,8 +42,6 @@ public class SelectAllOccurrencesAction extends EditorAction {
@Override
public void doExecute(final Editor editor, @Nullable Caret c, DataContext dataContext) {
- if (executeEquivalentFindPanelAction(editor, dataContext)) return;
-
Caret caret = c == null ? editor.getCaretModel().getPrimaryCaret() : c;
boolean wholeWordsSearch = false;
@@ -88,10 +86,5 @@ public class SelectAllOccurrencesAction extends EditorAction {
}, caretShiftFromSelectionStart);
editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
}
-
- @Override
- protected EditorHeaderAction getEquivalentFindPanelAction(EditorSearchComponent searchComponent) {
- return new SelectAllAction(searchComponent);
- }
}
}
diff --git a/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectNextOccurrenceAction.java b/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectNextOccurrenceAction.java
index 7d3c408ee152..74390f15b149 100644
--- a/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectNextOccurrenceAction.java
+++ b/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectNextOccurrenceAction.java
@@ -40,8 +40,6 @@ public class SelectNextOccurrenceAction extends EditorAction {
@Override
public void doExecute(Editor editor, @Nullable Caret c, DataContext dataContext) {
- if (executeEquivalentFindPanelAction(editor, dataContext)) return;
-
Caret caret = c == null ? editor.getCaretModel().getPrimaryCaret() : c;
TextRange wordSelectionRange = getSelectionRange(editor, caret);
boolean notFoundPreviously = getAndResetNotFoundStatus(editor);
@@ -56,7 +54,7 @@ public class SelectNextOccurrenceAction extends EditorAction {
FindModel model = getFindModel(selectedText, wholeWordSearch);
- findManager.setFindWasPerformed();
+ findManager.setSelectNextOccurrenceWasPerformed();
findManager.setFindNextModel(model);
int searchStartOffset = notFoundPreviously ? 0 : caret.getSelectionEnd();
@@ -84,10 +82,5 @@ public class SelectNextOccurrenceAction extends EditorAction {
}
editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
}
-
- @Override
- protected EditorHeaderAction getEquivalentFindPanelAction(EditorSearchComponent searchComponent) {
- return new AddOccurrenceAction(searchComponent);
- }
}
}
diff --git a/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectOccurrencesActionHandler.java b/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectOccurrencesActionHandler.java
index 7b189281dfd0..1858ef53b3f5 100644
--- a/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectOccurrencesActionHandler.java
+++ b/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectOccurrencesActionHandler.java
@@ -107,25 +107,4 @@ abstract public class SelectOccurrencesActionHandler extends EditorActionHandler
model.setWholeWordsOnly(wholeWords);
return model;
}
-
- protected boolean executeEquivalentFindPanelAction(Editor editor, DataContext context) {
- if (editor.getHeaderComponent() instanceof EditorSearchComponent) {
- EditorSearchComponent searchComponent = (EditorSearchComponent)editor.getHeaderComponent();
- EditorHeaderAction action = getEquivalentFindPanelAction(searchComponent);
- if (action != null) {
- Presentation presentation = new Presentation();
- AnActionEvent event = new AnActionEvent(null, context, ActionPlaces.MAIN_MENU, presentation, ActionManager.getInstance(), 0);
- action.update(event);
- if (presentation.isEnabled()) {
- action.actionPerformed(event);
- return true;
- }
- }
- }
- return false;
- }
-
- protected EditorHeaderAction getEquivalentFindPanelAction(EditorSearchComponent searchComponent) {
- return null;
- }
}
diff --git a/platform/lang-impl/src/com/intellij/openapi/editor/actions/UnselectPreviousOccurrenceAction.java b/platform/lang-impl/src/com/intellij/openapi/editor/actions/UnselectPreviousOccurrenceAction.java
index fffff56b12dc..a5657ff89b27 100644
--- a/platform/lang-impl/src/com/intellij/openapi/editor/actions/UnselectPreviousOccurrenceAction.java
+++ b/platform/lang-impl/src/com/intellij/openapi/editor/actions/UnselectPreviousOccurrenceAction.java
@@ -15,9 +15,6 @@
*/
package com.intellij.openapi.editor.actions;
-import com.intellij.find.EditorSearchComponent;
-import com.intellij.find.editorHeaderActions.EditorHeaderAction;
-import com.intellij.find.editorHeaderActions.RemoveOccurrenceAction;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
@@ -38,8 +35,6 @@ public class UnselectPreviousOccurrenceAction extends EditorAction {
@Override
public void doExecute(Editor editor, @Nullable Caret caret, DataContext dataContext) {
- if (executeEquivalentFindPanelAction(editor, dataContext)) return;
-
if (editor.getCaretModel().getCaretCount() > 1) {
editor.getCaretModel().removeCaret(editor.getCaretModel().getPrimaryCaret());
}
@@ -49,10 +44,5 @@ public class UnselectPreviousOccurrenceAction extends EditorAction {
getAndResetNotFoundStatus(editor);
editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
}
-
- @Override
- protected EditorHeaderAction getEquivalentFindPanelAction(EditorSearchComponent searchComponent) {
- return new RemoveOccurrenceAction(searchComponent);
- }
}
}
diff --git a/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/FontMapper.java b/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/FontMapper.java
index 4fec39342090..c5fd5592b634 100644
--- a/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/FontMapper.java
+++ b/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/FontMapper.java
@@ -16,10 +16,10 @@
package com.intellij.openapi.editor.richcopy;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.util.ReflectionUtil;
import org.jetbrains.annotations.NotNull;
import java.awt.*;
-import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Locale;
@@ -46,20 +46,18 @@ public class FontMapper {
}
Method findFontMethod = Class.forName("sun.font.FontManager").getMethod("findFont2D", String.class, int.class, int.class);
for (String logicalFont : logicalFontsToMap) {
- String physicalFont = null;
Object font2D = findFontMethod.invoke(fontManager, logicalFont, Font.PLAIN, 0);
if (font2D == null) {
continue;
}
String fontClassName = font2D.getClass().getName();
+ String physicalFont = null;
if ("sun.font.CompositeFont".equals(fontClassName)) { // Windows and Linux case
Object physicalFontObject = Class.forName("sun.font.CompositeFont").getMethod("getSlotFont", int.class).invoke(font2D, 0);
physicalFont = (String)Class.forName("sun.font.Font2D").getMethod("getFamilyName", Locale.class).invoke(physicalFontObject, Locale.getDefault());
}
else if ("sun.font.CFont".equals(fontClassName)) { // MacOS case
- Field field = Class.forName("sun.font.CFont").getDeclaredField("nativeFontName");
- field.setAccessible(true);
- physicalFont = (String)field.get(font2D);
+ physicalFont = ReflectionUtil.getField(Class.forName("sun.font.CFont"), font2D, String.class, "nativeFontName");
}
if (physicalFont != null) {
logicalToPhysicalMapping.put(logicalFont, physicalFont);
diff --git a/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/TextWithMarkupProcessor.java b/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/TextWithMarkupProcessor.java
index 54406106b976..504496a27716 100644
--- a/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/TextWithMarkupProcessor.java
+++ b/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/TextWithMarkupProcessor.java
@@ -23,6 +23,7 @@ import com.intellij.ide.highlighter.HighlighterFactory;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
+import com.intellij.openapi.editor.colors.FontPreferences;
import com.intellij.openapi.editor.colors.TextAttributesKey;
import com.intellij.openapi.editor.ex.DisposableIterator;
import com.intellij.openapi.editor.ex.MarkupModelEx;
@@ -418,7 +419,7 @@ public class TextWithMarkupProcessor extends CopyPastePostProcessor<RawTextWithM
private MarkupIterator(@NotNull CharSequence charSequence, @NotNull RangeIterator rangeIterator, @NotNull EditorColorsScheme colorsScheme) {
myRangeIterator = rangeIterator;
- mySegmentIterator = new SegmentIterator(charSequence, colorsScheme.getEditorFontName(), colorsScheme.getEditorFontSize());
+ mySegmentIterator = new SegmentIterator(charSequence, colorsScheme.getFontPreferences());
}
public boolean atEnd() {
@@ -812,8 +813,7 @@ public class TextWithMarkupProcessor extends CopyPastePostProcessor<RawTextWithM
private static class SegmentIterator {
private final CharSequence myCharSequence;
- private final String myDefaultFontFamilyName;
- private final int myFontSize;
+ private final FontPreferences myFontPreferences;
private int myCurrentStartOffset;
private int myCurrentOffset;
@@ -822,10 +822,9 @@ public class TextWithMarkupProcessor extends CopyPastePostProcessor<RawTextWithM
private String myCurrentFontFamilyName;
private String myNextFontFamilyName;
- private SegmentIterator(CharSequence charSequence, String defaultFontFamilyName, int fontSize) {
+ private SegmentIterator(CharSequence charSequence, FontPreferences fontPreferences) {
myCharSequence = charSequence;
- myDefaultFontFamilyName = defaultFontFamilyName;
- myFontSize = fontSize;
+ myFontPreferences = fontPreferences;
}
public void reset(int startOffset, int endOffset, int fontStyle) {
@@ -843,9 +842,8 @@ public class TextWithMarkupProcessor extends CopyPastePostProcessor<RawTextWithM
myCurrentStartOffset = myCurrentOffset;
for (; myCurrentOffset < myEndOffset; myCurrentOffset++) {
FontInfo fontInfo = ComplementaryFontsRegistry.getFontAbleToDisplay(myCharSequence.charAt(myCurrentOffset),
- myFontSize,
myFontStyle,
- myDefaultFontFamilyName);
+ myFontPreferences);
String fontFamilyName = fontInfo.getFont().getFamily();
if (myCurrentFontFamilyName == null) {
diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexImpl.java b/platform/lang-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexImpl.java
index b1385686bc3a..09e489b3d1df 100644
--- a/platform/lang-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexImpl.java
+++ b/platform/lang-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexImpl.java
@@ -25,15 +25,14 @@ import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.roots.ModuleRootAdapter;
-import com.intellij.openapi.roots.ModuleRootEvent;
-import com.intellij.openapi.roots.ModuleRootManager;
+import com.intellij.openapi.roots.*;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.openapi.vfs.newvfs.BulkFileListener;
import com.intellij.openapi.vfs.newvfs.NewVirtualFile;
import com.intellij.openapi.vfs.newvfs.events.VFileEvent;
+import com.intellij.util.IncorrectOperationException;
import com.intellij.util.Query;
import com.intellij.util.containers.ConcurrentIntObjectMap;
import com.intellij.util.containers.StripedLockIntObjectConcurrentHashMap;
@@ -43,6 +42,8 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
public class DirectoryIndexImpl extends DirectoryIndex {
@@ -68,7 +69,7 @@ public class DirectoryIndexImpl extends DirectoryIndex {
});
}
- private void subscribeToFileChanges() {
+ protected void subscribeToFileChanges() {
myConnection.subscribe(FileTypeManager.TOPIC, new FileTypeListener.Adapter() {
@Override
public void fileTypesChanged(@NotNull FileTypeEvent event) {
@@ -98,7 +99,7 @@ public class DirectoryIndexImpl extends DirectoryIndex {
});
}
- private void markContentRootsForRefresh() {
+ protected void markContentRootsForRefresh() {
Module[] modules = ModuleManager.getInstance(myProject).getModules();
for (Module module : modules) {
VirtualFile[] contentRoots = ModuleRootManager.getInstance(module).getContentRoots();
@@ -110,7 +111,7 @@ public class DirectoryIndexImpl extends DirectoryIndex {
}
}
- private void dispatchPendingEvents() {
+ protected void dispatchPendingEvents() {
myConnection.deliverImmediately();
}
@@ -124,24 +125,27 @@ public class DirectoryIndexImpl extends DirectoryIndex {
private RootIndex getRootIndex() {
RootIndex rootIndex = myRootIndex;
if (rootIndex == null) {
- myRootIndex = rootIndex = new RootIndex(myProject, new RootIndex.InfoCache() {
- // Upsource can't use int-mapping because different files may have the same id there
- private final ConcurrentIntObjectMap<DirectoryInfo> myInfoCache = new StripedLockIntObjectConcurrentHashMap<DirectoryInfo>();
- @Override
- public void cacheInfo(@NotNull VirtualFile dir, @NotNull DirectoryInfo info) {
- myInfoCache.put(((NewVirtualFile)dir).getId(), info);
- }
-
- @Override
- public DirectoryInfo getCachedInfo(@NotNull VirtualFile dir) {
- return myInfoCache.get(((NewVirtualFile)dir).getId());
- }
- });
+ myRootIndex = rootIndex = new RootIndex(myProject, createRootInfoCache());
}
return rootIndex;
}
- @Override
+ protected RootIndex.InfoCache createRootInfoCache() {
+ return new RootIndex.InfoCache() {
+ // Upsource can't use int-mapping because different files may have the same id there
+ private final ConcurrentIntObjectMap<DirectoryInfo> myInfoCache = new StripedLockIntObjectConcurrentHashMap<DirectoryInfo>();
+ @Override
+ public void cacheInfo(@NotNull VirtualFile dir, @NotNull DirectoryInfo info) {
+ myInfoCache.put(((NewVirtualFile)dir).getId(), info);
+ }
+
+ @Override
+ public DirectoryInfo getCachedInfo(@NotNull VirtualFile dir) {
+ return myInfoCache.get(((NewVirtualFile)dir).getId());
+ }
+ };
+ }
+
@TestOnly
public void checkConsistency() {
getRootIndex().checkConsistency();
@@ -181,6 +185,21 @@ public class DirectoryIndexImpl extends DirectoryIndex {
return getRootIndex().getPackageName(dir);
}
+ @NotNull
+ @Override
+ public OrderEntry[] getOrderEntries(@NotNull DirectoryInfo info) {
+ checkAvailability();
+ return getRootIndex().getOrderEntries(info);
+ }
+
+ @TestOnly
+ void assertConsistency(DirectoryInfo info) {
+ OrderEntry[] entries = getOrderEntries(info);
+ for (int i = 1; i < entries.length; i++) {
+ assert RootIndex.BY_OWNER_MODULE.compare(entries[i - 1], entries[i]) <= 0;
+ }
+ }
+
private void checkAvailability() {
if (myDisposed) {
ProgressManager.checkCanceled();
@@ -188,4 +207,95 @@ public class DirectoryIndexImpl extends DirectoryIndex {
}
}
+ @NotNull
+ private static OrderEntry createFakeOrderEntry(@NotNull final Module ownerModule) {
+ return new OrderEntry() {
+ @NotNull
+ @Override
+ public VirtualFile[] getFiles(OrderRootType type) {
+ throw new IncorrectOperationException();
+ }
+
+ @NotNull
+ @Override
+ public String[] getUrls(OrderRootType rootType) {
+ throw new IncorrectOperationException();
+ }
+
+ @NotNull
+ @Override
+ public String getPresentableName() {
+ throw new IncorrectOperationException();
+ }
+
+ @Override
+ public boolean isValid() {
+ throw new IncorrectOperationException();
+ }
+
+ @NotNull
+ @Override
+ public Module getOwnerModule() {
+ return ownerModule;
+ }
+
+ @Override
+ public <R> R accept(RootPolicy<R> policy, @Nullable R initialValue) {
+ throw new IncorrectOperationException();
+ }
+
+ @Override
+ public int compareTo(@NotNull OrderEntry o) {
+ throw new IncorrectOperationException();
+ }
+
+ @Override
+ public boolean isSynthetic() {
+ throw new IncorrectOperationException();
+ }
+ };
+ }
+
+ @Override
+ @Nullable
+ OrderEntry findOrderEntryWithOwnerModule(@NotNull DirectoryInfo info, @NotNull Module ownerModule) {
+ OrderEntry[] entries = getOrderEntries(info);
+ if (entries.length < 10) {
+ for (OrderEntry entry : entries) {
+ if (entry.getOwnerModule() == ownerModule) return entry;
+ }
+ return null;
+ }
+ int index = Arrays.binarySearch(entries, createFakeOrderEntry(ownerModule), RootIndex.BY_OWNER_MODULE);
+ return index < 0 ? null : entries[index];
+ }
+
+ @Override
+ @NotNull
+ List<OrderEntry> findAllOrderEntriesWithOwnerModule(@NotNull DirectoryInfo info, @NotNull Module ownerModule) {
+ OrderEntry[] entries = getOrderEntries(info);
+ if (entries.length == 0) return Collections.emptyList();
+
+ if (entries.length == 1) {
+ OrderEntry entry = entries[0];
+ return entry.getOwnerModule() == ownerModule ? Arrays.asList(entries) : Collections.<OrderEntry>emptyList();
+ }
+ int index = Arrays.binarySearch(entries, createFakeOrderEntry(ownerModule), RootIndex.BY_OWNER_MODULE);
+ if (index < 0) {
+ return Collections.emptyList();
+ }
+ int firstIndex = index;
+ while (firstIndex - 1 >= 0 && entries[firstIndex - 1].getOwnerModule() == ownerModule) {
+ firstIndex--;
+ }
+ int lastIndex = index + 1;
+ while (lastIndex < entries.length && entries[lastIndex].getOwnerModule() == ownerModule) {
+ lastIndex++;
+ }
+
+ OrderEntry[] subArray = new OrderEntry[lastIndex - firstIndex];
+ System.arraycopy(entries, firstIndex, subArray, 0, lastIndex - firstIndex);
+
+ return Arrays.asList(subArray);
+ }
}
diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerComponent.java b/platform/lang-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerComponent.java
index 932204c6dbd3..4ba8b7b03a8d 100644
--- a/platform/lang-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerComponent.java
+++ b/platform/lang-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerComponent.java
@@ -72,10 +72,8 @@ public class ProjectRootManagerComponent extends ProjectRootManagerImpl {
private Set<LocalFileSystem.WatchRequest> myRootsToWatch = new THashSet<LocalFileSystem.WatchRequest>();
private final boolean myDoLogCachesUpdate;
- public ProjectRootManagerComponent(Project project,
- DirectoryIndex directoryIndex,
- StartupManager startupManager) {
- super(project, directoryIndex);
+ public ProjectRootManagerComponent(Project project, StartupManager startupManager) {
+ super(project);
myConnection = project.getMessageBus().connect(project);
myConnection.subscribe(FileTypeManager.TOPIC, new FileTypeListener() {
diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/DetectedRootsChooserDialog.java b/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/DetectedRootsChooserDialog.java
index ee44bdf2f08b..bf3d383aeebb 100644
--- a/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/DetectedRootsChooserDialog.java
+++ b/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/DetectedRootsChooserDialog.java
@@ -26,11 +26,13 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.*;
import com.intellij.ui.treeStructure.treetable.TreeColumnInfo;
import com.intellij.util.PlatformIcons;
+import com.intellij.util.containers.Convertor;
import com.intellij.util.ui.ColumnInfo;
import com.intellij.util.ui.ComboBoxCellEditor;
import com.intellij.util.ui.tree.TreeUtil;
import com.intellij.xml.util.XmlStringUtil;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -38,12 +40,11 @@ import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
+import javax.swing.tree.TreePath;
import java.awt.*;
import java.io.File;
-import java.util.Arrays;
-import java.util.HashMap;
+import java.util.*;
import java.util.List;
-import java.util.Map;
/**
* This dialog allows selecting paths inside selected archives or directories.
@@ -108,17 +109,17 @@ public class DetectedRootsChooserDialog extends DialogWrapper {
private JScrollPane myPane;
private String myDescription;
- public DetectedRootsChooserDialog(Component component, List<SuggestedChildRootInfo> suggestedRoots) {
+ public DetectedRootsChooserDialog(Component component, Collection<SuggestedChildRootInfo> suggestedRoots) {
super(component, true);
init(suggestedRoots);
}
- public DetectedRootsChooserDialog(Project project, List<SuggestedChildRootInfo> suggestedRoots) {
+ public DetectedRootsChooserDialog(Project project, Collection<SuggestedChildRootInfo> suggestedRoots) {
super(project, true);
init(suggestedRoots);
}
- private void init(List<SuggestedChildRootInfo> suggestedRoots) {
+ private void init(Collection<SuggestedChildRootInfo> suggestedRoots) {
myDescription = XmlStringUtil.wrapInHtml(ApplicationNamesInfo.getInstance().getFullProductName() +
" just scanned files and detected the following " + StringUtil.pluralize("root", suggestedRoots.size()) + ".<br>" +
"Select items in the tree below or press Cancel to cancel operation.");
@@ -128,7 +129,7 @@ public class DetectedRootsChooserDialog extends DialogWrapper {
init();
}
- private static CheckboxTreeTable createTreeTable(List<SuggestedChildRootInfo> suggestedRoots) {
+ private static CheckboxTreeTable createTreeTable(Collection<SuggestedChildRootInfo> suggestedRoots) {
final CheckedTreeNode root = createRoot(suggestedRoots);
CheckboxTreeTable treeTable = new CheckboxTreeTable(root, new CheckboxTree.CheckboxTreeCellRenderer(true) {
@Override
@@ -189,14 +190,30 @@ public class DetectedRootsChooserDialog extends DialogWrapper {
column.setPreferredWidth(width);
column.setMaxWidth(width);
treeTable.setRootVisible(false);
+ new TreeTableSpeedSearch(treeTable, new Convertor<TreePath, String>() {
+ @Override
+ public String convert(TreePath o) {
+ Object node = o.getLastPathComponent();
+ if (!(node instanceof VirtualFileCheckedTreeNode)) return "";
+ return ((VirtualFileCheckedTreeNode)node).getFile().getPresentableUrl();
+ }
+ });
TreeUtil.expandAll(treeTable.getTree());
return treeTable;
}
- private static CheckedTreeNode createRoot(List<SuggestedChildRootInfo> suggestedRoots) {
+ private static CheckedTreeNode createRoot(Collection<SuggestedChildRootInfo> suggestedRoots) {
+ SuggestedChildRootInfo[] sortedRoots = suggestedRoots.toArray(new SuggestedChildRootInfo[suggestedRoots.size()]);
+ Arrays.sort(sortedRoots, new Comparator<SuggestedChildRootInfo>() {
+ @Override
+ public int compare(@NotNull SuggestedChildRootInfo o1, @NotNull SuggestedChildRootInfo o2) {
+ return o1.getDetectedRoot().getFile().getPresentableUrl().compareTo(o2.getDetectedRoot().getFile().getPresentableUrl());
+ }
+ });
+
CheckedTreeNode root = new CheckedTreeNode(null);
Map<VirtualFile, CheckedTreeNode> rootCandidateNodes = new HashMap<VirtualFile, CheckedTreeNode>();
- for (SuggestedChildRootInfo rootInfo : suggestedRoots) {
+ for (SuggestedChildRootInfo rootInfo : sortedRoots) {
final VirtualFile rootCandidate = rootInfo.getRootCandidate();
CheckedTreeNode parent = rootCandidateNodes.get(rootCandidate);
if (parent == null) {
@@ -230,6 +247,12 @@ public class DetectedRootsChooserDialog extends DialogWrapper {
return "DetectedRootsChooserDialog";
}
+ @Nullable
+ @Override
+ public JComponent getPreferredFocusedComponent() {
+ return myTreeTable;
+ }
+
private static class VirtualFileCheckedTreeNode extends CheckedTreeNode {
private final VirtualFile myFile;
diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/SuggestedChildRootInfo.java b/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/SuggestedChildRootInfo.java
index 743e408b8c97..725216600ffa 100644
--- a/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/SuggestedChildRootInfo.java
+++ b/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/SuggestedChildRootInfo.java
@@ -19,6 +19,7 @@ import com.intellij.openapi.roots.libraries.LibraryRootType;
import com.intellij.openapi.roots.libraries.ui.DetectedLibraryRoot;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ArrayUtil;
+import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.Map;
@@ -32,17 +33,19 @@ class SuggestedChildRootInfo {
private final Map<LibraryRootType, String> myRootTypeNames;
private LibraryRootType mySelectedRootType;
- SuggestedChildRootInfo(VirtualFile rootCandidate, DetectedLibraryRoot detectedRoot, Map<LibraryRootType, String> rootTypeNames) {
+ SuggestedChildRootInfo(@NotNull VirtualFile rootCandidate, @NotNull DetectedLibraryRoot detectedRoot, @NotNull Map<LibraryRootType, String> rootTypeNames) {
myRootCandidate = rootCandidate;
myDetectedRoot = detectedRoot;
myRootTypeNames = rootTypeNames;
mySelectedRootType = detectedRoot.getTypes().get(0);
}
+ @NotNull
public VirtualFile getRootCandidate() {
return myRootCandidate;
}
+ @NotNull
public DetectedLibraryRoot getDetectedRoot() {
return myDetectedRoot;
}
@@ -51,6 +54,7 @@ class SuggestedChildRootInfo {
return myRootTypeNames.get(type);
}
+ @NotNull
public LibraryRootType getSelectedRootType() {
return mySelectedRootType;
}
@@ -64,6 +68,7 @@ class SuggestedChildRootInfo {
}
}
+ @NotNull
public String[] getRootTypeNames() {
final String[] types = ArrayUtil.toStringArray(myRootTypeNames.values());
Arrays.sort(types, String.CASE_INSENSITIVE_ORDER);
diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/CommonContentEntriesEditor.java b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/CommonContentEntriesEditor.java
index 72f9c5a965c0..04f908a17c00 100644
--- a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/CommonContentEntriesEditor.java
+++ b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/CommonContentEntriesEditor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -33,12 +33,15 @@ import com.intellij.openapi.roots.ModuleRootModel;
import com.intellij.openapi.roots.ui.componentsList.components.ScrollablePanel;
import com.intellij.openapi.roots.ui.componentsList.layout.VerticalStackLayout;
import com.intellij.openapi.roots.ui.configuration.actions.IconWithTextAction;
-import com.intellij.openapi.ui.Splitter;
+import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.openapi.vfs.ex.VirtualFileManagerAdapter;
+import com.intellij.ui.JBSplitter;
+import com.intellij.ui.OnePixelSplitter;
import com.intellij.ui.ScrollPaneFactory;
+import com.intellij.ui.border.CustomLineBorder;
import com.intellij.ui.roots.ToolbarPanel;
import com.intellij.util.Consumer;
import com.intellij.util.ui.UIUtil;
@@ -48,6 +51,7 @@ import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
import javax.swing.*;
import javax.swing.border.Border;
+import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
@@ -146,7 +150,9 @@ public class CommonContentEntriesEditor extends ModuleElementsEditor {
myContentEntryEditorListener = new MyContentEntryEditorListener();
final JPanel mainPanel = new JPanel(new BorderLayout());
- mainPanel.setBorder(BorderFactory.createEmptyBorder(6, 6, 6, 6));
+ if (!Registry.is("ide.new.project.settings")) {
+ mainPanel.setBorder(BorderFactory.createEmptyBorder(6, 6, 6, 6));
+ }
addAdditionalSettingsToPanel(mainPanel);
@@ -159,21 +165,32 @@ public class CommonContentEntriesEditor extends ModuleElementsEditor {
myEditorsPanel = new ScrollablePanel(new VerticalStackLayout());
myEditorsPanel.setBackground(BACKGROUND_COLOR);
- JScrollPane myScrollPane = ScrollPaneFactory.createScrollPane(myEditorsPanel);
- entriesPanel.add(new ToolbarPanel(myScrollPane, group), BorderLayout.CENTER);
+ JScrollPane myScrollPane = ScrollPaneFactory.createScrollPane(myEditorsPanel, Registry.is("ide.new.project.settings"));
+ final ToolbarPanel toolbarPanel = new ToolbarPanel(myScrollPane, group);
+ if (Registry.is("ide.new.project.settings")) {
+ toolbarPanel.setBorder(new CustomLineBorder(1,0,0,0));
+ }
+ entriesPanel.add(toolbarPanel, BorderLayout.CENTER);
- final Splitter splitter = new Splitter(false);
+ final JBSplitter splitter = Registry.is("ide.new.project.settings") ? new OnePixelSplitter(false) : new JBSplitter(false);
splitter.setProportion(0.6f);
splitter.setHonorComponentsMinimumSize(true);
myRootTreeEditor = createContentEntryTreeEditor(project);
- splitter.setFirstComponent(myRootTreeEditor.createComponent());
+ final JComponent component = myRootTreeEditor.createComponent();
+ if (Registry.is("ide.new.project.settings")) {
+ component.setBorder(new CustomLineBorder(1,0,0,0));
+ }
+
+ splitter.setFirstComponent(component);
splitter.setSecondComponent(entriesPanel);
JPanel contentPanel = new JPanel(new GridBagLayout());
- contentPanel.setBorder(BorderFactory.createEtchedBorder());
+ if (!Registry.is("ide.new.project.settings")) {
+ contentPanel.setBorder(BorderFactory.createEtchedBorder());
+ }
final ActionToolbar actionToolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, myRootTreeEditor.getEditingActionsGroup(), true);
contentPanel.add(new JLabel("Mark as:"),
- new GridBagConstraints(0, 0, 1, 1, 0, 0, GridBagConstraints.WEST, 0, new Insets(0, 5, 0, 5), 0, 0));
+ new GridBagConstraints(0, 0, 1, 1, 0, 0, GridBagConstraints.WEST, 0, new Insets(0, 10, 0, 10), 0, 0));
contentPanel.add(actionToolbar.getComponent(),
new GridBagConstraints(1, 0, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL,
new Insets(0, 0, 0, 0), 0, 0));
@@ -236,7 +253,11 @@ public class CommonContentEntriesEditor extends ModuleElementsEditor {
if (componentBorder != null) {
border = BorderFactory.createCompoundBorder(border, componentBorder);
}
- component.setBorder(border);
+ if (Registry.is("ide.new.project.settings")) {
+ component.setBorder(new EmptyBorder(0,0,0,0));
+ } else {
+ component.setBorder(border);
+ }
myEditorsPanel.add(component);
}
diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentRootPanel.java b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentRootPanel.java
index 469d966a29d8..bc10302c9c43 100644
--- a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentRootPanel.java
+++ b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentRootPanel.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,6 +36,7 @@ import com.intellij.ui.roots.IconActionComponent;
import com.intellij.ui.roots.ResizingWrapper;
import com.intellij.uiDesigner.core.GridConstraints;
import com.intellij.uiDesigner.core.GridLayoutManager;
+import com.intellij.util.NotNullProducer;
import com.intellij.util.containers.MultiMap;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
@@ -59,10 +60,22 @@ import java.util.Map;
*/
public abstract class ContentRootPanel extends JPanel {
private static final Color EXCLUDED_COLOR = new JBColor(new Color(0x992E00), DarculaColors.RED);
- private static final Color SELECTED_HEADER_COLOR = new JBColor(new Color(0xDEF2FF), UIUtil.getPanelBackground().darker());
+ private static final Color SELECTED_HEADER_COLOR = new JBColor(new NotNullProducer<Color>() {
+ @NotNull
+ @Override
+ public Color produce() {
+ return UIUtil.isUnderDarcula() ? UIUtil.getPanelBackground().darker() : new Color(0xDEF2FF);
+ }
+ });
private static final Color HEADER_COLOR = new JBColor(new Color(0xF5F5F5), Gray._82);
private static final Color SELECTED_CONTENT_COLOR = new Color(0xF0F9FF);
- private static final Color CONTENT_COLOR = new JBColor(Color.WHITE, UIUtil.getPanelBackground());
+ private static final Color CONTENT_COLOR = new JBColor(new NotNullProducer<Color>() {
+ @NotNull
+ @Override
+ public Color produce() {
+ return UIUtil.isUnderDarcula() ? UIUtil.getPanelBackground() : Gray._255;
+ }
+ });
private static final Color UNSELECTED_TEXT_COLOR = Gray._51;
protected final ActionCallback myCallback;
@@ -140,7 +153,7 @@ public abstract class ContentRootPanel extends JPanel {
headerLabel.setFont(headerLabel.getFont().deriveFont(Font.BOLD));
headerLabel.setOpaque(false);
if (getContentEntry().getFile() == null) {
- headerLabel.setForeground(Color.RED);
+ headerLabel.setForeground(JBColor.RED);
}
final IconActionComponent deleteIconComponent = new IconActionComponent(AllIcons.Modules.DeleteContentRoot,
AllIcons.Modules.DeleteContentRootRollover,
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/AddScopeUtil.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/AddScopeUtil.java
deleted file mode 100644
index d92445254f28..000000000000
--- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/AddScopeUtil.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright 2000-2012 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.
- */
-
-/*
- * User: anna
- * Date: 14-May-2009
- */
-package com.intellij.profile.codeInspection.ui;
-
-import com.intellij.codeHighlighting.HighlightDisplayLevel;
-import com.intellij.codeInspection.ex.Descriptor;
-import com.intellij.codeInspection.ex.InspectionProfileImpl;
-import com.intellij.codeInspection.ex.InspectionToolWrapper;
-import com.intellij.codeInspection.ex.ScopeToolState;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.Messages;
-import com.intellij.profile.codeInspection.ui.inspectionsTree.InspectionConfigTreeNode;
-import com.intellij.psi.search.scope.packageSet.CustomScopesProviderEx;
-import com.intellij.psi.search.scope.packageSet.NamedScope;
-import com.intellij.psi.search.scope.packageSet.NamedScopesHolder;
-import com.intellij.ui.treeStructure.Tree;
-import com.intellij.ui.treeStructure.treetable.TreeTable;
-import com.intellij.util.ArrayUtil;
-
-import javax.swing.tree.DefaultTreeModel;
-import javax.swing.tree.TreePath;
-import java.util.*;
-
-public class AddScopeUtil {
- public static ScopeToolState performAddScope(final TreeTable treeTable,
- final Project project,
- final InspectionProfileImpl inspectionProfile,
- final Collection<InspectionConfigTreeNode> selectedNodes) {
- final List<InspectionConfigTreeNode> nodes = new ArrayList<InspectionConfigTreeNode>();
- final List<Descriptor> descriptors = new ArrayList<Descriptor>();
- for (final InspectionConfigTreeNode node : selectedNodes) {
- collect(descriptors, nodes, node);
- }
-
- final List<String> availableScopes = getAvailableScopes(descriptors, project, inspectionProfile);
- final int idx = Messages.showChooseDialog(treeTable, "Scope:", "Choose Scope", ArrayUtil.toStringArray(availableScopes), availableScopes.get(0), Messages.getQuestionIcon());
- if (idx == -1) return null;
- final NamedScope chosenScope = NamedScopesHolder.getScope(project, availableScopes.get(idx));
-
- ScopeToolState scopeToolState = null;
- final Tree tree = treeTable.getTree();
-
- for (final InspectionConfigTreeNode node : nodes) {
- final Descriptor descriptor = node.getDefaultDescriptor();
- final InspectionToolWrapper toolWrapper = descriptor.getToolWrapper().createCopy(); //copy
- final HighlightDisplayLevel level = inspectionProfile.getErrorLevel(descriptor.getKey(), chosenScope, project);
- final boolean enabled = inspectionProfile.isToolEnabled(descriptor.getKey());
- scopeToolState = inspectionProfile.addScope(toolWrapper, chosenScope, level, enabled, project);
- node.dropCache();
- ((DefaultTreeModel)tree.getModel()).reload(node);
- tree.expandPath(new TreePath(node.getPath()));
- }
- tree.revalidate();
- return scopeToolState;
- }
-
- private static void collect(final List<Descriptor> descriptors,
- final List<InspectionConfigTreeNode> nodes,
- final InspectionConfigTreeNode node) {
- final ToolDescriptors currentDescriptors = node.getDescriptors();
- if (currentDescriptors != null) {
- nodes.add(node);
- descriptors.add(currentDescriptors.getDefaultDescriptor());
- descriptors.addAll(currentDescriptors.getNonDefaultDescriptors());
- } else if (node.getUserObject() instanceof String) {
- for(int i = 0; i < node.getChildCount(); i++) {
- final InspectionConfigTreeNode childNode = (InspectionConfigTreeNode)node.getChildAt(i);
- collect(descriptors, nodes, childNode);
- }
- }
- }
-
- private static List<String> getAvailableScopes(final List<Descriptor> descriptors, final Project project, final InspectionProfileImpl inspectionProfile) {
- final ArrayList<NamedScope> scopes = new ArrayList<NamedScope>();
- for (final NamedScopesHolder holder : NamedScopesHolder.getAllNamedScopeHolders(project)) {
- Collections.addAll(scopes, holder.getScopes());
- }
- scopes.remove(CustomScopesProviderEx.getAllScope());
-
- CustomScopesProviderEx.filterNoSettingsScopes(project, scopes);
-
- final Set<NamedScope> used = new HashSet<NamedScope>();
- for (final Descriptor descriptor : descriptors) {
- final List<ScopeToolState> nonDefaultTools = inspectionProfile.getNonDefaultTools(descriptor.getKey().toString(), project);
- if (nonDefaultTools != null) {
- for (final ScopeToolState state : nonDefaultTools) {
- used.add(state.getScope(project));
- }
- }
- }
- scopes.removeAll(used);
-
- final List<String> availableScopes = new ArrayList<String>();
- for (final NamedScope scope : scopes) {
- availableScopes.add(scope.getName());
- }
- return availableScopes;
- }
-} \ No newline at end of file
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/AdvancedSettingsAction.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/AdvancedSettingsAction.java
new file mode 100644
index 000000000000..b0746769d83c
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/AdvancedSettingsAction.java
@@ -0,0 +1,209 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.profile.codeInspection.ui;
+
+import com.intellij.codeInspection.ex.InspectionProfileImpl;
+import com.intellij.icons.AllIcons;
+import com.intellij.openapi.actionSystem.*;
+import com.intellij.openapi.application.ApplicationNamesInfo;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.popup.JBPopupFactory;
+import com.intellij.openapi.ui.popup.PopupStep;
+import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
+import com.intellij.profile.codeInspection.ui.inspectionsTree.InspectionConfigTreeNode;
+import com.intellij.ui.LayeredIcon;
+import com.intellij.ui.awt.RelativePoint;
+import com.intellij.ui.components.JBLabel;
+import com.intellij.ui.popup.list.ListPopupImpl;
+import com.intellij.util.Consumer;
+import com.intellij.util.PlatformIcons;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.ui.EmptyIcon;
+import com.intellij.util.ui.UIUtil;
+
+import javax.swing.*;
+import java.awt.*;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public abstract class AdvancedSettingsAction extends AnAction {
+ private final int myCheckBoxIndent;
+ private Project myProject;
+ private InspectionConfigTreeNode myRoot;
+
+ public AdvancedSettingsAction(final Project project, InspectionConfigTreeNode root) {
+ super("Advanced Settings");
+ getTemplatePresentation().setIcon(AllIcons.General.Gear);
+ myProject = project;
+ myRoot = root;
+ myCheckBoxIndent = calculateCheckBoxIndent();
+ }
+
+ @Override
+ public void update(AnActionEvent e) {
+ super.update(e);
+ final InspectionProfileImpl inspectionProfile = getInspectionProfile();
+ final Icon icon = AllIcons.General.Gear;
+ e.getPresentation().setIcon(
+ (inspectionProfile != null && inspectionProfile.isProfileLocked()) ? LayeredIcon.create(icon, PlatformIcons.LOCKED_ICON) : icon);
+ }
+
+ @Override
+ public void actionPerformed(AnActionEvent e) {
+ final ListPopupImpl actionGroupPopup = (ListPopupImpl)JBPopupFactory.getInstance().createListPopup(
+ new BaseListPopupStep<MyAction>(null, ContainerUtil.list(new MyDisableNewInspectionsAction(), new MyResetAction())) {
+ @Override
+ public PopupStep onChosen(MyAction selectedValue, boolean finalChoice) {
+ if (selectedValue.enabled()) {
+ selectedValue.actionPerformed();
+ }
+ return FINAL_CHOICE;
+ }
+ });
+ actionGroupPopup.getList().setCellRenderer(new ListCellRenderer() {
+ @Override
+ public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
+ return ((MyAction)value).createCustomComponent(isSelected);
+ }
+ });
+ final Component component = e.getInputEvent().getComponent();
+ actionGroupPopup.show(new RelativePoint(component, new Point(component.getWidth() - 1, 0)));
+ }
+
+ private JLabel installLeftIndentToLabel(final JLabel label) {
+ label.setBorder(BorderFactory.createEmptyBorder(0, myCheckBoxIndent, 0, 0));
+ return label;
+ }
+
+ private class MyResetAction extends MyAction {
+
+ protected MyResetAction() {
+ super("All your changes will be lost");
+ }
+
+ @Override
+ protected JComponent createBaseComponent() {
+ return installLeftIndentToLabel(new JLabel("Reset to Defaults Settings"));
+ }
+
+ @Override
+ public void actionPerformed() {
+ final InspectionProfileImpl inspectionProfile = getInspectionProfile();
+ if (inspectionProfile == null) {
+ return;
+ }
+ inspectionProfile.resetToBase(myProject);
+ postProcessModification();
+ }
+
+ @Override
+ protected boolean enabled() {
+ return myRoot.isProperSetting();
+ }
+ }
+
+ private class MyDisableNewInspectionsAction extends MyAction {
+ public MyDisableNewInspectionsAction() {
+ super("New inspections may appear when " + ApplicationNamesInfo.getInstance().getFullProductName() + " is updated");
+ }
+
+ @Override
+ protected JComponent createBaseComponent() {
+ final JCheckBox checkBox = new JCheckBox("Disable new inspections by default");
+ final InspectionProfileImpl profile = getInspectionProfile();
+ checkBox.setEnabled(profile != null);
+ if (profile != null) {
+ checkBox.setSelected(profile.isProfileLocked());
+ }
+ checkBox.setOpaque(false);
+ return checkBox;
+ }
+
+ @Override
+ public void actionPerformed() {
+ final InspectionProfileImpl profile = getInspectionProfile();
+ if (profile != null) {
+ profile.lockProfile(!profile.isProfileLocked());
+ }
+ }
+
+
+ @Override
+ protected boolean enabled() {
+ return true;
+ }
+ }
+
+ private abstract class MyAction {
+ private final String myDescription;
+
+ protected MyAction(String description) {
+ myDescription = description;
+ }
+
+ protected abstract JComponent createBaseComponent();
+
+ protected abstract void actionPerformed();
+
+ protected abstract boolean enabled();
+
+ public JComponent createCustomComponent(final boolean selected) {
+ JPanel panel = new JPanel();
+ panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS));
+ panel.add(createBaseComponent());
+ panel.add(installLeftIndentToLabel(new JBLabel(myDescription, UIUtil.ComponentStyle.MINI)));
+ panel.setBackground(selected ? UIUtil.getListSelectionBackground() : UIUtil.getListBackground());
+ panel.setForeground(selected ? UIUtil.getListSelectionForeground() : UIUtil.getListForeground());
+ UIUtil.setEnabled(panel, enabled(), true);
+ return panel;
+ }
+ }
+
+ protected abstract InspectionProfileImpl getInspectionProfile();
+
+ protected abstract void postProcessModification();
+
+ private static int calculateCheckBoxIndent() {
+ JCheckBox checkBox = new JCheckBox();
+ Icon icon = checkBox.getIcon();
+ int indent = 0;
+ if (icon == null) {
+ icon = UIManager.getIcon("CheckBox.icon");
+ }
+ if (UIUtil.isUnderDarcula() || UIUtil.isUnderIntelliJLaF()) {
+ icon = EmptyIcon.create(20, 18);
+ }
+ if (icon != null) {
+ final Insets i = checkBox.getInsets();
+ final Rectangle r = checkBox.getBounds();
+ final Rectangle r1 = new Rectangle();
+ r1.x = i.left;
+ r1.y = i.top;
+ r1.width = r.width - (i.right + r1.x);
+ r1.height = r.height - (i.bottom + r1.y);
+ final Rectangle iconRect = new Rectangle();
+ SwingUtilities.layoutCompoundLabel(
+ checkBox, checkBox.getFontMetrics(checkBox.getFont()), checkBox.getText(), icon,
+ checkBox.getVerticalAlignment(), checkBox.getHorizontalAlignment(),
+ checkBox.getVerticalTextPosition(), checkBox.getHorizontalTextPosition(),
+ r1, new Rectangle(), iconRect,
+ checkBox.getText() == null ? 0 : checkBox.getIconTextGap());
+ indent = iconRect.x;
+ }
+ return indent + checkBox.getIconTextGap();
+ }
+}
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/InspectionToolsConfigurable.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/InspectionToolsConfigurable.java
index 794945268d19..efc60c63f89d 100644
--- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/InspectionToolsConfigurable.java
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/InspectionToolsConfigurable.java
@@ -151,7 +151,7 @@ public abstract class InspectionToolsConfigurable extends BaseConfigurable imple
final Set<String> levels = new HashSet<String>();
for (Object o : rootElement.getChildren("inspection_tool")) {
final Element inspectElement = (Element)o;
- levels.add(inspectElement.getAttributeValue("l"));
+ levels.add(inspectElement.getAttributeValue("level"));
for (Object s : inspectElement.getChildren("scope")) {
levels.add(((Element)s).getAttributeValue("level"));
}
@@ -532,6 +532,6 @@ public abstract class InspectionToolsConfigurable extends BaseConfigurable imple
public JComponent getPreferredFocusedComponent() {
final InspectionProfileImpl inspectionProfile = getSelectedObject();
assert inspectionProfile != null : configuredProfiles();
- return getProfilePanel(inspectionProfile).getTree();
+ return getProfilePanel(inspectionProfile).getPreferredFocusedComponent();
}
}
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/LevelChooserAction.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/LevelChooserAction.java
index 1067a60ed358..df3b8bda3f3b 100644
--- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/LevelChooserAction.java
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/LevelChooserAction.java
@@ -43,7 +43,11 @@ public abstract class LevelChooserAction extends ComboBoxAction {
private HighlightSeverity myChosen = null;
public LevelChooserAction(final InspectionProfileImpl profile) {
- mySeverityRegistrar = ((SeverityProvider)profile.getProfileManager()).getOwnSeverityRegistrar();
+ this(((SeverityProvider)profile.getProfileManager()).getOwnSeverityRegistrar());
+ }
+
+ public LevelChooserAction(final SeverityRegistrar severityRegistrar) {
+ mySeverityRegistrar = severityRegistrar;
}
@NotNull
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/MultiScopeSeverityIcon.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/MultiScopeSeverityIcon.java
deleted file mode 100644
index 2bf909666f82..000000000000
--- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/MultiScopeSeverityIcon.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2000-2014 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.profile.codeInspection.ui;
-
-import javax.swing.*;
-import java.awt.*;
-import java.util.List;
-
-/**
- * @author Dmitry Batkovich
- */
-public class MultiScopeSeverityIcon implements Icon {
- private final int mySize;
- private final List<Color> myColors;
-
- public MultiScopeSeverityIcon(final int size, final List<Color> colors) {
- mySize = size;
- myColors = colors;
- }
-
- @Override
- public void paintIcon(final Component c, final Graphics g, final int i, final int j) {
- final int iconWidth = getIconWidth();
- final int iconHeightCoordinate = j + getIconHeight();
-
- final int partWidth = iconWidth / myColors.size();
-
- for (int idx = 0; idx < myColors.size(); idx++) {
- final Color color = myColors.get(idx);
- g.setColor(color);
- final int x = i + partWidth * idx;
- g.fillRect(x, j, x + partWidth, iconHeightCoordinate);
- }
- }
-
- @Override
- public int getIconWidth() {
- return mySize;
- }
-
- @Override
- public int getIconHeight() {
- return mySize;
- }
-}
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ScopeOrderComparator.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ScopeOrderComparator.java
new file mode 100644
index 000000000000..f2d8c5e1fd82
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ScopeOrderComparator.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.profile.codeInspection.ui;
+
+import com.intellij.codeInspection.ex.InspectionProfileImpl;
+import com.intellij.util.ArrayUtil;
+
+import java.util.Comparator;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class ScopeOrderComparator implements Comparator<String> {
+ private final String[] myScopesOrder;
+
+ public ScopeOrderComparator(final InspectionProfileImpl inspectionProfile) {
+ this(inspectionProfile.getScopesOrder());
+ }
+
+ public ScopeOrderComparator(String[] scopesOrder) {
+ myScopesOrder = scopesOrder;
+ }
+
+ private int getKey(String scope) {
+ return myScopesOrder == null ? -1 : ArrayUtil.indexOf(myScopesOrder, scope);
+ }
+
+ @Override
+ public int compare(String scope1, String scope2) {
+ final int key = getKey(scope1);
+ final int key1 = getKey(scope2);
+ if (key >= 0) {
+ if (key1 >= 0) {
+ return key - key1;
+ }
+ else {
+ return -1;
+ }
+ }
+ else {
+ if (key1 >= 0) {
+ return 1;
+ }
+ else {
+ return scope1.compareTo(scope2);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ScopesChooser.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ScopesChooser.java
index 4932e7ff5ca9..fde3b141084d 100644
--- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ScopesChooser.java
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ScopesChooser.java
@@ -22,13 +22,16 @@ import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.actionSystem.ex.ComboBoxAction;
import com.intellij.openapi.project.Project;
+import com.intellij.psi.search.scope.NonProjectFilesScope;
import com.intellij.psi.search.scope.packageSet.CustomScopesProviderEx;
import com.intellij.psi.search.scope.packageSet.NamedScope;
import com.intellij.psi.search.scope.packageSet.NamedScopesHolder;
+import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.util.ArrayList;
+import java.util.Set;
import java.util.List;
import java.util.Collections;
@@ -36,22 +39,28 @@ import java.util.Collections;
* @author Dmitry Batkovich
*/
public abstract class ScopesChooser extends ComboBoxAction {
+ public static final String TITLE = "Select a scope to change its settings";
private final List<Descriptor> myDefaultDescriptors;
private final InspectionProfileImpl myInspectionProfile;
private final Project myProject;
+ private final Set<String> myExcludedScopeNames;
- public ScopesChooser(final List<Descriptor> defaultDescriptors, final InspectionProfileImpl inspectionProfile, final Project project) {
+ public ScopesChooser(final List<Descriptor> defaultDescriptors,
+ final InspectionProfileImpl inspectionProfile,
+ final Project project,
+ final String[] excludedScopeNames) {
myDefaultDescriptors = defaultDescriptors;
myInspectionProfile = inspectionProfile;
myProject = project;
- setPopupTitle("Select a scope to change its settings");
+ myExcludedScopeNames = excludedScopeNames == null ? Collections.<String>emptySet() : ContainerUtil.newHashSet(excludedScopeNames);
+ setPopupTitle(TITLE);
getTemplatePresentation().setText("In All Scopes");
}
@NotNull
@Override
- protected DefaultActionGroup createPopupActionGroup(final JComponent button) {
+ public DefaultActionGroup createPopupActionGroup(final JComponent component) {
final DefaultActionGroup group = new DefaultActionGroup();
final List<NamedScope> predefinedScopes = new ArrayList<NamedScope>();
@@ -61,30 +70,47 @@ public abstract class ScopesChooser extends ComboBoxAction {
predefinedScopes.addAll(holder.getPredefinedScopes());
}
predefinedScopes.remove(CustomScopesProviderEx.getAllScope());
- fillActionGroup(group, predefinedScopes, myDefaultDescriptors, myInspectionProfile);
+ for (NamedScope predefinedScope : predefinedScopes) {
+ if (predefinedScope instanceof NonProjectFilesScope) {
+ predefinedScopes.remove(predefinedScope);
+ break;
+ }
+ }
+
+ fillActionGroup(group, predefinedScopes, myDefaultDescriptors, myInspectionProfile, myExcludedScopeNames);
group.addSeparator();
- fillActionGroup(group, customScopes, myDefaultDescriptors, myInspectionProfile);
+ fillActionGroup(group, customScopes, myDefaultDescriptors, myInspectionProfile, myExcludedScopeNames);
- //TODO edit scopes order
- //group.addSeparator();
- //group.add(new AnAction("Edit Scopes Order...") {
- // @Override
- // public void actionPerformed(final AnActionEvent e) {
- //
- // }
- //});
+ group.addSeparator();
+ group.add(new AnAction("Edit Scopes Order...") {
+ @Override
+ public void actionPerformed(final AnActionEvent e) {
+ final ScopesOrderDialog dlg = new ScopesOrderDialog(component, myInspectionProfile, myProject);
+ dlg.show();
+ if (dlg.isOK()) {
+ onScopesOrderChanged();
+ }
+ }
+ });
return group;
}
+ protected abstract void onScopesOrderChanged();
+
protected abstract void onScopeAdded();
private void fillActionGroup(final DefaultActionGroup group,
- final List<NamedScope> scopes,
- final List<Descriptor> defaultDescriptors,
- final InspectionProfileImpl inspectionProfile) {
+ final List<NamedScope> scopes,
+ final List<Descriptor> defaultDescriptors,
+ final InspectionProfileImpl inspectionProfile,
+ final Set<String> excludedScopeNames) {
for (final NamedScope scope : scopes) {
- group.add(new AnAction(scope.getName()) {
+ final String scopeName = scope.getName();
+ if (excludedScopeNames.contains(scopeName)) {
+ continue;
+ }
+ group.add(new AnAction(scopeName) {
@Override
public void actionPerformed(final AnActionEvent e) {
for (final Descriptor defaultDescriptor : defaultDescriptors) {
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ScopesOrderDialog.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ScopesOrderDialog.java
new file mode 100644
index 000000000000..c69a3e5566a2
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ScopesOrderDialog.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.profile.codeInspection.ui;
+
+import com.intellij.codeInspection.ex.InspectionProfileImpl;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.DialogWrapper;
+import com.intellij.psi.search.scope.NonProjectFilesScope;
+import com.intellij.psi.search.scope.packageSet.CustomScopesProviderEx;
+import com.intellij.psi.search.scope.packageSet.NamedScope;
+import com.intellij.psi.search.scope.packageSet.NamedScopesHolder;
+import com.intellij.ui.*;
+import com.intellij.ui.components.JBList;
+import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.awt.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class ScopesOrderDialog extends DialogWrapper {
+
+ private final JList myOptionsList = new JBList();
+
+ private final InspectionProfileImpl myInspectionProfile;
+ private final Project myProject;
+ private final JPanel myPanel;
+
+ public ScopesOrderDialog(final @NotNull Component parent,
+ final InspectionProfileImpl inspectionProfile,
+ final Project project) {
+ super(parent, true);
+ myInspectionProfile = inspectionProfile;
+ myProject = project;
+
+ final JPanel listPanel = ToolbarDecorator.createDecorator(myOptionsList).setMoveDownAction(new AnActionButtonRunnable() {
+ @Override
+ public void run(AnActionButton anActionButton) {
+ ListUtil.moveSelectedItemsDown(myOptionsList);
+ }
+ }).setMoveUpAction(new AnActionButtonRunnable() {
+ @Override
+ public void run(AnActionButton anActionButton) {
+ ListUtil.moveSelectedItemsUp(myOptionsList);
+ }
+ }).disableRemoveAction().disableAddAction().createPanel();
+ final JLabel descr = new JLabel("<html><p>If file appears in two or more scopes, it will be" +
+ "inspected with settings of the topmost scope in list above.</p><p/>" +
+ "<p>Scope order is set globally for all inspections in the profile.</p></html>");
+ descr.setPreferredSize(new Dimension(300, 100));
+ UIUtil.applyStyle(UIUtil.ComponentStyle.SMALL, descr);
+ myPanel = new JPanel();
+ myPanel.setLayout(new BorderLayout());
+ myPanel.add(listPanel, BorderLayout.CENTER);
+ myPanel.add(descr, BorderLayout.SOUTH);
+ fillList();
+ init();
+ setTitle("Scopes Order");
+ }
+
+ private void fillList() {
+ DefaultListModel model = new DefaultListModel();
+ model.removeAllElements();
+
+ final List<String> scopes = new ArrayList<String>();
+ for (final NamedScopesHolder holder : NamedScopesHolder.getAllNamedScopeHolders(myProject)) {
+ for (final NamedScope scope : holder.getScopes()) {
+ if (!(scope instanceof NonProjectFilesScope)) {
+ scopes.add(scope.getName());
+ }
+ }
+ }
+ scopes.remove(CustomScopesProviderEx.getAllScope().getName());
+ Collections.sort(scopes, new ScopeOrderComparator(myInspectionProfile));
+ for (String scopeName : scopes) {
+ model.addElement(scopeName);
+ }
+ myOptionsList.setModel(model);
+ myOptionsList.setSelectedIndex(0);
+ }
+
+ @Nullable
+ @Override
+ protected JComponent createCenterPanel() {
+ return myPanel;
+ }
+
+ @Override
+ protected void doOKAction() {
+ final int size = myOptionsList.getModel().getSize();
+ final String[] newScopeOrder = new String[size];
+ for (int i = 0; i < size; i++) {
+ final String scopeName = (String) myOptionsList.getModel().getElementAt(i);
+ newScopeOrder[i] = scopeName;
+ }
+ if (!Arrays.equals(newScopeOrder, myInspectionProfile.getScopesOrder())) {
+ myInspectionProfile.setScopesOrder(newScopeOrder);
+ }
+ super.doOKAction();
+ }
+}
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java
index ce5f308c1305..2da5c80a758b 100644
--- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java
@@ -132,6 +132,8 @@ public class SingleInspectionProfilePanel extends JPanel {
private Splitter myRightSplitter;
private Splitter myMainSplitter;
+ private String[] myInitialScopesOrder;
+
public SingleInspectionProfilePanel(@NotNull InspectionProjectProfileManager projectProfileManager,
@NotNull String inspectionProfileName,
@NotNull ModifiableModel profile) {
@@ -186,8 +188,10 @@ public class SingleInspectionProfilePanel extends JPanel {
if (myTreeTable != null) {
final TreePath selectionPath = myTreeTable.getTree().getSelectionPath();
if (selectionPath != null) {
- TreeUtil.selectNode(myTreeTable.getTree(), (TreeNode)selectionPath.getLastPathComponent());
- TreeUtil.showRowCentered(myTreeTable.getTree(), myTreeTable.getTree().getRowForPath(selectionPath), false);
+ TreeUtil.selectNode(myTreeTable.getTree(), (TreeNode) selectionPath.getLastPathComponent());
+ final int rowForPath = myTreeTable.getTree().getRowForPath(selectionPath);
+ TableUtil.selectRows(myTreeTable, new int[]{rowForPath});
+ scrollToCenter();
}
}
}
@@ -258,6 +262,7 @@ public class SingleInspectionProfilePanel extends JPanel {
if (!accept(state.getTool())) continue;
myInitialToolDescriptors.add(ToolDescriptors.fromScopeToolState(state, profile, project));
}
+ myInitialScopesOrder = mySelectedProfile.getScopesOrder();
}
protected boolean accept(InspectionToolWrapper entry) {
@@ -364,24 +369,6 @@ public class SingleInspectionProfilePanel extends JPanel {
actions.add(actionManager.createExpandAllAction(myTreeExpander, myTreeTable));
actions.add(actionManager.createCollapseAllAction(myTreeExpander, myTreeTable));
-
- actions.add(new AnAction(CommonBundle.message("button.reset.to.default"), CommonBundle.message("button.reset.to.default"),
- AllIcons.General.Reset) {
- {
- registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_R, InputEvent.CTRL_MASK)), myTreeTable);
- }
- @Override
- public void update(AnActionEvent e) {
- e.getPresentation().setEnabled(myRoot.isProperSetting());
- }
-
- @Override
- public void actionPerformed(AnActionEvent e) {
- mySelectedProfile.resetToBase(myProjectProfileManager.getProject());
- postProcessModification();
- }
- });
-
actions.add(new AnAction("Reset to Empty", "Reset to empty", AllIcons.Actions.Reset_to_empty){
@Override
@@ -396,18 +383,19 @@ public class SingleInspectionProfilePanel extends JPanel {
}
});
- actions.add(new ToggleAction("Lock Profile", "Lock profile", AllIcons.Nodes.Padlock) {
+ actions.add(new AdvancedSettingsAction(myProjectProfileManager.getProject(), myRoot) {
@Override
- public boolean isSelected(AnActionEvent e) {
- return mySelectedProfile != null && mySelectedProfile.isProfileLocked();
+ protected InspectionProfileImpl getInspectionProfile() {
+ return mySelectedProfile;
}
@Override
- public void setSelected(AnActionEvent e, boolean state) {
- mySelectedProfile.lockProfile(state);
+ protected void postProcessModification() {
+ SingleInspectionProfilePanel.this.postProcessModification();
}
});
+
final ActionToolbar actionToolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, actions, true);
actionToolbar.setTargetComponent(this);
return actionToolbar;
@@ -424,11 +412,24 @@ public class SingleInspectionProfilePanel extends JPanel {
public void selectInspectionTool(String name) {
final InspectionConfigTreeNode node = findNodeByKey(name, myRoot);
if (node != null) {
- TreeUtil.showRowCentered(myTreeTable.getTree(), myTreeTable.getTree().getRowForPath(new TreePath(node.getPath())) - 1, true);//myTree.isRootVisible ? 0 : 1;
TreeUtil.selectNode(myTreeTable.getTree(), node);
+ final int rowForPath = myTreeTable.getTree().getRowForPath(new TreePath(node.getPath()));
+ TableUtil.selectRows(myTreeTable, new int[]{rowForPath});
+ scrollToCenter();
}
}
+ private void scrollToCenter() {
+ ListSelectionModel selectionModel = myTreeTable.getSelectionModel();
+ int maxSelectionIndex = selectionModel.getMaxSelectionIndex();
+ final int maxColumnSelectionIndex = Math.max(0, myTreeTable.getColumnModel().getSelectionModel().getMinSelectionIndex());
+ Rectangle maxCellRect = myTreeTable.getCellRect(maxSelectionIndex, maxColumnSelectionIndex, false);
+
+ final Point selectPoint = maxCellRect.getLocation();
+ final int allHeight = myTreeTable.getVisibleRect().height;
+ myTreeTable.scrollRectToVisible(new Rectangle(new Point(0, Math.max(0, selectPoint.y - allHeight / 2)), new Dimension(0, allHeight)));
+ }
+
@Nullable
private static InspectionConfigTreeNode findNodeByKey(String name, InspectionConfigTreeNode root) {
for (int i = 0; i < root.getChildCount(); i++) {
@@ -524,6 +525,7 @@ public class SingleInspectionProfilePanel extends JPanel {
final JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(myTreeTable);
+ myTreeTable.getTree().setShowsRootHandles(true);
scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
TreeUtil.collapseAll(myTreeTable.getTree(), 1);
@@ -684,14 +686,15 @@ public class SingleInspectionProfilePanel extends JPanel {
}
private void updateOptionsAndDescriptionPanel(final TreePath... paths) {
- if (paths == null || paths.length == 0) {
+ if (mySelectedProfile == null || paths == null || paths.length == 0) {
return;
}
final TreePath path = paths[0];
if (path == null) return;
final List<InspectionConfigTreeNode> nodes = InspectionsAggregationUtil.getInspectionsNodes(paths);
if (!nodes.isEmpty()) {
- final InspectionConfigTreeNode singleNode = nodes.size() == 1 ? ContainerUtil.getFirstItem(nodes) : null;
+ final InspectionConfigTreeNode singleNode = paths.length == 1 && ((InspectionConfigTreeNode)paths[0].getLastPathComponent()).getDefaultDescriptor() != null
+ ? ContainerUtil.getFirstItem(nodes) : null;
if (singleNode != null && singleNode.getDefaultDescriptor().loadDescription() != null) {
// need this in order to correctly load plugin-supplied descriptions
final Descriptor defaultDescriptor = singleNode.getDefaultDescriptor();
@@ -721,7 +724,7 @@ public class SingleInspectionProfilePanel extends JPanel {
}
else {
try {
- myBrowser.read(new StringReader(EMPTY_HTML), null);
+ myBrowser.read(new StringReader("<html><body>Multiple inspections are selected. You can edit them as a single inspection.</body></html>"), null);
}
catch (IOException e1) {
//Can't be
@@ -733,7 +736,6 @@ public class SingleInspectionProfilePanel extends JPanel {
final JPanel severityPanel = new JPanel(new GridBagLayout());
final double severityPanelWeightY;
final JPanel configPanelAnchor = new JPanel(new GridLayout());
- configPanelAnchor.setBorder(IdeBorderFactory.createTitledBorder("Options", false, new Insets(0, 0, 0, 0)));
final Set<String> scopesNames = new THashSet<String>();
for (final InspectionConfigTreeNode node : nodes) {
@@ -754,7 +756,7 @@ public class SingleInspectionProfilePanel extends JPanel {
final HighlightDisplayKey key = node.getDefaultDescriptor().getKey();
final NamedScope scope = node.getDefaultDescriptor().getScope();
final boolean toUpdate = mySelectedProfile.getErrorLevel(key, scope, project) != level;
- mySelectedProfile.setErrorLevel(key, level, -1, project);
+ mySelectedProfile.setErrorLevel(key, level, null, project);
if (toUpdate) node.dropCache();
}
@@ -774,7 +776,13 @@ public class SingleInspectionProfilePanel extends JPanel {
public Descriptor fun(final InspectionConfigTreeNode node) {
return node.getDefaultDescriptor();
}
- }), mySelectedProfile, project) {
+ }), mySelectedProfile, project, null) {
+ @Override
+ protected void onScopesOrderChanged() {
+ myTreeTable.getTree().updateUI();
+ updateOptionsAndDescriptionPanel();
+ }
+
@Override
protected void onScopeAdded() {
updateOptionsAndDescriptionPanel();
@@ -812,12 +820,19 @@ public class SingleInspectionProfilePanel extends JPanel {
}
@Override
- protected void onChange() {
+ protected void onSettingsChanged() {
myTreeTable.getTree().updateUI();
}
@Override
protected void onScopeAdded() {
+ updateOptionsAndDescriptionPanel();
+ }
+
+ @Override
+ protected void onScopesOrderChanged() {
+ myTreeTable.getTree().updateUI();
+ updateOptionsAndDescriptionPanel();
}
@Override
@@ -829,8 +844,9 @@ public class SingleInspectionProfilePanel extends JPanel {
});
- final ToolbarDecorator wrappedTable = ToolbarDecorator.createDecorator(scopesAndScopesAndSeveritiesTable);
+ final ToolbarDecorator wrappedTable = ToolbarDecorator.createDecorator(scopesAndScopesAndSeveritiesTable).disableUpDownActions();
final JPanel panel = wrappedTable.createPanel();
+ panel.setMinimumSize(new Dimension(getMinimumSize().width, 3 * scopesAndScopesAndSeveritiesTable.getRowHeight()));
severityPanel.add(new JBLabel("Scopes & Severities"),
new GridBagConstraints(0, 0, 1, 1, 0, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE,
new Insets(5, 0, 2, 10), 0, 0));
@@ -842,8 +858,13 @@ public class SingleInspectionProfilePanel extends JPanel {
severityPanelWeightY = 0.3;
}
myOptionsPanel.add(severityPanel, new GridBagConstraints(0, 0, 1, 1, 1.0, severityPanelWeightY, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
- myOptionsPanel.add(configPanelAnchor, new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.BOTH,
- new Insets(0, 0, 0, 0), 0, 0));
+ if (configPanelAnchor.getComponentCount() != 0) {
+ configPanelAnchor.setBorder(IdeBorderFactory.createTitledBorder("Options", false, new Insets(0, 0, 0, 0)));
+ }
+ if (configPanelAnchor.getComponentCount() != 0 || scopesNames.isEmpty()) {
+ myOptionsPanel.add(configPanelAnchor, new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.BOTH,
+ new Insets(0, 0, 0, 0), 0, 0));
+ }
myOptionsPanel.revalidate();
GuiUtils.enableChildren(myOptionsPanel, isThoughOneNodeEnabled(nodes));
}
@@ -887,7 +908,10 @@ public class SingleInspectionProfilePanel extends JPanel {
private static void setConfigPanel(final JPanel configPanelAnchor, final ScopeToolState state) {
configPanelAnchor.removeAll();
- configPanelAnchor.add(state.getAdditionalConfigPanel());
+ final JComponent additionalConfigPanel = state.getAdditionalConfigPanel();
+ if (additionalConfigPanel != null) {
+ configPanelAnchor.add(ScrollPaneFactory.createScrollPane(additionalConfigPanel, SideBorder.NONE));
+ }
}
private static InspectionConfigTreeNode getGroupNode(InspectionConfigTreeNode root, String[] groupPath) {
@@ -1001,6 +1025,7 @@ public class SingleInspectionProfilePanel extends JPanel {
if (mySelectedProfile.isChanged()) return true;
if (myShareProfile != (mySelectedProfile.getProfileManager() == myProjectProfileManager)) return true;
if (!Comparing.strEqual(myInitialProfile, mySelectedProfile.getName())) return true;
+ if (!Comparing.equal(myInitialScopesOrder, mySelectedProfile.getScopesOrder())) return true;
if (descriptorsAreChanged()) {
return true;
}
@@ -1111,10 +1136,6 @@ public class SingleInspectionProfilePanel extends JPanel {
return false;
}
- public Tree getTreeTable() {
- return myTreeTable.getTree();
- }
-
public boolean isProfileShared() {
return myShareProfile;
}
@@ -1176,15 +1197,15 @@ public class SingleInspectionProfilePanel extends JPanel {
final boolean showOptionsAndDescriptorPanels,
@NotNull HighlightDisplayLevel level) {
final HighlightDisplayKey key = child.getDefaultDescriptor().getKey();
- mySelectedProfile.setErrorLevel(key, level, -1, myProjectProfileManager.getProject());
+ mySelectedProfile.setErrorLevel(key, level, null, myProjectProfileManager.getProject());
child.dropCache();
if (showOptionsAndDescriptorPanels) {
updateOptionsAndDescriptionPanel(new TreePath(child.getPath()));
}
}
- public JComponent getTree() {
- return myTreeTable.getTree();
+ public JComponent getPreferredFocusedComponent() {
+ return myTreeTable;
}
private class MyFilterComponent extends FilterComponent {
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/filter/InspectionFilterAction.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/filter/InspectionFilterAction.java
index cbd1c2482032..bccd2db28e21 100644
--- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/filter/InspectionFilterAction.java
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/filter/InspectionFilterAction.java
@@ -20,7 +20,6 @@ import com.intellij.codeInsight.daemon.impl.SeverityRegistrar;
import com.intellij.codeInspection.ex.InspectionProfileImpl;
import com.intellij.icons.AllIcons;
import com.intellij.lang.annotation.HighlightSeverity;
-import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.actionSystem.ex.CheckboxAction;
@@ -60,6 +59,23 @@ public class InspectionFilterAction extends DefaultActionGroup {
addSeparator();
add(new ShowAvailableOnlyOnAnalyzeInspectionsAction());
+ add(new ShowOnlyCleanupInspectionsAction());
+ }
+
+ private class ShowOnlyCleanupInspectionsAction extends CheckboxAction {
+ public ShowOnlyCleanupInspectionsAction() {
+ super("Show Only Cleanup Inspections");
+ }
+
+ @Override
+ public boolean isSelected(final AnActionEvent e) {
+ return myInspectionsFilter.isShowOnlyCleanupInspections();
+ }
+
+ @Override
+ public void setSelected(final AnActionEvent e, final boolean state) {
+ myInspectionsFilter.setShowOnlyCleanupInspections(state);
+ }
}
private class ShowAvailableOnlyOnAnalyzeInspectionsAction extends CheckboxAction {
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/filter/InspectionsFilter.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/filter/InspectionsFilter.java
index 432ef560ba58..117cd774dff8 100644
--- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/filter/InspectionsFilter.java
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/filter/InspectionsFilter.java
@@ -33,11 +33,16 @@ public abstract class InspectionsFilter {
private final Set<HighlightSeverity> mySuitableSeverities = new HashSet<HighlightSeverity>();
private Boolean mySuitableInspectionsStates;
private boolean myAvailableOnlyForAnalyze;
+ private boolean myShowOnlyCleanupInspections;
public boolean isAvailableOnlyForAnalyze() {
return myAvailableOnlyForAnalyze;
}
+ public boolean isShowOnlyCleanupInspections() {
+ return myShowOnlyCleanupInspections;
+ }
+
public Boolean getSuitableInspectionsStates() {
return mySuitableInspectionsStates;
}
@@ -46,6 +51,11 @@ public abstract class InspectionsFilter {
return mySuitableSeverities.contains(severity);
}
+ public void setShowOnlyCleanupInspections(final boolean showOnlyCleanupInspections) {
+ myShowOnlyCleanupInspections = showOnlyCleanupInspections;
+ filterChanged();
+ }
+
public void setAvailableOnlyForAnalyze(final boolean availableOnlyForAnalyze) {
myAvailableOnlyForAnalyze = availableOnlyForAnalyze;
filterChanged();
@@ -67,10 +77,17 @@ public abstract class InspectionsFilter {
}
public boolean isEmptyFilter() {
- return mySuitableInspectionsStates == null && !myAvailableOnlyForAnalyze && mySuitableSeverities.isEmpty();
+ return mySuitableInspectionsStates == null
+ && !myAvailableOnlyForAnalyze
+ && !myShowOnlyCleanupInspections
+ && mySuitableSeverities.isEmpty();
}
public boolean matches(final Tools tools) {
+ if (myShowOnlyCleanupInspections && !tools.getTool().isCleanupTool()) {
+ return false;
+ }
+
if (mySuitableInspectionsStates != null && mySuitableInspectionsStates != tools.isEnabled()) {
return false;
}
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/InspectionsConfigTreeTable.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/InspectionsConfigTreeTable.java
index 966a456e1d38..92cb62f0f800 100644
--- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/InspectionsConfigTreeTable.java
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/InspectionsConfigTreeTable.java
@@ -28,17 +28,21 @@ import com.intellij.openapi.util.Comparing;
import com.intellij.profile.codeInspection.ui.InspectionsAggregationUtil;
import com.intellij.profile.codeInspection.ui.table.ScopesAndSeveritiesTable;
import com.intellij.profile.codeInspection.ui.table.ThreeStateCheckBoxRenderer;
+import com.intellij.ui.DoubleClickListener;
import com.intellij.ui.treeStructure.treetable.TreeTable;
import com.intellij.ui.treeStructure.treetable.TreeTableModel;
+import com.intellij.ui.treeStructure.treetable.TreeTableTree;
+import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
+import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumn;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
+import javax.swing.tree.TreePath;
import java.awt.*;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
+import java.awt.event.*;
import java.util.*;
import java.util.List;
@@ -60,8 +64,8 @@ public class InspectionsConfigTreeTable extends TreeTable {
final TableColumn isEnabledColumn = getColumnModel().getColumn(IS_ENABLED_COLUMN);
isEnabledColumn.setMaxWidth(20);
- isEnabledColumn.setCellRenderer(new ThreeStateCheckBoxRenderer());
- isEnabledColumn.setCellEditor(new ThreeStateCheckBoxRenderer());
+ isEnabledColumn.setCellRenderer(new ThreeStateCheckBoxRenderer(false));
+ isEnabledColumn.setCellEditor(new ThreeStateCheckBoxRenderer(true));
addMouseMotionListener(new MouseAdapter() {
@Override
@@ -76,10 +80,42 @@ public class InspectionsConfigTreeTable extends TreeTable {
if (maybeIcon instanceof MultiScopeSeverityIcon) {
final LinkedHashMap<String, HighlightSeverity> scopeToAverageSeverityMap =
((MultiScopeSeverityIcon)maybeIcon).getScopeToAverageSeverityMap();
- IdeTooltipManager.getInstance().show(new IdeTooltip(InspectionsConfigTreeTable.this, point, new ScopesAndSeveritiesHintTable(scopeToAverageSeverityMap)), false);
+ IdeTooltipManager.getInstance().show(
+ new IdeTooltip(InspectionsConfigTreeTable.this, point, new ScopesAndSeveritiesHintTable(scopeToAverageSeverityMap)), false);
}
}
});
+
+ new DoubleClickListener() {
+ @Override
+ protected boolean onDoubleClick(MouseEvent event) {
+ final TreePath path = getTree().getPathForRow(getTree().getLeadSelectionRow());
+ if (path != null) {
+ final InspectionConfigTreeNode node = (InspectionConfigTreeNode)path.getLastPathComponent();
+ if (node.isLeaf()) {
+ swapInspectionEnableState();
+ }
+ }
+ return true;
+ }
+ }.installOn(this);
+
+ registerKeyboardAction(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ swapInspectionEnableState();
+ updateUI();
+ }
+ }, KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0), JComponent.WHEN_FOCUSED);
+
+ getEmptyText().setText("No enabled inspections available");
+ }
+
+ private void swapInspectionEnableState() {
+ for (int selectedRow : getSelectedRows()) {
+ final Object value = getValueAt(selectedRow, IS_ENABLED_COLUMN);
+ final boolean newValue = !Boolean.TRUE.equals(value);
+ setValueAt(newValue, selectedRow, IS_ENABLED_COLUMN);
+ }
}
public abstract static class InspectionsConfigTreeTableSettings {
@@ -107,6 +143,7 @@ public class InspectionsConfigTreeTable extends TreeTable {
private static class InspectionsConfigTreeTableModel extends DefaultTreeModel implements TreeTableModel {
private final InspectionsConfigTreeTableSettings mySettings;
+ private TreeTable myTreeTable;
public InspectionsConfigTreeTableModel(final InspectionsConfigTreeTableSettings settings) {
super(settings.getRoot());
@@ -154,7 +191,7 @@ public class InspectionsConfigTreeTable extends TreeTable {
mySettings.getInspectionProfile().getNonDefaultTools(toolId, mySettings.getProject()));
}
}
- return sink.constructIcon();
+ return sink.constructIcon(mySettings.getInspectionProfile());
} else if (column == IS_ENABLED_COLUMN) {
return isEnabled(inspectionsKeys);
}
@@ -195,26 +232,34 @@ public class InspectionsConfigTreeTable extends TreeTable {
aNode.dropCache();
mySettings.onChanged(aNode);
}
+ if (myTreeTable != null) {
+ UIUtil.invokeLaterIfNeeded(new Runnable() {
+ public void run() {
+ ((AbstractTableModel)myTreeTable.getModel()).fireTableDataChanged();
+ }
+ });
+ }
}
@Override
public void setTree(final JTree tree) {
+ myTreeTable = ((TreeTableTree)tree).getTreeTable();
}
}
private static class MultiColoredHighlightSeverityIconSink {
- private final LinkedHashMap<String, HighlightSeverity> myScopeToAverageSeverityMap = new LinkedHashMap<String, HighlightSeverity>();
+ private final Map<String, HighlightSeverity> myScopeToAverageSeverityMap = new HashMap<String, HighlightSeverity>();
+ private String myDefaultScopeName;
private boolean myIsFirst = true;
- public Icon constructIcon() {
+ public Icon constructIcon(final InspectionProfileImpl inspectionProfile) {
if (myScopeToAverageSeverityMap.isEmpty()) {
return null;
}
- //TODO order scopes
return !allScopesHasMixedSeverity()
- ? new MultiScopeSeverityIcon(myScopeToAverageSeverityMap)
+ ? new MultiScopeSeverityIcon(myScopeToAverageSeverityMap, myDefaultScopeName, inspectionProfile)
: ScopesAndSeveritiesTable.MIXED_FAKE_LEVEL.getIcon();
}
@@ -229,6 +274,9 @@ public class InspectionsConfigTreeTable extends TreeTable {
public void put(final ScopeToolState defaultState, final Collection<ScopeToolState> nonDefault) {
putOne(defaultState);
+ if (myDefaultScopeName == null) {
+ myDefaultScopeName = defaultState.getScopeName();
+ }
for (final ScopeToolState scopeToolState : nonDefault) {
putOne(scopeToolState);
}
@@ -237,7 +285,7 @@ public class InspectionsConfigTreeTable extends TreeTable {
}
}
- public void putOne(final ScopeToolState state) {
+ private void putOne(final ScopeToolState state) {
final Icon icon = state.getLevel().getIcon();
final String scopeName = state.getScopeName();
if (icon instanceof HighlightDisplayLevel.SingleColorIconWithMask) {
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/MultiScopeSeverityIcon.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/MultiScopeSeverityIcon.java
index 6f093ca66349..099dbb622261 100644
--- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/MultiScopeSeverityIcon.java
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/MultiScopeSeverityIcon.java
@@ -17,13 +17,15 @@ package com.intellij.profile.codeInspection.ui.inspectionsTree;
import com.intellij.codeHighlighting.HighlightDisplayLevel;
+import com.intellij.codeInspection.ex.InspectionProfileImpl;
import com.intellij.lang.annotation.HighlightSeverity;
+import com.intellij.profile.codeInspection.ui.ScopeOrderComparator;
import com.intellij.ui.JBColor;
import javax.swing.*;
import java.awt.*;
-import java.util.Collection;
-import java.util.LinkedHashMap;
+import java.util.*;
+import java.util.List;
/**
* @author Dmitry Batkovich
@@ -35,8 +37,17 @@ public class MultiScopeSeverityIcon implements Icon {
private final LinkedHashMap<String, HighlightSeverity> myScopeToAverageSeverityMap;
- public MultiScopeSeverityIcon(final LinkedHashMap<String, HighlightSeverity> scopeToAverageSeverityMap) {
- myScopeToAverageSeverityMap = scopeToAverageSeverityMap;
+ public MultiScopeSeverityIcon(final Map<String, HighlightSeverity> scopeToAverageSeverityMap,
+ final String defaultScopeName,
+ final InspectionProfileImpl inspectionProfile) {
+ final List<String> sortedScopeNames = new ArrayList<String>(scopeToAverageSeverityMap.keySet());
+ myScopeToAverageSeverityMap = new LinkedHashMap<String, HighlightSeverity>();
+ Collections.sort(sortedScopeNames, new ScopeOrderComparator(inspectionProfile));
+ sortedScopeNames.remove(defaultScopeName);
+ sortedScopeNames.add(defaultScopeName);
+ for (final String scopeName : sortedScopeNames) {
+ myScopeToAverageSeverityMap.put(scopeName, scopeToAverageSeverityMap.get(scopeName));
+ }
}
public LinkedHashMap<String, HighlightSeverity> getScopeToAverageSeverityMap() {
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/ScopesAndSeveritiesHintTable.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/ScopesAndSeveritiesHintTable.java
index 05cb7ab193f5..68c7f20119bd 100644
--- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/ScopesAndSeveritiesHintTable.java
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/ScopesAndSeveritiesHintTable.java
@@ -19,10 +19,12 @@ import com.intellij.codeHighlighting.HighlightDisplayLevel;
import com.intellij.lang.annotation.HighlightSeverity;
import com.intellij.profile.codeInspection.ui.SingleInspectionProfilePanel;
import com.intellij.ui.table.JBTable;
+import com.intellij.util.ui.UIUtil;
import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
+import javax.swing.table.TableColumn;
import java.awt.*;
import java.util.ArrayList;
import java.util.LinkedHashMap;
@@ -38,9 +40,20 @@ public class ScopesAndSeveritiesHintTable extends JBTable {
public ScopesAndSeveritiesHintTable(final LinkedHashMap<String, HighlightSeverity> scopeToAverageSeverityMap) {
super(new MyModel(scopeToAverageSeverityMap));
- final DefaultTableCellRenderer cellRenderer = new DefaultTableCellRenderer();
- cellRenderer.setOpaque(false);
- getColumnModel().getColumn(SCOPE_COLUMN).setCellRenderer(cellRenderer);
+ getColumnModel().getColumn(SCOPE_COLUMN).setCellRenderer(new DefaultTableCellRenderer() {
+ @Override
+ public Component getTableCellRendererComponent(JTable table,
+ Object value,
+ boolean isSelected,
+ boolean hasFocus,
+ int row,
+ int column) {
+ super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
+ setOpaque(false);
+ UIUtil.applyStyle(UIUtil.ComponentStyle.SMALL, this);
+ return this;
+ }
+ });
getColumnModel().getColumn(SEVERITY_COLUMN).setCellRenderer(new DefaultTableCellRenderer() {
@Override
@@ -55,6 +68,7 @@ public class ScopesAndSeveritiesHintTable extends JBTable {
setIcon(HighlightDisplayLevel.find(severity).getIcon());
setText(SingleInspectionProfilePanel.renderSeverity(severity));
setOpaque(false);
+ UIUtil.applyStyle(UIUtil.ComponentStyle.SMALL, this);
return this;
}
});
@@ -62,6 +76,16 @@ public class ScopesAndSeveritiesHintTable extends JBTable {
setRowSelectionAllowed(false);
setColumnSelectionAllowed(false);
setOpaque(false);
+
+ for (int i = 0; i < getColumnModel().getColumnCount(); i++) {
+ int w = 0;
+ final TableColumn column = getColumnModel().getColumn(i);
+ for (int j = 0; j < getModel().getRowCount(); j++) {
+ final Component component = prepareRenderer(column.getCellRenderer(), j, i);
+ w = Math.max(component.getPreferredSize().width, w);
+ }
+ column.setPreferredWidth(w);
+ }
}
private final static class MyModel extends AbstractTableModel {
@@ -96,7 +120,7 @@ public class ScopesAndSeveritiesHintTable extends JBTable {
@Override
public Object getValueAt(final int rowIndex, final int columnIndex) {
switch (columnIndex) {
- case SCOPE_COLUMN: return myScopes.get(rowIndex);
+ case SCOPE_COLUMN: return rowIndex < getRowCount() - 1 ? myScopes.get(rowIndex) : "Everywhere else";
case SEVERITY_COLUMN: return myScopeToAverageSeverityMap.get(myScopes.get(rowIndex));
default: throw new IllegalArgumentException();
}
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/ScopesAndSeveritiesTable.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/ScopesAndSeveritiesTable.java
index ad7dc946fff8..3b2c36bf7d34 100644
--- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/ScopesAndSeveritiesTable.java
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/ScopesAndSeveritiesTable.java
@@ -17,20 +17,30 @@ package com.intellij.profile.codeInspection.ui.table;
import com.intellij.codeHighlighting.HighlightDisplayLevel;
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
+import com.intellij.codeInspection.ex.Descriptor;
import com.intellij.codeInspection.ex.InspectionProfileImpl;
import com.intellij.codeInspection.ex.ScopeToolState;
import com.intellij.icons.AllIcons;
+import com.intellij.ide.DataManager;
import com.intellij.lang.annotation.HighlightSeverity;
+import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.popup.JBPopupFactory;
+import com.intellij.openapi.ui.popup.ListPopup;
import com.intellij.openapi.util.Comparing;
-import com.intellij.profile.codeInspection.ui.AddScopeUtil;
+import com.intellij.profile.codeInspection.ui.ScopeOrderComparator;
+import com.intellij.profile.codeInspection.ui.ScopesChooser;
import com.intellij.profile.codeInspection.ui.inspectionsTree.InspectionConfigTreeNode;
import com.intellij.psi.search.scope.packageSet.NamedScope;
+import com.intellij.ui.awt.RelativePoint;
import com.intellij.ui.table.JBTable;
import com.intellij.ui.treeStructure.treetable.TreeTable;
import com.intellij.util.ArrayUtil;
+import com.intellij.util.Function;
import com.intellij.util.SmartList;
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.EditableModel;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -41,8 +51,8 @@ import javax.swing.event.ListSelectionListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
-import java.util.ArrayList;
-import java.util.LinkedHashSet;
+import java.awt.*;
+import java.util.*;
import java.util.List;
/**
@@ -66,8 +76,8 @@ public class ScopesAndSeveritiesTable extends JBTable {
final TableColumn scopeEnabledColumn = columnModel.getColumn(SCOPE_ENABLED_COLUMN);
scopeEnabledColumn.setMaxWidth(30);
- scopeEnabledColumn.setCellRenderer(new ThreeStateCheckBoxRenderer());
- scopeEnabledColumn.setCellEditor(new ThreeStateCheckBoxRenderer());
+ scopeEnabledColumn.setCellRenderer(new ThreeStateCheckBoxRenderer(false));
+ scopeEnabledColumn.setCellEditor(new ThreeStateCheckBoxRenderer(true));
final TableColumn severityColumn = columnModel.getColumn(SEVERITY_COLUMN);
severityColumn.setCellRenderer(SeverityRenderer.create(tableSettings.getInspectionProfile()));
@@ -94,6 +104,8 @@ public class ScopesAndSeveritiesTable extends JBTable {
setStriped(true);
setShowGrid(false);
+
+ ((MyTableModel)getModel()).setTable(this);
}
public abstract static class TableSettings {
@@ -148,11 +160,13 @@ public class ScopesAndSeveritiesTable extends JBTable {
protected abstract void onScopeAdded();
+ protected abstract void onScopesOrderChanged();
+
protected abstract void onScopeRemoved(final int scopesCount);
protected abstract void onScopeChosen(final @NotNull ScopeToolState scopeToolState);
- protected abstract void onChange();
+ protected abstract void onSettingsChanged();
}
@NotNull
@@ -177,7 +191,9 @@ public class ScopesAndSeveritiesTable extends JBTable {
private final Project myProject;
private final TableSettings myTableSettings;
private final List<HighlightDisplayKey> myKeys;
+ private final Comparator<String> myScopeComparator;
+ private JTable myTable;
private String[] myScopeNames;
public MyTableModel(final TableSettings tableSettings) {
@@ -188,12 +204,24 @@ public class ScopesAndSeveritiesTable extends JBTable {
myKeyNames = tableSettings.getKeyNames();
myNodes = tableSettings.getNodes();
myTreeTable = tableSettings.getTreeTable();
+ myScopeComparator = new ScopeOrderComparator(myInspectionProfile);
refreshAggregatedScopes();
}
+ public void setTable(JTable table) {
+ myTable = table;
+ }
+
@Override
public boolean isCellEditable(final int rowIndex, final int columnIndex) {
- return columnIndex != SCOPE_NAME_COLUMN;
+ if (columnIndex == SCOPE_NAME_COLUMN) {
+ return false;
+ } else if (columnIndex == SCOPE_ENABLED_COLUMN) {
+ return true;
+ }
+ assert columnIndex == SEVERITY_COLUMN;
+ final ExistedScopesStatesAndNonExistNames scopeToolState = getScopeToolState(rowIndex);
+ return scopeToolState.getNonExistNames().isEmpty();
}
@Override
@@ -221,7 +249,7 @@ public class ScopesAndSeveritiesTable extends JBTable {
return String.class;
}
if (SEVERITY_COLUMN == columnIndex) {
- return HighlightSeverity.class;
+ return SeverityState.class;
}
throw new IllegalArgumentException();
}
@@ -235,9 +263,9 @@ public class ScopesAndSeveritiesTable extends JBTable {
case SCOPE_ENABLED_COLUMN:
return isEnabled(rowIndex);
case SCOPE_NAME_COLUMN:
- return getScope(rowIndex).getName();
+ return rowIndex == lastRowIndex() ? "Everywhere else" : getScope(rowIndex).getName();
case SEVERITY_COLUMN:
- return getSeverity(rowIndex);
+ return getSeverityState(rowIndex);
default:
throw new IllegalArgumentException("Invalid column index " + columnIndex);
}
@@ -248,12 +276,12 @@ public class ScopesAndSeveritiesTable extends JBTable {
}
@NotNull
- private HighlightSeverity getSeverity(final int rowIndex) {
+ private SeverityState getSeverityState(final int rowIndex) {
final ExistedScopesStatesAndNonExistNames existedScopesStatesAndNonExistNames = getScopeToolState(rowIndex);
if (!existedScopesStatesAndNonExistNames.getNonExistNames().isEmpty()) {
- return MIXED_FAKE_SEVERITY;
+ return new SeverityState(MIXED_FAKE_SEVERITY, false);
}
- return ScopesAndSeveritiesTable.getSeverity(existedScopesStatesAndNonExistNames.getExistedStates());
+ return new SeverityState(ScopesAndSeveritiesTable.getSeverity(existedScopesStatesAndNonExistNames.getExistedStates()), true);
}
@Nullable
@@ -314,6 +342,7 @@ public class ScopesAndSeveritiesTable extends JBTable {
}
}
myScopeNames = ArrayUtil.toStringArray(scopesNames);
+ Arrays.sort(myScopeNames, myScopeComparator);
}
private int lastRowIndex() {
@@ -326,13 +355,14 @@ public class ScopesAndSeveritiesTable extends JBTable {
return;
}
if (columnIndex == SEVERITY_COLUMN) {
- final HighlightDisplayLevel level = HighlightDisplayLevel.find(((HighlightSeverity)value).getName());
+ final SeverityState severityState = (SeverityState)value;
+ final HighlightDisplayLevel level = HighlightDisplayLevel.find(severityState.getSeverity().getName());
if (level == null) {
- LOG.error("no display level found for name " + ((HighlightSeverity)value).getName());
+ LOG.error("no display level found for name " + severityState.getSeverity().getName());
return;
}
- final int idx = rowIndex == lastRowIndex() ? -1 : rowIndex;
- myInspectionProfile.setErrorLevel(myKeys, level, idx, myProject);
+ final String scopeName = rowIndex == lastRowIndex() ? null : getScope(rowIndex).getName();
+ myInspectionProfile.setErrorLevel(myKeys, level, scopeName, myProject);
}
else if (columnIndex == SCOPE_ENABLED_COLUMN) {
final NamedScope scope = getScope(rowIndex);
@@ -354,7 +384,7 @@ public class ScopesAndSeveritiesTable extends JBTable {
}
}
}
- myTableSettings.onChange();
+ myTableSettings.onSettingsChanged();
}
@Override
@@ -368,9 +398,31 @@ public class ScopesAndSeveritiesTable extends JBTable {
@Override
public void addRow() {
- AddScopeUtil.performAddScope(myTreeTable, myProject, myInspectionProfile, myNodes);
- myTableSettings.onScopeAdded();
- refreshAggregatedScopes();
+ final List<Descriptor> descriptors = ContainerUtil.map(myTableSettings.getNodes(), new Function<InspectionConfigTreeNode, Descriptor>() {
+ @Override
+ public Descriptor fun(InspectionConfigTreeNode inspectionConfigTreeNode) {
+ return inspectionConfigTreeNode.getDefaultDescriptor();
+ }
+ });
+ final ScopesChooser scopesChooser = new ScopesChooser(descriptors, myInspectionProfile, myProject, myScopeNames) {
+ @Override
+ protected void onScopeAdded() {
+ myTableSettings.onScopeAdded();
+ refreshAggregatedScopes();
+ }
+
+ @Override
+ protected void onScopesOrderChanged() {
+ myTableSettings.onScopesOrderChanged();
+ }
+ };
+ DataContext dataContext = DataManager.getInstance().getDataContext(myTable);
+ final JComponent component = (JComponent)PlatformDataKeys.CONTEXT_COMPONENT.getData(dataContext);
+ final ListPopup popup = JBPopupFactory.getInstance()
+ .createActionGroupPopup(ScopesChooser.TITLE, scopesChooser.createPopupActionGroup(myTable), dataContext,
+ JBPopupFactory.ActionSelectionAid.SPEEDSEARCH, false);
+ final RelativePoint point = new RelativePoint(myTable, new Point(myTable.getWidth() - popup.getContent().getPreferredSize().width, 0));
+ popup.show(point);
}
@Override
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/SeverityRenderer.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/SeverityRenderer.java
index 2fe95e6d7224..e1b3d54b8fb7 100644
--- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/SeverityRenderer.java
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/SeverityRenderer.java
@@ -22,6 +22,8 @@ import com.intellij.openapi.ui.ComboBoxTableRenderer;
import com.intellij.profile.codeInspection.SeverityProvider;
import com.intellij.profile.codeInspection.ui.LevelChooserAction;
import com.intellij.profile.codeInspection.ui.SingleInspectionProfilePanel;
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -32,33 +34,40 @@ import java.util.SortedSet;
/**
* @author Dmitry Batkovich
*/
-public class SeverityRenderer extends ComboBoxTableRenderer<HighlightSeverity> {
- public SeverityRenderer(final HighlightSeverity[] values) {
+public class SeverityRenderer extends ComboBoxTableRenderer<SeverityState> {
+ public SeverityRenderer(final SeverityState[] values) {
super(values);
}
public static SeverityRenderer create(final InspectionProfileImpl inspectionProfile) {
final SortedSet<HighlightSeverity> severities =
LevelChooserAction.getSeverities(((SeverityProvider)inspectionProfile.getProfileManager()).getOwnSeverityRegistrar());
- return new SeverityRenderer(severities.toArray(new HighlightSeverity[severities.size()]));
+ return new SeverityRenderer(ContainerUtil.map2Array(severities, new SeverityState[severities.size()], new Function<HighlightSeverity, SeverityState>() {
+ @Override
+ public SeverityState fun(HighlightSeverity severity) {
+ return new SeverityState(severity, true);
+ }
+ }));
}
+ @Override
+ protected void customizeComponent(SeverityState value, JTable table, boolean isSelected) {
+ super.customizeComponent(value, table, isSelected);
+ setPaintArrow(value.isEnabledForEditing());
+ }
@Override
- protected String getTextFor(@NotNull final HighlightSeverity value) {
- return SingleInspectionProfilePanel.renderSeverity(value);
+ protected String getTextFor(@NotNull final SeverityState value) {
+ return SingleInspectionProfilePanel.renderSeverity(value.getSeverity());
}
@Override
- protected Icon getIconFor(@NotNull final HighlightSeverity value) {
- return HighlightDisplayLevel.find(value).getIcon();
+ protected Icon getIconFor(@NotNull final SeverityState value) {
+ return HighlightDisplayLevel.find(value.getSeverity()).getIcon();
}
@Override
public boolean isCellEditable(final EventObject event) {
- if (event instanceof MouseEvent) {
- return ((MouseEvent)event).getClickCount() >= 1;
- }
- return true;
+ return !(event instanceof MouseEvent) || ((MouseEvent)event).getClickCount() >= 1;
}
}
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/SeverityState.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/SeverityState.java
new file mode 100644
index 000000000000..2aefde070af7
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/SeverityState.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.profile.codeInspection.ui.table;
+
+import com.intellij.lang.annotation.HighlightSeverity;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class SeverityState {
+
+ private final HighlightSeverity mySeverity;
+ private final boolean myEnabledForEditing;
+
+ public SeverityState(HighlightSeverity severity, boolean enabledForEditing) {
+ mySeverity = severity;
+ myEnabledForEditing = enabledForEditing;
+ }
+
+ public HighlightSeverity getSeverity() {
+ return mySeverity;
+ }
+
+ public boolean isEnabledForEditing() {
+ return myEnabledForEditing;
+ }
+}
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/ThreeStateCheckBoxRenderer.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/ThreeStateCheckBoxRenderer.java
index 7d8cfdfc9db5..455e2a60cd19 100644
--- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/ThreeStateCheckBoxRenderer.java
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/ThreeStateCheckBoxRenderer.java
@@ -15,11 +15,9 @@
*/
package com.intellij.profile.codeInspection.ui.table;
-import com.intellij.ui.ClickListener;
import com.intellij.util.SmartList;
import com.intellij.util.ui.ThreeStateCheckBox;
import com.intellij.util.ui.UIUtil;
-import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -28,7 +26,7 @@ import javax.swing.event.ChangeEvent;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import java.awt.*;
-import java.awt.event.MouseEvent;
+import java.awt.event.*;
import java.util.EventObject;
import java.util.List;
@@ -39,10 +37,16 @@ public class ThreeStateCheckBoxRenderer extends ThreeStateCheckBox implements Ta
private final List<CellEditorListener> myListeners = new SmartList<CellEditorListener>();
- public ThreeStateCheckBoxRenderer() {
+ public ThreeStateCheckBoxRenderer(final boolean isEditor) {
setThirdStateEnabled(false);
setHorizontalAlignment(CENTER);
setVerticalAlignment(CENTER);
+ addItemListener(new ItemListener() {
+ @Override
+ public void itemStateChanged(ItemEvent e) {
+ stopCellEditing();
+ }
+ });
}
@Override
@@ -69,16 +73,6 @@ public class ThreeStateCheckBoxRenderer extends ThreeStateCheckBox implements Ta
} else {
setSelected((Boolean) value);
}
- new ClickListener() {
- @Override
- public boolean onClick(@NotNull final MouseEvent event, final int clickCount) {
- if (clickCount == 1) {
- stopCellEditing();
- return true;
- }
- return false;
- }
- }.installOn(this);
return this;
}
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerRunnable.java b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerRunnable.java
index 1b17faf21905..42dcb46c7ac0 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerRunnable.java
+++ b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerRunnable.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2010 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -149,7 +149,7 @@ abstract class CodeStyleManagerRunnable<T> {
SourceTreeToPsiMap.psiElementToTree(CodeStyleManagerImpl.findElementInTreeWithFormatterEnabled(file, offset));
if (elementAtOffset == null) {
int significantRangeStart = CharArrayUtil.shiftBackward(file.getText(), offset - 1, "\r\t ");
- return new TextRange(significantRangeStart, offset);
+ return new TextRange(Math.max(significantRangeStart, 0), offset);
}
final FormattingModelBuilder builder = LanguageFormatting.INSTANCE.forContext(file);
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java
index 27089fa70e91..fdc434d8d11a 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java
+++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java
@@ -16,6 +16,7 @@
package com.intellij.psi.impl.source.tree.injected;
+import com.intellij.extapi.psi.PsiFileBase;
import com.intellij.injected.editor.*;
import com.intellij.lang.Language;
import com.intellij.lang.LanguageUtil;
@@ -48,8 +49,10 @@ import java.util.List;
* @author cdr
*/
public class InjectedLanguageUtil {
- static final Key<List<Trinity<IElementType, SmartPsiElementPointer<PsiLanguageInjectionHost>, TextRange>>> HIGHLIGHT_TOKENS = Key.create("HIGHLIGHT_TOKENS");
- public static Key<Boolean> FRANKENSTEIN_INJECTION = Key.create("FRANKENSTEIN_INJECTION"); // meaning: injected file text is probably incorrect
+ static final Key<List<Trinity<IElementType, SmartPsiElementPointer<PsiLanguageInjectionHost>, TextRange>>> HIGHLIGHT_TOKENS =
+ Key.create("HIGHLIGHT_TOKENS");
+ public static Key<Boolean> FRANKENSTEIN_INJECTION = Key.create("FRANKENSTEIN_INJECTION");
+ // meaning: injected file text is probably incorrect
public static void forceInjectionOnElement(@NotNull PsiElement host) {
enumerate(host, new PsiLanguageInjectionHost.InjectedPsiVisitor() {
@@ -113,9 +116,9 @@ public class InjectedLanguageUtil {
* @return true if enumerated successfully
*/
public static boolean enumerate(@NotNull PsiElement host,
- @NotNull PsiFile containingFile,
- boolean probeUp,
- @NotNull PsiLanguageInjectionHost.InjectedPsiVisitor visitor) {
+ @NotNull PsiFile containingFile,
+ boolean probeUp,
+ @NotNull PsiLanguageInjectionHost.InjectedPsiVisitor visitor) {
//do not inject into nonphysical files except during completion
if (!containingFile.isPhysical() && containingFile.getOriginalFile() == containingFile) {
final PsiElement context = InjectedLanguageManager.getInstance(containingFile.getProject()).getInjectionHost(containingFile);
@@ -175,6 +178,32 @@ public class InjectedLanguageUtil {
return null;
}
+ /**
+ * Finds injected language in expression
+ *
+ * @param expression where to find
+ * @param classToFind class that represents language we look for
+ * @param <T> class that represents language we look for
+ * @return instance of class that represents language we look for or null of not found
+ */
+ @Nullable
+ @SuppressWarnings("unchecked") // We check types dynamically (using isAssignableFrom)
+ public static <T extends PsiFileBase> T findInjectedFile(@NotNull final PsiElement expression,
+ @NotNull final Class<T> classToFind) {
+ final List<Pair<PsiElement, TextRange>> files =
+ InjectedLanguageManager.getInstance(expression.getProject()).getInjectedPsiFiles(expression);
+ if (files == null) {
+ return null;
+ }
+ for (final Pair<PsiElement, TextRange> fileInfo : files) {
+ final PsiElement injectedFile = fileInfo.first;
+ if (classToFind.isAssignableFrom(injectedFile.getClass())) {
+ return (T)injectedFile;
+ }
+ }
+ return null;
+ }
+
public static Editor getEditorForInjectedLanguageNoCommit(@Nullable Editor editor, @Nullable PsiFile file, final int offset) {
if (editor == null || file == null || editor instanceof EditorWindow) return editor;
PsiFile injectedFile = findInjectedPsiNoCommit(file, offset);
@@ -200,7 +229,9 @@ public class InjectedLanguageUtil {
}
}
}
- if (!documentWindow.isValid()) return hostEditor; // since the moment we got hold of injectedFile and this moment call, document may have been dirtied
+ if (!documentWindow.isValid()) {
+ return hostEditor; // since the moment we got hold of injectedFile and this moment call, document may have been dirtied
+ }
return EditorWindowImpl.create(documentWindow, (EditorImpl)hostEditor, injectedFile);
}
@@ -284,7 +315,8 @@ public class InjectedLanguageUtil {
ParameterizedCachedValue<MultiHostRegistrarImpl, PsiElement> cachedValue =
CachedValuesManager.getManager(project).createParameterizedCachedValue(INJECTED_PSI_PROVIDER, false);
- CachedValueProvider.Result<MultiHostRegistrarImpl> result = CachedValueProvider.Result.create(registrar, PsiModificationTracker.MODIFICATION_COUNT, registrar);
+ CachedValueProvider.Result<MultiHostRegistrarImpl> result =
+ CachedValueProvider.Result.create(registrar, PsiModificationTracker.MODIFICATION_COUNT, registrar);
((PsiParameterizedCachedValue<MultiHostRegistrarImpl, PsiElement>)cachedValue).setValue(result);
e.putUserData(INJECTED_PSI, cachedValue);
@@ -307,7 +339,9 @@ public class InjectedLanguageUtil {
// returns (injected psi, leaf element at the offset, language of the leaf element)
// since findElementAt() is expensive, we trying to reuse its result
@NotNull
- private static Trinity<PsiElement,PsiElement,Language> tryOffset(@NotNull PsiFile hostFile, final int offset, @NotNull PsiDocumentManager documentManager) {
+ private static Trinity<PsiElement, PsiElement, Language> tryOffset(@NotNull PsiFile hostFile,
+ final int offset,
+ @NotNull PsiDocumentManager documentManager) {
FileViewProvider provider = hostFile.getViewProvider();
Language leafLanguage = null;
PsiElement leafElement = null;
@@ -319,11 +353,11 @@ public class InjectedLanguageUtil {
leafElement = element;
}
PsiElement injected = findInside(element, hostFile, offset, documentManager);
- if (injected != null) return Trinity.create(injected,element, language);
+ if (injected != null) return Trinity.create(injected, element, language);
}
// maybe we are at the border between two psi elements, then try to find injection at the end of the left element
if (offset != 0 && (element == null || element.getTextRange().getStartOffset() == offset)) {
- PsiElement leftElement = provider.findElementAt(offset-1, language);
+ PsiElement leftElement = provider.findElementAt(offset - 1, language);
if (leftElement != null && leftElement.getTextRange().getEndOffset() == offset) {
PsiElement injected = findInside(leftElement, hostFile, offset, documentManager);
if (injected != null) return Trinity.create(injected, element, language);
@@ -334,7 +368,10 @@ public class InjectedLanguageUtil {
return Trinity.create(null, leafElement, leafLanguage);
}
- private static PsiElement findInside(@NotNull PsiElement element, @NotNull PsiFile hostFile, final int hostOffset, @NotNull final PsiDocumentManager documentManager) {
+ private static PsiElement findInside(@NotNull PsiElement element,
+ @NotNull PsiFile hostFile,
+ final int hostOffset,
+ @NotNull final PsiDocumentManager documentManager) {
final Ref<PsiElement> out = new Ref<PsiElement>();
enumerate(element, hostFile, true, new PsiLanguageInjectionHost.InjectedPsiVisitor() {
@Override
@@ -361,10 +398,12 @@ public class InjectedLanguageUtil {
// modification of cachedInjectedDocuments must be under PsiLock only
ConcurrentList<DocumentWindow> injected = hostPsiFile.getUserData(INJECTED_DOCS_KEY);
if (injected == null) {
- injected = ((UserDataHolderEx)hostPsiFile).putUserDataIfAbsent(INJECTED_DOCS_KEY, ContainerUtil.<DocumentWindow>createConcurrentList());
+ injected =
+ ((UserDataHolderEx)hostPsiFile).putUserDataIfAbsent(INJECTED_DOCS_KEY, ContainerUtil.<DocumentWindow>createConcurrentList());
}
return injected;
}
+
public static void clearCachedInjectedFragmentsForFile(@NotNull PsiFile file) {
file.putUserData(INJECTED_DOCS_KEY, null);
}
@@ -426,10 +465,12 @@ public class InjectedLanguageUtil {
}
return containingFile;
}
+
@NotNull
public static Editor getTopLevelEditor(@NotNull Editor editor) {
return editor instanceof EditorWindow ? ((EditorWindow)editor).getDelegate() : editor;
}
+
public static boolean isInInjectedLanguagePrefixSuffix(@NotNull final PsiElement element) {
PsiFile injectedFile = element.getContainingFile();
if (injectedFile == null) return false;
@@ -461,13 +502,13 @@ public class InjectedLanguageUtil {
public static String getUnescapedText(PsiFile file, @Nullable final PsiElement startElement, @Nullable final PsiElement endElement) {
final InjectedLanguageManager manager = InjectedLanguageManager.getInstance(file.getProject());
if (manager.getInjectionHost(file) == null) {
- return file.getText().substring(startElement == null? 0 : startElement.getTextRange().getStartOffset(),
- endElement == null? file.getTextLength() : endElement.getTextRange().getStartOffset());
+ return file.getText().substring(startElement == null ? 0 : startElement.getTextRange().getStartOffset(),
+ endElement == null ? file.getTextLength() : endElement.getTextRange().getStartOffset());
}
final StringBuilder sb = new StringBuilder();
file.accept(new PsiRecursiveElementWalkingVisitor() {
- Boolean myState = startElement == null? Boolean.TRUE : null;
+ Boolean myState = startElement == null ? Boolean.TRUE : null;
@Override
public void visitElement(PsiElement element) {
diff --git a/platform/lang-impl/src/com/intellij/refactoring/introduce/inplace/KeyboardComboSwitcher.java b/platform/lang-impl/src/com/intellij/refactoring/introduce/inplace/KeyboardComboSwitcher.java
index 99ac9f7ec586..232ddd7bec3b 100644
--- a/platform/lang-impl/src/com/intellij/refactoring/introduce/inplace/KeyboardComboSwitcher.java
+++ b/platform/lang-impl/src/com/intellij/refactoring/introduce/inplace/KeyboardComboSwitcher.java
@@ -28,7 +28,7 @@ public class KeyboardComboSwitcher {
if (toggleStrategy) {
final int size = comboBox.getModel().getSize();
int next = comboBox.getSelectedIndex() + 1;
- if (next < 0 || next >= size) {
+ if (size > 0 && (next < 0 || next >= size)) {
if (!UISettings.getInstance().CYCLE_SCROLLING) {
return;
}
diff --git a/platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java b/platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java
index 1301079a1967..6e37711a9493 100644
--- a/platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java
+++ b/platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java
@@ -151,6 +151,7 @@ public class DetailViewImpl extends JPanel implements DetailView, UserDataHolder
getEditor().getSettings().setRefrainFromScrolling(false);
getEditor().getSettings().setLineNumbersShown(true);
getEditor().getSettings().setFoldingOutlineShown(false);
+ ((EditorEx)getEditor()).getFoldingModel().setFoldingEnabled(false);
add(getEditor().getComponent(), BorderLayout.CENTER);
}
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/ContentHashesSupport.java b/platform/lang-impl/src/com/intellij/util/indexing/ContentHashesSupport.java
index 34f80dae5cc9..451b0e7c1954 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/ContentHashesSupport.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/ContentHashesSupport.java
@@ -84,7 +84,7 @@ class ContentHashesSupport {
messageDigest.update((byte)0);
messageDigest.update(String.valueOf(bytes.length).getBytes(defaultCharset));
messageDigest.update((byte)0);
- messageDigest.update((charset != null ? charset.displayName():"null_charset").getBytes(defaultCharset));
+ messageDigest.update((charset != null ? charset.name():"null_charset").getBytes(defaultCharset));
messageDigest.update((byte)0);
messageDigest.update(bytes, 0, bytes.length);
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/DebugAssertions.java b/platform/lang-impl/src/com/intellij/util/indexing/DebugAssertions.java
index 6c866ad2283f..09aeea33b71e 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/DebugAssertions.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/DebugAssertions.java
@@ -31,7 +31,7 @@ public class DebugAssertions {
public static final boolean EXTRA_SANITY_CHECKS = SystemProperties.getBooleanProperty(
"intellij.idea.indices.debug.extra.sanity",
- true
+ DEBUG
);
public static void assertTrue(boolean value) {
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java
index 5242ee3b70cf..85077380ea6e 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java
@@ -1964,33 +1964,38 @@ public class FileBasedIndexImpl extends FileBasedIndex {
// For 'normal indices' schedule the file for update and reset stamps for all affected indices (there
// can be client that used indices between before and after events, in such case indices are up to date due to force update
// with old content)
- if (!fileIsDirectory && !isTooLarge(file)) {
- FileTypeManagerImpl.cacheFileType(file, file.getFileType());
- try {
- final List<ID<?, ?>> candidates = getAffectedIndexCandidates(file);
- //noinspection ForLoopReplaceableByForEach
- boolean scheduleForUpdate = false;
- boolean resetStamp = false;
-
- //noinspection ForLoopReplaceableByForEach
- for (int i = 0, size = candidates.size(); i < size; ++i) {
- final ID<?, ?> indexId = candidates.get(i);
- if (needsFileContentLoading(indexId) && getInputFilter(indexId).acceptInput(file)) {
- if (IndexingStamp.isFileIndexedStateCurrent(file, indexId)) {
- IndexingStamp.setFileIndexedStateOutdated(file, indexId);
- resetStamp = true;
+ if (!fileIsDirectory) {
+ if (isTooLarge(file)) {
+ // large file might be scheduled for update in before event when its size was not large
+ myChangedFilesCollector.myFilesToUpdate.remove(file);
+ } else {
+ FileTypeManagerImpl.cacheFileType(file, file.getFileType());
+ try {
+ final List<ID<?, ?>> candidates = getAffectedIndexCandidates(file);
+ //noinspection ForLoopReplaceableByForEach
+ boolean scheduleForUpdate = false;
+ boolean resetStamp = false;
+
+ //noinspection ForLoopReplaceableByForEach
+ for (int i = 0, size = candidates.size(); i < size; ++i) {
+ final ID<?, ?> indexId = candidates.get(i);
+ if (needsFileContentLoading(indexId) && getInputFilter(indexId).acceptInput(file)) {
+ if (IndexingStamp.isFileIndexedStateCurrent(file, indexId)) {
+ IndexingStamp.setFileIndexedStateOutdated(file, indexId);
+ resetStamp = true;
+ }
+ scheduleForUpdate = true;
}
- scheduleForUpdate = true;
}
- }
- if (scheduleForUpdate) {
- if (resetStamp) IndexingStamp.flushCache(file);
- scheduleForUpdate(file);
+ if (scheduleForUpdate) {
+ if (resetStamp) IndexingStamp.flushCache(file);
+ scheduleForUpdate(file);
+ }
+ }
+ finally {
+ FileTypeManagerImpl.cacheFileType(file, null);
}
- }
- finally {
- FileTypeManagerImpl.cacheFileType(file, null);
}
}
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/IndexingStamp.java b/platform/lang-impl/src/com/intellij/util/indexing/IndexingStamp.java
index 6bdd55b1d343..5ef1379eaaf4 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/IndexingStamp.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/IndexingStamp.java
@@ -59,7 +59,7 @@ public class IndexingStamp {
private static final long UNINDEXED_STAMP = -1L; // we don't store trivial "absent" state
private static final long INDEX_DATA_OUTDATED_STAMP = -2L;
- private static final int VERSION = 12;
+ private static final int VERSION = 13;
private static final ConcurrentHashMap<ID<?, ?>, Long> ourIndexIdToCreationStamp = new ConcurrentHashMap<ID<?, ?>, Long>();
private static volatile long ourLastStamp; // ensure any file index stamp increases
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/MapReduceIndex.java b/platform/lang-impl/src/com/intellij/util/indexing/MapReduceIndex.java
index ebb7911e82be..6427765295c5 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/MapReduceIndex.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/MapReduceIndex.java
@@ -354,7 +354,7 @@ public class MapReduceIndex<Key, Value, Input> implements UpdatableIndex<Key,Val
FileContent fileContent = (FileContent)content;
hashId = getHashOfContent(fileContent);
if (doReadSavedPersistentData) {
- if (!myContents.isBusyReading()) { // avoid blocking read, we can calculate index value
+ if (!myContents.isBusyReading() || DebugAssertions.EXTRA_SANITY_CHECKS) { // avoid blocking read, we can calculate index value
ByteSequence bytes = myContents.get(hashId);
if (bytes != null) {
data = deserializeSavedPersistentData(bytes);
@@ -367,7 +367,7 @@ public class MapReduceIndex<Key, Value, Input> implements UpdatableIndex<Key,Val
"Unexpected difference in indexing of %s by index %s, file type %s, charset %s\ndiff %s\nprevious indexed info %s",
fileContent.getFile(),
myIndexId,
- fileContent.getFileType(),
+ fileContent.getFileType().getName(),
((FileContentImpl)fileContent).getCharset(),
buildDiff(data, contentData),
myIndexingTrace.get(hashId)
@@ -396,7 +396,7 @@ public class MapReduceIndex<Key, Value, Input> implements UpdatableIndex<Key,Val
FileContent fileContent = (FileContent)content;
try {
- myIndexingTrace.put(hashId, ((FileContentImpl)fileContent).getCharset() + "," + fileContent.getFileType()+"," + fileContent.getFile().getPath() + "," +
+ myIndexingTrace.put(hashId, ((FileContentImpl)fileContent).getCharset() + "," + fileContent.getFileType().getName()+"," + fileContent.getFile().getPath() + "," +
ExceptionUtil.getThrowableText(new Throwable()));
} catch (IOException ex) {
LOG.error(ex);
diff --git a/platform/lang-impl/src/com/intellij/webcore/packaging/ManagePackagesDialog.java b/platform/lang-impl/src/com/intellij/webcore/packaging/ManagePackagesDialog.java
index 18961ca843c3..fcbaa21f330b 100644
--- a/platform/lang-impl/src/com/intellij/webcore/packaging/ManagePackagesDialog.java
+++ b/platform/lang-impl/src/com/intellij/webcore/packaging/ManagePackagesDialog.java
@@ -1,3 +1,18 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
package com.intellij.webcore.packaging;
import com.intellij.icons.AllIcons;
@@ -93,6 +108,7 @@ public class ManagePackagesDialog extends DialogWrapper {
public void run() {
try {
myController.reloadAllPackages();
+ initModel();
myPackages.setPaintBusy(false);
}
catch (final IOException e) {
@@ -310,6 +326,7 @@ public class ManagePackagesDialog extends DialogWrapper {
@Override
public void run() {
myPackages.setModel(myPackagesModel);
+ ((MyPackageFilter)myFilter).filter();
doSelectPackage(mySelectedPackageName);
setDownloadStatus(false);
}
@@ -473,6 +490,7 @@ public class ManagePackagesDialog extends DialogWrapper {
final Object pyPackage = myPackages.getSelectedValue();
if (pyPackage instanceof RepoPackage) {
final String packageName = ((RepoPackage)pyPackage).getName();
+ mySelectedPackageName = packageName;
myVersionComboBox.removeAllItems();
if (myVersionCheckBox.isEnabled()) {
myController.fetchPackageVersions(packageName, new CatchingConsumer<List<String>, Exception>() {
diff --git a/platform/lang-impl/src/com/intellij/webcore/packaging/PackagesNotificationPanel.java b/platform/lang-impl/src/com/intellij/webcore/packaging/PackagesNotificationPanel.java
index cb281cb3d7af..1513bb451aa2 100644
--- a/platform/lang-impl/src/com/intellij/webcore/packaging/PackagesNotificationPanel.java
+++ b/platform/lang-impl/src/com/intellij/webcore/packaging/PackagesNotificationPanel.java
@@ -8,6 +8,7 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.HyperlinkAdapter;
import com.intellij.ui.ScrollPaneFactory;
import com.intellij.ui.components.JBLabel;
+import com.intellij.util.ui.SwingHelper;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -22,18 +23,17 @@ import java.util.Map;
* @author yole
*/
public class PackagesNotificationPanel {
- private final JEditorPane myEditorPane = new MyNotificationPane();
private final Project myProject;
+ private final JEditorPane myHtmlViewer;
private final Map<String, Runnable> myLinkHandlers = new HashMap<String, Runnable>();
private String myErrorTitle;
private String myErrorDescription;
- public PackagesNotificationPanel(Project project) {
+ public PackagesNotificationPanel(@NotNull Project project) {
myProject = project;
- myEditorPane.setBackground(UIManager.getColor("ArrowButton.background"));
- myEditorPane.setContentType("text/html");
- myEditorPane.setEditable(false);
- myEditorPane.addHyperlinkListener(new HyperlinkAdapter() {
+ myHtmlViewer = SwingHelper.createHtmlViewer(true, null, null, null);
+ myHtmlViewer.setVisible(false);
+ myHtmlViewer.addHyperlinkListener(new HyperlinkAdapter() {
@Override
protected void hyperlinkActivated(HyperlinkEvent e) {
final Runnable handler = myLinkHandlers.get(e.getDescription());
@@ -76,11 +76,18 @@ public class PackagesNotificationPanel {
public void showResult(String packageName, @Nullable String errorDescription) {
if (StringUtil.isEmpty(errorDescription)) {
- showSuccess("Package successfully installed.");
+ String message = "Package installed successfully";
+ if (packageName != null) {
+ message = "Package '" + packageName + "' installed successfully";
+ }
+ showSuccess(message);
}
else {
- String title = "Install packages failed";
- final String firstLine = title + ": Error occurred when installing package " + packageName + ". ";
+ String title = "Failed to install packages";
+ if (packageName != null) {
+ title = "Failed to install package '" + packageName + "'";
+ }
+ String firstLine = "Error occurred when installing package '" + packageName + "'. ";
showError(firstLine + "<a href=\"xxx\">Details...</a>",
title,
firstLine + errorDescription);
@@ -96,19 +103,18 @@ public class PackagesNotificationPanel {
}
public JComponent getComponent() {
- return myEditorPane;
+ return myHtmlViewer;
}
public void showSuccess(String text) {
showContent(text, MessageType.INFO.getPopupBackground());
}
- private void showContent(String text, final Color background) {
- myEditorPane.removeAll();
+ private void showContent(@NotNull String text, @NotNull Color background) {
String htmlText = text.startsWith("<html>") ? text : UIUtil.toHtml(text);
- myEditorPane.setText(htmlText);
- myEditorPane.setBackground(background);
- myEditorPane.setVisible(true);
+ myHtmlViewer.setText(htmlText);
+ myHtmlViewer.setBackground(background);
+ setVisibleEditorPane(true);
myErrorTitle = null;
myErrorDescription = null;
}
@@ -124,22 +130,20 @@ public class PackagesNotificationPanel {
}
public void hide() {
- myEditorPane.setVisible(false);
+ setVisibleEditorPane(false);
}
- public boolean hasLinkHandler(String key) {
- return myLinkHandlers.containsKey(key);
+ private void setVisibleEditorPane(boolean visible) {
+ boolean oldVisible = myHtmlViewer.isVisible();
+ myHtmlViewer.setVisible(visible);
+ if (oldVisible != visible) {
+ myHtmlViewer.revalidate();
+ myHtmlViewer.repaint();
+ }
}
- private static class MyNotificationPane extends JEditorPane {
- @Override
- public Dimension getPreferredSize() {
- // This trick makes text component to carry text over to the next line
- // iff the text line width exceeds parent's width
- Dimension dimension = super.getPreferredSize();
- dimension.width = 0;
- return dimension;
- }
+ public boolean hasLinkHandler(String key) {
+ return myLinkHandlers.containsKey(key);
}
public void removeLinkHandler(String key) {
diff --git a/platform/lang-impl/testData/editor/indentingBackspace/beforeBrace-after.java b/platform/lang-impl/testData/editor/indentingBackspace/beforeBrace-after.java
new file mode 100644
index 000000000000..f1733f5e6d06
--- /dev/null
+++ b/platform/lang-impl/testData/editor/indentingBackspace/beforeBrace-after.java
@@ -0,0 +1,4 @@
+class A {
+ void foo() {
+ }
+<caret>}
diff --git a/platform/lang-impl/testData/editor/indentingBackspace/beforeBrace.java b/platform/lang-impl/testData/editor/indentingBackspace/beforeBrace.java
new file mode 100644
index 000000000000..5fd42398e146
--- /dev/null
+++ b/platform/lang-impl/testData/editor/indentingBackspace/beforeBrace.java
@@ -0,0 +1,5 @@
+class A {
+ void foo() {
+ }
+
+<caret>}
diff --git a/platform/lang-impl/testData/editor/indentingBackspace/spacingInsert-after.java b/platform/lang-impl/testData/editor/indentingBackspace/spacingInsert-after.java
new file mode 100644
index 000000000000..3284439c1b24
--- /dev/null
+++ b/platform/lang-impl/testData/editor/indentingBackspace/spacingInsert-after.java
@@ -0,0 +1,3 @@
+class Foo {
+ int <caret>i;
+}
diff --git a/platform/lang-impl/testData/editor/indentingBackspace/spacingInsert.java b/platform/lang-impl/testData/editor/indentingBackspace/spacingInsert.java
new file mode 100644
index 000000000000..25766081e3c2
--- /dev/null
+++ b/platform/lang-impl/testData/editor/indentingBackspace/spacingInsert.java
@@ -0,0 +1,4 @@
+class Foo {
+ int
+ <caret>i;
+}
diff --git a/platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart-after.java b/platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart-after.java
new file mode 100644
index 000000000000..3284439c1b24
--- /dev/null
+++ b/platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart-after.java
@@ -0,0 +1,3 @@
+class Foo {
+ int <caret>i;
+}
diff --git a/platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart.java b/platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart.java
new file mode 100644
index 000000000000..29e2260c35b8
--- /dev/null
+++ b/platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart.java
@@ -0,0 +1,4 @@
+class Foo {
+ int
+<caret> i;
+}
diff --git a/platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart2-after.java b/platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart2-after.java
new file mode 100644
index 000000000000..3284439c1b24
--- /dev/null
+++ b/platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart2-after.java
@@ -0,0 +1,3 @@
+class Foo {
+ int <caret>i;
+}
diff --git a/platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart2.java b/platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart2.java
new file mode 100644
index 000000000000..6c1bbe85b269
--- /dev/null
+++ b/platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart2.java
@@ -0,0 +1,4 @@
+class Foo {
+ int
+<caret>i;
+}
diff --git a/platform/lang-impl/testSources/com/intellij/codeInsight/editorActions/IndentingBackspaceHandlerUncommittedDocumentTest.java b/platform/lang-impl/testSources/com/intellij/codeInsight/editorActions/IndentingBackspaceHandlerUncommittedDocumentTest.java
new file mode 100644
index 000000000000..f51179dfa5d8
--- /dev/null
+++ b/platform/lang-impl/testSources/com/intellij/codeInsight/editorActions/IndentingBackspaceHandlerUncommittedDocumentTest.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.editorActions;
+
+import com.intellij.testFramework.LightPlatformCodeInsightTestCase;
+
+import java.io.IOException;
+
+public class IndentingBackspaceHandlerUncommittedDocumentTest extends LightPlatformCodeInsightTestCase {
+ public void testSequentialBackspaceInvocation() throws IOException {
+ configureFromFileText(getTestName(false) + ".java",
+ "class Foo {\n" +
+ "\n" +
+ "\n" +
+ "<caret>}");
+ backspace();
+ backspace();
+ checkResultByText("class Foo {\n" +
+ "<caret>}");
+ }
+
+ public void testMulticaretSequentialBackspaceInvocation() throws IOException {
+ configureFromFileText(getTestName(false) + ".java",
+ "class Foo {\n" +
+ " void m1() {\n" +
+ " \n" +
+ " <caret>}\n" +
+ " void m2() {\n" +
+ " \n" +
+ " <caret>}\n" +
+ "}");
+ backspace();
+ backspace();
+ checkResultByText("class Foo {\n" +
+ " void m1() {<caret>}\n" +
+ " void m2() {<caret>}\n" +
+ "}");
+ }
+} \ No newline at end of file
diff --git a/platform/lvcs-impl/src/com/intellij/history/core/Paths.java b/platform/lvcs-impl/src/com/intellij/history/core/Paths.java
index 440fd699ef7d..bd98591b4cb3 100644
--- a/platform/lvcs-impl/src/com/intellij/history/core/Paths.java
+++ b/platform/lvcs-impl/src/com/intellij/history/core/Paths.java
@@ -67,9 +67,18 @@ public class Paths {
}
public static Iterable<String> split(String path) {
- Iterable<String> result = StringUtil.tokenize(path, String.valueOf(DELIM));
- if (path.indexOf(DELIM) == 0) {
- result = ContainerUtil.concat(Collections.singleton(String.valueOf(DELIM)), result);
+ //must be consistent with LocalFileSystemBase.extractRootPath()
+ int prefixLen = 0;
+ if (path.startsWith("//")) {
+ prefixLen = path.indexOf(DELIM, 2);
+ if (prefixLen == -1) prefixLen = path.length();
+ }
+ else if (StringUtil.startsWithChar(path, DELIM)) {
+ prefixLen = 1;
+ }
+ Iterable<String> result = StringUtil.tokenize(path.substring(prefixLen), String.valueOf(DELIM));
+ if (prefixLen > 0) {
+ result = ContainerUtil.concat(Collections.singleton(path.substring(0, prefixLen)), result);
}
return result;
}
diff --git a/platform/platform-api/src/com/intellij/ide/BrowserUtil.java b/platform/platform-api/src/com/intellij/ide/BrowserUtil.java
index 90308f5dbfda..cd1d1b0dba49 100644
--- a/platform/platform-api/src/com/intellij/ide/BrowserUtil.java
+++ b/platform/platform-api/src/com/intellij/ide/BrowserUtil.java
@@ -20,6 +20,7 @@ import com.intellij.execution.util.ExecUtil;
import com.intellij.ide.browsers.BrowserLauncher;
import com.intellij.ide.browsers.BrowserLauncherAppless;
import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
@@ -106,6 +107,10 @@ public class BrowserUtil {
getBrowserLauncher().browse(uri);
}
+ public static void browse(@NotNull String url, @Nullable Project project) {
+ getBrowserLauncher().browse(url, null, project);
+ }
+
@SuppressWarnings("UnusedDeclaration")
@NotNull
@Deprecated
@@ -145,6 +150,9 @@ public class BrowserUtil {
else if (SystemInfo.isMac) {
return "open";
}
+ else if (SystemInfo.isUnix) {
+ return "/usr/bin/firefox";
+ }
else {
return "";
}
diff --git a/platform/platform-api/src/com/intellij/ide/browsers/BrowserFamily.java b/platform/platform-api/src/com/intellij/ide/browsers/BrowserFamily.java
index f6826b528427..f767ec90d49f 100644
--- a/platform/platform-api/src/com/intellij/ide/browsers/BrowserFamily.java
+++ b/platform/platform-api/src/com/intellij/ide/browsers/BrowserFamily.java
@@ -35,9 +35,9 @@ public enum BrowserFamily implements Iconable {
private final Icon myIcon;
BrowserFamily(@NotNull String name,
- @NotNull final String windowsPath,
- @Nullable final String unixPath,
- @Nullable final String macPath,
+ @NotNull String windowsPath,
+ @Nullable String unixPath,
+ @Nullable String macPath,
@NotNull Icon icon) {
myName = name;
myWindowsPath = windowsPath;
diff --git a/platform/platform-api/src/com/intellij/ide/browsers/BrowserLauncherAppless.java b/platform/platform-api/src/com/intellij/ide/browsers/BrowserLauncherAppless.java
index 0c34152861d1..736dcd8afe22 100644
--- a/platform/platform-api/src/com/intellij/ide/browsers/BrowserLauncherAppless.java
+++ b/platform/platform-api/src/com/intellij/ide/browsers/BrowserLauncherAppless.java
@@ -74,10 +74,10 @@ public class BrowserLauncherAppless extends BrowserLauncher {
Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(action);
}
- public static boolean canStartDefaultBrowser() {
+ public static boolean canUseSystemDefaultBrowserPolicy() {
return isDesktopActionSupported(Desktop.Action.BROWSE) ||
SystemInfo.isMac || SystemInfo.isWindows ||
- SystemInfo.isUnix && SystemInfo.hasXdgOpen();
+ (SystemInfo.isUnix && SystemInfo.hasXdgOpen());
}
private static GeneralSettings getGeneralSettingsInstance() {
@@ -109,7 +109,7 @@ public class BrowserLauncherAppless extends BrowserLauncher {
@Override
public void open(@NotNull String url) {
- openOrBrowse(url, false);
+ openOrBrowse(url, false, null);
}
@Override
@@ -119,6 +119,10 @@ public class BrowserLauncherAppless extends BrowserLauncher {
@Override
public void browse(@NotNull URI uri) {
+ browse(uri, null);
+ }
+
+ public void browse(@NotNull URI uri, @Nullable Project project) {
LOG.debug("Launch browser: [" + uri + "]");
GeneralSettings settings = getGeneralSettingsInstance();
@@ -136,15 +140,19 @@ public class BrowserLauncherAppless extends BrowserLauncher {
List<String> command = getDefaultBrowserCommand();
if (command != null) {
- doLaunch(uri.toString(), command, null, null, ArrayUtil.EMPTY_STRING_ARRAY, null);
+ doLaunch(uri.toString(), command, null, project, ArrayUtil.EMPTY_STRING_ARRAY, null);
return;
}
}
- browseUsingPath(uri.toString(), settings.getBrowserPath(), null, null, ArrayUtil.EMPTY_STRING_ARRAY);
+ browseUsingNotSystemDefaultBrowserPolicy(uri, settings, project);
}
- private void openOrBrowse(@NotNull String url, boolean browse) {
+ protected void browseUsingNotSystemDefaultBrowserPolicy(@NotNull URI uri, @NotNull GeneralSettings settings, @Nullable Project project) {
+ browseUsingPath(uri.toString(), settings.getBrowserPath(), null, project, ArrayUtil.EMPTY_STRING_ARRAY);
+ }
+
+ private void openOrBrowse(@NotNull String url, boolean browse, @Nullable Project project) {
url = url.trim();
if (url.startsWith("jar:")) {
@@ -181,7 +189,7 @@ public class BrowserLauncherAppless extends BrowserLauncher {
}
if (uri == null) {
- doShowError(IdeBundle.message("error.malformed.url", url), null, null, null, null);
+ doShowError(IdeBundle.message("error.malformed.url", url), null, project, null, null);
}
else {
browse(uri);
@@ -380,7 +388,7 @@ public class BrowserLauncherAppless extends BrowserLauncher {
@Override
public void browse(@NotNull String url, @Nullable WebBrowser browser, @Nullable Project project) {
if (browser == null) {
- openOrBrowse(url, true);
+ openOrBrowse(url, true, project);
}
else {
for (UrlOpener urlOpener : UrlOpener.EP_NAME.getExtensions()) {
@@ -436,8 +444,8 @@ public class BrowserLauncherAppless extends BrowserLauncher {
private boolean doLaunch(@Nullable String url,
@NotNull List<String> command,
- @Nullable final WebBrowser browser,
- @Nullable final Project project,
+ @Nullable WebBrowser browser,
+ @Nullable Project project,
@NotNull String[] additionalParameters,
@Nullable Runnable launchTask) {
GeneralCommandLine commandLine = new GeneralCommandLine(command);
@@ -454,7 +462,13 @@ public class BrowserLauncherAppless extends BrowserLauncher {
commandLine.addParameter(url);
}
- addArgs(commandLine, browser == null ? null : browser.getSpecificSettings(), additionalParameters);
+ final BrowserSpecificSettings browserSpecificSettings = browser == null ? null : browser.getSpecificSettings();
+ if (browserSpecificSettings != null) {
+ commandLine.getEnvironment().putAll(browserSpecificSettings.getEnvironmentVariables());
+ }
+
+ addArgs(commandLine, browserSpecificSettings, additionalParameters);
+
try {
Process process = commandLine.createProcess();
checkCreatedProcess(browser, project, commandLine, process, launchTask);
diff --git a/platform/platform-api/src/com/intellij/ide/browsers/BrowserSpecificSettings.java b/platform/platform-api/src/com/intellij/ide/browsers/BrowserSpecificSettings.java
index 826ca80cd21a..b7fd90ef3ade 100644
--- a/platform/platform-api/src/com/intellij/ide/browsers/BrowserSpecificSettings.java
+++ b/platform/platform-api/src/com/intellij/ide/browsers/BrowserSpecificSettings.java
@@ -20,6 +20,7 @@ import org.jetbrains.annotations.NotNull;
import java.util.Collections;
import java.util.List;
+import java.util.Map;
public abstract class BrowserSpecificSettings implements Cloneable {
@NotNull
@@ -30,6 +31,11 @@ public abstract class BrowserSpecificSettings implements Cloneable {
return Collections.emptyList();
}
+ @NotNull
+ public Map<String, String> getEnvironmentVariables() {
+ return Collections.emptyMap();
+ }
+
@Override
public BrowserSpecificSettings clone() {
try {
diff --git a/platform/platform-api/src/com/intellij/ide/browsers/chrome/ChromeSettings.java b/platform/platform-api/src/com/intellij/ide/browsers/chrome/ChromeSettings.java
index b6ca3e7ac44f..555097bb546c 100644
--- a/platform/platform-api/src/com/intellij/ide/browsers/chrome/ChromeSettings.java
+++ b/platform/platform-api/src/com/intellij/ide/browsers/chrome/ChromeSettings.java
@@ -21,7 +21,9 @@ import com.intellij.openapi.util.io.FileUtilRt;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.PathUtil;
import com.intellij.util.execution.ParametersListUtil;
+import com.intellij.util.xmlb.annotations.MapAnnotation;
import com.intellij.util.xmlb.annotations.Tag;
+import gnu.trove.THashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -33,6 +35,7 @@ public final class ChromeSettings extends BrowserSpecificSettings {
private @Nullable String myCommandLineOptions;
private @Nullable String myUserDataDirectoryPath;
private boolean myUseCustomProfile;
+ private @NotNull THashMap<String, String> myEnvironmentVariables = new THashMap<String, String>();
public ChromeSettings() {
}
@@ -85,6 +88,18 @@ public final class ChromeSettings extends BrowserSpecificSettings {
return cliOptions;
}
+ @Override
+ @NotNull
+ @Tag("environment-variables")
+ @MapAnnotation(surroundWithTag = false, surroundKeyWithTag = false, surroundValueWithTag = false)
+ public THashMap<String, String> getEnvironmentVariables() {
+ return myEnvironmentVariables;
+ }
+
+ public void setEnvironmentVariables(@NotNull final THashMap<String, String> environmentVariables) {
+ myEnvironmentVariables = environmentVariables;
+ }
+
@NotNull
@Override
public ChromeSettingsConfigurable createConfigurable() {
@@ -92,6 +107,13 @@ public final class ChromeSettings extends BrowserSpecificSettings {
}
@Override
+ public ChromeSettings clone() {
+ ChromeSettings clone = (ChromeSettings)super.clone();
+ clone.myEnvironmentVariables = myEnvironmentVariables.clone();
+ return clone;
+ }
+
+ @Override
public boolean equals(Object o) {
if (this == o) {
return true;
@@ -103,6 +125,7 @@ public final class ChromeSettings extends BrowserSpecificSettings {
ChromeSettings settings = (ChromeSettings)o;
return myUseCustomProfile == settings.myUseCustomProfile &&
Comparing.equal(myCommandLineOptions, settings.myCommandLineOptions) &&
- (!myUseCustomProfile || Comparing.equal(myUserDataDirectoryPath, settings.myUserDataDirectoryPath));
+ (!myUseCustomProfile || Comparing.equal(myUserDataDirectoryPath, settings.myUserDataDirectoryPath)) &&
+ myEnvironmentVariables.equals(settings.myEnvironmentVariables);
}
}
diff --git a/platform/platform-api/src/com/intellij/ide/browsers/firefox/FirefoxSettingsConfigurable.java b/platform/platform-api/src/com/intellij/ide/browsers/firefox/FirefoxSettingsConfigurable.java
index ef95f7cb872e..c28b7e495b41 100644
--- a/platform/platform-api/src/com/intellij/ide/browsers/firefox/FirefoxSettingsConfigurable.java
+++ b/platform/platform-api/src/com/intellij/ide/browsers/firefox/FirefoxSettingsConfigurable.java
@@ -26,7 +26,6 @@ import com.intellij.openapi.util.io.FileUtilRt;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.DocumentAdapter;
-import com.intellij.util.ObjectUtils;
import com.intellij.util.PathUtil;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.Nullable;
@@ -48,7 +47,7 @@ public class FirefoxSettingsConfigurable implements Configurable {
private final FirefoxSettings mySettings;
private String myLastProfilesIniPath;
private String myDefaultProfilesIniPath;
- private String myDefaultProfile;
+ private String defaultProfile;
public FirefoxSettingsConfigurable(FirefoxSettings settings) {
mySettings = settings;
@@ -89,11 +88,8 @@ public class FirefoxSettingsConfigurable implements Configurable {
@Nullable
private String getConfiguredProfileName() {
- final String selected = (String)myProfileCombobox.getSelectedItem();
- if (Comparing.equal(myDefaultProfile, selected)) {
- return null;
- }
- return selected;
+ String selected = (String)myProfileCombobox.getSelectedItem();
+ return Comparing.equal(defaultProfile, selected) ? null : selected;
}
@Override
@@ -110,7 +106,9 @@ public class FirefoxSettingsConfigurable implements Configurable {
String path = mySettings.getProfilesIniPath();
myProfilesIniPathField.setText(path != null ? FileUtilRt.toSystemDependentName(path) : myDefaultProfilesIniPath);
updateProfilesList();
- myProfileCombobox.setSelectedItem(ObjectUtils.notNull(mySettings.getProfile(), myDefaultProfile));
+
+ String profile = mySettings.getProfile();
+ myProfileCombobox.setSelectedItem(profile == null ? defaultProfile : profile);
}
private void updateProfilesList() {
@@ -122,7 +120,7 @@ public class FirefoxSettingsConfigurable implements Configurable {
myProfileCombobox.removeAllItems();
final List<FirefoxProfile> profiles = FirefoxUtil.computeProfiles(new File(profilesIniPath));
final FirefoxProfile defaultProfile = FirefoxUtil.getDefaultProfile(profiles);
- myDefaultProfile = defaultProfile != null ? defaultProfile.getName() : null;
+ this.defaultProfile = defaultProfile != null ? defaultProfile.getName() : null;
for (FirefoxProfile profile : profiles) {
//noinspection unchecked
myProfileCombobox.addItem(profile.getName());
diff --git a/platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java b/platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java
index 1d4fea4c01de..049bde52f582 100644
--- a/platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java
+++ b/platform/platform-api/src/com/intellij/openapi/actionSystem/IdeActions.java
@@ -36,6 +36,8 @@ public interface IdeActions {
@NonNls String ACTION_EDITOR_SELECT_WORD_AT_CARET = "EditorSelectWord";
@NonNls String ACTION_EDITOR_UNSELECT_WORD_AT_CARET = "EditorUnSelectWord";
@NonNls String ACTION_EDITOR_BACKSPACE = "EditorBackSpace";
+ @NonNls String ACTION_EDITOR_MOVE_CARET_LEFT_WITH_SELECTION = "EditorLeftWithSelection";
+ @NonNls String ACTION_EDITOR_MOVE_CARET_RIGHT_WITH_SELECTION = "EditorRightWithSelection";
@NonNls String ACTION_EDITOR_MOVE_CARET_UP = "EditorUp";
@NonNls String ACTION_EDITOR_MOVE_CARET_LEFT = "EditorLeft";
@NonNls String ACTION_EDITOR_MOVE_CARET_DOWN = "EditorDown";
@@ -269,7 +271,7 @@ public interface IdeActions {
String ACTION_UNDO = "$Undo";
String ACTION_REDO = "$Redo";
String GROUP_REFACTOR = "RefactoringMenu";
- String SELECTED_CHANGES_ROLLBACK = "RollbackLineStatusChanges";
+ String SELECTED_CHANGES_ROLLBACK = "Vcs.RollbackChangedLines";
String CHANGES_VIEW_ROLLBACK = "ChangesView.Rollback";
String CONSOLE_CLEAR_ALL = "ConsoleView.ClearAll";
diff --git a/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ComboBoxAction.java b/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ComboBoxAction.java
index 92a1d9c8b42c..7398bf706c78 100644
--- a/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ComboBoxAction.java
+++ b/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ComboBoxAction.java
@@ -110,10 +110,10 @@ public abstract class ComboBoxAction extends AnAction implements CustomComponent
private boolean myMouseInside = false;
private JBPopup myPopup;
private boolean myForceTransparent = false;
- private Boolean myForceEnabled = null;
public ComboBoxButton(Presentation presentation) {
myPresentation = presentation;
+ setEnabled(myPresentation.isEnabled());
setModel(new MyButtonModel());
setHorizontalAlignment(LEFT);
setFocusable(false);
@@ -207,12 +207,6 @@ public abstract class ComboBoxAction extends AnAction implements CustomComponent
}
}
- @Override
- public void setEnabled(final boolean enabled) {
- super.setEnabled(enabled);
- myForceEnabled = enabled;
- }
-
public void setForceTransparent(boolean transparent) {
myForceTransparent = transparent;
}
@@ -282,7 +276,6 @@ public abstract class ComboBoxAction extends AnAction implements CustomComponent
private void initButton() {
setIcon(myPresentation.getIcon());
- setEnabled(myPresentation.isEnabled());
setText(myPresentation.getText());
updateTooltipText(myPresentation.getDescription());
updateButtonSize();
@@ -383,7 +376,7 @@ public abstract class ComboBoxAction extends AnAction implements CustomComponent
final Dimension size = getSize();
final boolean isEmpty = getIcon() == null && StringUtil.isEmpty(getText());
- final Color textColor = (myForceEnabled == null ? myPresentation.isEnabled() : myForceEnabled)
+ final Color textColor = isEnabled()
? UIManager.getColor("Panel.foreground")
: UIUtil.getInactiveTextColor();
if (myForceTransparent) {
diff --git a/platform/platform-api/src/com/intellij/openapi/diff/DiffRequestFactory.java b/platform/platform-api/src/com/intellij/openapi/diff/DiffRequestFactory.java
index 78f07a04b4a9..e2c9175ac915 100644
--- a/platform/platform-api/src/com/intellij/openapi/diff/DiffRequestFactory.java
+++ b/platform/platform-api/src/com/intellij/openapi/diff/DiffRequestFactory.java
@@ -16,6 +16,7 @@
package com.intellij.openapi.diff;
import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
@@ -59,4 +60,12 @@ public abstract class DiffRequestFactory {
Project project,
@Nullable ActionButtonPresentation okButtonPresentation,
@Nullable ActionButtonPresentation cancelButtonPresentation);
+
+ public abstract MergeRequest create3WayDiffRequest(String leftText,
+ String rightText,
+ String originalContent,
+ @Nullable FileType type,
+ Project project,
+ @Nullable ActionButtonPresentation okButtonPresentation,
+ @Nullable ActionButtonPresentation cancelButtonPresentation);
}
diff --git a/platform/platform-api/src/com/intellij/openapi/diff/FragmentContent.java b/platform/platform-api/src/com/intellij/openapi/diff/FragmentContent.java
index 26537316b4e9..d630bad790df 100644
--- a/platform/platform-api/src/com/intellij/openapi/diff/FragmentContent.java
+++ b/platform/platform-api/src/com/intellij/openapi/diff/FragmentContent.java
@@ -41,18 +41,28 @@ public class FragmentContent extends DiffContent {
private final FileType myType;
private final MyDocumentsSynchronizer mySynchonizer;
public static final Key<Document> ORIGINAL_DOCUMENT = new Key<Document>("ORIGINAL_DOCUMENT");
+ private final boolean myForceReadOnly;
public FragmentContent(@NotNull DiffContent original, @NotNull TextRange range, Project project, VirtualFile file) {
- this(original, range, project, file != null ? DiffContentUtil.getContentType(file) : null);
+ this(original, range, project, file, false);
+ }
+
+ public FragmentContent(@NotNull DiffContent original, @NotNull TextRange range, Project project, VirtualFile file, boolean forceReadOnly) {
+ this(original, range, project, file != null ? DiffContentUtil.getContentType(file) : null, forceReadOnly);
}
public FragmentContent(@NotNull DiffContent original, @NotNull TextRange range, Project project, FileType fileType) {
+ this(original, range, project, fileType, false);
+ }
+
+ public FragmentContent(@NotNull DiffContent original, @NotNull TextRange range, Project project, FileType fileType, boolean forceReadOnly) {
RangeMarker rangeMarker = original.getDocument().createRangeMarker(range.getStartOffset(), range.getEndOffset(), true);
rangeMarker.setGreedyToLeft(true);
rangeMarker.setGreedyToRight(true);
mySynchonizer = new MyDocumentsSynchronizer(project, rangeMarker);
myOriginal = original;
myType = fileType;
+ myForceReadOnly = forceReadOnly;
}
public FragmentContent(DiffContent original, TextRange range, Project project) {
@@ -152,7 +162,7 @@ public class FragmentContent extends DiffContent {
String textInRange =
originalDocument.getCharsSequence().subSequence(myRangeMarker.getStartOffset(), myRangeMarker.getEndOffset()).toString();
final Document result = EditorFactory.getInstance().createDocument(textInRange);
- result.setReadOnly(!originalDocument.isWritable());
+ result.setReadOnly(myForceReadOnly || !originalDocument.isWritable());
result.putUserData(ORIGINAL_DOCUMENT, originalDocument);
return result;
}
diff --git a/platform/platform-api/src/com/intellij/openapi/diff/MergeRequest.java b/platform/platform-api/src/com/intellij/openapi/diff/MergeRequest.java
index 29243f7b9be0..ce8d56044f96 100644
--- a/platform/platform-api/src/com/intellij/openapi/diff/MergeRequest.java
+++ b/platform/platform-api/src/com/intellij/openapi/diff/MergeRequest.java
@@ -25,7 +25,7 @@ import org.jetbrains.annotations.Nullable;
* @see DiffRequestFactory#createMergeRequest
*/
public abstract class MergeRequest extends DiffRequest {
- protected MergeRequest(Project project) {
+ protected MergeRequest(@Nullable Project project) {
super(project);
}
diff --git a/platform/platform-api/src/com/intellij/openapi/editor/EditorCopyPasteHelper.java b/platform/platform-api/src/com/intellij/openapi/editor/EditorCopyPasteHelper.java
new file mode 100644
index 000000000000..f698d34efb50
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/openapi/editor/EditorCopyPasteHelper.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.editor;
+
+import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.util.TextRange;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.awt.datatransfer.Transferable;
+
+/**
+ * Support for data transfer between editor and clipboard.
+ */
+public abstract class EditorCopyPasteHelper {
+ public static EditorCopyPasteHelper getInstance() {
+ return ServiceManager.getService(EditorCopyPasteHelper.class);
+ }
+
+ /**
+ * Copies text selected in editor to clipboard.
+ */
+ public abstract void copySelectionToClipboard(@NotNull Editor editor);
+
+ /**
+ * Pastes from clipboard into editor at caret(s) position.
+ *
+ * @return ranges of text in the document, corresponding to pasted fragments, if paste succeeds, or <code>null</code> otherwise
+ */
+ @Nullable
+ public abstract TextRange[] pasteFromClipboard(@NotNull Editor editor);
+
+ /**
+ * Pastes given Transferable instance into editor at caret(s) position.
+ *
+ * @return ranges of text in the document, corresponding to pasted fragments, if paste succeeds, or <code>null</code> otherwise
+ */
+ @Nullable
+ public abstract TextRange[] pasteTransferable(@NotNull Editor editor, @NotNull Transferable content);
+}
diff --git a/platform/platform-api/src/com/intellij/openapi/editor/EditorModificationUtil.java b/platform/platform-api/src/com/intellij/openapi/editor/EditorModificationUtil.java
index ee5527967440..6ba31d7edb47 100644
--- a/platform/platform-api/src/com/intellij/openapi/editor/EditorModificationUtil.java
+++ b/platform/platform-api/src/com/intellij/openapi/editor/EditorModificationUtil.java
@@ -19,14 +19,19 @@ import com.intellij.codeStyle.CodeStyleFacade;
import com.intellij.openapi.editor.actionSystem.EditorActionManager;
import com.intellij.openapi.editor.event.DocumentEvent;
import com.intellij.openapi.editor.event.MockDocumentEvent;
+import com.intellij.openapi.ide.CopyPasteManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.util.text.LineTokenizer;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.util.Producer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.io.IOException;
import java.util.List;
public class EditorModificationUtil {
@@ -176,22 +181,100 @@ public class EditorModificationUtil {
}
/**
- * @deprecated Use {@link com.intellij.openapi.editor.CopyPasteSupport#pasteTransferable(Editor, com.intellij.util.Producer)} instead.
+ * @deprecated Use {@link com.intellij.openapi.editor.EditorCopyPasteHelper} methods instead.
* (to remove in IDEA 15)
*/
@Nullable
public static TextRange pasteTransferable(final Editor editor, @Nullable Producer<Transferable> producer) {
- return CopyPasteSupport.pasteTransferable(editor, producer);
+ EditorCopyPasteHelper helper = EditorCopyPasteHelper.getInstance();
+ if (producer == null) {
+ TextRange[] ranges = helper.pasteFromClipboard(editor);
+ return ranges != null && ranges.length == 1 ? ranges[0] : null;
+ }
+ Transferable transferable = producer.produce();
+ if (transferable == null) {
+ return null;
+ }
+ TextRange[] ranges = helper.pasteTransferable(editor, transferable);
+ return ranges != null && ranges.length == 1 ? ranges[0] : null;
}
- /**
- * @deprecated Use {@link com.intellij.openapi.editor.CopyPasteSupport#pasteTransferableAsBlock(Editor, com.intellij.util.Producer)} instead.
- * (to remove in IDEA 15)
- */
public static void pasteTransferableAsBlock(Editor editor, @Nullable Producer<Transferable> producer) {
- CopyPasteSupport.pasteTransferableAsBlock(editor, producer);
+ Transferable content = getTransferable(producer);
+ if (content == null) return;
+ String text = getStringContent(content);
+ if (text == null) return;
+
+ int caretLine = editor.getCaretModel().getLogicalPosition().line;
+ int originalCaretLine = caretLine;
+ int selectedLinesCount = 0;
+
+ final SelectionModel selectionModel = editor.getSelectionModel();
+ if (selectionModel.hasBlockSelection()) {
+ final LogicalPosition start = selectionModel.getBlockStart();
+ final LogicalPosition end = selectionModel.getBlockEnd();
+ assert start != null;
+ assert end != null;
+ LogicalPosition caret = new LogicalPosition(Math.min(start.line, end.line), Math.min(start.column, end.column));
+ selectedLinesCount = Math.abs(end.line - start.line);
+ caretLine = caret.line;
+
+ deleteSelectedText(editor);
+ editor.getCaretModel().moveToLogicalPosition(caret);
+ }
+
+ LogicalPosition caretToRestore = editor.getCaretModel().getLogicalPosition();
+
+ String[] lines = LineTokenizer.tokenize(text.toCharArray(), false);
+ if (lines.length > 1 || selectedLinesCount == 0) {
+ int longestLineLength = 0;
+ for (int i = 0; i < lines.length; i++) {
+ String line = lines[i];
+ longestLineLength = Math.max(longestLineLength, line.length());
+ editor.getCaretModel().moveToLogicalPosition(new LogicalPosition(caretLine + i, caretToRestore.column));
+ insertStringAtCaret(editor, line, false, true);
+ }
+ caretToRestore = new LogicalPosition(originalCaretLine, caretToRestore.column + longestLineLength);
+ }
+ else {
+ for (int i = 0; i <= selectedLinesCount; i++) {
+ editor.getCaretModel().moveToLogicalPosition(new LogicalPosition(caretLine + i, caretToRestore.column));
+ insertStringAtCaret(editor, text, false, true);
+ }
+ caretToRestore = new LogicalPosition(originalCaretLine, caretToRestore.column + text.length());
+ }
+
+ editor.getCaretModel().moveToLogicalPosition(caretToRestore);
+ zeroWidthBlockSelectionAtCaretColumn(editor, caretLine, caretLine + selectedLinesCount);
}
+ @Nullable
+ private static String getStringContent(@NotNull Transferable content) {
+ RawText raw = RawText.fromTransferable(content);
+ if (raw != null) return raw.rawText;
+
+ try {
+ return (String)content.getTransferData(DataFlavor.stringFlavor);
+ }
+ catch (UnsupportedFlavorException ignore) { }
+ catch (IOException ignore) { }
+
+ return null;
+ }
+
+ private static Transferable getTransferable(Producer<Transferable> producer) {
+ Transferable content = null;
+ if (producer != null) {
+ content = producer.produce();
+ }
+ else {
+ CopyPasteManager manager = CopyPasteManager.getInstance();
+ if (manager.areDataFlavorsAvailable(DataFlavor.stringFlavor)) {
+ content = manager.getContents();
+ }
+ }
+ return content;
+ }
/**
* Calculates difference in columns between current editor caret position and end of the logical line fragment displayed
* on a current visual line.
diff --git a/platform/platform-api/src/com/intellij/openapi/editor/LazyRangeMarkerFactory.java b/platform/platform-api/src/com/intellij/openapi/editor/LazyRangeMarkerFactory.java
index 3780e3a79e0c..942a33aaace8 100644
--- a/platform/platform-api/src/com/intellij/openapi/editor/LazyRangeMarkerFactory.java
+++ b/platform/platform-api/src/com/intellij/openapi/editor/LazyRangeMarkerFactory.java
@@ -15,276 +15,19 @@
*/
package com.intellij.openapi.editor;
-import com.intellij.codeStyle.CodeStyleFacade;
-import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.ServiceManager;
-import com.intellij.openapi.editor.event.DocumentAdapter;
-import com.intellij.openapi.editor.event.DocumentEvent;
-import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Computable;
-import com.intellij.openapi.util.Key;
-import com.intellij.openapi.util.UserDataHolderBase;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.util.SmartList;
-import com.intellij.util.containers.WeakList;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.List;
-
-public class LazyRangeMarkerFactory {
- private final Project myProject;
- private static final Key<WeakList<LazyMarker>> LAZY_MARKERS_KEY = Key.create("LAZY_MARKERS_KEY");
+public abstract class LazyRangeMarkerFactory {
public static LazyRangeMarkerFactory getInstance(Project project) {
return ServiceManager.getService(project, LazyRangeMarkerFactory.class);
}
- public LazyRangeMarkerFactory(@NotNull Project project, @NotNull final FileDocumentManager fileDocumentManager) {
- myProject = project;
-
- EditorFactory.getInstance().getEventMulticaster().addDocumentListener(new DocumentAdapter() {
- @Override
- public void beforeDocumentChange(DocumentEvent e) {
- transformRangeMarkers(e);
- }
-
- @Override
- public void documentChanged(DocumentEvent e) {
- transformRangeMarkers(e);
- }
-
- private void transformRangeMarkers(@NotNull DocumentEvent e) {
- Document document = e.getDocument();
- VirtualFile file = fileDocumentManager.getFile(document);
- if (file == null) {
- return;
- }
-
- WeakList<LazyMarker> lazyMarkers = file.getUserData(LAZY_MARKERS_KEY);
- if (lazyMarkers == null) {
- return;
- }
-
- List<LazyMarker> markers = lazyMarkers.toStrongList();
- List<LazyMarker> markersToRemove = null;
- for (LazyMarker marker : markers) {
- if (file.equals(marker.getFile()) && marker.documentChanged(document) != null) {
- if (markersToRemove == null) {
- markersToRemove = new SmartList<LazyMarker>();
- }
- markersToRemove.add(marker);
- }
- }
- if (markersToRemove != null) {
- lazyMarkers.removeAll(markersToRemove);
- }
- }
- }, project);
- }
-
- private static void addToLazyMarkersList(@NotNull LazyMarker marker, @NotNull VirtualFile file) {
- WeakList<LazyMarker> markers = file.getUserData(LAZY_MARKERS_KEY);
-
- if (markers == null) {
- markers = file.putUserDataIfAbsent(LAZY_MARKERS_KEY, new WeakList<LazyMarker>());
- }
- markers.add(marker);
- }
-
@NotNull
- public RangeMarker createRangeMarker(@NotNull final VirtualFile file, final int offset) {
- return ApplicationManager.getApplication().runReadAction(new Computable<RangeMarker>() {
- @Override
- public RangeMarker compute() {
- // even for already loaded document do not create range marker yet - wait until it really needed when e.g. user clicked to jump to OpenFileDescriptor
- final LazyMarker marker = new OffsetLazyMarker(file, offset);
- addToLazyMarkersList(marker, file);
- return marker;
- }
- });
- }
+ public abstract RangeMarker createRangeMarker(@NotNull final VirtualFile file, final int offset);
@NotNull
- public RangeMarker createRangeMarker(@NotNull final VirtualFile file, final int line, final int column, final boolean persistent) {
- return ApplicationManager.getApplication().runReadAction(new Computable<RangeMarker>() {
- @Override
- public RangeMarker compute() {
- final Document document = FileDocumentManager.getInstance().getCachedDocument(file);
- if (document != null) {
- final int offset = calculateOffset(myProject, file, document, line, column);
- return document.createRangeMarker(offset, offset, persistent);
- }
-
- final LazyMarker marker = new LineColumnLazyMarker(file, line, column);
- addToLazyMarkersList(marker, file);
- return marker;
- }
- });
- }
-
- private abstract static class LazyMarker extends UserDataHolderBase implements RangeMarker {
- private RangeMarker myDelegate;
- private final VirtualFile myFile;
- protected final int myInitialOffset;
-
- private LazyMarker(@NotNull VirtualFile file, int offset) {
- myFile = file;
- myInitialOffset = offset;
- }
-
- @NotNull
- public VirtualFile getFile() {
- return myFile;
- }
-
- @Nullable
- protected final RangeMarker getOrCreateDelegate() {
- if (myDelegate == null) {
- Document document = FileDocumentManager.getInstance().getDocument(myFile);
- if (document == null) {
- return null;
- }
- myDelegate = createDelegate(myFile, document);
- }
- return myDelegate;
- }
-
- @Nullable
- protected final RangeMarker documentChanged(@NotNull Document document) {
- if (myDelegate == null) {
- myDelegate = createDelegate(myFile, document);
- }
- return myDelegate;
- }
-
- @Nullable
- protected abstract RangeMarker createDelegate(@NotNull VirtualFile file, @NotNull Document document);
-
- @Override
- @NotNull
- public Document getDocument() {
- RangeMarker delegate = getOrCreateDelegate();
- if (delegate == null) {
- //noinspection ConstantConditions
- return FileDocumentManager.getInstance().getDocument(myFile);
- }
- return delegate.getDocument();
- }
-
- @Override
- public int getStartOffset() {
- return myDelegate == null ? myInitialOffset : myDelegate.getStartOffset();
- }
-
-
- @Override
- public int getEndOffset() {
- return myDelegate == null ? myInitialOffset : myDelegate.getEndOffset();
- }
-
- @Override
- public boolean isValid() {
- RangeMarker delegate = getOrCreateDelegate();
- return delegate != null && delegate.isValid();
- }
-
- @Override
- public void setGreedyToLeft(boolean greedy) {
- getOrCreateDelegate().setGreedyToLeft(greedy);
- }
-
- @Override
- public void setGreedyToRight(boolean greedy) {
- getOrCreateDelegate().setGreedyToRight(greedy);
- }
-
- @Override
- public boolean isGreedyToRight() {
- return getOrCreateDelegate().isGreedyToRight();
- }
-
- @Override
- public boolean isGreedyToLeft() {
- return getOrCreateDelegate().isGreedyToLeft();
- }
-
- @Override
- public void dispose() {
- RangeMarker delegate = getOrCreateDelegate();
- if (delegate != null) {
- delegate.dispose();
- }
- }
- }
-
- private static class OffsetLazyMarker extends LazyMarker {
- private OffsetLazyMarker(@NotNull VirtualFile file, int offset) {
- super(file, offset);
- }
-
- @Override
- @NotNull
- public RangeMarker createDelegate(@NotNull VirtualFile file, @NotNull final Document document) {
- final int offset = Math.min(myInitialOffset, document.getTextLength());
- return document.createRangeMarker(offset, offset);
- }
- }
-
- private class LineColumnLazyMarker extends LazyMarker {
- private final int myLine;
- private final int myColumn;
-
- private LineColumnLazyMarker(@NotNull VirtualFile file, int line, int column) {
- super(file, -1);
- myLine = line;
- myColumn = column;
- }
-
- @Override
- @Nullable
- public RangeMarker createDelegate(@NotNull VirtualFile file, @NotNull Document document) {
- if (document.getTextLength() == 0 && !(myLine == 0 && myColumn == 0)) {
- return null;
- }
-
- int offset = calculateOffset(myProject, file, document, myLine, myColumn);
- return document.createRangeMarker(offset, offset);
- }
-
- @Override
- public int getStartOffset() {
- getOrCreateDelegate();
- return super.getStartOffset();
- }
-
- @Override
- public int getEndOffset() {
- getOrCreateDelegate();
- return super.getEndOffset();
- }
- }
-
- private static int calculateOffset(@NotNull Project project, @NotNull VirtualFile file, @NotNull Document document, final int line, final int column) {
- int offset;
- if (line < document.getLineCount()) {
- final int lineStart = document.getLineStartOffset(line);
- final int lineEnd = document.getLineEndOffset(line);
- final CharSequence docText = document.getCharsSequence();
- final int tabSize = CodeStyleFacade.getInstance(project).getTabSize(file.getFileType());
-
- offset = lineStart;
- int col = 0;
- while (offset < lineEnd && col < column) {
- col += docText.charAt(offset) == '\t' ? tabSize : 1;
- offset++;
- }
- }
- else {
- offset = document.getTextLength();
- }
- return offset;
- }
-
+ public abstract RangeMarker createRangeMarker(@NotNull final VirtualFile file, final int line, final int column, final boolean persistent);
}
diff --git a/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/DialogAwareDataContext.java b/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/DialogAwareDataContext.java
new file mode 100644
index 000000000000..c49645254ebd
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/DialogAwareDataContext.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.editor.actionSystem;
+
+import com.intellij.ide.DataManager;
+import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.actionSystem.DataKey;
+import com.intellij.openapi.editor.Editor;
+import org.jetbrains.annotations.NonNls;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static com.intellij.openapi.actionSystem.CommonDataKeys.*;
+import static com.intellij.openapi.actionSystem.PlatformDataKeys.PROJECT_FILE_DIRECTORY;
+
+/**
+* @author Konstantin Bulenkov
+*/
+final class DialogAwareDataContext implements DataContext {
+ private static final DataKey[] keys = {PROJECT, PROJECT_FILE_DIRECTORY, EDITOR, VIRTUAL_FILE, PSI_FILE};
+ private final Map<String, Object> values = new HashMap<String, Object>();
+
+ DialogAwareDataContext(DataContext context) {
+ for (DataKey key : keys) {
+ values.put(key.getName(), key.getData(context));
+ }
+ }
+
+ @Override
+ public Object getData(@NonNls String dataId) {
+ if (values.keySet().contains(dataId)) {
+ return values.get(dataId);
+ }
+ final Editor editor = (Editor)values.get(EDITOR.getName());
+ if (editor != null) {
+ return DataManager.getInstance().getDataContext(editor.getContentComponent()).getData(dataId);
+ }
+ return null;
+ }
+}
diff --git a/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorAction.java b/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorAction.java
index 217ff70c3fb5..945c52022984 100644
--- a/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorAction.java
+++ b/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorAction.java
@@ -26,6 +26,8 @@ import org.jetbrains.annotations.Nullable;
import java.awt.event.KeyEvent;
+import static com.intellij.openapi.actionSystem.CommonDataKeys.PROJECT;
+
public abstract class EditorAction extends AnAction implements DumbAware {
private EditorActionHandler myHandler;
private boolean myHandlersLoaded;
@@ -126,14 +128,14 @@ public abstract class EditorAction extends AnAction implements DumbAware {
}
private static DataContext getProjectAwareDataContext(final Editor editor, @NotNull final DataContext original) {
- if (CommonDataKeys.PROJECT.getData(original) == editor.getProject()) {
- return original;
+ if (PROJECT.getData(original) == editor.getProject()) {
+ return new DialogAwareDataContext(original);
}
return new DataContext() {
@Override
public Object getData(String dataId) {
- if (CommonDataKeys.PROJECT.is(dataId)) {
+ if (PROJECT.is(dataId)) {
return editor.getProject();
}
return original.getData(dataId);
diff --git a/platform/platform-api/src/com/intellij/openapi/editor/highlighter/FragmentedEditorHighlighter.java b/platform/platform-api/src/com/intellij/openapi/editor/highlighter/FragmentedEditorHighlighter.java
index 9cd9ab29f4cd..db138237af81 100644
--- a/platform/platform-api/src/com/intellij/openapi/editor/highlighter/FragmentedEditorHighlighter.java
+++ b/platform/platform-api/src/com/intellij/openapi/editor/highlighter/FragmentedEditorHighlighter.java
@@ -71,31 +71,17 @@ public class FragmentedEditorHighlighter implements EditorHighlighter {
if (range.getEndOffset() >= iterator.getStart()) {
int relativeStart = Math.max(iterator.getStart() - range.getStartOffset(), 0);
int relativeEnd = Math.min(iterator.getEnd() - range.getStartOffset(), range.getLength() + 1);
- boolean merged = false;
- if (myMergeByTextAttributes && !myPieces.isEmpty()) {
- Element element = myPieces.get(myPieces.size() - 1);
- if (element.getEnd() >= offset + relativeStart &&
- Comparing.equal(element.getAttributes(), iterator.getTextAttributes()) &&
- Comparing.equal(element.getElementType(), iterator.getTokenType())) {
- merged = true;
- myPieces.add(new Element(element.getStart(),
- offset + relativeEnd,
- iterator.getTokenType(),
- iterator.getTextAttributes()));
- }
- }
- if (!merged) {
- myPieces.add(new Element(offset + relativeStart,
- offset + relativeEnd,
- iterator.getTokenType(),
- iterator.getTextAttributes()));
- }
+
+ addElement(new Element(offset + relativeStart,
+ offset + relativeEnd,
+ iterator.getTokenType(),
+ iterator.getTextAttributes()));
}
if (range.getEndOffset() < iterator.getEnd()) {
offset += range.getLength() + 1 + myAdditionalOffset; // myAdditionalOffset because of extra line - for shoene separators
int lastEnd = myPieces.isEmpty() ? -1 : myPieces.get(myPieces.size() - 1).getEnd();
- myPieces.add(new Element(Math.max(offset - 1 - myAdditionalOffset, lastEnd), offset, null, TextAttributes.ERASE_MARKER));
+ addElement(new Element(Math.max(offset - 1 - myAdditionalOffset, lastEnd), offset, null, TextAttributes.ERASE_MARKER));
index++;
continue;
}
@@ -104,6 +90,26 @@ public class FragmentedEditorHighlighter implements EditorHighlighter {
}
}
+ private void addElement(@NotNull Element element) {
+ boolean merged = false;
+ if (myMergeByTextAttributes && !myPieces.isEmpty()) {
+ Element oldElement = myPieces.get(myPieces.size() - 1);
+ if (oldElement.getEnd() >= element.getStart() &&
+ Comparing.equal(oldElement.getAttributes(), element.getAttributes()) &&
+ Comparing.equal(oldElement.getElementType(), element.getElementType())) {
+ merged = true;
+ myPieces.remove(myPieces.size() - 1);
+ myPieces.add(new Element(oldElement.getStart(),
+ element.getEnd(),
+ element.getElementType(),
+ element.getAttributes()));
+ }
+ }
+ if (!merged) {
+ myPieces.add(element);
+ }
+ }
+
@NotNull
@Override
public HighlighterIterator createIterator(int startOffset) {
diff --git a/platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooserDescriptorFactory.java b/platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooserDescriptorFactory.java
index 1e43287a1d94..c958dbca878e 100644
--- a/platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooserDescriptorFactory.java
+++ b/platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooserDescriptorFactory.java
@@ -19,9 +19,11 @@ import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.UIBundle;
+import org.jetbrains.annotations.NotNull;
public class FileChooserDescriptorFactory {
- private FileChooserDescriptorFactory() { }
+ private FileChooserDescriptorFactory() {
+ }
public static FileChooserDescriptor createAllButJarContentsDescriptor() {
return new FileChooserDescriptor(true, true, true, true, false, true);
@@ -83,7 +85,18 @@ public class FileChooserDescriptorFactory {
}
public static FileChooserDescriptor createSingleFileDescriptor(final FileType fileType) {
- return new FileChooserDescriptor(true, false, false, false, false, false) {
+ return createSingleFileDescriptor(fileType, false);
+ }
+
+ /**
+ * Creates file descriptor with certain type and (possible) folders.
+ * @param fileType supported type
+ * @param supportDirectories support directories or not
+ * @return descriptor
+ */
+ @NotNull
+ public static FileChooserDescriptor createSingleFileDescriptor(final FileType fileType, final boolean supportDirectories) {
+ return new FileChooserDescriptor(true, supportDirectories, false, false, false, false) {
@Override
public boolean isFileVisible(final VirtualFile file, final boolean showHiddenFiles) {
return file.isDirectory() || file.getFileType() == fileType;
@@ -91,18 +104,22 @@ public class FileChooserDescriptorFactory {
@Override
public boolean isFileSelectable(final VirtualFile file) {
- return super.isFileSelectable(file) && file.getFileType() == fileType;
+ return super.isFileSelectable(file) && (file.getFileType() == fileType || ((file.isDirectory() && supportDirectories)));
}
};
}
- /** @deprecated use {@link #createSingleFileNoJarsDescriptor()} (to be removed in IDEA 15) */
+ /**
+ * @deprecated use {@link #createSingleFileNoJarsDescriptor()} (to be removed in IDEA 15)
+ */
@SuppressWarnings({"UnusedDeclaration", "deprecation"})
public static FileChooserDescriptorBuilder onlyFiles() {
return FileChooserDescriptorBuilder.onlyFiles();
}
- /** @deprecated use {@link #createSingleFileOrFolderDescriptor()} ()} (to be removed in IDEA 15) */
+ /**
+ * @deprecated use {@link #createSingleFileOrFolderDescriptor()} ()} (to be removed in IDEA 15)
+ */
@SuppressWarnings({"UnusedDeclaration", "deprecation"})
public static FileChooserDescriptorBuilder filesAndFolders() {
return FileChooserDescriptorBuilder.filesAndFolders();
diff --git a/platform/platform-api/src/com/intellij/openapi/fileEditor/FileEditorManager.java b/platform/platform-api/src/com/intellij/openapi/fileEditor/FileEditorManager.java
index 366f69db9cc6..b9589574059d 100644
--- a/platform/platform-api/src/com/intellij/openapi/fileEditor/FileEditorManager.java
+++ b/platform/platform-api/src/com/intellij/openapi/fileEditor/FileEditorManager.java
@@ -30,7 +30,7 @@ public abstract class FileEditorManager {
public static final Key<Boolean> USE_CURRENT_WINDOW = Key.create("OpenFile.searchForOpen");
- public static FileEditorManager getInstance(Project project) {
+ public static FileEditorManager getInstance(@NotNull Project project) {
return project.getComponent(FileEditorManager.class);
}
diff --git a/platform/platform-api/src/com/intellij/openapi/fileEditor/OpenFileDescriptor.java b/platform/platform-api/src/com/intellij/openapi/fileEditor/OpenFileDescriptor.java
index 9ec804def43d..fdf32b9adcba 100644
--- a/platform/platform-api/src/com/intellij/openapi/fileEditor/OpenFileDescriptor.java
+++ b/platform/platform-api/src/com/intellij/openapi/fileEditor/OpenFileDescriptor.java
@@ -55,34 +55,31 @@ public class OpenFileDescriptor implements Navigatable {
private boolean myUseCurrentWindow = false;
public OpenFileDescriptor(@NotNull Project project, @NotNull VirtualFile file, int offset) {
- this(project, file, -1, -1, offset, null, false);
+ this(project, file, -1, -1, offset, false);
}
public OpenFileDescriptor(@NotNull Project project, @NotNull VirtualFile file, int logicalLine, int logicalColumn) {
- this(project, file, logicalLine, logicalColumn, -1, null, false);
+ this(project, file, logicalLine, logicalColumn, -1, false);
}
public OpenFileDescriptor(@NotNull Project project, @NotNull VirtualFile file,
int logicalLine, int logicalColumn, boolean persistent) {
- this(project, file, logicalLine, logicalColumn, -1, null, persistent);
+ this(project, file, logicalLine, logicalColumn, -1, persistent);
}
public OpenFileDescriptor(@NotNull Project project, @NotNull VirtualFile file) {
- this(project, file, -1, -1, -1, null, false);
+ this(project, file, -1, -1, -1, false);
}
private OpenFileDescriptor(@NotNull Project project, @NotNull VirtualFile file,
- int logicalLine, int logicalColumn, int offset, @Nullable RangeMarker rangeMarker, boolean persistent) {
+ int logicalLine, int logicalColumn, int offset, boolean persistent) {
myProject = project;
myFile = file;
myLogicalLine = logicalLine;
myLogicalColumn = logicalColumn;
myOffset = offset;
- if (rangeMarker != null) {
- myRangeMarker = rangeMarker;
- }
- else if (offset >= 0) {
+ if (offset >= 0) {
myRangeMarker = LazyRangeMarkerFactory.getInstance(project).createRangeMarker(file, offset);
}
else if (logicalLine >= 0 ){
diff --git a/platform/platform-api/src/com/intellij/openapi/ui/Banner.java b/platform/platform-api/src/com/intellij/openapi/ui/Banner.java
index 3f4a92aec5ff..8dbe02228bae 100644
--- a/platform/platform-api/src/com/intellij/openapi/ui/Banner.java
+++ b/platform/platform-api/src/com/intellij/openapi/ui/Banner.java
@@ -16,6 +16,8 @@
package com.intellij.openapi.ui;
import com.intellij.icons.AllIcons;
+import com.intellij.openapi.options.OptionsBundle;
+import com.intellij.openapi.project.Project;
import com.intellij.ui.components.labels.LinkLabel;
import com.intellij.ui.components.labels.LinkListener;
import com.intellij.ui.components.panels.NonOpaquePanel;
@@ -35,7 +37,7 @@ import java.util.Set;
class Banner extends NonOpaquePanel implements PropertyChangeListener{
private int myBannerMinHeight;
private final JComponent myText = new MyText();
-
+ private final JLabel myProjectIcon = new JLabel(AllIcons.General.ProjectConfigurableBanner, SwingConstants.LEFT);
private final NonOpaquePanel myActionsPanel = new NonOpaquePanel(new FlowLayout(FlowLayout.RIGHT, 2, 2));
private final Map<Action, LinkLabel> myActions = new HashMap<Action, LinkLabel>();
@@ -45,7 +47,10 @@ class Banner extends NonOpaquePanel implements PropertyChangeListener{
setBorder(new EmptyBorder(2, 6, 2, 4));
- add(myText, BorderLayout.CENTER);
+ myProjectIcon.setVisible(false);
+ myProjectIcon.setBorder(new EmptyBorder(0, 12, 0, 4));
+ add(myText, BorderLayout.WEST);
+ add(myProjectIcon, BorderLayout.CENTER);
add(myActionsPanel, BorderLayout.EAST);
}
@@ -112,6 +117,17 @@ class Banner extends NonOpaquePanel implements PropertyChangeListener{
repaint();
}
+ public void forProject(Project project) {
+ if (project != null) {
+ myProjectIcon.setVisible(true);
+ myProjectIcon.setText(OptionsBundle.message(project.isDefault()
+ ? "configurable.default.project.tooltip"
+ : "configurable.current.project.tooltip"));
+ } else {
+ myProjectIcon.setVisible(false);
+ }
+ }
+
public void setText(@NotNull final String... text) {
myText.removeAll();
for (int i = 0; i < text.length; i++) {
diff --git a/platform/platform-api/src/com/intellij/openapi/ui/ComboBoxTableRenderer.java b/platform/platform-api/src/com/intellij/openapi/ui/ComboBoxTableRenderer.java
index 5d2ecafb1b7e..c02f27af5d4b 100644
--- a/platform/platform-api/src/com/intellij/openapi/ui/ComboBoxTableRenderer.java
+++ b/platform/platform-api/src/com/intellij/openapi/ui/ComboBoxTableRenderer.java
@@ -46,6 +46,7 @@ public class ComboBoxTableRenderer<T> extends JLabel implements TableCellRendere
private WeakReference<ListPopup> myPopupRef;
private ChangeEvent myChangeEvent = null;
private T myValue;
+ private boolean myPaintArrow = true;
protected EventListenerList myListenerList = new EventListenerList();
@@ -80,6 +81,10 @@ public class ComboBoxTableRenderer<T> extends JLabel implements TableCellRendere
return null;
}
+ public void setPaintArrow(final boolean paintArrow) {
+ myPaintArrow = paintArrow;
+ }
+
protected Runnable onChosen(@NotNull final T value) {
stopCellEditing(value);
@@ -94,7 +99,7 @@ public class ComboBoxTableRenderer<T> extends JLabel implements TableCellRendere
protected void paintComponent(Graphics g) {
super.paintComponent(g);
- if (!StringUtil.isEmpty(getText())) {
+ if (!StringUtil.isEmpty(getText()) && myPaintArrow) {
final Rectangle r = getBounds();
final Insets i = getInsets();
final int x = r.width - i.right - AllIcons.General.ArrowDown.getIconWidth();
diff --git a/platform/platform-api/src/com/intellij/openapi/ui/DetailsComponent.java b/platform/platform-api/src/com/intellij/openapi/ui/DetailsComponent.java
index 34aaa93d2741..463d950ae900 100644
--- a/platform/platform-api/src/com/intellij/openapi/ui/DetailsComponent.java
+++ b/platform/platform-api/src/com/intellij/openapi/ui/DetailsComponent.java
@@ -16,7 +16,7 @@
package com.intellij.openapi.ui;
-import com.intellij.openapi.util.registry.Registry;
+import com.intellij.openapi.project.Project;
import com.intellij.ui.components.panels.NonOpaquePanel;
import com.intellij.ui.components.panels.Wrapper;
import com.intellij.util.ArrayUtil;
@@ -45,15 +45,21 @@ public class DetailsComponent {
private final NonOpaquePanel myBanner;
private String[] myBannerText;
- private boolean myDetailsEnabled = !Registry.is("ide.new.project.settings");
+ private boolean myDetailsEnabled;
private String[] myPrefix;
private String[] myText;
private final Wrapper myContentGutter = new Wrapper();
- private boolean myPaintBorder = !Registry.is("ide.new.project.settings");
+ private boolean myPaintBorder;
public DetailsComponent() {
+ this(true, true);
+ }
+
+ public DetailsComponent(boolean detailsEnabled, boolean paintBorder) {
+ myDetailsEnabled = detailsEnabled;
+ myPaintBorder = paintBorder;
myComponent = new JPanel(new BorderLayout()) {
@Override
protected void paintComponent(final Graphics g) {
@@ -110,7 +116,7 @@ public class DetailsComponent {
myBanner = new NonOpaquePanel(new BorderLayout());
myBannerLabel = new Banner();
- if (!Registry.is("ide.new.project.settings")) {
+ if (myDetailsEnabled) {
myBanner.add(myBannerLabel, BorderLayout.CENTER);
}
@@ -174,6 +180,9 @@ public class DetailsComponent {
}
}
+ public void forProject(Project project) {
+ myBannerLabel.forProject(project);
+ }
public void setPrefix(@Nullable String... prefix) {
myPrefix = prefix;
diff --git a/platform/platform-api/src/com/intellij/openapi/ui/FixedComboBoxEditor.java b/platform/platform-api/src/com/intellij/openapi/ui/FixedComboBoxEditor.java
index 25c52c75b077..6ef25dddb5bc 100644
--- a/platform/platform-api/src/com/intellij/openapi/ui/FixedComboBoxEditor.java
+++ b/platform/platform-api/src/com/intellij/openapi/ui/FixedComboBoxEditor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2010 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@ package com.intellij.openapi.ui;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.ui.Gray;
+import com.intellij.util.ReflectionUtil;
import com.intellij.util.ui.MacUIUtil;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.Nullable;
@@ -34,7 +35,6 @@ import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
-import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
@@ -118,17 +118,7 @@ public class FixedComboBoxEditor implements ComboBoxEditor {
final ComboBoxUI ui = comboBox.getUI();
ComboPopup popup = null;
if (ui instanceof BasicComboBoxUI) {
- try {
- final Field popupField = BasicComboBoxUI.class.getDeclaredField("popup");
- popupField.setAccessible(true);
- popup = (ComboPopup)popupField.get(ui);
- }
- catch (NoSuchFieldException e1) {
- popup = null;
- }
- catch (IllegalAccessException e1) {
- popup = null;
- }
+ popup = ReflectionUtil.getField(BasicComboBoxUI.class, ui, ComboPopup.class, "popup");
}
return popup;
diff --git a/platform/platform-api/src/com/intellij/openapi/ui/MasterDetailsComponent.java b/platform/platform-api/src/com/intellij/openapi/ui/MasterDetailsComponent.java
index 816349ed1c37..6c13964d5789 100644
--- a/platform/platform-api/src/com/intellij/openapi/ui/MasterDetailsComponent.java
+++ b/platform/platform-api/src/com/intellij/openapi/ui/MasterDetailsComponent.java
@@ -111,7 +111,7 @@ public abstract class MasterDetailsComponent implements Configurable, DetailsCom
protected MyNode myRoot = new MyRootNode();
protected Tree myTree = new Tree();
- private final DetailsComponent myDetails = new DetailsComponent();
+ private final DetailsComponent myDetails = new DetailsComponent(!Registry.is("ide.new.project.settings"), !Registry.is("ide.new.project.settings"));
protected JPanel myWholePanel;
public JPanel myNorthPanel = new JPanel(new BorderLayout());
@@ -131,12 +131,9 @@ public abstract class MasterDetailsComponent implements Configurable, DetailsCom
protected MasterDetailsComponent(MasterDetailsState state) {
myState = state;
- mySplitter = new JBSplitter(false, .2f);
+ mySplitter = Registry.is("ide.new.project.settings") ? new OnePixelSplitter(false, .2f) : new JBSplitter(false, .2f);
mySplitter.setSplitterProportionKey("ProjectStructure.SecondLevelElements");
mySplitter.setHonorComponentsMinimumSize(true);
- if (Registry.is("ide.new.project.settings")) {
- mySplitter.setOnePixelMode();
- }
installAutoScroll();
reInitWholePanelIfNeeded();
@@ -300,6 +297,7 @@ public abstract class MasterDetailsComponent implements Configurable, DetailsCom
@NotNull
public JComponent createComponent() {
+ myTree.updateUI();
reInitWholePanelIfNeeded();
updateSelectionFromTree();
@@ -962,7 +960,11 @@ public abstract class MasterDetailsComponent implements Configurable, DetailsCom
myPreselection != null ? myPreselection.getDefaultIndex() : 0, true);
final ListPopup listPopup = popupFactory.createListPopup(step);
listPopup.setHandleAutoSelectionBeforeShow(true);
- listPopup.showUnderneathOf(myNorthPanel);
+ if (e instanceof AnActionButton.AnActionEventWrapper) {
+ ((AnActionButton.AnActionEventWrapper)e).showPopup(listPopup);
+ } else {
+ listPopup.showUnderneathOf(myNorthPanel);
+ }
}
}
diff --git a/platform/platform-api/src/com/intellij/openapi/ui/NamedConfigurable.java b/platform/platform-api/src/com/intellij/openapi/ui/NamedConfigurable.java
index 12b84f8db465..e619473197e7 100644
--- a/platform/platform-api/src/com/intellij/openapi/ui/NamedConfigurable.java
+++ b/platform/platform-api/src/com/intellij/openapi/ui/NamedConfigurable.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,10 +18,12 @@ package com.intellij.openapi.ui;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.options.Configurable;
+import com.intellij.openapi.util.registry.Registry;
import com.intellij.ui.DocumentAdapter;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
+import javax.swing.border.EmptyBorder;
import javax.swing.event.DocumentEvent;
import java.awt.*;
@@ -55,6 +57,11 @@ public abstract class NamedConfigurable<T> implements Configurable {
}
});
}
+ if (Registry.is("ide.new.project.settings")) {
+ myNamePanel.setBorder(new EmptyBorder(10, 10, 6, 10));
+ } else {
+ myNamePanel.setBorder(new EmptyBorder(0,0,0,0));
+ }
}
public boolean isNameEditable() {
diff --git a/platform/platform-api/src/com/intellij/openapi/ui/OnePixelDivider.java b/platform/platform-api/src/com/intellij/openapi/ui/OnePixelDivider.java
new file mode 100644
index 000000000000..2b0097005dc1
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/openapi/ui/OnePixelDivider.java
@@ -0,0 +1,233 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.ui;
+
+import com.intellij.openapi.Disposable;
+import com.intellij.openapi.util.Disposer;
+import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.util.Weighted;
+import com.intellij.openapi.wm.IdeGlassPane;
+import com.intellij.openapi.wm.IdeGlassPaneUtil;
+import com.intellij.ui.Gray;
+import com.intellij.ui.JBColor;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public class OnePixelDivider extends Divider {
+ private boolean myVertical;
+ private Splitter mySplitter;
+ private boolean myResizeEnabled;
+ private boolean mySwitchOrientationEnabled;
+ protected Point myPoint;
+ private IdeGlassPane myGlassPane;
+ private final MouseAdapter myListener = new MyMouseAdapter();
+ private Disposable myDisposable;
+
+ public OnePixelDivider(boolean vertical, Splitter splitter) {
+ super(new GridBagLayout());
+ mySplitter = splitter;
+ myResizeEnabled = true;
+ mySwitchOrientationEnabled = false;
+ setFocusable(false);
+ enableEvents(AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK);
+ //setOpaque(false);
+ setOrientation(vertical);
+ setBackground(new JBColor(Gray._153.withAlpha(128), Gray._100.withAlpha(128)));
+ }
+
+ @Override
+ public void addNotify() {
+ super.addNotify();
+ init();
+ }
+
+ @Override
+ public void removeNotify() {
+ super.removeNotify();
+ if (myDisposable != null && !Disposer.isDisposed(myDisposable)) {
+ Disposer.dispose(myDisposable);
+ }
+ }
+
+ private boolean dragging = false;
+ private class MyMouseAdapter extends MouseAdapter implements Weighted {
+ @Override
+ public void mousePressed(MouseEvent e) {
+ dragging = isInDragZone(e);
+ _processMouseEvent(e);
+ }
+
+ boolean isInDragZone(MouseEvent e) {
+ final MouseEvent event = getTargetEvent(e);
+ final Point p = event.getPoint();
+ final int r = Math.abs(isVertical() ? p.y : p.x);
+ return r < 6;
+ }
+
+ @Override
+ public void mouseReleased(MouseEvent e) {
+ _processMouseEvent(e);
+ dragging = false;
+ }
+
+ @Override
+ public void mouseMoved(MouseEvent e) {
+ final OnePixelDivider divider = OnePixelDivider.this;
+ if (isInDragZone(e)) {
+ myGlassPane.setCursor(divider.getCursor(), divider);
+ } else {
+ myGlassPane.setCursor(null, divider);
+ }
+ _processMouseMotionEvent(e);
+ }
+
+ @Override
+ public void mouseDragged(MouseEvent e) {
+ _processMouseMotionEvent(e);
+ }
+ @Override
+ public double getWeight() {
+ return 1;
+ }
+ private void _processMouseMotionEvent(MouseEvent e) {
+ MouseEvent event = getTargetEvent(e);
+ if (event == null) {
+ myGlassPane.setCursor(null, myListener);
+ return;
+ }
+
+ processMouseMotionEvent(event);
+ if (event.isConsumed()) {
+ e.consume();
+ }
+ }
+
+ private void _processMouseEvent(MouseEvent e) {
+ MouseEvent event = getTargetEvent(e);
+ if (event == null) {
+ myGlassPane.setCursor(null, myListener);
+ return;
+ }
+
+ processMouseEvent(event);
+ if (event.isConsumed()) {
+ e.consume();
+ }
+ }
+ }
+
+ private MouseEvent getTargetEvent(MouseEvent e) {
+ return SwingUtilities.convertMouseEvent(e.getComponent(), e, this);
+ }
+
+ private void init() {
+ myGlassPane = IdeGlassPaneUtil.find(this);
+ myDisposable = Disposer.newDisposable();
+ myGlassPane.addMouseMotionPreprocessor(myListener, myDisposable);
+ myGlassPane.addMousePreprocessor(myListener, myDisposable);
+ }
+
+ public void setOrientation(boolean vertical) {
+ removeAll();
+ myVertical = vertical;
+ final int cursorType = isVertical() ? Cursor.N_RESIZE_CURSOR : Cursor.W_RESIZE_CURSOR;
+ setCursor(Cursor.getPredefinedCursor(cursorType));
+ }
+
+ @Override
+ protected void processMouseMotionEvent(MouseEvent e) {
+ super.processMouseMotionEvent(e);
+ if (!myResizeEnabled) return;
+ if (MouseEvent.MOUSE_DRAGGED == e.getID() && dragging) {
+ myPoint = SwingUtilities.convertPoint(this, e.getPoint(), mySplitter);
+ float proportion;
+ final float firstMinProportion = getMinProportion(mySplitter.getFirstComponent());
+ final float secondMinProportion = getMinProportion(mySplitter.getSecondComponent());
+ if (isVertical()) {
+ if (getHeight() > 0) {
+ proportion = Math.min(1.0f, Math
+ .max(.0f, Math.min(Math.max(firstMinProportion, (float)myPoint.y / (float)mySplitter.getHeight()), 1 - secondMinProportion)));
+ mySplitter.setProportion(proportion);
+ }
+ }
+ else {
+ if (getWidth() > 0) {
+ proportion = Math.min(1.0f, Math.max(.0f, Math.min(
+ Math.max(firstMinProportion, (float)myPoint.x / (float)mySplitter.getWidth()), 1 - secondMinProportion)));
+ mySplitter.setProportion(proportion);
+ }
+ }
+ }
+ }
+
+ private float getMinProportion(JComponent component) {
+ if (component != null &&
+ mySplitter.getFirstComponent() != null &&
+ mySplitter.getFirstComponent().isVisible() &&
+ mySplitter.getSecondComponent() != null &&
+ mySplitter.getSecondComponent().isVisible()) {
+ if (isVertical()) {
+ return (float)component.getMinimumSize().height / (float)(mySplitter.getHeight() - 1);
+ } else {
+ return (float)component.getMinimumSize().width / (float)(mySplitter.getWidth() - 1);
+ }
+ }
+
+ return 0.0f;
+ }
+
+ @Override
+ protected void processMouseEvent(MouseEvent e) {
+ super.processMouseEvent(e);
+ if (e.getID() == MouseEvent.MOUSE_CLICKED) {
+ if (mySwitchOrientationEnabled
+ && e.getClickCount() == 1
+ && SwingUtilities.isLeftMouseButton(e) && (SystemInfo.isMac ? e.isMetaDown() : e.isControlDown())) {
+ mySplitter.setOrientation(!mySplitter.getOrientation());
+ }
+ if (myResizeEnabled && e.getClickCount() == 2) {
+ mySplitter.setProportion(.5f);
+ }
+ }
+ }
+
+ public void setResizeEnabled(boolean resizeEnabled) {
+ myResizeEnabled = resizeEnabled;
+ if (!myResizeEnabled) {
+ setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
+ }
+ else {
+ setCursor(isVertical() ?
+ Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR) :
+ Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR));
+ }
+ }
+
+ public void setSwitchOrientationEnabled(boolean switchOrientationEnabled) {
+ mySwitchOrientationEnabled = switchOrientationEnabled;
+ }
+
+
+ public boolean isVertical() {
+ return myVertical;
+ }
+}
diff --git a/platform/platform-api/src/com/intellij/openapi/wm/FocusCommand.java b/platform/platform-api/src/com/intellij/openapi/wm/FocusCommand.java
index fc9eec268ece..6c40a04f5831 100644
--- a/platform/platform-api/src/com/intellij/openapi/wm/FocusCommand.java
+++ b/platform/platform-api/src/com/intellij/openapi/wm/FocusCommand.java
@@ -43,7 +43,7 @@ public abstract class FocusCommand extends ActiveRunnable implements Expirable {
private boolean myInvalidatesPendingFurtherRequestors = true;
private Expirable myExpirable;
- public static final Logger LOG = Logger.getInstance("#com.intellij.openapi.wm.FocusCommand");
+ private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.wm.FocusCommand");
public boolean isForced() {
return myForced;
diff --git a/platform/platform-api/src/com/intellij/ui/AnActionButton.java b/platform/platform-api/src/com/intellij/ui/AnActionButton.java
index 7c539b1bb2a4..d1c19df6e3ad 100644
--- a/platform/platform-api/src/com/intellij/ui/AnActionButton.java
+++ b/platform/platform-api/src/com/intellij/ui/AnActionButton.java
@@ -17,6 +17,7 @@ package com.intellij.ui;
import com.intellij.ide.DataManager;
import com.intellij.openapi.actionSystem.*;
+import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.util.containers.SmartHashSet;
import com.intellij.util.ui.UIUtil;
@@ -187,7 +188,7 @@ public abstract class AnActionButton extends AnAction implements ShortcutProvide
@Override
public void actionPerformed(AnActionEvent e) {
- myAction.actionPerformed(e);
+ myAction.actionPerformed(new AnActionEventWrapper(e, this));
}
@Override
@@ -205,4 +206,20 @@ public abstract class AnActionButton extends AnAction implements ShortcutProvide
return myAction.isDumbAware();
}
}
+
+ public static class AnActionEventWrapper extends AnActionEvent {
+ private final AnActionButton myPeer;
+
+ private AnActionEventWrapper(AnActionEvent e, AnActionButton peer) {
+ super(e.getInputEvent(), e.getDataContext(), e.getPlace(), e.getPresentation(), e.getActionManager(), e.getModifiers());
+ myPeer = peer;
+ }
+
+ public void showPopup(JBPopup popup) {
+ popup.show(myPeer.getPreferredPopupPoint());
+ }
+
+
+
+ }
}
diff --git a/jps/standalone-builder/src/org/jetbrains/jps/idea/IdeaProjectLoader.groovy b/platform/platform-api/src/com/intellij/ui/CheckboxTreeAdapter.java
index d7e52c6d061f..186904a4a843 100644
--- a/jps/standalone-builder/src/org/jetbrains/jps/idea/IdeaProjectLoader.groovy
+++ b/platform/platform-api/src/com/intellij/ui/CheckboxTreeAdapter.java
@@ -13,24 +13,23 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.jetbrains.jps.idea
+package com.intellij.ui;
+
+import org.jetbrains.annotations.NotNull;
/**
- * @author max
+ * @author nik
*/
-public class IdeaProjectLoader {
- public static String guessHome(Script script) {
- String uri = script["gant.file"]
- File home = new File(new URI(uri).getSchemeSpecificPart())
-
- while (home != null) {
- if (home.isDirectory() && new File(home, ".idea").exists()) {
- return home.getCanonicalPath()
- }
+public abstract class CheckboxTreeAdapter implements CheckboxTreeListener {
+ @Override
+ public void mouseDoubleClicked(@NotNull CheckedTreeNode node) {
+ }
- home = home.getParentFile()
- }
+ @Override
+ public void nodeStateChanged(@NotNull CheckedTreeNode node) {
+ }
- throw new IllegalArgumentException("Cannot guess project home from '" + uri + "'")
+ @Override
+ public void beforeNodeStateChanged(@NotNull CheckedTreeNode node) {
}
}
diff --git a/platform/platform-api/src/com/intellij/ui/CheckboxTreeBase.java b/platform/platform-api/src/com/intellij/ui/CheckboxTreeBase.java
index d9755f342a3f..88f433f7c62a 100644
--- a/platform/platform-api/src/com/intellij/ui/CheckboxTreeBase.java
+++ b/platform/platform-api/src/com/intellij/ui/CheckboxTreeBase.java
@@ -16,67 +16,49 @@
package com.intellij.ui;
import com.intellij.ui.treeStructure.Tree;
+import com.intellij.util.EventDispatcher;
import com.intellij.util.ui.UIUtil;
-import com.intellij.util.ui.tree.TreeUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
-import javax.swing.tree.*;
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.TreeCellRenderer;
+import javax.swing.tree.TreeNode;
import java.awt.*;
-import java.awt.event.KeyAdapter;
-import java.awt.event.KeyEvent;
-import java.awt.event.MouseEvent;
-import java.lang.reflect.Array;
-import java.util.ArrayList;
-import java.util.Enumeration;
public class CheckboxTreeBase extends Tree {
- private final CheckPolicy myCheckPolicy;
- private static final CheckPolicy DEFAULT_POLICY = new CheckPolicy(true, true, false, true);
+ private final CheckboxTreeHelper myHelper;
+ private final EventDispatcher<CheckboxTreeListener> myEventDispatcher;
public CheckboxTreeBase() {
this(new CheckboxTreeCellRendererBase(), null);
}
public CheckboxTreeBase(final CheckboxTreeCellRendererBase cellRenderer, CheckedTreeNode root) {
- this(cellRenderer, root, DEFAULT_POLICY);
+ this(cellRenderer, root, CheckboxTreeHelper.DEFAULT_POLICY);
}
public CheckboxTreeBase(CheckboxTreeCellRendererBase cellRenderer, @Nullable CheckedTreeNode root, CheckPolicy checkPolicy) {
- myCheckPolicy = checkPolicy;
-
- setRootVisible(false);
- setShowsRootHandles(true);
- setLineStyleAngled();
- TreeUtil.installActions(this);
-
- installRenderer(cellRenderer);
-
- addKeyListener(new KeyAdapter() {
- public void keyPressed(KeyEvent e) {
- if (isToggleEvent(e)) {
- TreePath treePath = getLeadSelectionPath();
- if (treePath == null) return;
- final Object o = treePath.getLastPathComponent();
- if (!(o instanceof CheckedTreeNode)) return;
- CheckedTreeNode firstNode = (CheckedTreeNode)o;
- boolean checked = toggleNode(firstNode);
-
- TreePath[] selectionPaths = getSelectionPaths();
- for (int i = 0; selectionPaths != null && i < selectionPaths.length; i++) {
- final TreePath selectionPath = selectionPaths[i];
- final Object o1 = selectionPath.getLastPathComponent();
- if (!(o1 instanceof CheckedTreeNode)) continue;
- CheckedTreeNode node = (CheckedTreeNode)o1;
- checkNode(node, checked);
- ((DefaultTreeModel)getModel()).nodeChanged(node);
- }
-
- e.consume();
- }
+ myEventDispatcher = EventDispatcher.create(CheckboxTreeListener.class);
+ myEventDispatcher.addListener(new CheckboxTreeListener() {
+ @Override
+ public void mouseDoubleClicked(@NotNull CheckedTreeNode node) {
+ onDoubleClick(node);
+ }
+
+ @Override
+ public void nodeStateChanged(@NotNull CheckedTreeNode node) {
+ CheckboxTreeBase.this.onNodeStateChanged(node);
+ }
+
+ @Override
+ public void beforeNodeStateChanged(@NotNull CheckedTreeNode node) {
+ CheckboxTreeBase.this.nodeStateWillChange(node);
}
});
+ myHelper = new CheckboxTreeHelper(checkPolicy, myEventDispatcher);
+ myHelper.initTree(this, this, cellRenderer);
setSelectionRow(0);
if (root != null) {
@@ -84,55 +66,37 @@ public class CheckboxTreeBase extends Tree {
}
}
+ @Deprecated
public void installRenderer(final CheckboxTreeCellRendererBase cellRenderer) {
setCellRenderer(cellRenderer);
- new ClickListener() {
- @Override
- public boolean onClick(@NotNull MouseEvent e, int clickCount) {
- int row = getRowForLocation(e.getX(), e.getY());
- if (row < 0) return false;
- final Object o = getPathForRow(row).getLastPathComponent();
- if (!(o instanceof CheckedTreeNode)) return false;
- Rectangle rowBounds = getRowBounds(row);
- cellRenderer.setBounds(rowBounds);
- Rectangle checkBounds = cellRenderer.myCheckbox.getBounds();
- checkBounds.setLocation(rowBounds.getLocation());
-
- if (checkBounds.height == 0) checkBounds.height = checkBounds.width = rowBounds.height;
-
- final CheckedTreeNode node = (CheckedTreeNode)o;
- if (checkBounds.contains(e.getPoint())) {
- if (node.isEnabled()) {
- toggleNode(node);
- setSelectionRow(row);
- return true;
- }
- }
- else if (clickCount > 1) {
- onDoubleClick(node);
- return true;
- }
- return false;
- }
- }.installOn(this);
}
- protected void onDoubleClick(final CheckedTreeNode node) {
+ /**
+ * @deprecated use {@link #setNodeState} to change node state or subscribe to {@link #addCheckboxTreeListener} to get notifications about state changes
+ */
+ @Deprecated
+ protected boolean toggleNode(CheckedTreeNode node) {
+ setNodeState(node, !node.isChecked());
+ return node.isChecked();
}
- protected boolean isToggleEvent(KeyEvent e) {
- return e.getKeyCode() == KeyEvent.VK_SPACE;
+ /**
+ * @deprecated use {@link #setNodeState} to change node state or subscribe to {@link #addCheckboxTreeListener} to get notifications about state changes
+ */
+ @Deprecated
+ protected void checkNode(CheckedTreeNode node, boolean checked) {
+ setNodeState(node, checked);
}
- protected boolean toggleNode(CheckedTreeNode node) {
- boolean checked = !node.isChecked();
- checkNode(node, checked);
+ public void setNodeState(@NotNull CheckedTreeNode node, boolean checked) {
+ myHelper.setNodeState(this, node, checked);
+ }
- // notify model listeners about model change
- final TreeModel model = getModel();
- model.valueForPathChanged(new TreePath(node.getPath()), node.getUserObject());
+ public void addCheckboxTreeListener(@NotNull CheckboxTreeListener listener) {
+ myEventDispatcher.addListener(listener);
+ }
- return checked;
+ protected void onDoubleClick(final CheckedTreeNode node) {
}
/**
@@ -144,38 +108,8 @@ public class CheckboxTreeBase extends Tree {
* @param <T> the type of the node
* @return an array of collected nodes
*/
- @SuppressWarnings("unchecked")
public <T> T[] getCheckedNodes(final Class<T> nodeType, @Nullable final NodeFilter<T> filter) {
- final ArrayList<T> nodes = new ArrayList<T>();
- final Object root = getModel().getRoot();
- if (!(root instanceof CheckedTreeNode)) {
- throw new IllegalStateException(
- "The root must be instance of the " + CheckedTreeNode.class.getName() + ": " + root.getClass().getName());
- }
- new Object() {
- @SuppressWarnings("unchecked")
- public void collect(CheckedTreeNode node) {
- if (node.isLeaf()) {
- Object userObject = node.getUserObject();
- if (node.isChecked() && userObject != null && nodeType.isAssignableFrom(userObject.getClass())) {
- final T value = (T)userObject;
- if (filter != null && !filter.accept(value)) return;
- nodes.add(value);
- }
- }
- else {
- for (int i = 0; i < node.getChildCount(); i++) {
- final TreeNode child = node.getChildAt(i);
- if (child instanceof CheckedTreeNode) {
- collect((CheckedTreeNode)child);
- }
- }
- }
- }
- }.collect((CheckedTreeNode)root);
- T[] result = (T[])Array.newInstance(nodeType, nodes.size());
- nodes.toArray(result);
- return result;
+ return CheckboxTreeHelper.getCheckedNodes(nodeType, filter, getModel());
}
@@ -184,118 +118,14 @@ public class CheckboxTreeBase extends Tree {
return -1;
}
- protected void checkNode(CheckedTreeNode node, boolean checked) {
- adjustParentsAndChildren(node, checked);
- repaint();
- }
-
protected void onNodeStateChanged(CheckedTreeNode node) {
-
}
protected void nodeStateWillChange(CheckedTreeNode node) {
-
- }
-
- protected void adjustParentsAndChildren(final CheckedTreeNode node, final boolean checked) {
- changeNodeState(node, checked);
- if (!checked) {
- if (myCheckPolicy.uncheckParentWithUncheckedChild) {
- TreeNode parent = node.getParent();
- while (parent != null) {
- if (parent instanceof CheckedTreeNode) {
- changeNodeState((CheckedTreeNode)parent, false);
- }
- parent = parent.getParent();
- }
- }
- if (myCheckPolicy.uncheckChildrenWithUncheckedParent) {
- uncheckChildren(node);
- }
-
- }
- else {
- if (myCheckPolicy.checkChildrenWithCheckedParent) {
- checkChildren(node);
- }
-
- if (myCheckPolicy.checkParentWithCheckedChild) {
- TreeNode parent = node.getParent();
- while (parent != null) {
- if (parent instanceof CheckedTreeNode) {
- changeNodeState((CheckedTreeNode)parent, true);
- }
- parent = parent.getParent();
- }
- }
-
- }
- repaint();
- }
-
- private void changeNodeState(final CheckedTreeNode node, final boolean checked) {
- if (node.isChecked() != checked) {
- nodeStateWillChange(node);
- node.setChecked(checked);
- onNodeStateChanged(node);
- }
- }
-
- private void uncheckChildren(final CheckedTreeNode node) {
- final Enumeration children = node.children();
- while (children.hasMoreElements()) {
- final Object o = children.nextElement();
- if (!(o instanceof CheckedTreeNode)) continue;
- CheckedTreeNode child = (CheckedTreeNode)o;
- changeNodeState(child, false);
- uncheckChildren(child);
- }
- }
-
- private void checkChildren(final CheckedTreeNode node) {
- final Enumeration children = node.children();
- while (children.hasMoreElements()) {
- final Object o = children.nextElement();
- if (!(o instanceof CheckedTreeNode)) continue;
- CheckedTreeNode child = (CheckedTreeNode)o;
- changeNodeState(child, true);
- checkChildren(child);
- }
}
+ @Deprecated
protected void adjustParents(final CheckedTreeNode node, final boolean checked) {
- TreeNode parentNode = node.getParent();
- if (!(parentNode instanceof CheckedTreeNode)) return;
- CheckedTreeNode parent = (CheckedTreeNode)parentNode;
-
- if (!checked && isAllChildrenUnchecked(parent)) {
- changeNodeState(parent, false);
- adjustParents(parent, false);
- }
- else if (checked && isAllChildrenChecked(parent)) {
- changeNodeState(parent, true);
- adjustParents(parent, true);
- }
- }
-
- private static boolean isAllChildrenUnchecked(final CheckedTreeNode node) {
- for (int i = 0; i < node.getChildCount(); i++) {
- final TreeNode o = node.getChildAt(i);
- if ((o instanceof CheckedTreeNode) && ((CheckedTreeNode)o).isChecked()) {
- return false;
- }
- }
- return true;
- }
-
- private static boolean isAllChildrenChecked(final CheckedTreeNode node) {
- for (int i = 0; i < node.getChildCount(); i++) {
- final TreeNode o = node.getChildAt(i);
- if ((o instanceof CheckedTreeNode) && !((CheckedTreeNode)o).isChecked()) {
- return false;
- }
- }
- return true;
}
public static class CheckboxTreeCellRendererBase extends JPanel implements TreeCellRenderer {
@@ -395,8 +225,8 @@ public class CheckboxTreeBase extends Tree {
}
/**
- * @deprecated
* @see CheckboxTreeCellRendererBase#customizeRenderer(javax.swing.JTree, Object, boolean, boolean, boolean, int, boolean)
+ * @deprecated
*/
@Deprecated
public void customizeCellRenderer(JTree tree,
diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/CheckboxTreeTable.java b/platform/platform-api/src/com/intellij/ui/CheckboxTreeHelper.java
index dd72da957fa2..3048d131caa7 100644
--- a/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/CheckboxTreeTable.java
+++ b/platform/platform-api/src/com/intellij/ui/CheckboxTreeHelper.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,19 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.intellij.openapi.roots.libraries.ui.impl;
-
-import com.intellij.ui.CheckboxTree;
-import com.intellij.ui.CheckedTreeNode;
-import com.intellij.ui.ClickListener;
-import com.intellij.ui.dualView.TreeTableView;
-import com.intellij.ui.treeStructure.treetable.ListTreeTableModelOnColumns;
-import com.intellij.ui.treeStructure.treetable.TreeTableTree;
-import com.intellij.util.ui.ColumnInfo;
+package com.intellij.ui;
+
+import com.intellij.ui.speedSearch.SpeedSearchSupply;
+import com.intellij.ui.treeStructure.Tree;
+import com.intellij.util.EventDispatcher;
import com.intellij.util.ui.tree.TreeUtil;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
-import javax.swing.tree.DefaultTreeModel;
+import javax.swing.*;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
@@ -40,122 +37,82 @@ import java.util.Enumeration;
/**
* @author nik
*/
-public class CheckboxTreeTable extends TreeTableView {
- public CheckboxTreeTable(CheckedTreeNode root, CheckboxTree.CheckboxTreeCellRenderer renderer, final ColumnInfo[] columns) {
- super(new ListTreeTableModelOnColumns(root, columns));
- initTree(getTree(), renderer);
+class CheckboxTreeHelper {
+ static final CheckboxTreeBase.CheckPolicy DEFAULT_POLICY = new CheckboxTreeBase.CheckPolicy(true, true, false, true);
+ private final CheckboxTreeBase.CheckPolicy myCheckPolicy;
+ private final EventDispatcher<CheckboxTreeListener> myEventDispatcher;
+
+ CheckboxTreeHelper(CheckboxTreeBase.CheckPolicy checkPolicy, EventDispatcher<CheckboxTreeListener> dispatcher) {
+ myCheckPolicy = checkPolicy;
+ myEventDispatcher = dispatcher;
}
- //todo[nik] I hate to copy-paste but have to copy the code below from CheckboxTreeBase to support CheckboxTree inside TreeTable in IDEA 11.1.x branch
- //todo[nik] I solemnly swear to get rid of this code in IDEA 12 branch
- private void initTree(final TreeTableTree tree, final CheckboxTree.CheckboxTreeCellRenderer cellRenderer) {
+ public void initTree(@NotNull final Tree tree, JComponent mainComponent, CheckboxTreeBase.CheckboxTreeCellRendererBase cellRenderer) {
tree.setCellRenderer(cellRenderer);
tree.setRootVisible(false);
tree.setShowsRootHandles(true);
tree.setLineStyleAngled();
TreeUtil.installActions(tree);
- new ClickListener() {
- @Override
- public boolean onClick(@NotNull MouseEvent e, int clickCount) {
- int row = tree.getRowForLocation(e.getX(), e.getY());
- if (row < 0) return false;
- final Object o = tree.getPathForRow(row).getLastPathComponent();
- if (!(o instanceof CheckedTreeNode)) return false;
- Rectangle rowBounds = tree.getRowBounds(row);
- cellRenderer.setBounds(rowBounds);
- Rectangle checkBounds = cellRenderer.myCheckbox.getBounds();
- checkBounds.setLocation(rowBounds.getLocation());
-
- if (checkBounds.height == 0) checkBounds.height = rowBounds.height;
-
- final CheckedTreeNode node = (CheckedTreeNode)o;
- if (checkBounds.contains(e.getPoint())) {
- if (node.isEnabled()) {
- toggleNode(node);
- tree.setSelectionRow(row);
- return true;
- }
- }
-
- return false;
- }
- }.installOn(this);
-
- addKeyListener(new KeyAdapter() {
- @Override
- public void keyPressed(KeyEvent e) {
- if (isToggleEvent(e)) {
- TreePath treePath = tree.getLeadSelectionPath();
- if (treePath == null) return;
- final Object o = treePath.getLastPathComponent();
- if (!(o instanceof CheckedTreeNode)) return;
- CheckedTreeNode firstNode = (CheckedTreeNode)o;
- boolean checked = toggleNode(firstNode);
-
- TreePath[] selectionPaths = tree.getSelectionPaths();
- for (int i = 0; selectionPaths != null && i < selectionPaths.length; i++) {
- final TreePath selectionPath = selectionPaths[i];
- final Object o1 = selectionPath.getLastPathComponent();
- if (!(o1 instanceof CheckedTreeNode)) continue;
- CheckedTreeNode node = (CheckedTreeNode)o1;
- checkNode(node, checked);
- ((DefaultTreeModel)tree.getModel()).nodeChanged(node);
- }
-
- e.consume();
- }
- }
- });
-
- tree.setSelectionRow(0);
+ setupKeyListener(tree, mainComponent);
+ setupMouseListener(tree, mainComponent, cellRenderer);
}
- private static boolean isToggleEvent(KeyEvent e) {
- return e.getKeyCode() == KeyEvent.VK_SPACE;
- }
-
- protected boolean toggleNode(CheckedTreeNode node) {
- boolean checked = !node.isChecked();
- checkNode(node, checked);
+ public void setNodeState(Tree tree, CheckedTreeNode node, boolean checked) {
+ changeNodeState(node, checked);
+ adjustParentsAndChildren(node, checked);
+ tree.repaint();
// notify model listeners about model change
- final TreeModel model = getTree().getModel();
+ final TreeModel model = tree.getModel();
model.valueForPathChanged(new TreePath(node.getPath()), node.getUserObject());
-
- return checked;
}
- private void checkNode(CheckedTreeNode node, boolean checked) {
- adjustParentsAndChildren(node, checked);
- repaint();
+ private void toggleNode(Tree tree, CheckedTreeNode node) {
+ setNodeState(tree, node, !node.isChecked());
}
private void adjustParentsAndChildren(final CheckedTreeNode node, final boolean checked) {
- changeNodeState(node, checked);
if (!checked) {
- TreeNode parent = node.getParent();
- while (parent != null) {
- if (parent instanceof CheckedTreeNode) {
- changeNodeState((CheckedTreeNode)parent, false);
+ if (myCheckPolicy.uncheckParentWithUncheckedChild) {
+ TreeNode parent = node.getParent();
+ while (parent != null) {
+ if (parent instanceof CheckedTreeNode) {
+ changeNodeState((CheckedTreeNode)parent, false);
+ }
+ parent = parent.getParent();
}
- parent = parent.getParent();
}
- uncheckChildren(node);
+ if (myCheckPolicy.uncheckChildrenWithUncheckedParent) {
+ uncheckChildren(node);
+ }
}
else {
- checkChildren(node);
+ if (myCheckPolicy.checkChildrenWithCheckedParent) {
+ checkChildren(node);
+ }
+
+ if (myCheckPolicy.checkParentWithCheckedChild) {
+ TreeNode parent = node.getParent();
+ while (parent != null) {
+ if (parent instanceof CheckedTreeNode) {
+ changeNodeState((CheckedTreeNode)parent, true);
+ }
+ parent = parent.getParent();
+ }
+ }
}
- repaint();
}
- private static void changeNodeState(final CheckedTreeNode node, final boolean checked) {
+ private void changeNodeState(final CheckedTreeNode node, final boolean checked) {
if (node.isChecked() != checked) {
+ myEventDispatcher.getMulticaster().beforeNodeStateChanged(node);
node.setChecked(checked);
+ myEventDispatcher.getMulticaster().nodeStateChanged(node);
}
}
- private static void uncheckChildren(final CheckedTreeNode node) {
+ private void uncheckChildren(final CheckedTreeNode node) {
final Enumeration children = node.children();
while (children.hasMoreElements()) {
final Object o = children.nextElement();
@@ -166,7 +123,7 @@ public class CheckboxTreeTable extends TreeTableView {
}
}
- private static void checkChildren(final CheckedTreeNode node) {
+ private void checkChildren(final CheckedTreeNode node) {
final Enumeration children = node.children();
while (children.hasMoreElements()) {
final Object o = children.nextElement();
@@ -177,12 +134,77 @@ public class CheckboxTreeTable extends TreeTableView {
}
}
+ private void setupKeyListener(final Tree tree, final JComponent mainComponent) {
+ mainComponent.addKeyListener(new KeyAdapter() {
+ public void keyPressed(@NotNull KeyEvent e) {
+ if (isToggleEvent(e, mainComponent)) {
+ TreePath treePath = tree.getLeadSelectionPath();
+ if (treePath == null) return;
+ final Object o = treePath.getLastPathComponent();
+ if (!(o instanceof CheckedTreeNode)) return;
+ CheckedTreeNode firstNode = (CheckedTreeNode)o;
+ toggleNode(tree, firstNode);
+ boolean checked = firstNode.isChecked();
+
+ TreePath[] selectionPaths = tree.getSelectionPaths();
+ for (int i = 0; selectionPaths != null && i < selectionPaths.length; i++) {
+ final TreePath selectionPath = selectionPaths[i];
+ final Object o1 = selectionPath.getLastPathComponent();
+ if (!(o1 instanceof CheckedTreeNode)) continue;
+ CheckedTreeNode node = (CheckedTreeNode)o1;
+ setNodeState(tree, node, checked);
+ }
+
+ e.consume();
+ }
+ }
+ });
+ }
+
+ private static boolean isToggleEvent(KeyEvent e, JComponent mainComponent) {
+ return e.getKeyCode() == KeyEvent.VK_SPACE && SpeedSearchSupply.getSupply(mainComponent) == null;
+ }
+
+ private void setupMouseListener(final Tree tree, JComponent mainComponent, final CheckboxTreeBase.CheckboxTreeCellRendererBase cellRenderer) {
+ new ClickListener() {
+ @Override
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
+ int row = tree.getRowForLocation(e.getX(), e.getY());
+ if (row < 0) return false;
+ final Object o = tree.getPathForRow(row).getLastPathComponent();
+ if (!(o instanceof CheckedTreeNode)) return false;
+ Rectangle rowBounds = tree.getRowBounds(row);
+ cellRenderer.setBounds(rowBounds);
+ Rectangle checkBounds = cellRenderer.myCheckbox.getBounds();
+ checkBounds.setLocation(rowBounds.getLocation());
+
+ if (checkBounds.height == 0) checkBounds.height = checkBounds.width = rowBounds.height;
+
+ final CheckedTreeNode node = (CheckedTreeNode)o;
+ if (checkBounds.contains(e.getPoint())) {
+ if (node.isEnabled()) {
+ toggleNode(tree, node);
+ tree.setSelectionRow(row);
+ return true;
+ }
+ }
+ else if (clickCount > 1) {
+ myEventDispatcher.getMulticaster().mouseDoubleClicked(node);
+ return true;
+ }
+
+ return false;
+ }
+ }.installOn(mainComponent);
+ }
+
@SuppressWarnings("unchecked")
- public <T> T[] getCheckedNodes(final Class<T> nodeType) {
+ public static <T> T[] getCheckedNodes(final Class<T> nodeType, @Nullable final Tree.NodeFilter<T> filter, final TreeModel model) {
final ArrayList<T> nodes = new ArrayList<T>();
- final Object root = getTree().getModel().getRoot();
+ final Object root = model.getRoot();
if (!(root instanceof CheckedTreeNode)) {
- throw new IllegalStateException("The root must be instance of the " + CheckedTreeNode.class.getName() + ": " + root.getClass().getName());
+ throw new IllegalStateException(
+ "The root must be instance of the " + CheckedTreeNode.class.getName() + ": " + root.getClass().getName());
}
new Object() {
@SuppressWarnings("unchecked")
@@ -191,6 +213,7 @@ public class CheckboxTreeTable extends TreeTableView {
Object userObject = node.getUserObject();
if (node.isChecked() && userObject != null && nodeType.isAssignableFrom(userObject.getClass())) {
final T value = (T)userObject;
+ if (filter != null && !filter.accept(value)) return;
nodes.add(value);
}
}
diff --git a/platform/platform-api/src/com/intellij/ui/CheckboxTreeListener.java b/platform/platform-api/src/com/intellij/ui/CheckboxTreeListener.java
new file mode 100644
index 000000000000..792c4589c85d
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/ui/CheckboxTreeListener.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.ui;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.EventListener;
+
+/**
+ * @author nik
+ */
+public interface CheckboxTreeListener extends EventListener {
+ void mouseDoubleClicked(@NotNull CheckedTreeNode node);
+
+ void nodeStateChanged(@NotNull CheckedTreeNode node);
+
+ void beforeNodeStateChanged(@NotNull CheckedTreeNode node);
+}
diff --git a/platform/platform-api/src/com/intellij/ui/CommonActionsPanel.java b/platform/platform-api/src/com/intellij/ui/CommonActionsPanel.java
index 846378cc1633..2d4213da3954 100644
--- a/platform/platform-api/src/com/intellij/ui/CommonActionsPanel.java
+++ b/platform/platform-api/src/com/intellij/ui/CommonActionsPanel.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -165,6 +165,9 @@ public class CommonActionsPanel extends JPanel {
@Override
public void addNotify() {
+ if (getBackground() != null && !getBackground().equals(UIUtil.getPanelBackground())) {
+ SwingUtilities.updateComponentTreeUI(this.getParent());
+ }
final JRootPane pane = getRootPane();
for (AnActionButton button : myActions) {
final ShortcutSet shortcut = button.getShortcut();
diff --git a/platform/platform-api/src/com/intellij/ui/JBSplitter.java b/platform/platform-api/src/com/intellij/ui/JBSplitter.java
index b4000dbcfae2..5f01602d92c5 100644
--- a/platform/platform-api/src/com/intellij/ui/JBSplitter.java
+++ b/platform/platform-api/src/com/intellij/ui/JBSplitter.java
@@ -94,14 +94,6 @@ public class JBSplitter extends Splitter {
saveProportion();
}
- public void setOnePixelMode() {
- setDividerWidth(1);
- setShowDividerIcon(false);
- getDivider().setBackground(new JBColor(Gray._153.withAlpha(128), Gray._100.withAlpha(128)));
- setShowDividerControls(false);
- setOrientation(getOrientation());
- }
-
protected void loadProportion() {
if (! StringUtil.isEmpty(mySplitterProportionKey)) {
setProportion(PropertiesComponent.getInstance().getFloat(mySplitterProportionKey, myProportion));
diff --git a/platform/platform-api/src/com/intellij/ui/OnePixelSplitter.java b/platform/platform-api/src/com/intellij/ui/OnePixelSplitter.java
new file mode 100644
index 000000000000..15dd5fdc2abb
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/ui/OnePixelSplitter.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.ui;
+
+import com.intellij.openapi.ui.Divider;
+import com.intellij.openapi.ui.OnePixelDivider;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public class OnePixelSplitter extends JBSplitter {
+
+ public OnePixelSplitter() {
+ super();
+ init();
+ }
+
+ public OnePixelSplitter(boolean vertical) {
+ super(vertical);
+ init();
+ }
+
+ public OnePixelSplitter(boolean vertical, float proportion) {
+ super(vertical, proportion);
+ init();
+ }
+
+ public OnePixelSplitter(float proportion) {
+ super(proportion);
+ init();
+ }
+
+ public OnePixelSplitter(boolean vertical, float proportion, float minProp, float maxProp) {
+ super(vertical, proportion, minProp, maxProp);
+ init();
+ }
+
+ protected void init() {
+ setDividerWidth(1);
+ }
+
+ @Override
+ protected Divider createDivider() {
+ return new OnePixelDivider(isVertical(), this);
+ }
+}
diff --git a/platform/platform-api/src/com/intellij/ui/border/CustomLineBorder.java b/platform/platform-api/src/com/intellij/ui/border/CustomLineBorder.java
index ee68a3f94ae8..2f5bf0343ed6 100644
--- a/platform/platform-api/src/com/intellij/ui/border/CustomLineBorder.java
+++ b/platform/platform-api/src/com/intellij/ui/border/CustomLineBorder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@ package com.intellij.ui.border;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import javax.swing.border.Border;
import java.awt.*;
@@ -28,17 +29,17 @@ public class CustomLineBorder implements Border {
private final Color myColor;
private final Insets myInsets;
- public CustomLineBorder(@NotNull Color color, @NotNull Insets insets) {
+ public CustomLineBorder(@Nullable Color color, @NotNull Insets insets) {
myColor = color;
myInsets = insets;
}
- public CustomLineBorder(@NotNull Color color, int top, int left, int bottom, int right) {
+ public CustomLineBorder(@Nullable Color color, int top, int left, int bottom, int right) {
this(color, new Insets(top, left, bottom, right));
}
public CustomLineBorder(@NotNull Insets insets) {
- this(UIUtil.getBorderColor(), insets);
+ this(null, insets);
}
public CustomLineBorder(int top, int left, int bottom, int right) {
@@ -59,7 +60,7 @@ public class CustomLineBorder implements Border {
}
protected Color getColor() {
- return myColor;
+ return myColor == null ? UIUtil.getBorderColor() : myColor;
}
@Override
diff --git a/platform/platform-api/src/com/intellij/ui/table/BaseTableView.java b/platform/platform-api/src/com/intellij/ui/table/BaseTableView.java
index a79349b5f6aa..46bce6b3834d 100644
--- a/platform/platform-api/src/com/intellij/ui/table/BaseTableView.java
+++ b/platform/platform-api/src/com/intellij/ui/table/BaseTableView.java
@@ -17,12 +17,12 @@ package com.intellij.ui.table;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.util.config.Storage;
-import com.intellij.util.ui.ListTableModel;
import org.jetbrains.annotations.NonNls;
import javax.swing.*;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
+import javax.swing.table.TableModel;
import java.util.ArrayList;
import java.util.Arrays;
@@ -33,10 +33,14 @@ import java.util.Arrays;
public class BaseTableView extends JBTable {
private static final Logger LOG = Logger.getInstance("#com.intellij.ui.table.BaseTableView");
- public BaseTableView(final ListTableModel model) {
+ public BaseTableView(final TableModel model) {
super(model);
}
+ public BaseTableView(TableModel model, TableColumnModel columnModel) {
+ super(model, columnModel);
+ }
+
@NonNls
private static String orderPropertyName(final int index) {
return "Order"+index;
diff --git a/platform/platform-api/src/com/intellij/ui/table/JBTable.java b/platform/platform-api/src/com/intellij/ui/table/JBTable.java
index e7ff935e57f9..435c4358959f 100644
--- a/platform/platform-api/src/com/intellij/ui/table/JBTable.java
+++ b/platform/platform-api/src/com/intellij/ui/table/JBTable.java
@@ -62,8 +62,12 @@ public class JBTable extends JTable implements ComponentWithEmptyText, Component
this(new DefaultTableModel());
}
- public JBTable(final TableModel model) {
- super(model);
+ public JBTable(TableModel model) {
+ this(model, null);
+ }
+
+ public JBTable(final TableModel model, final TableColumnModel columnModel) {
+ super(model, columnModel);
myEmptyText = new StatusText(this) {
@Override
diff --git a/platform/platform-api/src/com/intellij/ui/tabs/TabInfo.java b/platform/platform-api/src/com/intellij/ui/tabs/TabInfo.java
index d1dfa976e479..c8c944c86e4a 100644
--- a/platform/platform-api/src/com/intellij/ui/tabs/TabInfo.java
+++ b/platform/platform-api/src/com/intellij/ui/tabs/TabInfo.java
@@ -92,6 +92,7 @@ public final class TabInfo implements Queryable, PlaceProvider<String> {
* out of its container. (IDEA-61536)
*/
private WeakReference<TabInfo> myPreviousSelection = new WeakReference<TabInfo>(null);
+ private boolean myTitleShortened;
public TabInfo(final JComponent component) {
myComponent = component;
@@ -392,6 +393,14 @@ public final class TabInfo implements Queryable, PlaceProvider<String> {
return myPreviousSelection.get();
}
+ public boolean isTitleShortened() {
+ return myTitleShortened;
+ }
+
+ public void setTitleIsShortened(boolean titleIsShortened) {
+ myTitleShortened = titleIsShortened;
+ }
+
public interface DragOutDelegate {
void dragOutStarted(MouseEvent mouseEvent, TabInfo info);
diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/DragHelper.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/DragHelper.java
index 655854ac933c..b0df0917dfe0 100644
--- a/platform/platform-api/src/com/intellij/ui/tabs/impl/DragHelper.java
+++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/DragHelper.java
@@ -240,7 +240,7 @@ class DragHelper extends MouseDragHelper {
final JBTabsPosition position = myTabs.getTabsPosition();
- if (!willDragOutStart && JBEditorTabs.isAlphabeticalMode() && position != JBTabsPosition.top && position != JBTabsPosition.bottom) {
+ if (!willDragOutStart && myTabs.isAlphabeticalMode() && position != JBTabsPosition.top && position != JBTabsPosition.bottom) {
Point p = new Point(event.getPoint());
p = SwingUtilities.convertPoint(event.getComponent(), p, myTabs);
if (myTabs.getVisibleRect().contains(p) && myPressedOnScreenPoint.distance(new RelativePoint(event).getScreenPoint()) > 15) {
diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBEditorTabs.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBEditorTabs.java
index 761d3ea0d341..a842f623ac45 100644
--- a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBEditorTabs.java
+++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBEditorTabs.java
@@ -43,7 +43,8 @@ import java.util.List;
* @author pegov
*/
public class JBEditorTabs extends JBTabsImpl {
- private static final String TABS_ALPHABETICAL_KEY = "tabs.alphabetical";
+ public static final String TABS_ALPHABETICAL_KEY = "tabs.alphabetical";
+ static final String TABS_SHORTEN_TITLE_IF_NEED = "tabs.shorten.title.if.need";
private JBEditorTabsPainter myDarkPainter = new DarculaEditorTabsPainter();
private JBEditorTabsPainter myDefaultPainter = new DefaultEditorTabsPainter();
@@ -61,6 +62,13 @@ public class JBEditorTabs extends JBTabsImpl {
}
@Override
+ protected TabLabel createTabLabel(TabInfo info) {
+ TabLabel label = super.createTabLabel(info);
+ label.putClientProperty(TABS_SHORTEN_TITLE_IF_NEED, Boolean.TRUE);
+ return label;
+ }
+
+ @Override
public boolean isEditorTabs() {
return true;
}
@@ -130,7 +138,7 @@ public class JBEditorTabs extends JBTabsImpl {
return UIUtil.isUnderDarcula() ? myDarkPainter : myDefaultPainter;
}
- public static boolean isAlphabeticalMode() {
+ public boolean isAlphabeticalMode() {
return Registry.is(TABS_ALPHABETICAL_KEY);
}
diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java
index a058badddd41..60898a6e9bd8 100644
--- a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java
+++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java
@@ -1262,6 +1262,10 @@ public class JBTabsImpl extends JComponent
return null;
}
+ public boolean isAlphabeticalMode() {
+ return false;
+ }
+
@Nullable
private TabInfo findEnabledBackward(int from, boolean cycle) {
if (from < 0) return null;
@@ -1653,19 +1657,13 @@ public class JBTabsImpl extends JComponent
config.setAntialiasing(false);
- if (isSideComponentVertical()) {
- Toolbar toolbarComp = myInfo2Toolbar.get(mySelectedInfo);
- if (toolbarComp != null && !toolbarComp.isEmpty()) {
- Rectangle toolBounds = toolbarComp.getBounds();
- g2d.setColor(CaptionPanel.CNT_ACTIVE_BORDER_COLOR);
+ Toolbar toolbarComp = myInfo2Toolbar.get(mySelectedInfo);
+ if (toolbarComp != null && !toolbarComp.isEmpty()) {
+ Rectangle toolBounds = toolbarComp.getBounds();
+ g2d.setColor(CaptionPanel.CNT_ACTIVE_BORDER_COLOR);
+ if (isSideComponentVertical()) {
g2d.drawLine((int)toolBounds.getMaxX(), toolBounds.y, (int)toolBounds.getMaxX(), (int)toolBounds.getMaxY() - 1);
- }
- }
- else if (!isSideComponentOnTabs()) {
- Toolbar toolbarComp = myInfo2Toolbar.get(mySelectedInfo);
- if (toolbarComp != null && !toolbarComp.isEmpty()) {
- Rectangle toolBounds = toolbarComp.getBounds();
- g2d.setColor(CaptionPanel.CNT_ACTIVE_BORDER_COLOR);
+ } else if (!isSideComponentOnTabs()) {
g2d.drawLine(toolBounds.x, (int)toolBounds.getMaxY(), (int)toolBounds.getMaxX() - 1, (int)toolBounds.getMaxY());
}
}
diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLabel.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLabel.java
index 21c36d5dd66a..a360c4e9294f 100644
--- a/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLabel.java
+++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLabel.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@ import com.intellij.openapi.actionSystem.ActionPlaces;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.util.Pass;
import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.*;
import com.intellij.ui.components.panels.Wrapper;
import com.intellij.ui.tabs.JBTabsPosition;
@@ -317,6 +318,16 @@ public class TabLabel extends JPanel {
public void setText(final SimpleColoredText text) {
+ myInfo.setTitleIsShortened(false);
+ if (text != null && text.getTexts().size() == 1 && Boolean.TRUE == getClientProperty(JBEditorTabs.TABS_SHORTEN_TITLE_IF_NEED)) {
+ String title = text.getTexts().get(0);
+ if (title.length() > UISettings.getInstance().EDITOR_TAB_TITLE_LIMIT) {
+ SimpleTextAttributes attributes = text.getAttributes().get(0);
+ text.clear();
+ text.append(StringUtil.getShortened(title, UISettings.getInstance().EDITOR_TAB_TITLE_LIMIT), attributes);
+ myInfo.setTitleIsShortened(true);
+ }
+ }
myLabel.change(new Runnable() {
public void run() {
myLabel.clear();
diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayout.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayout.java
index 653420ae261f..4e5925d2a2ee 100644
--- a/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayout.java
+++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayout.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -147,7 +147,7 @@ public class SingleRowLayout extends TabLayout {
}
public LayoutPassInfo layoutSingleRow(List<TabInfo> visibleInfos) {
- if (JBEditorTabs.isAlphabeticalMode()) {
+ if (myTabs.isAlphabeticalMode()) {
Collections.sort(visibleInfos, new Comparator<TabInfo>() {
@Override
public int compare(TabInfo o1, TabInfo o2) {
diff --git a/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java b/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java
index 169b5d57479b..0975876055b2 100644
--- a/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java
+++ b/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -828,4 +828,35 @@ public class Tree extends JTree implements ComponentWithEmptyText, ComponentWith
public void setHorizontalAutoScrollingEnabled(boolean enabled) {
myHorizontalAutoScrolling = enabled;
}
+
+ /**
+ * Returns the deepest visible component
+ * that will be rendered at the specified location.
+ *
+ * @param x horizontal location in the tree
+ * @param y vertical location in the tree
+ * @return the deepest visible component of the renderer
+ */
+ @Nullable
+ protected Component getDeepestRendererComponentAt(int x, int y) {
+ int row = getRowForLocation(x, y);
+ if (row >= 0) {
+ TreeCellRenderer renderer = getCellRenderer();
+ if (renderer != null) {
+ TreePath path = getPathForRow(row);
+ Object node = path.getLastPathComponent();
+ Component component = renderer.getTreeCellRendererComponent(this, node,
+ isRowSelected(row),
+ isExpanded(row),
+ getModel().isLeaf(node),
+ row, true);
+ Rectangle bounds = getPathBounds(path);
+ if (bounds != null) {
+ component.setBounds(bounds); // initialize size to layout complex renderer
+ return SwingUtilities.getDeepestComponentAt(component, x - bounds.x, y - bounds.y);
+ }
+ }
+ }
+ return null;
+ }
} \ No newline at end of file
diff --git a/platform/platform-api/src/com/intellij/ui/treeStructure/treetable/TreeTableTree.java b/platform/platform-api/src/com/intellij/ui/treeStructure/treetable/TreeTableTree.java
index dac3354a24fb..b574926a7eb8 100644
--- a/platform/platform-api/src/com/intellij/ui/treeStructure/treetable/TreeTableTree.java
+++ b/platform/platform-api/src/com/intellij/ui/treeStructure/treetable/TreeTableTree.java
@@ -98,7 +98,9 @@ public class TreeTableTree extends Tree {
public void setVisibleRow(int row) {
myVisibleRow = row;
- setPreferredSize(new Dimension(getRowBounds(myVisibleRow).width, getPreferredSize().height));
+ final Rectangle rowBounds = getRowBounds(myVisibleRow);
+ final int indent = rowBounds.x - getVisibleRect().x;
+ setPreferredSize(new Dimension(getRowBounds(myVisibleRow).width + indent, getPreferredSize().height));
}
public void _processKeyEvent(KeyEvent e){
diff --git a/platform/platform-api/src/com/intellij/util/net/HttpConfigurable.java b/platform/platform-api/src/com/intellij/util/net/HttpConfigurable.java
index 94eaa4db1ccb..0bcb416c7334 100644
--- a/platform/platform-api/src/com/intellij/util/net/HttpConfigurable.java
+++ b/platform/platform-api/src/com/intellij/util/net/HttpConfigurable.java
@@ -29,6 +29,7 @@ import com.intellij.openapi.util.*;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.openapi.wm.IdeFrame;
+import com.intellij.util.SystemProperties;
import com.intellij.util.WaitForProgressToShow;
import com.intellij.util.proxy.CommonProxy;
import com.intellij.util.proxy.JavaProxyProperty;
@@ -64,6 +65,7 @@ import java.util.*;
)
public class HttpConfigurable implements PersistentStateComponent<HttpConfigurable>, ApplicationComponent,
ExportableApplicationComponent {
+ public static final int CONNECTION_TIMEOUT = SystemProperties.getIntProperty("connection.timeout", 10000);
private static final Logger LOG = Logger.getInstance("#com.intellij.util.net.HttpConfigurable");
public boolean PROXY_TYPE_IS_SOCKS = false;
public boolean USE_HTTP_PROXY = false;
@@ -348,8 +350,8 @@ public class HttpConfigurable implements PersistentStateComponent<HttpConfigurab
final URLConnection connection = openConnection(url);
try {
- connection.setConnectTimeout(3 * 1000);
- connection.setReadTimeout(3 * 1000);
+ connection.setConnectTimeout(CONNECTION_TIMEOUT);
+ connection.setReadTimeout(CONNECTION_TIMEOUT);
connection.connect();
connection.getInputStream();
}
diff --git a/platform/platform-api/src/com/intellij/util/ui/FormBuilder.java b/platform/platform-api/src/com/intellij/util/ui/FormBuilder.java
index c2d3d829440d..89d5a238c188 100644
--- a/platform/platform-api/src/com/intellij/util/ui/FormBuilder.java
+++ b/platform/platform-api/src/com/intellij/util/ui/FormBuilder.java
@@ -108,6 +108,11 @@ public class FormBuilder {
}
public FormBuilder addVerticalGap(final int height) {
+ if (height == -1) {
+ myPanel.add(new JLabel(), new GridBagConstraints(0, myLineCount++, 2, 1, 0, 1, CENTER, NONE, new Insets(0, 0, 0, 0), 0, 0));
+ return this;
+ }
+
return addLabeledComponent((JLabel)null,
new Box.Filler(new Dimension(0, height), new Dimension(0, height), new Dimension(Short.MAX_VALUE, height)));
}
diff --git a/platform/platform-api/src/org/jetbrains/ide/HttpRequestHandler.java b/platform/platform-api/src/org/jetbrains/ide/HttpRequestHandler.java
index 669766ee104b..3000b49656c6 100644
--- a/platform/platform-api/src/org/jetbrains/ide/HttpRequestHandler.java
+++ b/platform/platform-api/src/org/jetbrains/ide/HttpRequestHandler.java
@@ -29,7 +29,7 @@ public abstract class HttpRequestHandler {
public static final ExtensionPointName<HttpRequestHandler> EP_NAME = ExtensionPointName.create("com.intellij.httpRequestHandler");
public boolean isSupported(@NotNull FullHttpRequest request) {
- return request.getMethod() == HttpMethod.GET || request.getMethod() == HttpMethod.HEAD;
+ return request.method() == HttpMethod.GET || request.method() == HttpMethod.HEAD;
}
public abstract boolean process(@NotNull QueryStringDecoder urlDecoder, @NotNull FullHttpRequest request, @NotNull ChannelHandlerContext context)
diff --git a/platform/platform-api/src/com/intellij/codeInsight/editorActions/TextBlockTransferable.java b/platform/platform-impl/src/com/intellij/codeInsight/editorActions/TextBlockTransferable.java
index 7d972816769c..7d972816769c 100644
--- a/platform/platform-api/src/com/intellij/codeInsight/editorActions/TextBlockTransferable.java
+++ b/platform/platform-impl/src/com/intellij/codeInsight/editorActions/TextBlockTransferable.java
diff --git a/platform/platform-api/src/com/intellij/codeInsight/editorActions/TextBlockTransferableData.java b/platform/platform-impl/src/com/intellij/codeInsight/editorActions/TextBlockTransferableData.java
index bdaf6f2ea546..bdaf6f2ea546 100644
--- a/platform/platform-api/src/com/intellij/codeInsight/editorActions/TextBlockTransferableData.java
+++ b/platform/platform-impl/src/com/intellij/codeInsight/editorActions/TextBlockTransferableData.java
diff --git a/platform/platform-impl/src/com/intellij/execution/DelayedDocumentWatcher.java b/platform/platform-impl/src/com/intellij/execution/DelayedDocumentWatcher.java
index 64aefa4c0977..b8e17ea3eded 100644
--- a/platform/platform-impl/src/com/intellij/execution/DelayedDocumentWatcher.java
+++ b/platform/platform-impl/src/com/intellij/execution/DelayedDocumentWatcher.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -115,7 +115,7 @@ public class DelayedDocumentWatcher {
public void documentChanged(DocumentEvent event) {
if (myDocumentSavingInProgress) {
/** When {@link FileDocumentManager#saveAllDocuments} is called,
- * {@link com.intellij.openapi.fileEditor.impl.TrailingSpacesStripper} can change a document.
+ * {@link com.intellij.openapi.editor.impl.TrailingSpacesStripper} can change a document.
* These needless 'documentChanged' events should be filtered out.
*/
return;
diff --git a/platform/platform-impl/src/com/intellij/help/impl/MacHelpUtil.java b/platform/platform-impl/src/com/intellij/help/impl/MacHelpUtil.java
index 90d633f0d621..a73295c90f74 100644
--- a/platform/platform-impl/src/com/intellij/help/impl/MacHelpUtil.java
+++ b/platform/platform-impl/src/com/intellij/help/impl/MacHelpUtil.java
@@ -41,7 +41,7 @@ public class MacHelpUtil {
}
static boolean isApplicable() {
- return SystemInfo.isMac && Registry.is("ide.mac.show.native.help", false) && !PlatformUtils.isCidr() && !PlatformUtils
+ return SystemInfo.isMac && Registry.is("ide.mac.show.native.help") && !PlatformUtils.isCidr() && !PlatformUtils
.isIdeaCommunity();
}
}
diff --git a/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java b/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java
index 1bbd74984fcc..c8699c083ef4 100644
--- a/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java
+++ b/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java
@@ -952,25 +952,18 @@ public class IdeEventQueue extends EventQueue {
}
private static class WindowsAltSupressor implements EventDispatcher {
-
- private boolean myPureAltWasPressed;
private boolean myWaitingForAltRelease;
- private boolean myWaiterScheduled;
-
private Robot myRobot;
@Override
public boolean dispatch(AWTEvent e) {
boolean dispatch = true;
- if (!Registry.is("actionSystem.win.suppressAlt.new") && e instanceof KeyEvent) {
+ if (e instanceof KeyEvent) {
KeyEvent ke = (KeyEvent)e;
final Component component = ke.getComponent();
- final Window window = component == null ? null : SwingUtilities.windowForComponent(component);
boolean pureAlt = ke.getKeyCode() == KeyEvent.VK_ALT && (ke.getModifiers() | InputEvent.ALT_MASK) == InputEvent.ALT_MASK;
if (!pureAlt) {
- myPureAltWasPressed = false;
myWaitingForAltRelease = false;
- myWaiterScheduled = false;
}
else {
if (ApplicationManager.getApplication() == null ||
@@ -978,28 +971,25 @@ public class IdeEventQueue extends EventQueue {
!SystemInfo.isWindows ||
!Registry.is("actionSystem.win.suppressAlt") ||
!(UISettings.getInstance().HIDE_TOOL_STRIPES || UISettings.getInstance().PRESENTATION_MODE)) {
- return !dispatch;
+ return true;
}
if (ke.getID() == KeyEvent.KEY_PRESSED) {
- myPureAltWasPressed = true;
dispatch = !myWaitingForAltRelease;
}
else if (ke.getID() == KeyEvent.KEY_RELEASED) {
if (myWaitingForAltRelease) {
- myPureAltWasPressed = false;
myWaitingForAltRelease = false;
- myWaiterScheduled = false;
dispatch = false;
}
- else {
- myWaiterScheduled = true;
+ else if (component != null) {
//noinspection SSBasedInspection
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
try {
- if (SystemInfo.isWindows || window == null || !window.isActive()) {
+ final Window window = component instanceof Window ? (Window)component : SwingUtilities.windowForComponent(component);
+ if (window == null || !window.isActive()) {
return;
}
myWaitingForAltRelease = true;
diff --git a/platform/platform-impl/src/com/intellij/ide/IdeRepaintManager.java b/platform/platform-impl/src/com/intellij/ide/IdeRepaintManager.java
index 8aa0e38c0d0d..d7118949e5de 100644
--- a/platform/platform-impl/src/com/intellij/ide/IdeRepaintManager.java
+++ b/platform/platform-impl/src/com/intellij/ide/IdeRepaintManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,13 +24,12 @@ package com.intellij.ide;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.reference.SoftReference;
-import org.jetbrains.annotations.NonNls;
+import com.intellij.util.ReflectionUtil;
import javax.swing.*;
import java.awt.*;
import java.awt.image.VolatileImage;
import java.lang.ref.WeakReference;
-import java.lang.reflect.Field;
import java.util.Map;
/**
@@ -40,7 +39,6 @@ public class IdeRepaintManager extends RepaintManager {
private static final Logger LOG = Logger.getInstance("#com.intellij.ide.HackyRepaintManager");
private Map<GraphicsConfiguration, VolatileImage> myImagesMap;
- @NonNls private static final String FAULTY_FIELD_NAME = "volatileMap";
WeakReference<JComponent> myLastComponent;
@@ -53,14 +51,7 @@ public class IdeRepaintManager extends RepaintManager {
// sync here is to avoid data race when two(!) AWT threads on startup try to compete for the single myImagesMap
private synchronized void clearLeakyImages(boolean force) {
if (myImagesMap == null) {
- try {
- Field volMapField = RepaintManager.class.getDeclaredField(FAULTY_FIELD_NAME);
- volMapField.setAccessible(true);
- myImagesMap = (Map<GraphicsConfiguration, VolatileImage>)volMapField.get(this);
- }
- catch (Exception e) {
- LOG.error(e);
- }
+ myImagesMap = ReflectionUtil.getField(RepaintManager.class, this, Map.class, "volatileMap");
}
if (force ||
@@ -90,12 +81,12 @@ public class IdeRepaintManager extends RepaintManager {
// We must keep a strong reference to the DisplayChangedListener,
// since SunDisplayChanger keeps only a WeakReference to it.
- private Object displayChangeHack;
+ private DisplayChangeHandler displayChangeHack;
{
try {
GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
- GraphicsDevice[] devices = env.getScreenDevices(); // init
+ env.getScreenDevices(); // init
Class<?> aClass = Class.forName("sun.awt.DisplayChangedListener"); // might be absent
displayChangeHack = new DisplayChangeHandler();
@@ -104,7 +95,8 @@ public class IdeRepaintManager extends RepaintManager {
.getMethod("addDisplayChangedListener", new Class[]{aClass})
.invoke(env, displayChangeHack);
}
- } catch (Throwable t) {
+ }
+ catch (Throwable t) {
if (!(t instanceof HeadlessException)) LOG.error("Cannot setup display change listener", t);
}
}
diff --git a/platform/platform-impl/src/com/intellij/ide/XmlRpcServerImpl.java b/platform/platform-impl/src/com/intellij/ide/XmlRpcServerImpl.java
index e3e1945d14f1..3b8bacee5457 100644
--- a/platform/platform-impl/src/com/intellij/ide/XmlRpcServerImpl.java
+++ b/platform/platform-impl/src/com/intellij/ide/XmlRpcServerImpl.java
@@ -59,7 +59,7 @@ public class XmlRpcServerImpl implements XmlRpcServer {
static final class XmlRpcRequestHandler extends HttpRequestHandler {
@Override
public boolean isSupported(@NotNull FullHttpRequest request) {
- return request.getMethod() == HttpMethod.POST || request.getMethod() == HttpMethod.OPTIONS;
+ return request.method() == HttpMethod.POST || request.method() == HttpMethod.OPTIONS;
}
@Override
@@ -89,7 +89,7 @@ public class XmlRpcServerImpl implements XmlRpcServer {
return false;
}
- if (request.getMethod() == HttpMethod.POST) {
+ if (request.method() == HttpMethod.POST) {
ByteBuf result;
ByteBufInputStream in = new ByteBufInputStream(request.content());
try {
@@ -116,7 +116,7 @@ public class XmlRpcServerImpl implements XmlRpcServer {
return true;
}
else if (HttpMethod.POST.name().equals(request.headers().get("Access-Control-Request-Method"))) {
- LOG.assertTrue(request.getMethod() == HttpMethod.OPTIONS);
+ LOG.assertTrue(request.method() == HttpMethod.OPTIONS);
Responses.sendOptionsResponse("POST, OPTIONS", request, context);
return true;
}
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ChooseComponentsToExportDialog.java b/platform/platform-impl/src/com/intellij/ide/actions/ChooseComponentsToExportDialog.java
index 7bbc3e0c6cba..006830479db3 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/ChooseComponentsToExportDialog.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/ChooseComponentsToExportDialog.java
@@ -33,6 +33,7 @@ import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.FieldPanel;
import com.intellij.util.Consumer;
+import com.intellij.util.containers.MultiMap;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -55,15 +56,14 @@ public class ChooseComponentsToExportDialog extends DialogWrapper {
private final boolean myShowFilePath;
private final String myDescription;
- public ChooseComponentsToExportDialog(List<ExportableComponent> components,
- Map<File, Set<ExportableComponent>> fileToComponents,
+ public ChooseComponentsToExportDialog(MultiMap<File, ExportableComponent> fileToComponents,
boolean showFilePath, final String title, String description) {
super(false);
myDescription = description;
myShowFilePath = showFilePath;
Map<ExportableComponent, ComponentElementProperties> componentToContainingListElement = new LinkedHashMap<ExportableComponent, ComponentElementProperties>();
- for (ExportableComponent component : components) {
+ for (ExportableComponent component : fileToComponents.values()) {
if (!addToExistingListElement(component, componentToContainingListElement, fileToComponents)) {
ComponentElementProperties componentElementProperties = new ComponentElementProperties();
componentElementProperties.addComponent(component);
@@ -149,14 +149,14 @@ public class ChooseComponentsToExportDialog extends DialogWrapper {
}
private static boolean addToExistingListElement(ExportableComponent component,
- Map<ExportableComponent,ComponentElementProperties> componentToContainingListElement,
- Map<File, Set<ExportableComponent>> fileToComponents) {
+ Map<ExportableComponent, ComponentElementProperties> componentToContainingListElement,
+ MultiMap<File, ExportableComponent> fileToComponents) {
final File[] exportFiles = component.getExportFiles();
File file = null;
for (File exportFile : exportFiles) {
- final Set<ExportableComponent> tiedComponents = fileToComponents.get(exportFile);
+ Collection<ExportableComponent> tiedComponents = fileToComponents.get(exportFile);
- for (final ExportableComponent tiedComponent : tiedComponents) {
+ for (ExportableComponent tiedComponent : tiedComponents) {
if (tiedComponent == component) continue;
final ComponentElementProperties elementProperties = componentToContainingListElement.get(tiedComponent);
if (elementProperties != null && !FileUtil.filesEqual(exportFile, file)) {
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ExportSettingsAction.java b/platform/platform-impl/src/com/intellij/ide/actions/ExportSettingsAction.java
index e82e22d926ea..19a6502b8add 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/ExportSettingsAction.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/ExportSettingsAction.java
@@ -35,7 +35,9 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.MultiMap;
import com.intellij.util.io.ZipUtil;
+import org.jetbrains.annotations.NotNull;
import java.io.BufferedOutputStream;
import java.io.File;
@@ -47,10 +49,18 @@ import java.util.jar.JarOutputStream;
public class ExportSettingsAction extends AnAction implements DumbAware {
public void actionPerformed(AnActionEvent e) {
Project project = getEventProject(e);
- List<ExportableComponent> exportableComponents = new ArrayList<ExportableComponent>();
- Map<File,Set<ExportableComponent>> fileToComponents = getRegisteredComponentsAndFiles(exportableComponents);
- final ChooseComponentsToExportDialog dialog = new ChooseComponentsToExportDialog(exportableComponents, fileToComponents, true,
+ ApplicationManager.getApplication().saveSettings();
+
+ MultiMap<File, ExportableComponent> fileToComponents = getExportableComponentsMap();
+ for (Iterator<File> it = fileToComponents.keySet().iterator(); it.hasNext(); ) {
+ File file = it.next();
+ if (!file.exists()) {
+ it.remove();
+ }
+ }
+
+ final ChooseComponentsToExportDialog dialog = new ChooseComponentsToExportDialog(fileToComponents, true,
IdeBundle.message("title.select.components.to.export"),
IdeBundle.message(
"prompt.please.check.all.components.to.export"));
@@ -65,8 +75,6 @@ public class ExportSettingsAction extends AnAction implements DumbAware {
ContainerUtil.addAll(exportFiles, markedComponent.getExportFiles());
}
- ApplicationManager.getApplication().saveSettings();
-
final File saveFile = dialog.getExportFile();
try {
if (saveFile.exists()) {
@@ -121,24 +129,18 @@ public class ExportSettingsAction extends AnAction implements DumbAware {
}
}
- public static Map<File, Set<ExportableComponent>> getRegisteredComponentsAndFiles(List<ExportableComponent> exportableComponents) {
- Map<File,Set<ExportableComponent>> fileToComponents = new HashMap<File, Set<ExportableComponent>>();
+ @NotNull
+ public static MultiMap<File, ExportableComponent> getExportableComponentsMap() {
+ MultiMap<File, ExportableComponent> result = MultiMap.createSet();
- final List<ExportableComponent> components = new ArrayList<ExportableComponent>(Arrays.asList(ApplicationManager.getApplication().getComponents(ExportableApplicationComponent.class)));
+ ExportableApplicationComponent[] components1 = ApplicationManager.getApplication().getComponents(ExportableApplicationComponent.class);
+ List<ExportableComponent> components2 = ServiceBean.loadServicesFromBeans(ExportableComponent.EXTENSION_POINT, ExportableComponent.class);
- components.addAll(ServiceBean.loadServicesFromBeans(ExportableComponent.EXTENSION_POINT, ExportableComponent.class));
-
- for (ExportableComponent component : components) {
- exportableComponents.add(component);
+ for (ExportableComponent component : ContainerUtil.concat(Arrays.asList(components1), components2)) {
for (File exportFile : component.getExportFiles()) {
- Set<ExportableComponent> componentsTied = fileToComponents.get(exportFile);
- if (componentsTied == null) {
- componentsTied = new HashSet<ExportableComponent>();
- fileToComponents.put(exportFile, componentsTied);
- }
- componentsTied.add(component);
+ result.putValue(exportFile, component);
}
}
- return fileToComponents;
+ return result;
}
}
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ImportSettingsAction.java b/platform/platform-impl/src/com/intellij/ide/actions/ImportSettingsAction.java
index 1e989946ab2f..f06c45e1af7a 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/ImportSettingsAction.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/ImportSettingsAction.java
@@ -36,13 +36,17 @@ import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.updateSettings.impl.UpdateSettings;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.Consumer;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.MultiMap;
import com.intellij.util.io.ZipUtil;
import java.awt.*;
import java.io.File;
import java.io.IOException;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
@@ -77,10 +81,10 @@ public class ImportSettingsAction extends AnAction implements DumbAware {
return;
}
- final ArrayList<ExportableComponent> registeredComponents = new ArrayList<ExportableComponent>();
- final Map<File, Set<ExportableComponent>> filesToComponents = ExportSettingsAction.getRegisteredComponentsAndFiles(registeredComponents);
- List<ExportableComponent> components = getComponentsStored(saveFile, registeredComponents);
- final ChooseComponentsToExportDialog dialog = new ChooseComponentsToExportDialog(components, filesToComponents, false,
+ MultiMap<File, ExportableComponent> filesToComponents = ExportSettingsAction.getExportableComponentsMap();
+ List<ExportableComponent> components = getComponentsStored(saveFile, ContainerUtil.newArrayList(filesToComponents.values()));
+ filesToComponents.values().retainAll(components);
+ final ChooseComponentsToExportDialog dialog = new ChooseComponentsToExportDialog(filesToComponents, false,
IdeBundle.message("title.select.components.to.import"),
IdeBundle.message("prompt.check.components.to.import"));
dialog.show();
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/SendFeedbackAction.java b/platform/platform-impl/src/com/intellij/ide/actions/SendFeedbackAction.java
index 40bfe41fb26f..4a72eda21a3e 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/SendFeedbackAction.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/SendFeedbackAction.java
@@ -27,17 +27,20 @@ import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.application.ex.ApplicationInfoEx;
import com.intellij.openapi.project.DumbAware;
+import com.intellij.openapi.project.Project;
import com.intellij.ui.LicensingFacade;
import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.Nullable;
import java.awt.*;
public class SendFeedbackAction extends AnAction implements DumbAware {
+ @Override
public void actionPerformed(AnActionEvent e) {
- launchBrowser();
+ launchBrowser(e.getProject());
}
- public static void launchBrowser() {
+ public static void launchBrowser(@Nullable Project project) {
final ApplicationInfoEx appInfo = ApplicationInfoEx.getInstanceEx();
boolean eap = appInfo.isEAP();
String urlTemplate = eap ? appInfo.getEAPFeedbackUrl() : appInfo.getReleaseFeedbackUrl();
@@ -47,7 +50,7 @@ public class SendFeedbackAction extends AnAction implements DumbAware {
.replace("$VERSION", appInfo.getFullVersion())
.replace("$EVAL", isEvaluationLicense() ? "true" : "false")
.replace("$DESCR", getDescription());
- BrowserUtil.browse(urlTemplate);
+ BrowserUtil.browse(urlTemplate, project);
}
private static String getDescription() {
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/SplitterActionBase.java b/platform/platform-impl/src/com/intellij/ide/actions/SplitterActionBase.java
index 851c9096a38b..dde5a5c898dd 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/SplitterActionBase.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/SplitterActionBase.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,14 +27,9 @@ public abstract class SplitterActionBase extends AnAction implements DumbAware {
public void update(final AnActionEvent event) {
final Project project = CommonDataKeys.PROJECT.getData(event.getDataContext());
final Presentation presentation = event.getPresentation();
- boolean enabled;
- if (project == null) {
- enabled = false;
- }
- else {
- enabled = isActionEnabled(project);
- }
- if (ActionPlaces.isPopupPlace(event.getPlace())) {
+ boolean inContextMenu = ActionPlaces.isPopupPlace(event.getPlace());
+ boolean enabled = project != null && isActionEnabled(project, inContextMenu);
+ if (inContextMenu) {
presentation.setVisible(enabled);
}
else {
@@ -42,7 +37,17 @@ public abstract class SplitterActionBase extends AnAction implements DumbAware {
}
}
- protected boolean isActionEnabled(Project project) {
+ /**
+ * This method determines whether the action is enabled for {@code project}
+ * if {@code inContextMenu} is set to {@code false}. Otherwise,
+ * it determines whether the action is visible in the context menu.
+ *
+ * @param project the specified project
+ * @param inContextMenu whether the action is used in context menu
+ * @return {@code true} if the action is enabled,
+ * {@code false} otherwise
+ */
+ protected boolean isActionEnabled(Project project, boolean inContextMenu) {
final FileEditorManagerEx fileEditorManager = FileEditorManagerEx.getInstanceEx(project);
return fileEditorManager.isInSplitter();
}
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java
index 4541f4664751..cb35b5a504f9 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java
@@ -1071,7 +1071,7 @@ public class Switcher extends AnAction implements DumbAware {
public void layoutContainer(Container target) {
final JScrollPane scrollPane = UIUtil.getParentOfType(JScrollPane.class, files);
JComponent filesPane = scrollPane != null ? scrollPane : files;
- if (sBounds == null) {
+ if (sBounds == null || !target.isShowing()) {
super.layoutContainer(target);
sBounds = separator.getBounds();
tBounds = toolWindows.getBounds();
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/TabsAlphabeticalModeSwitcher.java b/platform/platform-impl/src/com/intellij/ide/actions/TabsAlphabeticalModeSwitcher.java
index 8431364c5d61..7b000f530bdf 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/TabsAlphabeticalModeSwitcher.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/TabsAlphabeticalModeSwitcher.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@ package com.intellij.ide.actions;
import com.intellij.ide.ui.UISettings;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.ToggleAction;
+import com.intellij.openapi.util.registry.Registry;
import com.intellij.ui.tabs.impl.JBEditorTabs;
import javax.swing.*;
@@ -28,7 +29,7 @@ import javax.swing.*;
public class TabsAlphabeticalModeSwitcher extends ToggleAction {
@Override
public boolean isSelected(AnActionEvent e) {
- return JBEditorTabs.isAlphabeticalMode();
+ return Registry.is(JBEditorTabs.TABS_ALPHABETICAL_KEY);
}
@Override
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/UnsplitAllAction.java b/platform/platform-impl/src/com/intellij/ide/actions/UnsplitAllAction.java
index 12df75e75656..ec724884ef2d 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/UnsplitAllAction.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/UnsplitAllAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -32,8 +32,8 @@ public final class UnsplitAllAction extends SplitterActionBase {
}
@Override
- protected boolean isActionEnabled(Project project) {
+ protected boolean isActionEnabled(Project project, boolean inContextMenu) {
final FileEditorManagerEx fileEditorManager = FileEditorManagerEx.getInstanceEx(project);
- return fileEditorManager.getWindowSplitCount() > 2;
+ return inContextMenu ? fileEditorManager.getWindowSplitCount() > 2 : fileEditorManager.isInSplitter();
}
}
diff --git a/platform/platform-impl/src/com/intellij/ide/customize/CustomizeUIThemeStepPanel.java b/platform/platform-impl/src/com/intellij/ide/customize/CustomizeUIThemeStepPanel.java
index d450cf454291..1af2fb883efb 100644
--- a/platform/platform-impl/src/com/intellij/ide/customize/CustomizeUIThemeStepPanel.java
+++ b/platform/platform-impl/src/com/intellij/ide/customize/CustomizeUIThemeStepPanel.java
@@ -25,7 +25,6 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.util.IconUtil;
-import com.intellij.util.PlatformUtils;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.Nullable;
@@ -55,12 +54,12 @@ public class CustomizeUIThemeStepPanel extends AbstractCustomizeWizardStep {
myLafNames.put(DARCULA, IconLoader.getIcon("/lafs/OSXDarcula.png"));
}
else if (SystemInfo.isWindows) {
- if (PlatformUtils.isIdeaCommunity()) {
+ //if (PlatformUtils.isIdeaCommunity()) {
myLafNames.put(INTELLIJ, IconLoader.getIcon("/lafs/WindowsIntelliJ.png"));
- }
- else {
- myLafNames.put(ALLOY, IconLoader.getIcon("/lafs/WindowsAlloy.png"));
- }
+ //}
+ //else {
+ // myLafNames.put(ALLOY, IconLoader.getIcon("/lafs/WindowsAlloy.png"));
+ //}
myLafNames.put(DARCULA, IconLoader.getIcon("/lafs/WindowsDarcula.png"));
}
else {
diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/PasswordStorage.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/PasswordStorage.java
index e5b9f1530256..b1ea1332986e 100644
--- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/PasswordStorage.java
+++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/PasswordStorage.java
@@ -25,21 +25,15 @@ import org.jetbrains.annotations.Nullable;
* The interface defines basic password management operations
*/
public interface PasswordStorage {
-
/**
- * @deprecated To remove in IDEA 15. Use {@link #getPassword(Project, Class, String, ModalityState)}
- */
- @Deprecated
- @Nullable
- String getPassword(@Nullable Project project, @NotNull Class requestor, String key) throws PasswordSafeException;
-
- /**
- * Get password stored in a password safe.
- * <p/>
- * The method may be called from any thread. It may need to show a master password dialog to unlock the password database,
- * and then will use {@link Application#invokeAndWait(Runnable, ModalityState) invokeAndWait()}.
- * So make sure to pass correct {@link ModalityState} to the method to make sure the dialog is shown above all other dialog or progress
- * windows.
+ * <p>Get password stored in a password safe.</p>
+ *
+ * <p><b>NB: </b>
+ * This method may be called from the background,
+ * and it may need to ask user to enter the master password to access the database by calling
+ * {@link Application#invokeAndWait(Runnable, ModalityState) invokeAndWait()} to show a modal dialog.
+ * So make sure not to call it from the read action.
+ * Calling this method from the dispatch thread is allowed.</p>
*
* @param project the project, that is used to ask for the master password if this is the first access to password safe
* @param requestor the requestor class
@@ -49,53 +43,25 @@ public interface PasswordStorage {
* @throws IllegalStateException if the method is called from the read action.
*/
@Nullable
- String getPassword(@Nullable Project project, @NotNull Class requestor, String key,
- @Nullable ModalityState state) throws PasswordSafeException;
-
+ String getPassword(@Nullable Project project, @NotNull Class requestor, String key) throws PasswordSafeException;
/**
- * Store password in password safe
- * <p/>
- * The method may be called from any thread. It may need to show a master password dialog to unlock the password database,
- * and then will use {@link Application#invokeAndWait(Runnable, ModalityState) invokeAndWait()}.
- * So make sure to pass correct {@link ModalityState} to the method to make sure the dialog is shown above all other dialog or progress
- * windows.
+ * Remove password stored in a password safe
*
* @param project the project, that is used to ask for the master password if this is the first access to password safe
* @param requestor the requestor class
* @param key the key for the password
- * @param value the value to store
+ * @return the plugin key
* @throws PasswordSafeException if password safe cannot be accessed
*/
- void storePassword(@Nullable Project project, @NotNull Class requestor, String key, String value,
- @Nullable ModalityState modalityState) throws PasswordSafeException;
-
- /**
- * @deprecated To remove in IDEA 15. Use {@link #storePassword(Project, Class, String, String, ModalityState)}
- */
- @Deprecated
- void storePassword(@Nullable Project project, @NotNull Class requestor, String key, String value) throws PasswordSafeException;
-
- /**
- * @deprecated To remove in IDEA 15. Use {@link #removePassword(Project, Class, String, ModalityState)}
- */
- @Deprecated
void removePassword(@Nullable Project project, @NotNull Class requestor, String key) throws PasswordSafeException;
-
/**
- * Remove password stored in a password safe
- * <p/>
- * The method may be called from any thread. It may need to show a master password dialog to unlock the password database,
- * and then will use {@link Application#invokeAndWait(Runnable, ModalityState) invokeAndWait()}.
- * So make sure to pass correct {@link ModalityState} to the method to make sure the dialog is shown above all other dialog or progress
- * windows.
+ * Store password in password safe
*
* @param project the project, that is used to ask for the master password if this is the first access to password safe
* @param requestor the requestor class
* @param key the key for the password
- * @return the plugin key
+ * @param value the value to store
* @throws PasswordSafeException if password safe cannot be accessed
*/
- void removePassword(@Nullable Project project, @NotNull Class requestor, String key,
- @Nullable ModalityState modalityState) throws PasswordSafeException;
-
+ void storePassword(@Nullable Project project, @NotNull Class requestor, String key, String value) throws PasswordSafeException;
}
diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/PasswordSafeImpl.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/PasswordSafeImpl.java
index 34aee7aaad38..6d5127b376ad 100644
--- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/PasswordSafeImpl.java
+++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/PasswordSafeImpl.java
@@ -22,7 +22,6 @@ import com.intellij.ide.passwordSafe.impl.providers.masterKey.MasterKeyPasswordS
import com.intellij.ide.passwordSafe.impl.providers.masterKey.PasswordDatabase;
import com.intellij.ide.passwordSafe.impl.providers.memory.MemoryPasswordSafe;
import com.intellij.ide.passwordSafe.impl.providers.nil.NilProvider;
-import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
@@ -71,19 +70,11 @@ public class PasswordSafeImpl extends PasswordSafe {
}
@Nullable
- @Override
public String getPassword(@Nullable Project project, @NotNull Class requester, String key) throws PasswordSafeException {
- return getPassword(project, requester, key, null);
- }
-
- @Nullable
- @Override
- public String getPassword(@Nullable Project project, @NotNull Class requester, String key,
- @Nullable ModalityState modalityState) throws PasswordSafeException {
if (mySettings.getProviderType().equals(PasswordSafeSettings.ProviderType.MASTER_PASSWORD)) {
- String password = getMemoryProvider().getPassword(project, requester, key, modalityState);
+ String password = getMemoryProvider().getPassword(project, requester, key);
if (password == null) {
- password = provider().getPassword(project, requester, key, modalityState);
+ password = provider().getPassword(project, requester, key);
if (password != null) {
// cache the password in memory as well for easier access during the session
getMemoryProvider().storePassword(project, requester, key, password);
@@ -91,35 +82,21 @@ public class PasswordSafeImpl extends PasswordSafe {
}
return password;
}
- return provider().getPassword(project, requester, key, modalityState);
+ return provider().getPassword(project, requester, key);
}
- @Override
- public void removePassword(@Nullable Project project, @NotNull Class requestor, String key) throws PasswordSafeException {
- removePassword(project, requestor, key, null);
- }
-
- @Override
- public void removePassword(@Nullable Project project, @NotNull Class requester, String key,
- @Nullable ModalityState modalityState) throws PasswordSafeException {
+ public void removePassword(@Nullable Project project, @NotNull Class requester, String key) throws PasswordSafeException {
if (mySettings.getProviderType().equals(PasswordSafeSettings.ProviderType.MASTER_PASSWORD)) {
getMemoryProvider().removePassword(project, requester, key);
}
- provider().removePassword(project, requester, key, modalityState);
- }
-
- @Override
- public void storePassword(@Nullable Project project, @NotNull Class requestor, String key, String value) throws PasswordSafeException {
- storePassword(project, requestor, key, value, null);
+ provider().removePassword(project, requester, key);
}
- @Override
- public void storePassword(@Nullable Project project, @NotNull Class requester, String key, String value,
- @Nullable ModalityState modalityState) throws PasswordSafeException {
+ public void storePassword(@Nullable Project project, @NotNull Class requester, String key, String value) throws PasswordSafeException {
if (mySettings.getProviderType().equals(PasswordSafeSettings.ProviderType.MASTER_PASSWORD)) {
getMemoryProvider().storePassword(project, requester, key, value);
}
- provider().storePassword(project, requester, key, value, modalityState);
+ provider().storePassword(project, requester, key, value);
}
/**
diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/PasswordSafeProvider.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/PasswordSafeProvider.java
index 3a40d617e99b..18dee7c755f5 100644
--- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/PasswordSafeProvider.java
+++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/PasswordSafeProvider.java
@@ -15,11 +15,7 @@
*/
package com.intellij.ide.passwordSafe.impl;
-import com.intellij.ide.passwordSafe.PasswordSafeException;
import com.intellij.ide.passwordSafe.PasswordStorage;
-import com.intellij.openapi.project.Project;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
/**
* The provider for password safe component
@@ -38,21 +34,4 @@ public abstract class PasswordSafeProvider implements PasswordStorage {
* @return the name of provider
*/
public abstract String getName();
-
- @Nullable
- @Override
- public String getPassword(@Nullable Project project, @NotNull Class requestor, String key) throws PasswordSafeException {
- return getPassword(project, requestor, key, null);
- }
-
- @Override
- public void storePassword(@Nullable Project project, @NotNull Class requestor, String key, String value) throws PasswordSafeException {
- storePassword(project, requestor, key, value, null);
- }
-
- @Override
- public void removePassword(@Nullable Project project, @NotNull Class requestor, String key) throws PasswordSafeException {
- removePassword(project, requestor, key, null);
- }
-
}
diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/BasePasswordSafeProvider.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/BasePasswordSafeProvider.java
index 8c8f921f18b8..a0b001824d90 100644
--- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/BasePasswordSafeProvider.java
+++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/BasePasswordSafeProvider.java
@@ -43,15 +43,13 @@ public abstract class BasePasswordSafeProvider extends PasswordSafeProvider {
* @throws PasswordSafeException in case of problems with access to the password database.
* @throws IllegalStateException if the method is called from the read action.
*/
- protected abstract byte[] key(@Nullable Project project, @NotNull Class requestor,
- @Nullable ModalityState modalityState) throws PasswordSafeException;
+ protected abstract byte[] key(@Nullable Project project, @NotNull Class requestor) throws PasswordSafeException;
@Nullable
- public String getPassword(@Nullable Project project, @NotNull Class requestor, String key,
- @Nullable ModalityState modalityState) throws PasswordSafeException {
- byte[] k = dbKey(project, requestor, key, modalityState);
+ public String getPassword(@Nullable Project project, @NotNull Class requestor, String key) throws PasswordSafeException {
+ byte[] k = dbKey(project, requestor, key);
byte[] ct = getEncryptedPassword(k);
- return ct == null ? null : EncryptionUtil.decryptText(key(project, requestor, modalityState), ct);
+ return ct == null ? null : EncryptionUtil.decryptText(key(project, requestor), ct);
}
/**
@@ -68,17 +66,14 @@ public abstract class BasePasswordSafeProvider extends PasswordSafeProvider {
* @param project
* @param requestor the requestor class
* @param key the key to use
- * @param modalityState
* @return the key to use for map
*/
- private byte[] dbKey(@Nullable Project project, @NotNull Class requestor, String key,
- @Nullable ModalityState modalityState) throws PasswordSafeException {
- return EncryptionUtil.dbKey(key(project, requestor, modalityState), requestor, key);
+ private byte[] dbKey(@Nullable Project project, Class requestor, String key) throws PasswordSafeException {
+ return EncryptionUtil.dbKey(key(project, requestor), requestor, key);
}
- public void removePassword(@Nullable Project project, @NotNull Class requester, String key,
- @Nullable ModalityState modalityState) throws PasswordSafeException {
- byte[] k = dbKey(project, requester, key, modalityState);
+ public void removePassword(@Nullable Project project, @NotNull Class requester, String key) throws PasswordSafeException {
+ byte[] k = dbKey(project, requester, key);
removeEncryptedPassword(k);
}
@@ -89,10 +84,9 @@ public abstract class BasePasswordSafeProvider extends PasswordSafeProvider {
*/
protected abstract void removeEncryptedPassword(byte[] key);
- public void storePassword(@Nullable Project project, @NotNull Class requestor, String key, String value,
- @Nullable ModalityState modalityState) throws PasswordSafeException {
- byte[] k = dbKey(project, requestor, key, modalityState);
- byte[] ct = EncryptionUtil.encryptText(key(project, requestor, modalityState), value);
+ public void storePassword(@Nullable Project project, @NotNull Class requestor, String key, String value) throws PasswordSafeException {
+ byte[] k = dbKey(project, requestor, key);
+ byte[] ct = EncryptionUtil.encryptText(key(project, requestor), value);
storeEncryptedPassword(k, ct);
}
diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterKeyPasswordSafe.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterKeyPasswordSafe.java
index b74e51315cd5..840159270a8d 100644
--- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterKeyPasswordSafe.java
+++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterKeyPasswordSafe.java
@@ -154,8 +154,7 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider {
}
@Override
- protected byte[] key(@Nullable final Project project, @NotNull final Class requestor,
- @Nullable ModalityState modalityState) throws PasswordSafeException {
+ protected byte[] key(@Nullable final Project project, @NotNull final Class requestor) throws PasswordSafeException {
Application application = ApplicationManager.getApplication();
if (!isTestMode() && application.isHeadlessEnvironment()) {
throw new MasterPasswordUnavailableException("The provider is not available in headless environment");
@@ -200,7 +199,7 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider {
}
}
}
- }, modalityState == null ? ModalityState.defaultModalityState() : modalityState);
+ }, ModalityState.any());
//noinspection ThrowableResultOfMethodCallIgnored
if (ex.get() != null) {
throw ex.get();
@@ -211,12 +210,11 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider {
}
@Override
- public String getPassword(@Nullable Project project, @NotNull Class requestor, String key,
- @Nullable ModalityState modalityState) throws PasswordSafeException {
+ public String getPassword(@Nullable Project project, @NotNull Class requestor, String key) throws PasswordSafeException {
if (database.isEmpty()) {
return null;
}
- return super.getPassword(project, requestor, key, modalityState);
+ return super.getPassword(project, requestor, key);
}
@Override
diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/memory/MemoryPasswordSafe.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/memory/MemoryPasswordSafe.java
index da82bb986fdb..4989789b4ec0 100644
--- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/memory/MemoryPasswordSafe.java
+++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/memory/MemoryPasswordSafe.java
@@ -19,12 +19,10 @@ import com.intellij.ide.passwordSafe.impl.PasswordSafeTimed;
import com.intellij.ide.passwordSafe.impl.providers.BasePasswordSafeProvider;
import com.intellij.ide.passwordSafe.impl.providers.ByteArrayWrapper;
import com.intellij.ide.passwordSafe.impl.providers.EncryptionUtil;
-import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
import java.security.SecureRandom;
import java.util.Collections;
@@ -60,7 +58,7 @@ public class MemoryPasswordSafe extends BasePasswordSafeProvider {
}
@Override
- protected byte[] key(Project project, @NotNull Class requestor, @Nullable ModalityState modalityState) {
+ protected byte[] key(Project project, @NotNull Class requestor) {
if (key.get() == null) {
byte[] rnd = new byte[EncryptionUtil.SECRET_KEY_SIZE_BYTES * 16];
new SecureRandom().nextBytes(rnd);
diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/nil/NilProvider.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/nil/NilProvider.java
index e3a77325b06e..4bf024d697c2 100644
--- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/nil/NilProvider.java
+++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/nil/NilProvider.java
@@ -17,7 +17,6 @@ package com.intellij.ide.passwordSafe.impl.providers.nil;
import com.intellij.ide.passwordSafe.PasswordSafeException;
import com.intellij.ide.passwordSafe.impl.PasswordSafeProvider;
-import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -42,22 +41,16 @@ public final class NilProvider extends PasswordSafeProvider {
return "Do not Store";
}
- @Nullable
- public String getPassword(@Nullable Project project, @NotNull Class requester, String key,
- @Nullable ModalityState modalityState) throws PasswordSafeException {
+ public String getPassword(@Nullable Project project, @NotNull Class requester, String key) throws PasswordSafeException {
// nothing is stored
return null;
}
- @Override
- public void removePassword(@Nullable Project project, @NotNull Class requester, String key,
- @Nullable ModalityState modalityState) throws PasswordSafeException {
+ public void removePassword(@Nullable Project project, @NotNull Class requester, String key) throws PasswordSafeException {
// do nothing
}
- @Override
- public void storePassword(@Nullable Project project, @NotNull Class requester, String key, String value,
- @Nullable ModalityState modalityState) throws PasswordSafeException {
+ public void storePassword(@Nullable Project project, @NotNull Class requester, String key, String value) throws PasswordSafeException {
// just forget about password
}
}
diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/ui/PasswordSafePromptDialog.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/ui/PasswordSafePromptDialog.java
index 353e836f3f33..8aa0099ccd1d 100644
--- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/ui/PasswordSafePromptDialog.java
+++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/ui/PasswordSafePromptDialog.java
@@ -73,10 +73,7 @@ public class PasswordSafePromptDialog extends DialogWrapper {
/**
* Ask password possibly asking password database first. The method could be invoked from any thread. If UI needs to be shown,
* the method invokes {@link UIUtil#invokeAndWaitIfNeeded(Runnable)}
- *
* @param project the context project
- * @param modalityState the modality state using which any prompts initiated by the git process should be shown in the UI.
- * If null then {@link ModalityState#defaultModalityState() the default modality state} will be used.
* @param title the dialog title
* @param message the message describing a resource for which password is asked
* @param requestor the password requestor
@@ -86,13 +83,12 @@ public class PasswordSafePromptDialog extends DialogWrapper {
*/
@Nullable
public static String askPassword(final Project project,
- @Nullable ModalityState modalityState,
final String title,
final String message,
@NotNull final Class<?> requestor,
final String key,
boolean resetPassword, String error) {
- return askPassword(project, modalityState, title, message, requestor, key, resetPassword, error, null, null);
+ return askPassword(project, title, message, requestor, key, resetPassword, error, null, null);
}
/**
@@ -112,17 +108,14 @@ public class PasswordSafePromptDialog extends DialogWrapper {
@NotNull final Class<?> requestor,
final String key,
boolean resetPassword) {
- return askPassword(null, null, title, message, requestor, key, resetPassword, null);
+ return askPassword(null, title, message, requestor, key, resetPassword, null);
}
/**
* Ask passphrase possibly asking password database first. The method could be invoked from any thread. If UI needs to be shown,
* the method invokes {@link UIUtil#invokeAndWaitIfNeeded(Runnable)}
- *
* @param project the context project (might be null)
- * @param modalityState the modality state using which any prompts initiated by the git process should be shown in the UI.
- * If null then {@link ModalityState#defaultModalityState() the default modality state} will be used.
* @param title the dialog title
* @param message the message describing a resource for which password is asked
* @param requestor the password requestor
@@ -132,13 +125,13 @@ public class PasswordSafePromptDialog extends DialogWrapper {
*/
@Nullable
public static String askPassphrase(final Project project,
- @Nullable ModalityState modalityState, final String title,
+ final String title,
final String message,
@NotNull final Class<?> requestor,
final String key,
boolean resetPassword,
String error) {
- return askPassword(project, modalityState, title, message, requestor, key, resetPassword, error,
+ return askPassword(project, title, message, requestor, key, resetPassword, error,
"Passphrase:", "Remember the passphrase");
}
@@ -146,10 +139,7 @@ public class PasswordSafePromptDialog extends DialogWrapper {
/**
* Ask password possibly asking password database first. The method could be invoked from any thread. If UI needs to be shown,
* the method invokes {@link UIUtil#invokeAndWaitIfNeeded(Runnable)}
- *
* @param project the context project
- * @param modalityState the modality state using which any prompts initiated by the git process should be shown in the UI.
- * If null then {@link ModalityState#defaultModalityState() the default modality state} will be used.
* @param title the dialog title
* @param message the message describing a resource for which password is asked
* @param requestor the password requestor
@@ -161,7 +151,6 @@ public class PasswordSafePromptDialog extends DialogWrapper {
*/
@Nullable
private static String askPassword(final Project project,
- @Nullable ModalityState modalityState,
final String title,
final String message,
@NotNull final Class<?> requestor,
@@ -176,7 +165,7 @@ public class PasswordSafePromptDialog extends DialogWrapper {
ps.removePassword(project, requestor, key);
}
else {
- String pw = ps.getPassword(project, requestor, key, modalityState);
+ String pw = ps.getPassword(project, requestor, key);
if (pw != null) {
return pw;
}
@@ -214,7 +203,7 @@ public class PasswordSafePromptDialog extends DialogWrapper {
}
}
}
- }, modalityState == null ? ModalityState.defaultModalityState() : modalityState);
+ }, ModalityState.any());
return ref.get();
}
}
diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java
index 20a41e3a886a..931458ff8bc0 100644
--- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java
+++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java
@@ -161,7 +161,7 @@ public abstract class PluginManagerMain implements Disposable {
g.fillRect(0,0, getWidth(), getHeight());
}
};
- header.setBorder(new CustomLineBorder(UIUtil.getBorderColor(), 1, 1, 0, 1));
+ header.setBorder(new CustomLineBorder(1, 1, 0, 1));
final JLabel mySortLabel = new JLabel();
mySortLabel.setForeground(UIUtil.getLabelDisabledForeground());
mySortLabel.setBorder(new EmptyBorder(1, 1, 1, 5));
diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/RepositoryHelper.java b/platform/platform-impl/src/com/intellij/ide/plugins/RepositoryHelper.java
index be7aa3c8f600..ec763a8d5a76 100644
--- a/platform/platform-impl/src/com/intellij/ide/plugins/RepositoryHelper.java
+++ b/platform/platform-impl/src/com/intellij/ide/plugins/RepositoryHelper.java
@@ -68,6 +68,8 @@ public class RepositoryHelper {
HttpConfigurable.getInstance().openHttpConnection(url) :
(HttpURLConnection)new URL(url).openConnection();
connection.setRequestProperty("Accept-Encoding", "gzip");
+ connection.setReadTimeout(HttpConfigurable.CONNECTION_TIMEOUT);
+ connection.setConnectTimeout(HttpConfigurable.CONNECTION_TIMEOUT);
if (indicator != null) {
indicator.setText2(IdeBundle.message("progress.waiting.for.reply.from.plugin.manager", appInfo.getPluginManagerUrl()));
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java
index 19d924dff777..1036307e97d7 100644
--- a/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java
@@ -46,6 +46,7 @@ import com.intellij.ui.JBColor;
import com.intellij.ui.ScreenUtil;
import com.intellij.ui.content.Content;
import com.intellij.ui.mac.MacPopupMenuUI;
+import com.intellij.ui.popup.OurHeavyWeightPopup;
import com.intellij.util.IJSwingUtilities;
import com.intellij.util.ObjectUtils;
import com.intellij.util.PlatformUtils;
@@ -853,6 +854,9 @@ public final class LafManagerImpl extends LafManager implements ApplicationCompo
final Point point = fixPopupLocation(contents, x, y);
final int popupType = UIUtil.isUnderGTKLookAndFeel() ? WEIGHT_HEAVY : PopupUtil.getPopupType(this);
+ if (popupType == WEIGHT_HEAVY && OurHeavyWeightPopup.isEnabled()) {
+ return new OurHeavyWeightPopup(owner, contents, point.x, point.y);
+ }
if (popupType >= 0) {
PopupUtil.setPopupType(myDelegate, popupType);
}
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java
index a86a28a375d5..b06cd21daa60 100644
--- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java
+++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java
@@ -79,7 +79,7 @@ public class DarculaLaf extends BasicLookAndFeel {
@SuppressWarnings("UnusedParameters")
private static void log(Exception e) {
// everything is gonna be alright
- e.printStackTrace();
+// e.printStackTrace();
}
@Override
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.properties b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.properties
index 255d356d5bc0..5ddd24560338 100644
--- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.properties
+++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula.properties
@@ -48,6 +48,13 @@ MenuBar.shadow=3c3f41
MenuBar.darcula.borderColor=555555
MenuBar.darcula.borderShadowColor=282828
+CheckBoxMenuItemUI=com.intellij.ide.ui.laf.darcula.ui.DarculaCheckBoxMenuItemUI
+CheckBoxMenuItem.borderPainted=false
+
+RadioButtonMenuItemUI=com.intellij.ide.ui.laf.darcula.ui.DarculaRadioButtonMenuItemUI
+RadioButtonMenuItem.borderPainted=false
+
+
TabbedPaneUI=com.intellij.ide.ui.laf.darcula.ui.DarculaTabbedPaneUI
TabbedPane.tabInsets=0,4,0,4
TabbedPane.highlight=292b2d
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaCheckBoxMenuItemUI.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaCheckBoxMenuItemUI.java
new file mode 100644
index 000000000000..d9c4ac7895e6
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaCheckBoxMenuItemUI.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.ide.ui.laf.darcula.ui;
+
+import com.intellij.openapi.ui.GraphicsConfig;
+import com.intellij.ui.Gray;
+import com.intellij.util.ui.UIUtil;
+import sun.swing.MenuItemLayoutHelper;
+
+import javax.swing.*;
+import javax.swing.plaf.ComponentUI;
+import java.awt.*;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public class DarculaCheckBoxMenuItemUI extends DarculaMenuItemUIBase {
+
+ @SuppressWarnings({"MethodOverridesStaticMethodOfSuperclass", "UnusedDeclaration"})
+ public static ComponentUI createUI(JComponent c) {
+ return new DarculaCheckBoxMenuItemUI();
+ }
+
+ protected String getPropertyPrefix() {
+ return "CheckBoxMenuItem";
+ }
+
+ @Override
+ public Dimension getPreferredSize(JComponent c) {
+ return super.getPreferredSize(c);
+ }
+
+ @Override
+ protected void paintCheckIcon(Graphics g2, MenuItemLayoutHelper lh, MenuItemLayoutHelper.LayoutResult lr, Color holdc, Color foreground) {
+ Graphics2D g = (Graphics2D) g2;
+ final GraphicsConfig config = new GraphicsConfig(g);
+ g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+ g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_DEFAULT);
+
+ g.translate(lr.getCheckRect().x-2, lr.getCheckRect().y);
+
+ final int sz = 13;
+ g.setPaint(new GradientPaint(sz / 2, 1, Gray._110, sz / 2, sz, Gray._95));
+ g.fillRoundRect(0, 0, sz, sz - 1 , 4, 4);
+
+ g.setPaint(new GradientPaint(sz / 2, 1, Gray._120.withAlpha(0x5a), sz / 2, sz, Gray._105.withAlpha(90)));
+ g.drawRoundRect(0, (UIUtil.isUnderDarcula() ? 1 : 0), sz, sz - 1, 4, 4);
+
+ g.setPaint(Gray._40.withAlpha(180));
+ g.drawRoundRect(0, 0, sz, sz - 1, 4, 4);
+
+
+ if (lh.getMenuItem().isSelected()) {
+ g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
+ g.setStroke(new BasicStroke(2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
+ g.setPaint(Gray._30);
+ g.drawLine(4, 7, 7, 10);
+ g.drawLine(7, 10, sz, 2);
+ g.setPaint(Gray._170);
+ g.drawLine(4, 5, 7, 8);
+ g.drawLine(7, 8, sz, 0);
+ }
+
+ g.translate(-lr.getCheckRect().x+2, -lr.getCheckRect().y);
+ config.restore();
+ g.setColor(foreground);
+ }
+}
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaMenuItemUIBase.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaMenuItemUIBase.java
new file mode 100644
index 000000000000..cc69d24b6ca3
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaMenuItemUIBase.java
@@ -0,0 +1,208 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.ide.ui.laf.darcula.ui;
+
+import sun.swing.MenuItemLayoutHelper;
+import sun.swing.SwingUtilities2;
+
+import javax.swing.*;
+import javax.swing.plaf.ComponentUI;
+import javax.swing.plaf.basic.BasicMenuItemUI;
+import java.awt.*;
+import java.awt.event.MouseEvent;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public class DarculaMenuItemUIBase extends BasicMenuItemUI {
+ @SuppressWarnings({"MethodOverridesStaticMethodOfSuperclass", "UnusedDeclaration"})
+ public static ComponentUI createUI(JComponent c) {
+ return new DarculaMenuItemUIBase();
+ }
+
+ public void processMouseEvent(JMenuItem item, MouseEvent e, MenuElement path[], MenuSelectionManager manager) {
+ Point p = e.getPoint();
+ if (p.x >= 0 && p.x < item.getWidth() &&
+ p.y >= 0 && p.y < item.getHeight()) {
+ if (e.getID() == MouseEvent.MOUSE_RELEASED) {
+ manager.clearSelectedPath();
+ item.doClick(0);
+ item.setArmed(false);
+ } else
+ manager.setSelectedPath(path);
+ } else if (item.getModel().isArmed()) {
+ MenuElement newPath[] = new MenuElement[path.length - 1];
+ int i, c;
+ for (i = 0, c = path.length - 1; i < c; i++)
+ newPath[i] = path[i];
+ manager.setSelectedPath(newPath);
+ }
+ }
+
+ protected void paintMenuItem(Graphics g, JComponent c,
+ Icon checkIcon, Icon arrowIcon,
+ Color background, Color foreground,
+ int defaultTextIconGap) {
+ // Save original graphics font and color
+ Font holdf = g.getFont();
+ Color holdc = g.getColor();
+
+ JMenuItem mi = (JMenuItem) c;
+ g.setFont(mi.getFont());
+
+ Rectangle viewRect = new Rectangle(0, 0, mi.getWidth(), mi.getHeight());
+ applyInsets(viewRect, mi.getInsets());
+
+ MenuItemLayoutHelper lh = new MenuItemLayoutHelper(mi, checkIcon,
+ arrowIcon, viewRect, defaultTextIconGap, "-", //todo[kb] use protected field BasicMenuItemUI.acceleratorDelimiter when we move to java 1.7
+ mi.getComponentOrientation().isLeftToRight(), mi.getFont(),
+ acceleratorFont, MenuItemLayoutHelper.useCheckAndArrow(menuItem),
+ getPropertyPrefix());
+ MenuItemLayoutHelper.LayoutResult lr = lh.layoutMenuItem();
+
+ paintBackground(g, mi, background);
+ paintCheckIcon(g, lh, lr, holdc, foreground);
+ paintIcon(g, lh, lr, holdc);
+ g.setColor(foreground);
+ paintText(g, lh, lr);
+ paintAccText(g, lh, lr);
+ paintArrowIcon(g, lh, lr, foreground);
+
+ // Restore original graphics font and color
+ g.setColor(holdc);
+ g.setFont(holdf);
+ }
+
+ protected void paintIcon(Graphics g, MenuItemLayoutHelper lh,
+ MenuItemLayoutHelper.LayoutResult lr, Color holdc) {
+ if (lh.getIcon() != null) {
+ Icon icon;
+ ButtonModel model = lh.getMenuItem().getModel();
+ if (!model.isEnabled()) {
+ icon = lh.getMenuItem().getDisabledIcon();
+ } else if (model.isPressed() && model.isArmed()) {
+ icon = lh.getMenuItem().getPressedIcon();
+ if (icon == null) {
+ // Use default icon
+ icon = lh.getMenuItem().getIcon();
+ }
+ } else {
+ icon = lh.getMenuItem().getIcon();
+ }
+
+ if (icon != null) {
+ icon.paintIcon(lh.getMenuItem(), g, lr.getIconRect().x,
+ lr.getIconRect().y);
+ g.setColor(holdc);
+ }
+ }
+ }
+
+ protected void paintCheckIcon(Graphics g, MenuItemLayoutHelper lh,
+ MenuItemLayoutHelper.LayoutResult lr,
+ Color holdc, Color foreground) {
+ if (lh.getCheckIcon() != null) {
+ ButtonModel model = lh.getMenuItem().getModel();
+ if (model.isArmed() || (lh.getMenuItem() instanceof JMenu
+ && model.isSelected())) {
+ g.setColor(foreground);
+ } else {
+ g.setColor(holdc);
+ }
+ if (lh.useCheckAndArrow()) {
+ lh.getCheckIcon().paintIcon(lh.getMenuItem(), g,
+ lr.getCheckRect().x, lr.getCheckRect().y);
+ }
+ g.setColor(holdc);
+ }
+ }
+
+ protected void paintAccText(Graphics g, MenuItemLayoutHelper lh,
+ MenuItemLayoutHelper.LayoutResult lr) {
+ if (!lh.getAccText().equals("")) {
+ ButtonModel model = lh.getMenuItem().getModel();
+ g.setFont(lh.getAccFontMetrics().getFont());
+ if (!model.isEnabled()) {
+ // *** paint the accText disabled
+ if (disabledForeground != null) {
+ g.setColor(disabledForeground);
+ SwingUtilities2.drawString(lh.getMenuItem(), g,
+ lh.getAccText(), lr.getAccRect().x,
+ lr.getAccRect().y + lh.getAccFontMetrics().getAscent());
+ } else {
+ g.setColor(lh.getMenuItem().getBackground().brighter());
+ SwingUtilities2.drawString(lh.getMenuItem(), g,
+ lh.getAccText(), lr.getAccRect().x,
+ lr.getAccRect().y + lh.getAccFontMetrics().getAscent());
+ g.setColor(lh.getMenuItem().getBackground().darker());
+ SwingUtilities2.drawString(lh.getMenuItem(), g,
+ lh.getAccText(), lr.getAccRect().x - 1,
+ lr.getAccRect().y + lh.getFontMetrics().getAscent() - 1);
+ }
+ } else {
+ // *** paint the accText normally
+ if (model.isArmed()
+ || (lh.getMenuItem() instanceof JMenu
+ && model.isSelected())) {
+ g.setColor(acceleratorSelectionForeground);
+ } else {
+ g.setColor(acceleratorForeground);
+ }
+ SwingUtilities2.drawString(lh.getMenuItem(), g, lh.getAccText(),
+ lr.getAccRect().x, lr.getAccRect().y +
+ lh.getAccFontMetrics().getAscent());
+ }
+ }
+ }
+
+ protected void paintText(Graphics g, MenuItemLayoutHelper lh,
+ MenuItemLayoutHelper.LayoutResult lr) {
+ if (!lh.getText().equals("")) {
+ if (lh.getHtmlView() != null) {
+ // Text is HTML
+ lh.getHtmlView().paint(g, lr.getTextRect());
+ } else {
+ // Text isn't HTML
+ paintText(g, lh.getMenuItem(), lr.getTextRect(), lh.getText());
+ }
+ }
+ }
+
+ protected void paintArrowIcon(Graphics g, MenuItemLayoutHelper lh,
+ MenuItemLayoutHelper.LayoutResult lr,
+ Color foreground) {
+ if (lh.getArrowIcon() != null) {
+ ButtonModel model = lh.getMenuItem().getModel();
+ if (model.isArmed() || (lh.getMenuItem() instanceof JMenu
+ && model.isSelected())) {
+ g.setColor(foreground);
+ }
+ if (lh.useCheckAndArrow()) {
+ lh.getArrowIcon().paintIcon(lh.getMenuItem(), g,
+ lr.getArrowRect().x, lr.getArrowRect().y);
+ }
+ }
+ }
+
+ protected void applyInsets(Rectangle rect, Insets insets) {
+ if(insets != null) {
+ rect.x += insets.left;
+ rect.y += insets.top;
+ rect.width -= (insets.right + rect.x);
+ rect.height -= (insets.bottom + rect.y);
+ }
+ }
+}
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaRadioButtonMenuItemUI.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaRadioButtonMenuItemUI.java
new file mode 100644
index 000000000000..1048e5d0449b
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaRadioButtonMenuItemUI.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.ide.ui.laf.darcula.ui;
+
+import com.intellij.openapi.ui.GraphicsConfig;
+import com.intellij.ui.ColorUtil;
+import com.intellij.ui.Gray;
+import sun.swing.MenuItemLayoutHelper;
+
+import javax.swing.*;
+import javax.swing.plaf.ComponentUI;
+import java.awt.*;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public class DarculaRadioButtonMenuItemUI extends DarculaMenuItemUIBase {
+ @SuppressWarnings({"MethodOverridesStaticMethodOfSuperclass", "UnusedDeclaration"})
+ public static ComponentUI createUI(JComponent c) {
+ return new DarculaRadioButtonMenuItemUI();
+ }
+
+ protected String getPropertyPrefix() {
+ return "RadioButtonMenuItem";
+ }
+
+ @Override
+ protected void paintCheckIcon(Graphics g2, MenuItemLayoutHelper lh, MenuItemLayoutHelper.LayoutResult lr, Color holdc, Color foreground) {
+ Graphics2D g = (Graphics2D) g2;
+ final GraphicsConfig config = new GraphicsConfig(g);
+ g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+ g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_DEFAULT);
+
+ g.translate(lr.getCheckRect().x-1, lr.getCheckRect().y-1);
+
+ int rad = 5;
+
+ final int x = 0;
+ final int y = 0;
+ final int w = 13;
+ final int h = 13;
+
+ g.translate(x, y);
+
+ //setup AA for lines
+ Color bg = lh.getMenuItem().getBackground();
+ g.setPaint(new GradientPaint(0, 0, ColorUtil.shift(bg, 1.5),
+ 0, 16, ColorUtil.shift(bg, 1.2)));
+
+ g.fillOval(0, 1, w - 1, h - 1);
+
+ g.setPaint(new GradientPaint(w / 2, 1, Gray._160.withAlpha(90), w / 2, h, Gray._100.withAlpha(90)));
+ g.drawOval(0, 2, w - 1, h - 1);
+
+ g.setPaint(Gray._40.withAlpha(200));
+ g.drawOval(0, 1, w - 1, h - 1);
+
+ if (lh.getMenuItem().isSelected()) {
+ final boolean enabled = lh.getMenuItem().isEnabled();
+ g.setColor(UIManager.getColor(enabled ? "RadioButton.darcula.selectionEnabledShadowColor" : "RadioButton.darcula.selectionDisabledShadowColor"));
+ g.fillOval((w - rad)/2 , h/2 , rad, rad);
+ g.setColor(UIManager.getColor(enabled ? "RadioButton.darcula.selectionEnabledColor" : "RadioButton.darcula.selectionDisabledColor"));
+ g.fillOval((w - rad)/2 , h/2 - 1, rad, rad);
+ }
+ config.restore();
+ g.translate(-x, -y);
+
+
+ g.translate(-lr.getCheckRect().x+1, -lr.getCheckRect().y+1);
+ config.restore();
+ }
+}
diff --git a/platform/platform-impl/src/com/intellij/ide/util/ElementsChooser.java b/platform/platform-impl/src/com/intellij/ide/util/ElementsChooser.java
index 2b8a8a499621..fcbe27f5c4a5 100644
--- a/platform/platform-impl/src/com/intellij/ide/util/ElementsChooser.java
+++ b/platform/platform-impl/src/com/intellij/ide/util/ElementsChooser.java
@@ -15,383 +15,89 @@
*/
package com.intellij.ide.util;
-import com.intellij.ui.*;
-import com.intellij.ui.table.JBTable;
-import com.intellij.util.containers.ContainerUtil;
-import com.intellij.util.ui.ComponentWithEmptyText;
-import com.intellij.util.ui.StatusText;
-import com.intellij.util.ui.Table;
-import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import javax.swing.*;
-import javax.swing.event.ListSelectionListener;
-import javax.swing.table.*;
-import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.InputEvent;
-import java.awt.event.KeyEvent;
-import java.util.*;
+import javax.swing.table.TableCellRenderer;
+import java.util.ArrayList;
+import java.util.Collection;
import java.util.List;
+import java.util.Map;
/**
* @see ChooseElementsDialog
*/
-public class ElementsChooser<T> extends JPanel implements ComponentWithEmptyText, ComponentWithExpandableItems<TableCell> {
- private JBTable myTable = null;
- private MyTableModel myTableModel = null;
- private boolean myColorUnmarkedElements = true;
- private final List<ElementsMarkListener<T>> myListeners = ContainerUtil.createLockFreeCopyOnWriteList();
- private final Map<T,ElementProperties> myElementToPropertiesMap = new HashMap<T, ElementProperties>();
- private final Map<T, Boolean> myDisabledMap = new HashMap<T, Boolean>();
+public class ElementsChooser<T> extends MultiStateElementsChooser<T, Boolean> {
+ private static final BooleanMarkStateDescriptor MARK_STATE_DESCRIPTOR = new BooleanMarkStateDescriptor();
public interface ElementsMarkListener<T> {
void elementMarkChanged(T element, boolean isMarked);
}
public ElementsChooser(final boolean elementsCanBeMarked) {
- this(null, false, elementsCanBeMarked);
+ super(elementsCanBeMarked, ElementsChooser.<T>getMarkStateDescriptor());
}
public ElementsChooser(List<T> elements, boolean marked) {
- this(elements, marked, true);
- }
-
- private ElementsChooser(@Nullable List<T> elements, boolean marked, boolean elementsCanBeMarked) {
- super(new BorderLayout());
-
- myTableModel = new MyTableModel(elementsCanBeMarked);
- myTable = new Table(myTableModel);
- myTable.setShowGrid(false);
- myTable.setIntercellSpacing(new Dimension(0, 0));
- myTable.setTableHeader(null);
- myTable.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
- myTable.setColumnSelectionAllowed(false);
- JScrollPane pane = ScrollPaneFactory.createScrollPane(myTable);
- pane.setPreferredSize(new Dimension(100, 155));
- TableColumnModel columnModel = myTable.getColumnModel();
-
- if (elementsCanBeMarked) {
- TableColumn checkMarkColumn = columnModel.getColumn(myTableModel.CHECK_MARK_COLUM_INDEX);
- TableUtil.setupCheckboxColumn(checkMarkColumn);
- checkMarkColumn.setCellRenderer(new CheckMarkColumnCellRenderer(myTable.getDefaultRenderer(Boolean.class)));
- }
- columnModel.getColumn(myTableModel.ELEMENT_COLUMN_INDEX).setCellRenderer(new MyElementColumnCellRenderer());
-
- add(pane, BorderLayout.CENTER);
- myTable.registerKeyboardAction(
- new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- final int[] selectedRows = myTable.getSelectedRows();
- boolean currentlyMarked = true;
- for (int selectedRow : selectedRows) {
- currentlyMarked = myTableModel.isElementMarked(selectedRow);
- if (!currentlyMarked) {
- break;
- }
- }
- myTableModel.setMarked(selectedRows, !currentlyMarked);
- }
- },
- KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0),
- JComponent.WHEN_FOCUSED
- );
-
- final SpeedSearchBase<JBTable> speedSearch = new SpeedSearchBase<JBTable>(myTable) {
- @Override
- public int getSelectedIndex() {
- return myTable.getSelectedRow();
- }
-
- @Override
- protected int convertIndexToModel(int viewIndex) {
- return myTable.convertRowIndexToModel(viewIndex);
- }
-
- @Override
- public Object[] getAllElements() {
- final int count = myTableModel.getRowCount();
- Object[] elements = new Object[count];
- for (int idx = 0; idx < count; idx++) {
- elements[idx] = myTableModel.getElementAt(idx);
- }
- return elements;
- }
-
- @Override
- public String getElementText(Object element) {
- return getItemText((T)element);
- }
-
- @Override
- public void selectElement(Object element, String selectedText) {
- final int count = myTableModel.getRowCount();
- for (int row = 0; row < count; row++) {
- if (element.equals(myTableModel.getElementAt(row))) {
- final int viewRow = myTable.convertRowIndexToView(row);
- myTable.getSelectionModel().setSelectionInterval(viewRow, viewRow);
- TableUtil.scrollSelectionToVisible(myTable);
- break;
- }
- }
- }
- };
- speedSearch.setComparator(new SpeedSearchComparator(false));
- setElements(elements, marked);
- installActions(myTable);
- }
-
- private static void installActions(JTable table) {
- InputMap inputMap = table.getInputMap(WHEN_FOCUSED);
- inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_END, 0), "selectLastRow");
- inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_HOME, 0), "selectFirstRow");
- inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_HOME, InputEvent.SHIFT_DOWN_MASK), "selectFirstRowExtendSelection");
- inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_END, InputEvent.SHIFT_DOWN_MASK), "selectLastRowExtendSelection");
- }
-
- @NotNull
- @Override
- public StatusText getEmptyText() {
- return myTable.getEmptyText();
- }
-
- @NotNull
- @Override
- public ExpandableItemsHandler<TableCell> getExpandableItemsHandler() {
- return myTable.getExpandableItemsHandler();
- }
-
- @Override
- public void setExpandableItemsEnabled(boolean enabled) {
- myTable.setExpandableItemsEnabled(enabled);
- }
-
- public void setSingleSelectionMode() {
- myTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
- }
-
- public void refresh() {
- myTableModel.fireTableDataChanged();
- }
-
- public void refresh(T element) {
- final int row = myTableModel.getElementRow(element);
- if (row >= 0) {
- myTableModel.fireTableRowsUpdated(row, row);
- }
- }
-
- private int[] mySavedSelection = null;
- public void saveSelection() {
- mySavedSelection = myTable.getSelectedRows();
- }
-
- public void restoreSelection() {
- if (mySavedSelection != null) {
- TableUtil.selectRows(myTable, mySavedSelection);
- mySavedSelection = null;
- }
- }
-
- public boolean isColorUnmarkedElements() {
- return myColorUnmarkedElements;
- }
-
- public void setColorUnmarkedElements(boolean colorUnmarkedElements) {
- myColorUnmarkedElements = colorUnmarkedElements;
+ super(elements, marked, ElementsChooser.<T>getMarkStateDescriptor());
}
public void addElementsMarkListener(ElementsMarkListener<T> listener) {
- myListeners.add(listener);
+ addElementsMarkListener(new ElementsMarkStateListenerAdapter<T>(listener));
}
public void removeElementsMarkListener(ElementsMarkListener<T> listener) {
- myListeners.remove(listener);
- }
-
- public void addListSelectionListener(ListSelectionListener listener) {
- myTable.getSelectionModel().addListSelectionListener(listener);
- }
- public void removeListSelectionListener(ListSelectionListener listener) {
- myTable.getSelectionModel().removeListSelectionListener(listener);
+ removeElementsMarkListener(new ElementsMarkStateListenerAdapter<T>(listener));
}
public void addElement(T element, final boolean isMarked) {
- addElement(element, isMarked, element instanceof ElementProperties ? (ElementProperties)element : null);
+ addElement(element, getMarkState(isMarked));
}
/**
* Check if element is marked
+ *
* @param element an element to test
* @return true if element is marked
*/
public boolean isElementMarked(T element) {
- final int elementRow = myTableModel.getElementRow(element);
- return myTableModel.isElementMarked(elementRow);
+ return getElementMarkState(element);
}
/**
- * Check if element is marked
+ * Update element mark
+ *
* @param element an element to test
- * @param marked a new value of mark.
+ * @param marked a new value of mark.
*/
public void setElementMarked(T element, boolean marked) {
- final int elementRow = myTableModel.getElementRow(element);
- myTableModel.setMarked(elementRow, marked);
- }
-
-
- public void removeElement(T element) {
- final int elementRow = myTableModel.getElementRow(element);
- if (elementRow < 0) {
- return; // no such element
- }
- final boolean wasSelected = myTable.getSelectionModel().isSelectedIndex(elementRow);
-
- myTableModel.removeElement(element);
- myElementToPropertiesMap.remove(element);
-
- if (wasSelected) {
- final int rowCount = myTableModel.getRowCount();
- if (rowCount > 0) {
- selectRow(elementRow % rowCount);
- }
- else {
- myTable.getSelectionModel().clearSelection();
- }
- }
- myTable.requestFocus();
+ setElementMarkState(element, getMarkState(marked));
}
- public void removeAllElements() {
- myTableModel.removeAllElements();
- myTable.getSelectionModel().clearSelection();
- }
-
- private void selectRow(final int row) {
- myTable.getSelectionModel().setSelectionInterval(row, row);
- myTable.scrollRectToVisible(myTable.getCellRect(row, 0, true));
- }
-
- public void moveElement(T element, int newRow) {
- final int elementRow = myTableModel.getElementRow(element);
- if (elementRow < 0 || elementRow == newRow || newRow < 0 || newRow >= myTableModel.getRowCount()) {
- return;
- }
- final boolean wasSelected = myTable.getSelectionModel().isSelectedIndex(elementRow);
- myTableModel.changeElementRow(element, newRow);
- if (wasSelected) {
- selectRow(newRow);
- }
- }
-
- public interface ElementProperties {
- @Nullable
- Icon getIcon();
- @Nullable
- Color getColor();
- }
public void addElement(T element, final boolean isMarked, ElementProperties elementProperties) {
- myTableModel.addElement(element, isMarked);
- myElementToPropertiesMap.put(element, elementProperties);
- selectRow(myTableModel.getRowCount() - 1);
- myTable.requestFocus();
- }
-
- public void setElementProperties(T element, ElementProperties properties) {
- myElementToPropertiesMap.put(element, properties);
+ addElement(element, getMarkState(isMarked), elementProperties);
}
public void setElements(List<T> elements, boolean marked) {
- myTableModel.clear();
- myTableModel.addElements(elements, marked);
- }
-
- @Nullable
- public T getSelectedElement() {
- final int selectedRow = getSelectedElementRow();
- return selectedRow < 0? null : myTableModel.getElementAt(selectedRow);
- }
-
- public int getSelectedElementRow() {
- return myTable.getSelectedRow();
- }
-
- @NotNull
- public List<T> getSelectedElements() {
- final List<T> elements = new ArrayList<T>();
- final int[] selectedRows = myTable.getSelectedRows();
- for (int selectedRow : selectedRows) {
- if (selectedRow < 0) {
- continue;
- }
- elements.add(myTableModel.getElementAt(selectedRow));
- }
- return elements;
- }
-
- public void selectElements(Collection<? extends T> elements) {
- if (elements.isEmpty()) {
- myTable.clearSelection();
- return;
- }
- final int[] rows = getElementsRows(elements);
- TableUtil.selectRows(myTable, rows);
- TableUtil.scrollSelectionToVisible(myTable);
- myTable.requestFocus();
- }
-
- private int[] getElementsRows(final Collection<? extends T> elements) {
- final int[] rows = new int[elements.size()];
- int index = 0;
- for (final T element : elements) {
- rows[index++] = myTable.convertRowIndexToView(myTableModel.getElementRow(element));
- }
- return rows;
+ setElements(elements, getMarkState(marked));
}
public void markElements(Collection<T> elements) {
- myTableModel.setMarked(getElementsRows(elements), true);
+ markElements(elements, Boolean.TRUE);
}
@NotNull
public List<T> getMarkedElements() {
- final int count = myTableModel.getRowCount();
+ Map<T, Boolean> elementMarkStates = getElementMarkStates();
List<T> elements = new ArrayList<T>();
- for (int idx = 0; idx < count; idx++) {
- final T element = myTableModel.getElementAt(idx);
- if (myTableModel.isElementMarked(idx)) {
- elements.add(element);
+ for (Map.Entry<T, Boolean> entry : elementMarkStates.entrySet()) {
+ if (entry.getValue()) {
+ elements.add(entry.getKey());
}
}
return elements;
}
- public void sort(Comparator<T> comparator) {
- myTableModel.sort(comparator);
- }
-
- @Override
- public void setEnabled(boolean enabled) {
- super.setEnabled(enabled);
- myTable.setRowSelectionAllowed(enabled);
- myTableModel.fireTableDataChanged();
- }
-
- public void stopEditing() {
- TableCellEditor editor = myTable.getCellEditor();
- if (editor != null) {
- editor.stopCellEditing();
- }
- }
-
- public JComponent getComponent() {
- return myTable;
- }
-
public void invertSelection() {
final int count = getElementCount();
for (int i = 0; i < count; i++) {
@@ -401,264 +107,89 @@ public class ElementsChooser<T> extends JPanel implements ComponentWithEmptyText
}
public void setAllElementsMarked(boolean marked) {
- final int[] rows = new int[myTableModel.getRowCount()];
- for (int idx = 0; idx < rows.length; idx++) {
- rows[idx] = idx;
- }
- myTableModel.setMarked(rows, marked);
- }
-
- private void notifyElementMarked(T element, boolean isMarked) {
- for (ElementsMarkListener<T> listener : myListeners) {
- listener.elementMarkChanged(element, isMarked);
- }
+ setAllElementsMarked(getMarkState(marked));
}
- public void clear() {
- myTableModel.clear();
- myElementToPropertiesMap.clear();
+ private static Boolean getMarkState(boolean marked) {
+ return marked;
}
- public int getElementCount() {
- return myTableModel.getRowCount();
+ @SuppressWarnings("unchecked")
+ private static <T> MarkStateDescriptor<T, Boolean> getMarkStateDescriptor() {
+ return MARK_STATE_DESCRIPTOR;
}
- public T getElementAt(int row) {
- return myTableModel.getElementAt(row);
- }
-
- public void disableElement(T element) {
- myDisabledMap.put(element, Boolean.TRUE);
- }
-
- private final class MyTableModel extends AbstractTableModel {
- private final List<T> myElements = new ArrayList<T>();
- private final Map<T, Boolean> myMarkedMap = new HashMap<T, Boolean>();
- public final int CHECK_MARK_COLUM_INDEX;
- public final int ELEMENT_COLUMN_INDEX;
- private final boolean myElementsCanBeMarked;
-
- public MyTableModel(final boolean elementsCanBeMarked) {
- myElementsCanBeMarked = elementsCanBeMarked;
- if (elementsCanBeMarked) {
- CHECK_MARK_COLUM_INDEX = 0;
- ELEMENT_COLUMN_INDEX = 1;
- }
- else {
- CHECK_MARK_COLUM_INDEX = -1;
- ELEMENT_COLUMN_INDEX = 0;
- }
- }
-
- public void sort(Comparator<T> comparator) {
- Collections.sort(myElements, comparator);
- fireTableDataChanged();
- }
-
- public T getElementAt(int index) {
- return myElements.get(index);
- }
-
- public boolean isElementMarked(int index) {
- final T element = myElements.get(index);
- final Boolean isMarked = myMarkedMap.get(element);
- return isMarked.booleanValue();
- }
-
- private void addElement(T element, boolean isMarked) {
- myElements.add(element);
- myMarkedMap.put(element, isMarked? Boolean.TRUE : Boolean.FALSE);
- int row = myElements.size() - 1;
- fireTableRowsInserted(row, row);
- }
-
- private void addElements(@Nullable List<T> elements, boolean isMarked) {
- if (elements == null || elements.isEmpty()) {
- return;
- }
- for (final T element : elements) {
- myElements.add(element);
- myMarkedMap.put(element, isMarked ? Boolean.TRUE : Boolean.FALSE);
- }
- fireTableRowsInserted(myElements.size() - elements.size(), myElements.size() - 1);
- }
-
- public void removeElement(T element) {
- final boolean reallyRemoved = myElements.remove(element);
- if (reallyRemoved) {
- myMarkedMap.remove(element);
- fireTableDataChanged();
- }
- }
-
- public void changeElementRow(T element, int row) {
- final boolean reallyRemoved = myElements.remove(element);
- if (reallyRemoved) {
- myElements.add(row, element);
- fireTableDataChanged();
- }
- }
-
- public int getElementRow(T element) {
- return myElements.indexOf(element);
- }
-
- public void removeAllElements() {
- myElements.clear();
- fireTableDataChanged();
- }
-
- public void removeRows(int[] rows) {
- final List<T> toRemove = new ArrayList<T>();
- for (int row : rows) {
- final T element = myElements.get(row);
- toRemove.add(element);
- myMarkedMap.remove(element);
- }
- myElements.removeAll(toRemove);
- fireTableDataChanged();
- }
-
+ private static class BooleanMarkStateDescriptor<T> implements MarkStateDescriptor<T, Boolean> {
+ @NotNull
@Override
- public int getRowCount() {
- return myElements.size();
+ public Boolean getDefaultState(@NotNull T element) {
+ return Boolean.FALSE;
}
+ @NotNull
@Override
- public int getColumnCount() {
- return myElementsCanBeMarked? 2 : 1;
+ public Boolean getNextState(@NotNull T element, @NotNull Boolean state) {
+ return !state;
}
- @Override
@Nullable
- public Object getValueAt(int rowIndex, int columnIndex) {
- T element = myElements.get(rowIndex);
- if (columnIndex == ELEMENT_COLUMN_INDEX) {
- return element;
- }
- if (columnIndex == CHECK_MARK_COLUM_INDEX) {
- return myMarkedMap.get(element);
- }
- return null;
- }
-
@Override
- public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
- if (columnIndex == CHECK_MARK_COLUM_INDEX) {
- setMarked(rowIndex, ((Boolean)aValue).booleanValue());
- }
- }
-
- private void setMarked(int rowIndex, final boolean marked) {
- final T element = myElements.get(rowIndex);
- final Boolean newValue = marked? Boolean.TRUE : Boolean.FALSE;
- final Boolean prevValue = myMarkedMap.put(element, newValue);
- fireTableRowsUpdated(rowIndex, rowIndex);
- if (!newValue.equals(prevValue)) {
- notifyElementMarked(element, marked);
- }
- }
-
- private void setMarked(int[] rows, final boolean marked) {
- if (rows == null || rows.length == 0) {
- return;
- }
- int firstRow = Integer.MAX_VALUE;
- int lastRow = Integer.MIN_VALUE;
- final Boolean newValue = marked? Boolean.TRUE : Boolean.FALSE;
- for (final int row : rows) {
- final T element = myElements.get(row);
- final Boolean prevValue = myMarkedMap.put(element, newValue);
- if (!newValue.equals(prevValue)) {
- notifyElementMarked(element, newValue.booleanValue());
+ public Boolean getNextState(@NotNull Map<T, Boolean> elementsWithStates) {
+ boolean currentlyMarked = true;
+ for (Boolean state : elementsWithStates.values()) {
+ currentlyMarked = state;
+ if (!currentlyMarked) {
+ break;
}
- firstRow = Math.min(firstRow, row);
- lastRow = Math.max(lastRow, row);
}
- fireTableRowsUpdated(firstRow, lastRow);
+ return !currentlyMarked;
}
@Override
- public Class getColumnClass(int columnIndex) {
- if (columnIndex == CHECK_MARK_COLUM_INDEX) {
- return Boolean.class;
- }
- return super.getColumnClass(columnIndex);
+ public boolean isMarked(@NotNull Boolean state) {
+ return state;
}
+ @Nullable
@Override
- public boolean isCellEditable(int rowIndex, int columnIndex) {
- if (!isEnabled() || columnIndex != CHECK_MARK_COLUM_INDEX) {
- return false;
- }
- final T o = (T)getValueAt(rowIndex, ELEMENT_COLUMN_INDEX);
- return myDisabledMap.get(o) == null;
+ public Boolean getMarkState(@Nullable Object value) {
+ return value instanceof Boolean ? ((Boolean)value) : null;
}
- public void clear() {
- myElements.clear();
- myMarkedMap.clear();
- fireTableDataChanged();
+ @Nullable
+ @Override
+ public TableCellRenderer getMarkRenderer() {
+ return null;
}
}
- protected String getItemText(@NotNull T value) {
- return value.toString();
- }
+ private static class ElementsMarkStateListenerAdapter<T> implements ElementsMarkStateListener<T, Boolean> {
+ private final ElementsMarkListener<T> myListener;
- @Nullable
- protected Icon getItemIcon(@NotNull T value) {
- return null;
- }
+ public ElementsMarkStateListenerAdapter(ElementsMarkListener<T> listener) {
+ myListener = listener;
+ }
- private class MyElementColumnCellRenderer extends DefaultTableCellRenderer {
@Override
- public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
- final Color color = UIUtil.getTableFocusCellBackground();
- Component component;
- T t = (T)value;
- try {
- UIManager.put(UIUtil.TABLE_FOCUS_CELL_BACKGROUND_PROPERTY, table.getSelectionBackground());
- component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
- setText(t != null ? getItemText(t) : "");
- if (component instanceof JLabel) {
- ((JLabel)component).setBorder(noFocusBorder);
- }
- }
- finally {
- UIManager.put(UIUtil.TABLE_FOCUS_CELL_BACKGROUND_PROPERTY, color);
- }
- final MyTableModel model = (MyTableModel)table.getModel();
- component.setEnabled(ElementsChooser.this.isEnabled() && (!myColorUnmarkedElements || model.isElementMarked(row)));
- final ElementProperties properties = myElementToPropertiesMap.get(t);
- if (component instanceof JLabel) {
- final Icon icon = properties != null ? properties.getIcon() : t != null ? getItemIcon(t) : null;
- JLabel label = (JLabel)component;
- label.setIcon(icon);
- label.setDisabledIcon(icon);
- }
- component.setForeground(properties != null && properties.getColor() != null ?
- properties.getColor() :
- isSelected ? table.getSelectionForeground() : table.getForeground());
- return component;
+ public void elementMarkChanged(T element, Boolean markState) {
+ myListener.elementMarkChanged(element, markState);
}
- }
- private class CheckMarkColumnCellRenderer implements TableCellRenderer {
- private final TableCellRenderer myDelegate;
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ ElementsMarkStateListenerAdapter that = (ElementsMarkStateListenerAdapter)o;
- public CheckMarkColumnCellRenderer(TableCellRenderer delegate) {
- myDelegate = delegate;
+ if (!myListener.equals(that.myListener)) return false;
+
+ return true;
}
@Override
- public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
- Component component = myDelegate.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
- component.setEnabled(isEnabled());
- if (component instanceof JComponent) {
- ((JComponent)component).setBorder(null);
- }
- return component;
+ public int hashCode() {
+ return myListener.hashCode();
}
}
}
diff --git a/platform/platform-impl/src/com/intellij/ide/util/MultiStateElementsChooser.java b/platform/platform-impl/src/com/intellij/ide/util/MultiStateElementsChooser.java
new file mode 100644
index 000000000000..bccbd7b144ac
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/ide/util/MultiStateElementsChooser.java
@@ -0,0 +1,692 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.ide.util;
+
+import com.intellij.ui.*;
+import com.intellij.ui.table.JBTable;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.ui.ComponentWithEmptyText;
+import com.intellij.util.ui.StatusText;
+import com.intellij.util.ui.Table;
+import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import javax.swing.event.ListSelectionListener;
+import javax.swing.table.*;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+import java.util.*;
+import java.util.List;
+
+public class MultiStateElementsChooser<T, S> extends JPanel implements ComponentWithEmptyText, ComponentWithExpandableItems<TableCell> {
+ private MarkStateDescriptor<T, S> myMarkStateDescriptor;
+ private JBTable myTable = null;
+ private MyTableModel myTableModel = null;
+ private boolean myColorUnmarkedElements = true;
+ private final List<ElementsMarkStateListener<T, S>> myListeners = ContainerUtil.createLockFreeCopyOnWriteList();
+ private final Map<T,ElementProperties> myElementToPropertiesMap = new HashMap<T, ElementProperties>();
+ private final Map<T, Boolean> myDisabledMap = new HashMap<T, Boolean>();
+
+ public interface ElementsMarkStateListener<T, S> {
+ void elementMarkChanged(T element, S markState);
+ }
+
+ public interface MarkStateDescriptor<T, S> {
+ @NotNull
+ S getDefaultState(@NotNull T element);
+
+ @NotNull
+ S getNextState(@NotNull T element, @NotNull S state);
+
+ @Nullable
+ S getNextState(@NotNull Map<T, S> elementsWithStates);
+
+ boolean isMarked(@NotNull S state);
+
+ @Nullable
+ S getMarkState(@Nullable Object value);
+
+ @Nullable
+ TableCellRenderer getMarkRenderer();
+ }
+
+ public MultiStateElementsChooser(final boolean elementsCanBeMarked, MarkStateDescriptor<T, S> markStateDescriptor) {
+ this(null, null, elementsCanBeMarked, markStateDescriptor);
+ }
+
+ public MultiStateElementsChooser(List<T> elements, S markState, MarkStateDescriptor<T, S> markStateDescriptor) {
+ this(elements, markState, true, markStateDescriptor);
+ }
+
+ private MultiStateElementsChooser(@Nullable List<T> elements,
+ S markState,
+ boolean elementsCanBeMarked,
+ MarkStateDescriptor<T, S> markStateDescriptor) {
+ super(new BorderLayout());
+
+ myMarkStateDescriptor = markStateDescriptor;
+
+ myTableModel = new MyTableModel(elementsCanBeMarked);
+ myTable = new Table(myTableModel);
+ myTable.setShowGrid(false);
+ myTable.setIntercellSpacing(new Dimension(0, 0));
+ myTable.setTableHeader(null);
+ myTable.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);
+ myTable.setColumnSelectionAllowed(false);
+ JScrollPane pane = ScrollPaneFactory.createScrollPane(myTable);
+ pane.setPreferredSize(new Dimension(100, 155));
+ TableColumnModel columnModel = myTable.getColumnModel();
+
+ if (elementsCanBeMarked) {
+ TableColumn checkMarkColumn = columnModel.getColumn(myTableModel.CHECK_MARK_COLUM_INDEX);
+ TableUtil.setupCheckboxColumn(checkMarkColumn);
+ TableCellRenderer checkMarkRenderer = myMarkStateDescriptor.getMarkRenderer();
+ if (checkMarkRenderer == null) {
+ checkMarkRenderer = new CheckMarkColumnCellRenderer(myTable.getDefaultRenderer(Boolean.class));
+ }
+ checkMarkColumn.setCellRenderer(checkMarkRenderer);
+ }
+ columnModel.getColumn(myTableModel.ELEMENT_COLUMN_INDEX).setCellRenderer(new MyElementColumnCellRenderer());
+
+ add(pane, BorderLayout.CENTER);
+ myTable.registerKeyboardAction(
+ new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ final int[] selectedRows = myTable.getSelectedRows();
+ Map<T, S> selectedElements = new LinkedHashMap<T, S>(selectedRows.length);
+ for (int selectedRow : selectedRows) {
+ selectedElements.put(myTableModel.getElementAt(selectedRow), myTableModel.getElementMarkState(selectedRow));
+ }
+ S nextState = myMarkStateDescriptor.getNextState(selectedElements);
+ if (nextState != null) {
+ myTableModel.setMarkState(selectedRows, nextState);
+ }
+ }
+ },
+ KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0),
+ JComponent.WHEN_FOCUSED
+ );
+
+ final SpeedSearchBase<JBTable> speedSearch = new SpeedSearchBase<JBTable>(myTable) {
+ @Override
+ public int getSelectedIndex() {
+ return myTable.getSelectedRow();
+ }
+
+ @Override
+ protected int convertIndexToModel(int viewIndex) {
+ return myTable.convertRowIndexToModel(viewIndex);
+ }
+
+ @Override
+ public Object[] getAllElements() {
+ final int count = myTableModel.getRowCount();
+ Object[] elements = new Object[count];
+ for (int idx = 0; idx < count; idx++) {
+ elements[idx] = myTableModel.getElementAt(idx);
+ }
+ return elements;
+ }
+
+ @Override
+ public String getElementText(Object element) {
+ return getItemText((T)element);
+ }
+
+ @Override
+ public void selectElement(Object element, String selectedText) {
+ final int count = myTableModel.getRowCount();
+ for (int row = 0; row < count; row++) {
+ if (element.equals(myTableModel.getElementAt(row))) {
+ final int viewRow = myTable.convertRowIndexToView(row);
+ myTable.getSelectionModel().setSelectionInterval(viewRow, viewRow);
+ TableUtil.scrollSelectionToVisible(myTable);
+ break;
+ }
+ }
+ }
+ };
+ speedSearch.setComparator(new SpeedSearchComparator(false));
+ setElements(elements, markState);
+ installActions(myTable);
+ }
+
+ private static void installActions(JTable table) {
+ InputMap inputMap = table.getInputMap(WHEN_FOCUSED);
+ inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_END, 0), "selectLastRow");
+ inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_HOME, 0), "selectFirstRow");
+ inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_HOME, InputEvent.SHIFT_DOWN_MASK), "selectFirstRowExtendSelection");
+ inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_END, InputEvent.SHIFT_DOWN_MASK), "selectLastRowExtendSelection");
+ }
+
+ @NotNull
+ @Override
+ public StatusText getEmptyText() {
+ return myTable.getEmptyText();
+ }
+
+ @NotNull
+ @Override
+ public ExpandableItemsHandler<TableCell> getExpandableItemsHandler() {
+ return myTable.getExpandableItemsHandler();
+ }
+
+ @Override
+ public void setExpandableItemsEnabled(boolean enabled) {
+ myTable.setExpandableItemsEnabled(enabled);
+ }
+
+ public void setSingleSelectionMode() {
+ myTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+ }
+
+ public void refresh() {
+ myTableModel.fireTableDataChanged();
+ }
+
+ public void refresh(T element) {
+ final int row = myTableModel.getElementRow(element);
+ if (row >= 0) {
+ myTableModel.fireTableRowsUpdated(row, row);
+ }
+ }
+
+ private int[] mySavedSelection = null;
+ public void saveSelection() {
+ mySavedSelection = myTable.getSelectedRows();
+ }
+
+ public void restoreSelection() {
+ if (mySavedSelection != null) {
+ TableUtil.selectRows(myTable, mySavedSelection);
+ mySavedSelection = null;
+ }
+ }
+
+ public boolean isColorUnmarkedElements() {
+ return myColorUnmarkedElements;
+ }
+
+ public void setColorUnmarkedElements(boolean colorUnmarkedElements) {
+ myColorUnmarkedElements = colorUnmarkedElements;
+ }
+
+ public void addElementsMarkListener(ElementsMarkStateListener<T, S> listener) {
+ myListeners.add(listener);
+ }
+
+ public void removeElementsMarkListener(ElementsMarkStateListener<T, S> listener) {
+ myListeners.remove(listener);
+ }
+
+ public void addListSelectionListener(ListSelectionListener listener) {
+ myTable.getSelectionModel().addListSelectionListener(listener);
+ }
+ public void removeListSelectionListener(ListSelectionListener listener) {
+ myTable.getSelectionModel().removeListSelectionListener(listener);
+ }
+
+ public void addElement(T element, final S markState) {
+ addElement(element, markState, element instanceof ElementProperties ? (ElementProperties)element : null);
+ }
+
+ /**
+ * Gets element mark state
+ * @param element an element to test
+ * @return state of element
+ */
+ public S getElementMarkState(T element) {
+ final int elementRow = myTableModel.getElementRow(element);
+ return myTableModel.getElementMarkState(elementRow);
+ }
+
+ /**
+ * Update element mark state
+ * @param element an element to test
+ * @param markState a new value of mark state
+ */
+ public void setElementMarkState(T element, S markState) {
+ final int elementRow = myTableModel.getElementRow(element);
+ myTableModel.setMarkState(elementRow, markState);
+ }
+
+
+ public void removeElement(T element) {
+ final int elementRow = myTableModel.getElementRow(element);
+ if (elementRow < 0) {
+ return; // no such element
+ }
+ final boolean wasSelected = myTable.getSelectionModel().isSelectedIndex(elementRow);
+
+ myTableModel.removeElement(element);
+ myElementToPropertiesMap.remove(element);
+
+ if (wasSelected) {
+ final int rowCount = myTableModel.getRowCount();
+ if (rowCount > 0) {
+ selectRow(elementRow % rowCount);
+ }
+ else {
+ myTable.getSelectionModel().clearSelection();
+ }
+ }
+ myTable.requestFocus();
+ }
+
+ public void removeAllElements() {
+ myTableModel.removeAllElements();
+ myTable.getSelectionModel().clearSelection();
+ }
+
+ private void selectRow(final int row) {
+ myTable.getSelectionModel().setSelectionInterval(row, row);
+ myTable.scrollRectToVisible(myTable.getCellRect(row, 0, true));
+ }
+
+ public void moveElement(T element, int newRow) {
+ final int elementRow = myTableModel.getElementRow(element);
+ if (elementRow < 0 || elementRow == newRow || newRow < 0 || newRow >= myTableModel.getRowCount()) {
+ return;
+ }
+ final boolean wasSelected = myTable.getSelectionModel().isSelectedIndex(elementRow);
+ myTableModel.changeElementRow(element, newRow);
+ if (wasSelected) {
+ selectRow(newRow);
+ }
+ }
+
+ public interface ElementProperties {
+ @Nullable
+ Icon getIcon();
+ @Nullable
+ Color getColor();
+ }
+
+ public void addElement(T element, final S markState, ElementProperties elementProperties) {
+ myTableModel.addElement(element, markState);
+ myElementToPropertiesMap.put(element, elementProperties);
+ selectRow(myTableModel.getRowCount() - 1);
+ myTable.requestFocus();
+ }
+
+ public void setElementProperties(T element, ElementProperties properties) {
+ myElementToPropertiesMap.put(element, properties);
+ }
+
+ public void setElements(List<T> elements, S markState) {
+ myTableModel.clear();
+ myTableModel.addElements(elements, markState);
+ }
+
+ @Nullable
+ public T getSelectedElement() {
+ final int selectedRow = getSelectedElementRow();
+ return selectedRow < 0? null : myTableModel.getElementAt(selectedRow);
+ }
+
+ public int getSelectedElementRow() {
+ return myTable.getSelectedRow();
+ }
+
+ @NotNull
+ public List<T> getSelectedElements() {
+ final List<T> elements = new ArrayList<T>();
+ final int[] selectedRows = myTable.getSelectedRows();
+ for (int selectedRow : selectedRows) {
+ if (selectedRow < 0) {
+ continue;
+ }
+ elements.add(myTableModel.getElementAt(selectedRow));
+ }
+ return elements;
+ }
+
+ public void selectElements(Collection<? extends T> elements) {
+ if (elements.isEmpty()) {
+ myTable.clearSelection();
+ return;
+ }
+ final int[] rows = getElementsRows(elements);
+ TableUtil.selectRows(myTable, rows);
+ TableUtil.scrollSelectionToVisible(myTable);
+ myTable.requestFocus();
+ }
+
+ private int[] getElementsRows(final Collection<? extends T> elements) {
+ final int[] rows = new int[elements.size()];
+ int index = 0;
+ for (final T element : elements) {
+ rows[index++] = myTable.convertRowIndexToView(myTableModel.getElementRow(element));
+ }
+ return rows;
+ }
+
+ public void markElements(Collection<T> elements, S markState) {
+ myTableModel.setMarkState(getElementsRows(elements), markState);
+ }
+
+ @NotNull
+ public Map<T, S> getElementMarkStates() {
+ final int count = myTableModel.getRowCount();
+ Map<T, S> elements = new LinkedHashMap<T, S>();
+ for (int idx = 0; idx < count; idx++) {
+ final T element = myTableModel.getElementAt(idx);
+ elements.put(element, myTableModel.getElementMarkState(idx));
+ }
+ return elements;
+ }
+
+ public void sort(Comparator<T> comparator) {
+ myTableModel.sort(comparator);
+ }
+
+ @Override
+ public void setEnabled(boolean enabled) {
+ super.setEnabled(enabled);
+ myTable.setRowSelectionAllowed(enabled);
+ myTableModel.fireTableDataChanged();
+ }
+
+ public void stopEditing() {
+ TableCellEditor editor = myTable.getCellEditor();
+ if (editor != null) {
+ editor.stopCellEditing();
+ }
+ }
+
+ public JComponent getComponent() {
+ return myTable;
+ }
+
+ public void setAllElementsMarked(S markState) {
+ final int[] rows = new int[myTableModel.getRowCount()];
+ for (int idx = 0; idx < rows.length; idx++) {
+ rows[idx] = idx;
+ }
+ myTableModel.setMarkState(rows, markState);
+ }
+
+ private void notifyElementMarked(T element, S markState) {
+ for (ElementsMarkStateListener<T, S> listener : myListeners) {
+ listener.elementMarkChanged(element, markState);
+ }
+ }
+
+ public void clear() {
+ myTableModel.clear();
+ myElementToPropertiesMap.clear();
+ }
+
+ public int getElementCount() {
+ return myTableModel.getRowCount();
+ }
+
+ public T getElementAt(int row) {
+ return myTableModel.getElementAt(row);
+ }
+
+ public void disableElement(T element) {
+ myDisabledMap.put(element, Boolean.TRUE);
+ }
+
+ private final class MyTableModel extends AbstractTableModel {
+ private final List<T> myElements = new ArrayList<T>();
+ private final Map<T, S> myMarkedMap = new HashMap<T, S>();
+ public final int CHECK_MARK_COLUM_INDEX;
+ public final int ELEMENT_COLUMN_INDEX;
+ private final boolean myElementsCanBeMarked;
+
+ public MyTableModel(final boolean elementsCanBeMarked) {
+ myElementsCanBeMarked = elementsCanBeMarked;
+ if (elementsCanBeMarked) {
+ CHECK_MARK_COLUM_INDEX = 0;
+ ELEMENT_COLUMN_INDEX = 1;
+ }
+ else {
+ CHECK_MARK_COLUM_INDEX = -1;
+ ELEMENT_COLUMN_INDEX = 0;
+ }
+ }
+
+ public void sort(Comparator<T> comparator) {
+ Collections.sort(myElements, comparator);
+ fireTableDataChanged();
+ }
+
+ public T getElementAt(int index) {
+ return myElements.get(index);
+ }
+
+ public S getElementMarkState(int index) {
+ final T element = myElements.get(index);
+ return myMarkedMap.get(element);
+ }
+
+ private void addElement(T element, S markState) {
+ myElements.add(element);
+ myMarkedMap.put(element, notNullMarkState(element, markState));
+ int row = myElements.size() - 1;
+ fireTableRowsInserted(row, row);
+ }
+
+ private void addElements(@Nullable List<T> elements, S markState) {
+ if (elements == null || elements.isEmpty()) {
+ return;
+ }
+ for (final T element : elements) {
+ myElements.add(element);
+ myMarkedMap.put(element, notNullMarkState(element, markState));
+ }
+ fireTableRowsInserted(myElements.size() - elements.size(), myElements.size() - 1);
+ }
+
+ public void removeElement(T element) {
+ final boolean reallyRemoved = myElements.remove(element);
+ if (reallyRemoved) {
+ myMarkedMap.remove(element);
+ fireTableDataChanged();
+ }
+ }
+
+ public void changeElementRow(T element, int row) {
+ final boolean reallyRemoved = myElements.remove(element);
+ if (reallyRemoved) {
+ myElements.add(row, element);
+ fireTableDataChanged();
+ }
+ }
+
+ public int getElementRow(T element) {
+ return myElements.indexOf(element);
+ }
+
+ public void removeAllElements() {
+ myElements.clear();
+ fireTableDataChanged();
+ }
+
+ public void removeRows(int[] rows) {
+ final List<T> toRemove = new ArrayList<T>();
+ for (int row : rows) {
+ final T element = myElements.get(row);
+ toRemove.add(element);
+ myMarkedMap.remove(element);
+ }
+ myElements.removeAll(toRemove);
+ fireTableDataChanged();
+ }
+
+ @Override
+ public int getRowCount() {
+ return myElements.size();
+ }
+
+ @Override
+ public int getColumnCount() {
+ return myElementsCanBeMarked? 2 : 1;
+ }
+
+ @Override
+ @Nullable
+ public Object getValueAt(int rowIndex, int columnIndex) {
+ T element = myElements.get(rowIndex);
+ if (columnIndex == ELEMENT_COLUMN_INDEX) {
+ return element;
+ }
+ if (columnIndex == CHECK_MARK_COLUM_INDEX) {
+ return myMarkedMap.get(element);
+ }
+ return null;
+ }
+
+ @Override
+ public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
+ if (columnIndex == CHECK_MARK_COLUM_INDEX) {
+ S nextState = myMarkStateDescriptor.getMarkState(aValue);
+ if (nextState == null) {
+ T element = myTableModel.getElementAt(rowIndex);
+ S currentState = myTableModel.getElementMarkState(rowIndex);
+ nextState = myMarkStateDescriptor.getNextState(element, currentState);
+ }
+ setMarkState(rowIndex, nextState);
+ }
+ }
+
+ private void setMarkState(int rowIndex, final S markState) {
+ final T element = myElements.get(rowIndex);
+ final S newValue = notNullMarkState(element, markState);
+ final S prevValue = myMarkedMap.put(element, newValue);
+ fireTableRowsUpdated(rowIndex, rowIndex);
+ if (!newValue.equals(prevValue)) {
+ notifyElementMarked(element, newValue);
+ }
+ }
+
+ private void setMarkState(int[] rows, final S markState) {
+ if (rows == null || rows.length == 0) {
+ return;
+ }
+ int firstRow = Integer.MAX_VALUE;
+ int lastRow = Integer.MIN_VALUE;
+ for (final int row : rows) {
+ final T element = myElements.get(row);
+ final S newValue = notNullMarkState(element, markState);
+ final S prevValue = myMarkedMap.put(element, newValue);
+ if (!newValue.equals(prevValue)) {
+ notifyElementMarked(element, newValue);
+ }
+ firstRow = Math.min(firstRow, row);
+ lastRow = Math.max(lastRow, row);
+ }
+ fireTableRowsUpdated(firstRow, lastRow);
+ }
+
+ @NotNull
+ private S notNullMarkState(T element, S markState) {
+ return markState != null ? markState : myMarkStateDescriptor.getDefaultState(element);
+ }
+
+ @Override
+ public Class getColumnClass(int columnIndex) {
+ if (columnIndex == CHECK_MARK_COLUM_INDEX) {
+ return Boolean.class;
+ }
+ return super.getColumnClass(columnIndex);
+ }
+
+ @Override
+ public boolean isCellEditable(int rowIndex, int columnIndex) {
+ if (!isEnabled() || columnIndex != CHECK_MARK_COLUM_INDEX) {
+ return false;
+ }
+ final T o = (T)getValueAt(rowIndex, ELEMENT_COLUMN_INDEX);
+ return myDisabledMap.get(o) == null;
+ }
+
+ public void clear() {
+ myElements.clear();
+ myMarkedMap.clear();
+ fireTableDataChanged();
+ }
+ }
+
+ protected String getItemText(@NotNull T value) {
+ return value.toString();
+ }
+
+ @Nullable
+ protected Icon getItemIcon(@NotNull T value) {
+ return null;
+ }
+
+ private class MyElementColumnCellRenderer extends DefaultTableCellRenderer {
+ @Override
+ public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
+ final Color color = UIUtil.getTableFocusCellBackground();
+ Component component;
+ T t = (T)value;
+ try {
+ UIManager.put(UIUtil.TABLE_FOCUS_CELL_BACKGROUND_PROPERTY, table.getSelectionBackground());
+ component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
+ setText(t != null ? getItemText(t) : "");
+ if (component instanceof JLabel) {
+ ((JLabel)component).setBorder(noFocusBorder);
+ }
+ }
+ finally {
+ UIManager.put(UIUtil.TABLE_FOCUS_CELL_BACKGROUND_PROPERTY, color);
+ }
+ final MyTableModel model = (MyTableModel)table.getModel();
+ component.setEnabled(MultiStateElementsChooser.this.isEnabled() &&
+ (!myColorUnmarkedElements || myMarkStateDescriptor.isMarked(model.getElementMarkState(row))));
+ final ElementProperties properties = myElementToPropertiesMap.get(t);
+ if (component instanceof JLabel) {
+ final Icon icon = properties != null ? properties.getIcon() : t != null ? getItemIcon(t) : null;
+ JLabel label = (JLabel)component;
+ label.setIcon(icon);
+ label.setDisabledIcon(icon);
+ }
+ component.setForeground(properties != null && properties.getColor() != null ?
+ properties.getColor() :
+ isSelected ? table.getSelectionForeground() : table.getForeground());
+ return component;
+ }
+ }
+
+ private class CheckMarkColumnCellRenderer implements TableCellRenderer {
+ private final TableCellRenderer myDelegate;
+
+ public CheckMarkColumnCellRenderer(TableCellRenderer delegate) {
+ myDelegate = delegate;
+ }
+
+ @Override
+ public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
+ Component component = myDelegate.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
+ component.setEnabled(isEnabled());
+ if (component instanceof JComponent) {
+ ((JComponent)component).setBorder(null);
+ }
+ return component;
+ }
+ }
+}
diff --git a/platform/platform-impl/src/com/intellij/internal/statistic/ideSettings/IdeSettingsStatisticsUtils.java b/platform/platform-impl/src/com/intellij/internal/statistic/ideSettings/IdeSettingsStatisticsUtils.java
index 897491532833..2873ed3a222a 100644
--- a/platform/platform-impl/src/com/intellij/internal/statistic/ideSettings/IdeSettingsStatisticsUtils.java
+++ b/platform/platform-impl/src/com/intellij/internal/statistic/ideSettings/IdeSettingsStatisticsUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,12 +21,11 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.PersistentStateComponent;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.util.Function;
+import com.intellij.util.ReflectionUtil;
import com.intellij.util.containers.hash.HashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Set;
@@ -60,19 +59,11 @@ public class IdeSettingsStatisticsUtils {
@Nullable
private static Object getPropertyValue(Object componentInstance, String propertyName) {
final Class<? extends Object> componentInstanceClass = componentInstance.getClass();
- Object propertyValue = null;
- try {
- Field field = componentInstanceClass.getDeclaredField(propertyName);
- propertyValue = field.get(componentInstance);
- }
- catch (NoSuchFieldException ignored) {
- }
- catch (IllegalAccessException ignored) {
- }
+ Object propertyValue = ReflectionUtil.getField(componentInstanceClass, componentInstance, null, propertyName);
if (propertyValue == null) {
- Method method = getMethod(componentInstanceClass, "get" + StringUtil.capitalize(propertyName));
+ Method method = ReflectionUtil.getMethod(componentInstanceClass, "get" + StringUtil.capitalize(propertyName));
if (method == null) {
- method = getMethod(componentInstanceClass, "is" + StringUtil.capitalize(propertyName));
+ method = ReflectionUtil.getMethod(componentInstanceClass, "is" + StringUtil.capitalize(propertyName));
}
if (method != null) {
try {
@@ -85,16 +76,6 @@ public class IdeSettingsStatisticsUtils {
return propertyValue;
}
- @Nullable
- private static Method getMethod(@NotNull Class componentInstanceClass, @NotNull String name) {
- try {
- return componentInstanceClass.getMethod(name);
- }
- catch (NoSuchMethodException ignored) {
- }
- return null;
- }
-
private static String getUsageDescriptorKey(@NotNull String providerName, @NotNull String name, @NotNull String value) {
final String shortName = StringUtil.getShortName(providerName);
return shortName + "#" + name + "(" + value + ")";
diff --git a/platform/platform-impl/src/com/intellij/notification/impl/ui/NotificationsConfigurablePanel.java b/platform/platform-impl/src/com/intellij/notification/impl/ui/NotificationsConfigurablePanel.java
index 73af2c304beb..2d6a768a92c2 100644
--- a/platform/platform-impl/src/com/intellij/notification/impl/ui/NotificationsConfigurablePanel.java
+++ b/platform/platform-impl/src/com/intellij/notification/impl/ui/NotificationsConfigurablePanel.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@ import com.intellij.openapi.Disposable;
import com.intellij.openapi.ui.ComboBoxTableRenderer;
import com.intellij.openapi.ui.StripeTable;
import com.intellij.openapi.util.SystemInfo;
+import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.TableSpeedSearch;
import com.intellij.ui.components.JBScrollPane;
import com.intellij.util.ui.UIUtil;
@@ -30,6 +31,7 @@ import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.border.LineBorder;
import javax.swing.table.AbstractTableModel;
+import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableColumn;
import java.awt.*;
import java.awt.event.ActionEvent;
@@ -126,6 +128,22 @@ public class NotificationsConfigurablePanel extends JPanel implements Disposable
final TableColumn idColumn = getColumnModel().getColumn(ID_COLUMN);
idColumn.setPreferredWidth(200);
+ idColumn.setCellRenderer(new DefaultTableCellRenderer() {
+ @NotNull
+ @Override
+ public Component getTableCellRendererComponent(@NotNull JTable table,
+ Object value,
+ boolean isSelected,
+ boolean hasFocus,
+ int row,
+ int column) {
+ Component component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
+ if (component instanceof JComponent) {
+ ((JComponent)component).setBorder(IdeBorderFactory.createEmptyBorder(0, 4, 0, 4));
+ }
+ return component;
+ }
+ });
final TableColumn displayTypeColumn = getColumnModel().getColumn(DISPLAY_TYPE_COLUMN);
displayTypeColumn.setMaxWidth(300);
diff --git a/platform/platform-impl/src/com/intellij/openapi/application/ConfigImportHelper.java b/platform/platform-impl/src/com/intellij/openapi/application/ConfigImportHelper.java
index ed40589a7d20..8120b0644675 100644
--- a/platform/platform-impl/src/com/intellij/openapi/application/ConfigImportHelper.java
+++ b/platform/platform-impl/src/com/intellij/openapi/application/ConfigImportHelper.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,7 +22,6 @@ import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.AppUIUtil;
import com.intellij.util.PlatformUtils;
-import com.intellij.util.SystemProperties;
import com.intellij.util.ThreeState;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -423,15 +422,12 @@ public class ConfigImportHelper {
dir = dir.substring(1, dir.length() - 1);
}
if (replaceUserHome) {
- if (dir.startsWith("~\\") || dir.startsWith("~//") || StringUtil.startsWithConcatenation(dir, "~", File.separator)) {
- dir = SystemProperties.getUserHome() + dir.substring(1);
- }
+ dir = FileUtil.expandUserHome(dir);
}
return dir;
}
- public static boolean isInstallationHomeOrConfig(@NotNull final String installationHome,
- @NotNull final ConfigImportSettings settings) {
+ public static boolean isInstallationHomeOrConfig(@NotNull final String installationHome, @NotNull final ConfigImportSettings settings) {
if (new File(installationHome, OPTIONS_XML).exists()) return true;
if (new File(installationHome, CONFIG_RELATED_PATH + OPTIONS_XML).exists()) return true;
diff --git a/platform/platform-impl/src/com/intellij/openapi/application/ConfigImportSettings.java b/platform/platform-impl/src/com/intellij/openapi/application/ConfigImportSettings.java
index b0d4d3f909c2..005c006d1717 100644
--- a/platform/platform-impl/src/com/intellij/openapi/application/ConfigImportSettings.java
+++ b/platform/platform-impl/src/com/intellij/openapi/application/ConfigImportSettings.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,8 +15,7 @@
*/
package com.intellij.openapi.application;
-import com.intellij.openapi.util.SystemInfo;
-import com.intellij.util.SystemProperties;
+import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.ThreeState;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -74,10 +73,7 @@ public class ConfigImportSettings {
}
protected String getAutoImportLabel(File guessedOldConfig) {
- String path = guessedOldConfig.getAbsolutePath();
- if (SystemInfo.isUnix) {
- path = path.replace(SystemProperties.getUserHome(), "~");
- }
+ String path = FileUtil.getLocationRelativeToUserHome(guessedOldConfig.getAbsolutePath());
return ApplicationBundle.message("radio.import.auto", path);
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/command/impl/UndoManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/command/impl/UndoManagerImpl.java
index bf7fe9c9652f..9f43164cf9d4 100644
--- a/platform/platform-impl/src/com/intellij/openapi/command/impl/UndoManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/command/impl/UndoManagerImpl.java
@@ -20,7 +20,6 @@ import com.intellij.ide.DataManager;
import com.intellij.idea.ActionsBundle;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.CommonDataKeys;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.*;
@@ -96,11 +95,11 @@ public class UndoManagerImpl extends UndoManager implements ProjectComponent, Ap
}
public static int getGlobalUndoLimit() {
- return Registry.intValue("undo.globalUndoLimit", 10);
+ return Registry.intValue("undo.globalUndoLimit");
}
public static int getDocumentUndoLimit() {
- return Registry.intValue("undo.documentUndoLimit", 100);
+ return Registry.intValue("undo.documentUndoLimit");
}
public UndoManagerImpl(Application application, CommandProcessor commandProcessor) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/actions/CompareClipboardWithSelection.java b/platform/platform-impl/src/com/intellij/openapi/diff/actions/CompareClipboardWithSelection.java
index a916d9e5bb34..372b14efcfe6 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/actions/CompareClipboardWithSelection.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/actions/CompareClipboardWithSelection.java
@@ -73,8 +73,9 @@ public class CompareClipboardWithSelection extends BaseDiffAction {
SelectionModel selectionModel = myEditor.getSelectionModel();
if (selectionModel.hasSelection()) {
TextRange range = new TextRange(selectionModel.getSelectionStart(), selectionModel.getSelectionEnd());
+ boolean forceReadOnly = myEditor.isViewer();
myContents[1] = new FragmentContent(DiffContent.fromDocument(getProject(), getDocument()),
- range, getProject(), getDocumentFile(getDocument()));
+ range, getProject(), getDocumentFile(getDocument()), forceReadOnly);
}
else {
myContents [1] = DiffContent.fromDocument(getProject(), getDocument());
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/ex/DiffPanelOptions.java b/platform/platform-impl/src/com/intellij/openapi/diff/ex/DiffPanelOptions.java
index 538058d2d190..ec7a316357e2 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/ex/DiffPanelOptions.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/ex/DiffPanelOptions.java
@@ -23,6 +23,8 @@ import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.DialogWrapperDialog;
import com.intellij.openapi.util.Disposer;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.awt.*;
@@ -56,25 +58,26 @@ public class DiffPanelOptions {
myShowSourcePolicy = showSourcePolicy;
}
- public void showSource(OpenFileDescriptor descriptor) {
+ public void showSource(@Nullable OpenFileDescriptor descriptor) {
+ if (descriptor == null || myDiffPanel.getProject() == null) return;
myShowSourcePolicy.showSource(descriptor, myDiffPanel);
}
public interface ShowSourcePolicy {
- void showSource(OpenFileDescriptor descriptor, DiffPanelImpl diffPanel);
+ void showSource(@NotNull OpenFileDescriptor descriptor, @NotNull DiffPanelImpl diffPanel);
ShowSourcePolicy DONT_SHOW = new ShowSourcePolicy() {
- public void showSource(OpenFileDescriptor descriptor, DiffPanelImpl diffPanel) {}
+ public void showSource(@NotNull OpenFileDescriptor descriptor, @NotNull DiffPanelImpl diffPanel) {}
};
ShowSourcePolicy OPEN_EDITOR = new ShowSourcePolicy() {
- public void showSource(OpenFileDescriptor descriptor, DiffPanelImpl diffPanel) {
+ public void showSource(@NotNull OpenFileDescriptor descriptor, @NotNull DiffPanelImpl diffPanel) {
FileEditorManager.getInstance(diffPanel.getProject()).openTextEditor(descriptor, true);
}
};
ShowSourcePolicy OPEN_EDITOR_AND_CLOSE_DIFF = new ShowSourcePolicy() {
- public void showSource(OpenFileDescriptor descriptor, DiffPanelImpl diffPanel) {
+ public void showSource(@NotNull OpenFileDescriptor descriptor, @NotNull DiffPanelImpl diffPanel) {
OPEN_EDITOR.showSource(descriptor, diffPanel);
if (diffPanel.getOwnerWindow() == null) return;
Disposer.dispose(diffPanel);
@@ -97,7 +100,7 @@ public class DiffPanelOptions {
};
ShowSourcePolicy DEFAULT = new ShowSourcePolicy() {
- public void showSource(OpenFileDescriptor descriptor, DiffPanelImpl diffPanel) {
+ public void showSource(@NotNull OpenFileDescriptor descriptor, @NotNull DiffPanelImpl diffPanel) {
Window window = diffPanel.getOwnerWindow();
if (window == null) return;
else if (window instanceof Frame) OPEN_EDITOR.showSource(descriptor, diffPanel);
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java
index 5f169146145c..8ea3242d9361 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java
@@ -73,7 +73,6 @@ import com.intellij.util.LineSeparator;
import com.intellij.util.containers.CacheOneStepIterator;
import com.intellij.util.diff.FilesTooBigForDiffException;
import com.intellij.util.ui.PlatformColors;
-import com.intellij.util.ui.UIUtil;
import gnu.trove.TIntFunction;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -160,8 +159,8 @@ public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSid
myOwnerWindow = owner;
myIsSyncScroll = true;
final boolean v = !horizontal;
- myLeftSide = new DiffSideView(this, new CustomLineBorder(UIUtil.getBorderColor(), 1, 0, v ? 0 : 1, v ? 0 : 1));
- myRightSide = new DiffSideView(this, new CustomLineBorder(UIUtil.getBorderColor(), v ? 0 : 1, v ? 0 : 1, 1, 0));
+ myLeftSide = new DiffSideView(this, new CustomLineBorder(1, 0, v ? 0 : 1, v ? 0 : 1));
+ myRightSide = new DiffSideView(this, new CustomLineBorder(v ? 0 : 1, v ? 0 : 1, 1, 0));
myLeftSide.becomeMaster();
myDiffUpdater = new Rediffers(this);
@@ -298,13 +297,11 @@ public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSid
myData.setContents(content1, content2);
Project project = myData.getProject();
FileType[] types = DiffUtil.chooseContentTypes(new DiffContent[]{content1, content2});
- VirtualFile baseFile = content1.getFile();
- if (baseFile == null && myDiffRequest != null) {
- String path = myDiffRequest.getWindowTitle();
- if (path != null) baseFile = LocalFileSystem.getInstance().findFileByPath(path);
- }
- myLeftSide.setHighlighterFactory(createHighlighter(types[0], baseFile, project));
- myRightSide.setHighlighterFactory(createHighlighter(types[1], baseFile, project));
+ VirtualFile beforeFile = content1.getFile();
+ VirtualFile afterFile = content2.getFile();
+ String path = myDiffRequest == null ? null : myDiffRequest.getWindowTitle();
+ myLeftSide.setHighlighterFactory(createHighlighter(types[0], beforeFile, afterFile, path, project));
+ myRightSide.setHighlighterFactory(createHighlighter(types[1], afterFile, beforeFile, path, project));
setSplitterProportion(content1, content2);
rediff();
if (myIsRequestFocus) {
@@ -344,8 +341,16 @@ public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSid
}
}
// todo pay attention here
- private static DiffHighlighterFactory createHighlighter(FileType contentType, VirtualFile file, Project project) {
- return new DiffHighlighterFactoryImpl(contentType, file, project);
+ private static DiffHighlighterFactory createHighlighter(FileType contentType,
+ VirtualFile file,
+ VirtualFile otherFile,
+ String path,
+ Project project) {
+ VirtualFile baseFile = file;
+ if (baseFile == null) baseFile = otherFile;
+ if (baseFile == null && path != null) baseFile = LocalFileSystem.getInstance().findFileByPath(path);
+
+ return new DiffHighlighterFactoryImpl(contentType, baseFile, project);
}
void rediff() {
@@ -607,7 +612,7 @@ public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSid
return myData.getProject();
}
- public void showSource(OpenFileDescriptor descriptor) {
+ public void showSource(@Nullable OpenFileDescriptor descriptor) {
myOptions.showSource(descriptor);
}
@@ -1004,10 +1009,7 @@ public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSid
@Override
public void navigate(boolean requestFocus) {
- final OpenFileDescriptor descriptor = mySide.getCurrentOpenFileDescriptor();
- if (descriptor != null) {
- showSource(descriptor);
- }
+ showSource(mySide.getCurrentOpenFileDescriptor());
}
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffSplitter.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffSplitter.java
index 5f4507dcfad3..4b6a289d476e 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffSplitter.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffSplitter.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@ import com.intellij.openapi.diff.impl.highlighting.DiffPanelState;
import com.intellij.openapi.diff.impl.splitter.DiffDividerPaint;
import com.intellij.openapi.editor.event.VisibleAreaEvent;
import com.intellij.openapi.editor.event.VisibleAreaListener;
+import com.intellij.openapi.ui.Divider;
import com.intellij.openapi.ui.Splitter;
import javax.swing.*;
@@ -43,8 +44,8 @@ class DiffSplitter extends Splitter implements DiffSplitterI {
setHonorComponentsMinimumSize(false);
}
- protected Splitter.Divider createDivider() {
- return new Divider(){
+ protected Divider createDivider() {
+ return new DividerImpl(){
public void paint(Graphics g) {
super.paint(g);
myPaint.paint(g, this);
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ui/MergePanel2.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ui/MergePanel2.java
index 10362cc8b304..cbad541fe129 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ui/MergePanel2.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ui/MergePanel2.java
@@ -27,9 +27,7 @@ import com.intellij.openapi.diff.*;
import com.intellij.openapi.diff.actions.NextDiffAction;
import com.intellij.openapi.diff.actions.PreviousDiffAction;
import com.intellij.openapi.diff.actions.ToggleAutoScrollAction;
-import com.intellij.openapi.diff.impl.DiffUtil;
-import com.intellij.openapi.diff.impl.EditingSides;
-import com.intellij.openapi.diff.impl.GenericDataProvider;
+import com.intellij.openapi.diff.impl.*;
import com.intellij.openapi.diff.impl.highlighting.FragmentSide;
import com.intellij.openapi.diff.impl.incrementalMerge.ChangeCounter;
import com.intellij.openapi.diff.impl.incrementalMerge.ChangeList;
@@ -49,16 +47,20 @@ import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.editor.ex.EditorMarkupModel;
+import com.intellij.openapi.editor.highlighter.EditorHighlighter;
import com.intellij.openapi.editor.highlighter.EditorHighlighterFactory;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.FileTypes;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogBuilder;
+import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.LabeledComponent;
+import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.EditorNotificationPanel;
-import com.intellij.util.diff.FilesTooBigForDiffException;
+import com.intellij.util.containers.Convertor;
import gnu.trove.TIntHashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -141,9 +143,6 @@ public class MergePanel2 implements DiffViewer {
private DiffRequest.ToolbarAddons createToolbar() {
return new DiffRequest.ToolbarAddons() {
public void customize(DiffToolbar toolbar) {
- ActionManager actionManager = ActionManager.getInstance();
- toolbar.addAction(actionManager.getAction(IdeActions.ACTION_COPY));
- toolbar.addAction(actionManager.getAction(IdeActions.ACTION_FIND));
toolbar.addAction(PreviousDiffAction.find());
toolbar.addAction(NextDiffAction.find());
toolbar.addSeparator();
@@ -235,6 +234,8 @@ public class MergePanel2 implements DiffViewer {
Editor base = getEditor(1);
Editor right = getEditor(2);
+ setupHighlighterSettings(left, base, right);
+
myMergeList.setMarkups(left, base, right);
EditingSides[] sides = {getFirstEditingSide(), getSecondEditingSide()};
myScrollSupport.install(sides);
@@ -271,6 +272,37 @@ public class MergePanel2 implements DiffViewer {
return myScrollSupport.isEnabled();
}
+ private void setupHighlighterSettings(Editor left, Editor base, Editor right) {
+ Editor[] editors = new Editor[]{left, base, right};
+ DiffContent[] contents = myData.getContents();
+ FileType[] types = DiffUtil.chooseContentTypes(contents);
+
+ VirtualFile fallbackFile = contents[1].getFile();
+ FileType fallbackType = contents[1].getContentType();
+
+ for (int i = 0; i < 3; i++) {
+ Editor editor = editors[i];
+ DiffContent content = contents[i];
+
+ EditorHighlighter highlighter =
+ createHighlighter(types[i], content.getFile(), fallbackFile, fallbackType, myData.getProject()).createHighlighter();
+ if (highlighter != null) {
+ ((EditorEx)editor).setHighlighter(highlighter);
+ }
+ }
+ }
+
+ private static DiffHighlighterFactory createHighlighter(FileType contentType,
+ VirtualFile file,
+ VirtualFile otherFile,
+ FileType otherType,
+ Project project) {
+ if (file == null) file = otherFile;
+ if (contentType == null) contentType = otherType;
+
+ return new DiffHighlighterFactoryImpl(contentType, file, project);
+ }
+
public void setHighlighterSettings(@Nullable EditorColorsScheme settings) {
for (EditorPlace place : getEditorPlaces()) {
setHighlighterSettings(settings, place);
@@ -337,7 +369,20 @@ public class MergePanel2 implements DiffViewer {
data.customizeToolbar(myPanel.resetToolbar());
myPanel.registerToolbarActions();
if ( data instanceof MergeRequestImpl && myBuilder != null){
- ((MergeRequestImpl)data).setActions(myBuilder, this);
+ Convertor<DialogWrapper, Boolean> preOkHook = new Convertor<DialogWrapper, Boolean>() {
+ @Override
+ public Boolean convert(DialogWrapper dialog) {
+ ChangeCounter counter = ChangeCounter.getOrCreate(myMergeList);
+ int changes = counter.getChangeCounter();
+ int conflicts = counter.getConflictCounter();
+ if (changes == 0 && conflicts == 0) return true;
+ return Messages.showYesNoDialog(dialog.getRootPane(),
+ DiffBundle.message("merge.dialog.apply.partially.resolved.changes.confirmation.message", changes, conflicts),
+ DiffBundle.message("apply.partially.resolved.merge.dialog.title"),
+ Messages.getQuestionIcon()) == Messages.YES;
+ }
+ };
+ ((MergeRequestImpl)data).setActions(myBuilder, this, preOkHook);
}
}
finally {
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/DiffRequestFactoryImpl.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/DiffRequestFactoryImpl.java
index 3b13543e6972..962a0712465b 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/DiffRequestFactoryImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/DiffRequestFactoryImpl.java
@@ -20,6 +20,7 @@ import com.intellij.openapi.diff.DiffRequestFactory;
import com.intellij.openapi.diff.MergeRequest;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
@@ -27,11 +28,11 @@ import org.jetbrains.annotations.Nullable;
public class DiffRequestFactoryImpl extends DiffRequestFactory {
- public MergeRequest createMergeRequest(String leftText,
- String rightText,
- String originalContent,
+ public MergeRequest createMergeRequest(@NotNull String leftText,
+ @NotNull String rightText,
+ @NotNull String originalContent,
@NotNull VirtualFile file,
- Project project,
+ @Nullable Project project,
@Nullable final ActionButtonPresentation okButtonPresentation,
@Nullable final ActionButtonPresentation cancelButtonPresentation) {
final Document document = FileDocumentManager.getInstance().getDocument(file);
@@ -41,16 +42,26 @@ public class DiffRequestFactoryImpl extends DiffRequestFactory {
cancelButtonPresentation);
}
else {
- return create3WayDiffRequest(leftText, rightText, originalContent, project, okButtonPresentation, cancelButtonPresentation);
+ return create3WayDiffRequest(leftText, rightText, originalContent, file.getFileType(), project, okButtonPresentation, cancelButtonPresentation);
}
}
- public MergeRequest create3WayDiffRequest(final String leftText,
- final String rightText,
- final String originalContent,
- final Project project,
+ public MergeRequest create3WayDiffRequest(@NotNull String leftText,
+ @NotNull String rightText,
+ @NotNull String originalContent,
+ @Nullable FileType type,
+ @Nullable Project project,
@Nullable final ActionButtonPresentation okButtonPresentation,
@Nullable final ActionButtonPresentation cancelButtonPresentation) {
- return new MergeRequestImpl(leftText, originalContent, rightText, project, okButtonPresentation, cancelButtonPresentation);
+ return new MergeRequestImpl(leftText, originalContent, rightText, type, project, okButtonPresentation, cancelButtonPresentation);
+ }
+
+ public MergeRequest create3WayDiffRequest(@NotNull String leftText,
+ @NotNull String rightText,
+ @NotNull String originalContent,
+ @Nullable Project project,
+ @Nullable final ActionButtonPresentation okButtonPresentation,
+ @Nullable final ActionButtonPresentation cancelButtonPresentation) {
+ return create3WayDiffRequest(leftText, rightText, originalContent, null, project, okButtonPresentation, cancelButtonPresentation);
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/MergeRequestImpl.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/MergeRequestImpl.java
index 3b1385eb7a59..938c1ee7a42d 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/MergeRequestImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/MergeRequestImpl.java
@@ -28,6 +28,7 @@ import com.intellij.openapi.ui.DialogBuilder;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.containers.Convertor;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -46,39 +47,51 @@ public class MergeRequestImpl extends MergeRequest {
@Nullable private final ActionButtonPresentation myOkButtonPresentation;
@Nullable private final ActionButtonPresentation myCancelButtonPresentation;
- public MergeRequestImpl(String left,
- MergeVersion base,
- String right,
- Project project,
+ public MergeRequestImpl(@NotNull String left,
+ @NotNull MergeVersion base,
+ @NotNull String right,
+ @Nullable Project project,
@Nullable final ActionButtonPresentation okButtonPresentation,
@Nullable final ActionButtonPresentation cancelButtonPresentation) {
this(new SimpleContent(left), new MergeContent(base, project), new SimpleContent(right), project, okButtonPresentation,
cancelButtonPresentation);
}
- public MergeRequestImpl(DiffContent left,
- MergeVersion base,
- DiffContent right,
- Project project,
+ public MergeRequestImpl(@NotNull DiffContent left,
+ @NotNull MergeVersion base,
+ @NotNull DiffContent right,
+ @Nullable Project project,
@Nullable final ActionButtonPresentation okButtonPresentation,
@Nullable final ActionButtonPresentation cancelButtonPresentation) {
this(left, new MergeContent(base, project), right, project, okButtonPresentation, cancelButtonPresentation);
}
- public MergeRequestImpl(String left,
- String base,
- String right,
- Project project,
+ public MergeRequestImpl(@NotNull String left,
+ @NotNull String base,
+ @NotNull String right,
+ @Nullable Project project,
@Nullable final ActionButtonPresentation okButtonPresentation,
@Nullable final ActionButtonPresentation cancelButtonPresentation) {
- this(new SimpleContent(left), new SimpleContent(base), new SimpleContent(right), project, okButtonPresentation,
- cancelButtonPresentation);
+ this(left, base, right, null, project, okButtonPresentation, cancelButtonPresentation);
}
- private MergeRequestImpl(DiffContent left,
- DiffContent base,
- DiffContent right,
- Project project,
+ public MergeRequestImpl(@NotNull String left,
+ @NotNull String base,
+ @NotNull String right,
+ @Nullable FileType type,
+ @Nullable Project project,
+ @Nullable final ActionButtonPresentation okButtonPresentation,
+ @Nullable final ActionButtonPresentation cancelButtonPresentation) {
+ this(new SimpleContent(left, type),
+ new SimpleContent(base, type),
+ new SimpleContent(right, type),
+ project, okButtonPresentation, cancelButtonPresentation);
+ }
+
+ private MergeRequestImpl(@NotNull DiffContent left,
+ @NotNull DiffContent base,
+ @NotNull DiffContent right,
+ @Nullable Project project,
@Nullable final ActionButtonPresentation okButtonPresentation,
@Nullable final ActionButtonPresentation cancelButtonPresentation) {
super(project);
@@ -176,6 +189,10 @@ public class MergeRequestImpl extends MergeRequest {
}
public void setActions(final DialogBuilder builder, MergePanel2 mergePanel) {
+ setActions(builder, mergePanel, null);
+ }
+
+ public void setActions(final DialogBuilder builder, MergePanel2 mergePanel, final Convertor<DialogWrapper, Boolean> preOkHook) {
builder.removeAllActions(); // otherwise dialog will get default actions (OK, Cancel)
if (myOkButtonPresentation != null) {
@@ -187,6 +204,7 @@ public class MergeRequestImpl extends MergeRequest {
builder.setOkOperation(new Runnable() {
@Override
public void run() {
+ if (preOkHook != null && !preOkHook.convert(builder.getDialogWrapper())) return;
myOkButtonPresentation.run(builder.getDialogWrapper());
}
});
@@ -221,11 +239,11 @@ public class MergeRequestImpl extends MergeRequest {
}
public static class MergeContent extends DiffContent {
- private final MergeVersion myTarget;
+ @NotNull private final MergeVersion myTarget;
private final Document myWorkingDocument;
private final Project myProject;
- public MergeContent(MergeVersion target, Project project) {
+ public MergeContent(@NotNull MergeVersion target, Project project) {
myTarget = target;
myProject = project;
myWorkingDocument = myTarget.createWorkingDocument(project);
diff --git a/platform/platform-api/src/com/intellij/openapi/editor/CaretStateTransferableData.java b/platform/platform-impl/src/com/intellij/openapi/editor/CaretStateTransferableData.java
index f0d2085cbb6b..f0d2085cbb6b 100644
--- a/platform/platform-api/src/com/intellij/openapi/editor/CaretStateTransferableData.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/CaretStateTransferableData.java
diff --git a/platform/platform-api/src/com/intellij/openapi/editor/ClipboardTextPerCaretSplitter.java b/platform/platform-impl/src/com/intellij/openapi/editor/ClipboardTextPerCaretSplitter.java
index a3e62412f4a4..a3e62412f4a4 100644
--- a/platform/platform-api/src/com/intellij/openapi/editor/ClipboardTextPerCaretSplitter.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/ClipboardTextPerCaretSplitter.java
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretAbove.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretAbove.java
index f8b3cf7bc83a..c42cd6533e1c 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretAbove.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretAbove.java
@@ -15,31 +15,10 @@
*/
package com.intellij.openapi.editor.actions;
-import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.editor.Caret;
-import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.EditorAction;
-import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
-import org.jetbrains.annotations.NotNull;
public class CloneCaretAbove extends EditorAction {
public CloneCaretAbove() {
- super(new Handler());
- }
-
- private static class Handler extends EditorActionHandler {
- public Handler() {
- super(true);
- }
-
- @Override
- public void doExecute(Editor editor, @NotNull Caret caret, DataContext dataContext) {
- caret.clone(true);
- }
-
- @Override
- public boolean isEnabled(Editor editor, DataContext dataContext) {
- return editor.getCaretModel().supportsMultipleCarets();
- }
+ super(new CloneCaretActionHandler(true));
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretActionHandler.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretActionHandler.java
new file mode 100644
index 000000000000..5c5528a38153
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretActionHandler.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.editor.actions;
+
+import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.actionSystem.IdeActions;
+import com.intellij.openapi.editor.Caret;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.EditorLastActionTracker;
+import com.intellij.openapi.editor.ScrollType;
+import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
+import com.intellij.openapi.util.Key;
+import com.intellij.util.containers.HashSet;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+
+public class CloneCaretActionHandler extends EditorActionHandler {
+ private static final Key<Integer> LEVEL = Key.create("CloneCaretActionHandler.level");
+
+ private static final Set<String> OUR_ACTIONS = new HashSet<String>(Arrays.asList(
+ IdeActions.ACTION_EDITOR_CLONE_CARET_ABOVE,
+ IdeActions.ACTION_EDITOR_CLONE_CARET_BELOW,
+ IdeActions.ACTION_EDITOR_MOVE_CARET_LEFT_WITH_SELECTION,
+ IdeActions.ACTION_EDITOR_MOVE_CARET_RIGHT_WITH_SELECTION
+ ));
+
+ private final boolean myCloneAbove;
+
+ public CloneCaretActionHandler(boolean above) {
+ myCloneAbove = above;
+ }
+
+ @Override
+ public boolean isEnabled(Editor editor, DataContext dataContext) {
+ return editor.getCaretModel().supportsMultipleCarets();
+ }
+
+ @Override
+ protected void doExecute(Editor editor, @Nullable Caret targetCaret, DataContext dataContext) {
+ if (targetCaret != null) {
+ targetCaret.clone(myCloneAbove);
+ return;
+ }
+ int currentLevel = 0;
+ List<Caret> currentCarets = new ArrayList<Caret>();
+ for (Caret caret : editor.getCaretModel().getAllCarets()) {
+ int level = getLevel(caret);
+ if (Math.abs(level) > Math.abs(currentLevel)) {
+ currentLevel = level;
+ currentCarets.clear();
+ }
+ if (Math.abs(level) == Math.abs(currentLevel)) {
+ currentCarets.add(caret);
+ }
+ }
+ boolean removeCarets = currentLevel > 0 && myCloneAbove || currentLevel < 0 && !myCloneAbove;
+ Integer newLevel = myCloneAbove ? currentLevel - 1 : currentLevel + 1;
+ for (Caret caret : currentCarets) {
+ if (removeCarets) {
+ editor.getCaretModel().removeCaret(caret);
+ }
+ else {
+ Caret clone = caret;
+ do {
+ Caret original = clone;
+ clone = clone.clone(myCloneAbove);
+ if (original != caret) {
+ editor.getCaretModel().removeCaret(original);
+ }
+ } while (clone != null && caret.hasSelection() && !clone.hasSelection());
+ if (clone != null) {
+ clone.putUserData(LEVEL, newLevel);
+ }
+ }
+ }
+ if (removeCarets) {
+ editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
+ }
+ }
+
+ private static int getLevel(Caret caret) {
+ if (isRepeatedActionInvocation()) {
+ Integer value = caret.getUserData(LEVEL);
+ return value == null ? 0 : value;
+ }
+ else {
+ caret.putUserData(LEVEL, null);
+ return 0;
+ }
+ }
+
+ private static boolean isRepeatedActionInvocation() {
+ String lastActionId = EditorLastActionTracker.getInstance().getLastActionId();
+ return OUR_ACTIONS.contains(lastActionId);
+ }
+}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretBelow.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretBelow.java
index 17d17708b900..974087796e08 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretBelow.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretBelow.java
@@ -15,35 +15,10 @@
*/
package com.intellij.openapi.editor.actions;
-import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.editor.Caret;
-import com.intellij.openapi.editor.CaretModel;
-import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.EditorAction;
-import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
-import org.jetbrains.annotations.NotNull;
public class CloneCaretBelow extends EditorAction {
public CloneCaretBelow() {
- super(new Handler());
- }
-
- private static class Handler extends EditorActionHandler {
- public Handler() {
- super(true);
- }
-
- @Override
- public void doExecute(Editor editor, @NotNull Caret caret, DataContext dataContext) {
- CaretModel caretModel = editor.getCaretModel();
- if (caretModel.supportsMultipleCarets()) {
- caret.clone(false);
- }
- }
-
- @Override
- public boolean isEnabled(Editor editor, DataContext dataContext) {
- return editor.getCaretModel().supportsMultipleCarets();
- }
+ super(new CloneCaretActionHandler(false));
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java
index cfd039a5d504..c769f92fff78 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java
@@ -62,7 +62,13 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
private int myVisualLineEnd;
private RangeMarker savedBeforeBulkCaretMarker;
private boolean mySkipChangeRequests;
+ /**
+ * Initial horizontal caret position during vertical navigation.
+ * Similar to {@link #myDesiredX}, but represents logical caret position (<code>getLogicalPosition().column</code>) rather than visual.
+ */
private int myLastColumnNumber = 0;
+ private int myDesiredSelectionStartColumn = -1;
+ private int myDesiredSelectionEndColumn = -1;
/**
* We check that caret is located at the target offset at the end of {@link #moveToOffset(int, boolean)} method. However,
* it's possible that the following situation occurs:
@@ -82,11 +88,10 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
*/
private boolean myReportCaretMoves;
/**
- * There is a possible case that user defined non-monospaced font for editor. That means that various symbols have different
- * visual widths. That means that if we move caret vertically it may deviate to the left/right. However, we can try to preserve
- * its initial visual position when possible.
+ * This field holds initial horizontal caret position during vertical navigation. It's used to determine target position when
+ * moving to the new line. It is stored in pixels, not in columns, to account for non-monospaced fonts as well.
* <p/>
- * This field holds desired value for visual <code>'x'</code> caret coordinate (negative value if no coordinate should be preserved).
+ * Negative value means no coordinate should be preserved.
*/
private int myDesiredX = -1;
@@ -255,10 +260,11 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
EditorSettings editorSettings = myEditor.getSettings();
VisualPosition visualCaret = getVisualPosition();
+ int lastColumnNumber = myLastColumnNumber;
int desiredX = myDesiredX;
if (columnShift == 0) {
if (myDesiredX < 0) {
- desiredX = myEditor.visualPositionToXY(visualCaret).x;
+ desiredX = getCurrentX();
}
}
else {
@@ -267,15 +273,12 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
int newLineNumber = visualCaret.line + lineShift;
int newColumnNumber = visualCaret.column + columnShift;
- if (desiredX >= 0 && !ApplicationManager.getApplication().isUnitTestMode()) {
+ if (desiredX >= 0) {
newColumnNumber = myEditor.xyToVisualPosition(new Point(desiredX, Math.max(0, newLineNumber) * myEditor.getLineHeight())).column;
}
Document document = myEditor.getDocument();
- if (!editorSettings.isVirtualSpace() && columnShift == 0 && getLogicalPosition().softWrapLinesOnCurrentLogicalLine <= 0) {
- newColumnNumber = supportsMultipleCarets() ? myLastColumnNumber : myEditor.getLastColumnNumber();
- }
- else if (!editorSettings.isVirtualSpace() && lineShift == 0 && columnShift == 1) {
+ if (!editorSettings.isVirtualSpace() && lineShift == 0 && columnShift == 1) {
int lastLine = document.getLineCount() - 1;
if (lastLine < 0) lastLine = 0;
if (EditorModificationUtil.calcAfterLineEnd(myEditor) >= 0 &&
@@ -303,18 +306,21 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
// We want to move caret to the first column if it's already located at the first line and 'Up' is pressed.
newColumnNumber = 0;
desiredX = -1;
+ lastColumnNumber = -1;
}
VisualPosition pos = new VisualPosition(newLineNumber, newColumnNumber);
- int lastColumnNumber = newColumnNumber;
if (!myEditor.getSoftWrapModel().isInsideSoftWrap(pos)) {
LogicalPosition log = myEditor.visualToLogicalPosition(new VisualPosition(newLineNumber, newColumnNumber));
int offset = myEditor.logicalPositionToOffset(log);
if (offset >= document.getTextLength()) {
int lastOffsetColumn = myEditor.offsetToVisualPosition(document.getTextLength()).column;
// We want to move caret to the last column if if it's located at the last line and 'Down' is pressed.
- newColumnNumber = lastColumnNumber = Math.max(lastOffsetColumn, newColumnNumber);
- desiredX = -1;
+ if (lastOffsetColumn > newColumnNumber) {
+ newColumnNumber = lastOffsetColumn;
+ desiredX = -1;
+ lastColumnNumber = -1;
+ }
}
if (!editorSettings.isCaretInsideTabs()) {
CharSequence text = document.getCharsSequence();
@@ -353,7 +359,7 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
}
else {
moveToVisualPosition(pos);
- if (!editorSettings.isVirtualSpace() && columnShift == 0) {
+ if (!editorSettings.isVirtualSpace() && columnShift == 0 && lastColumnNumber >=0) {
setLastColumnNumber(lastColumnNumber);
}
}
@@ -550,6 +556,7 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
}
setLastColumnNumber(myLogicalCaret.column);
+ myDesiredSelectionStartColumn = myDesiredSelectionEndColumn = -1;
myVisibleCaret = myEditor.logicalToVisualPosition(myLogicalCaret);
updateOffsetsFromLogicalPosition();
@@ -705,7 +712,8 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
myEditor.getFoldingModel().flushCaretPosition();
- setLastColumnNumber(column);
+ setLastColumnNumber(myLogicalCaret.column);
+ myDesiredSelectionStartColumn = myDesiredSelectionEndColumn = -1;
myEditor.updateCaretCursor();
requestRepaint(oldInfo);
@@ -962,6 +970,8 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
clone.myLastColumnNumber = this.myLastColumnNumber;
clone.myReportCaretMoves = this.myReportCaretMoves;
clone.myDesiredX = this.myDesiredX;
+ clone.myDesiredSelectionStartColumn = -1;
+ clone.myDesiredSelectionEndColumn = -1;
return clone;
}
@@ -971,10 +981,10 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
assertIsDispatchThread();
int lineShift = above ? -1 : 1;
final CaretImpl clone = cloneWithoutSelection();
- final int newSelectionStartOffset, newSelectionEndOffset;
+ final int newSelectionStartOffset, newSelectionEndOffset, newSelectionStartColumn, newSelectionEndColumn;
final VisualPosition newSelectionStartPosition, newSelectionEndPosition;
final boolean hasNewSelection;
- if (hasSelection()) {
+ if (hasSelection() || myDesiredSelectionStartColumn >=0 || myDesiredSelectionEndColumn >= 0) {
VisualPosition startPosition = getSelectionStartPosition();
VisualPosition endPosition = getSelectionEndPosition();
VisualPosition leadPosition = getLeadSelectionPosition();
@@ -982,8 +992,10 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
boolean leadIsEnd = leadPosition.equals(endPosition);
LogicalPosition selectionStart = myEditor.visualToLogicalPosition(leadIsStart || leadIsEnd ? leadPosition : startPosition);
LogicalPosition selectionEnd = myEditor.visualToLogicalPosition(leadIsEnd ? startPosition : endPosition);
- LogicalPosition newSelectionStart = truncate(new LogicalPosition(selectionStart.line + lineShift, selectionStart.column));
- LogicalPosition newSelectionEnd = truncate(new LogicalPosition(selectionEnd.line + lineShift, selectionEnd.column));
+ newSelectionStartColumn = myDesiredSelectionStartColumn < 0 ? selectionStart.column : myDesiredSelectionStartColumn;
+ newSelectionEndColumn = myDesiredSelectionEndColumn < 0 ? selectionEnd.column : myDesiredSelectionEndColumn;
+ LogicalPosition newSelectionStart = truncate(selectionStart.line + lineShift, newSelectionStartColumn);
+ LogicalPosition newSelectionEnd = truncate(selectionEnd.line + lineShift, newSelectionEndColumn);
newSelectionStartOffset = myEditor.logicalPositionToOffset(newSelectionStart);
newSelectionEndOffset = myEditor.logicalPositionToOffset(newSelectionEnd);
newSelectionStartPosition = myEditor.logicalToVisualPosition(newSelectionStart);
@@ -996,6 +1008,8 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
newSelectionStartPosition = null;
newSelectionEndPosition = null;
hasNewSelection = false;
+ newSelectionStartColumn = -1;
+ newSelectionEndColumn = -1;
}
LogicalPosition oldPosition = getLogicalPosition();
int newLine = oldPosition.line + lineShift;
@@ -1003,7 +1017,12 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
Disposer.dispose(clone);
return null;
}
- clone.moveToLogicalPosition(new LogicalPosition(newLine, oldPosition.column), false, null, false);
+ clone.moveToLogicalPosition(new LogicalPosition(newLine, myLastColumnNumber), false, null, false);
+ clone.myLastColumnNumber = myLastColumnNumber;
+ clone.myDesiredX = myDesiredX >= 0 ? myDesiredX : getCurrentX();
+ clone.myDesiredSelectionStartColumn = newSelectionStartColumn;
+ clone.myDesiredSelectionEndColumn = newSelectionEndColumn;
+
if (myEditor.getCaretModel().addCaret(clone)) {
if (hasNewSelection) {
myEditor.getCaretModel().doWithCaretMerging(new Runnable() {
@@ -1025,15 +1044,15 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
}
}
- private LogicalPosition truncate(LogicalPosition position) {
- if (position.line < 0) {
+ private LogicalPosition truncate(int line, int column) {
+ if (line < 0) {
return new LogicalPosition(0, 0);
}
- else if (position.line >= myEditor.getDocument().getLineCount()) {
+ else if (line >= myEditor.getDocument().getLineCount()) {
return myEditor.offsetToLogicalPosition(myEditor.getDocument().getTextLength());
}
else {
- return position;
+ return new LogicalPosition(line, column);
}
}
@@ -1396,9 +1415,8 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
}
try {
- EditorActionHandler handler = EditorActionManager.getInstance().getActionHandler(
- IdeActions.ACTION_EDITOR_SELECT_WORD_AT_CARET);
- handler.execute(myEditor, myEditor.getDataContext());
+ EditorActionHandler handler = EditorActionManager.getInstance().getActionHandler(IdeActions.ACTION_EDITOR_SELECT_WORD_AT_CARET);
+ handler.execute(myEditor, CaretImpl.this, myEditor.getDataContext());
}
finally {
if (needOverrideSetting) {
@@ -1453,6 +1471,10 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
return marker != null && marker.isValid() && isVirtualSelectionEnabled() && myEndVirtualOffset > myStartVirtualOffset;
}
+ private int getCurrentX() {
+ return myEditor.visualPositionToXY(myVisibleCaret).x;
+ }
+
@Override
@NotNull
public EditorImpl getEditor() {
diff --git a/platform/platform-api/src/com/intellij/openapi/editor/CopyPasteSupport.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorCopyPasteHelperImpl.java
index 7095080aa13d..c26c7e99ba63 100644
--- a/platform/platform-api/src/com/intellij/openapi/editor/CopyPasteSupport.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorCopyPasteHelperImpl.java
@@ -13,16 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.intellij.openapi.editor;
+package com.intellij.openapi.editor.impl;
import com.intellij.codeInsight.editorActions.TextBlockTransferable;
import com.intellij.codeInsight.editorActions.TextBlockTransferableData;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.*;
import com.intellij.openapi.ide.CopyPasteManager;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.LineTokenizer;
-import com.intellij.util.Producer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -36,12 +36,11 @@ import java.util.Collection;
import java.util.Iterator;
import java.util.List;
-public class CopyPasteSupport {
- private static final Logger LOG = Logger.getInstance(CopyPasteSupport.class);
+public class EditorCopyPasteHelperImpl extends EditorCopyPasteHelper {
+ private static final Logger LOG = Logger.getInstance(EditorCopyPasteHelperImpl.class);
- private CopyPasteSupport() { }
-
- public static void copySelectionToClipboard(@NotNull Editor editor) {
+ @Override
+ public void copySelectionToClipboard(@NotNull Editor editor) {
ApplicationManager.getApplication().assertIsDispatchThread();
List<TextBlockTransferableData> extraData = new ArrayList<TextBlockTransferableData>();
String s = editor.getCaretModel().supportsMultipleCarets() ? getSelectedTextForClipboard(editor, extraData)
@@ -73,25 +72,22 @@ public class CopyPasteSupport {
return buf.toString();
}
-
- public static TextRange pasteFromClipboard(Editor editor) {
- return pasteTransferable(editor, (Producer<Transferable>)null);
- }
-
- public static TextRange pasteTransferable(Editor editor, final Transferable content) {
- return pasteTransferable(editor, new Producer<Transferable>() {
- @Nullable
- @Override
- public Transferable produce() {
- return content;
+ @Nullable
+ @Override
+ public TextRange[] pasteFromClipboard(@NotNull Editor editor) {
+ CopyPasteManager manager = CopyPasteManager.getInstance();
+ if (manager.areDataFlavorsAvailable(DataFlavor.stringFlavor)) {
+ Transferable clipboardContents = manager.getContents();
+ if (clipboardContents != null) {
+ return pasteTransferable(editor, clipboardContents);
}
- });
+ }
+ return null;
}
@Nullable
- public static TextRange pasteTransferable(final Editor editor, @Nullable Producer<Transferable> producer) {
- Transferable content = getTransferable(producer);
- if (content == null) return null;
+ @Override
+ public TextRange[] pasteTransferable(final @NotNull Editor editor, @NotNull Transferable content) {
String text = getStringContent(content);
if (text == null) return null;
@@ -117,69 +113,25 @@ public class CopyPasteSupport {
catch (Exception e) {
LOG.error(e);
}
+ final TextRange[] ranges = new TextRange[caretCount];
final Iterator<String> segments = new ClipboardTextPerCaretSplitter().split(text, caretData, caretCount).iterator();
+ final int[] index = {0};
editor.getCaretModel().runForEachCaret(new CaretAction() {
@Override
public void perform(Caret caret) {
- EditorModificationUtil.insertStringAtCaret(editor, segments.next(), false, true);
+ String segment = segments.next();
+ int caretOffset = caret.getOffset();
+ ranges[index[0]++] = new TextRange(caretOffset, caretOffset + segment.length());
+ EditorModificationUtil.insertStringAtCaret(editor, segment, false, true);
}
});
- return null;
+ return ranges;
}
else {
int caretOffset = editor.getCaretModel().getOffset();
EditorModificationUtil.insertStringAtCaret(editor, text, false, true);
- return new TextRange(caretOffset, caretOffset + text.length());
- }
- }
-
- public static void pasteTransferableAsBlock(Editor editor, @Nullable Producer<Transferable> producer) {
- Transferable content = getTransferable(producer);
- if (content == null) return;
- String text = getStringContent(content);
- if (text == null) return;
-
- int caretLine = editor.getCaretModel().getLogicalPosition().line;
- int originalCaretLine = caretLine;
- int selectedLinesCount = 0;
-
- final SelectionModel selectionModel = editor.getSelectionModel();
- if (selectionModel.hasBlockSelection()) {
- final LogicalPosition start = selectionModel.getBlockStart();
- final LogicalPosition end = selectionModel.getBlockEnd();
- assert start != null;
- assert end != null;
- LogicalPosition caret = new LogicalPosition(Math.min(start.line, end.line), Math.min(start.column, end.column));
- selectedLinesCount = Math.abs(end.line - start.line);
- caretLine = caret.line;
-
- EditorModificationUtil.deleteSelectedText(editor);
- editor.getCaretModel().moveToLogicalPosition(caret);
+ return new TextRange[] { new TextRange(caretOffset, caretOffset + text.length())};
}
-
- LogicalPosition caretToRestore = editor.getCaretModel().getLogicalPosition();
-
- String[] lines = LineTokenizer.tokenize(text.toCharArray(), false);
- if (lines.length > 1 || selectedLinesCount == 0) {
- int longestLineLength = 0;
- for (int i = 0; i < lines.length; i++) {
- String line = lines[i];
- longestLineLength = Math.max(longestLineLength, line.length());
- editor.getCaretModel().moveToLogicalPosition(new LogicalPosition(caretLine + i, caretToRestore.column));
- EditorModificationUtil.insertStringAtCaret(editor, line, false, true);
- }
- caretToRestore = new LogicalPosition(originalCaretLine, caretToRestore.column + longestLineLength);
- }
- else {
- for (int i = 0; i <= selectedLinesCount; i++) {
- editor.getCaretModel().moveToLogicalPosition(new LogicalPosition(caretLine + i, caretToRestore.column));
- EditorModificationUtil.insertStringAtCaret(editor, text, false, true);
- }
- caretToRestore = new LogicalPosition(originalCaretLine, caretToRestore.column + text.length());
- }
-
- editor.getCaretModel().moveToLogicalPosition(caretToRestore);
- EditorModificationUtil.zeroWidthBlockSelectionAtCaretColumn(editor, caretLine, caretLine + selectedLinesCount);
}
@Nullable
@@ -195,18 +147,4 @@ public class CopyPasteSupport {
return null;
}
-
- private static Transferable getTransferable(Producer<Transferable> producer) {
- Transferable content = null;
- if (producer != null) {
- content = producer.produce();
- }
- else {
- CopyPasteManager manager = CopyPasteManager.getInstance();
- if (manager.areDataFlavorsAvailable(DataFlavor.stringFlavor)) {
- content = manager.getContents();
- }
- }
- return content;
- }
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java
index f600c606a98d..39706f016adc 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java
@@ -992,7 +992,16 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
}
public void setLineNumberAreaWidth(@NotNull TIntFunction calculator) {
- final int lineNumberAreaWidth = calculator.execute(myLineNumberConvertor.execute(endLineNumber()));
+ int maxLineNumber = 0;
+ for (int i = endLineNumber(); i >= 0; i--) {
+ int number = myLineNumberConvertor.execute(i);
+ if (number >= 0) {
+ maxLineNumber = number;
+ break;
+ }
+ }
+
+ final int lineNumberAreaWidth = calculator.execute(maxLineNumber);
if (myLineNumberAreaWidth != lineNumberAreaWidth) {
myLineNumberAreaWidth = lineNumberAreaWidth;
fireResized();
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorHighlighterCache.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorHighlighterCache.java
index c1499a71a71b..8be2284e8360 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorHighlighterCache.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorHighlighterCache.java
@@ -15,10 +15,19 @@
*/
package com.intellij.openapi.editor.impl;
+import com.intellij.lexer.Lexer;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.ex.util.LexerEditorHighlighter;
import com.intellij.openapi.editor.highlighter.EditorHighlighter;
+import com.intellij.openapi.editor.highlighter.EditorHighlighterFactory;
+import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiManager;
+import com.intellij.psi.impl.cache.impl.id.PlatformIdTableBuilding;
+import com.intellij.psi.impl.search.LexerEditorHighlighterLexer;
import com.intellij.reference.SoftReference;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -55,4 +64,28 @@ public class EditorHighlighterCache {
return null;
}
+ @Nullable
+ public static Lexer getLexerBasedOnLexerHighlighter(CharSequence text, VirtualFile virtualFile, Project project) {
+ EditorHighlighter highlighter = null;
+
+ PsiFile psiFile = virtualFile != null ? PsiManager.getInstance(project).findFile(virtualFile) : null;
+ final Document document = psiFile != null ? PsiDocumentManager.getInstance(project).getDocument(psiFile) : null;
+ final EditorHighlighter cachedEditorHighlighter;
+ boolean alreadyInitializedHighlighter = false;
+
+ if (document != null &&
+ (cachedEditorHighlighter = getEditorHighlighterForCachesBuilding(document)) != null &&
+ PlatformIdTableBuilding.checkCanUseCachedEditorHighlighter(text, cachedEditorHighlighter)) {
+ highlighter = cachedEditorHighlighter;
+ alreadyInitializedHighlighter = true;
+ }
+ else if (virtualFile != null) {
+ highlighter = EditorHighlighterFactory.getInstance().createEditorHighlighter(project, virtualFile);
+ }
+
+ if (highlighter != null) {
+ return new LexerEditorHighlighterLexer(highlighter, alreadyInitializedHighlighter);
+ }
+ return null;
+ }
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java
index b708f38a9190..c0ffbd10aca4 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java
@@ -33,7 +33,7 @@ import com.intellij.openapi.actionSystem.ex.ActionManagerEx;
import com.intellij.openapi.actionSystem.impl.MouseGestureManager;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
-import com.intellij.openapi.application.ex.ApplicationManagerEx;
+import com.intellij.openapi.application.impl.LaterInvocator;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.command.UndoConfirmationPolicy;
import com.intellij.openapi.diagnostic.Logger;
@@ -147,7 +147,6 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
@NotNull private final EditorComponentImpl myEditorComponent;
@NotNull private final EditorGutterComponentImpl myGutterComponent;
private final TraceableDisposable myTraceableDisposable = new TraceableDisposable(new Throwable());
- private volatile boolean hasTabs; // optimisation flag: when editor contains no tabs it is dramatically easier to calculate positions
static {
ComplementaryFontsRegistry.getFontAbleToDisplay(' ', 0, 0, UIManager.getFont("Label.font").getFamily()); // load costly font info
@@ -168,6 +167,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
@NotNull private final CaretCursor myCaretCursor;
private final ScrollingTimer myScrollingTimer = new ScrollingTimer();
+ @SuppressWarnings("RedundantStringConstructorCall")
private final Object MOUSE_DRAGGED_GROUP = new String("MouseDraggedGroup");
@NotNull private final SettingsImpl mySettings;
@@ -246,8 +246,6 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
@Nullable private Color myForcedBackground = null;
@Nullable private Dimension myPreferredSize;
private int myVirtualPageHeight;
- @Nullable private Runnable myGutterSizeUpdater = null;
- private boolean myGutterNeedsUpdate = false;
private Alarm myAppleRepaintAlarm;
private final Alarm myMouseSelectionStateAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD);
@@ -317,8 +315,12 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
}
EditorImpl(@NotNull Document document, boolean viewer, @Nullable Project project) {
+ assertIsDispatchThread();
myProject = project;
myDocument = (DocumentEx)document;
+ if (myDocument instanceof DocumentImpl) {
+ ((DocumentImpl)myDocument).requestTabTracking();
+ }
myScheme = createBoundColorSchemeDelegate(null);
initTabPainter();
myIsViewer = viewer;
@@ -433,13 +435,13 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
if (myPrimaryCaret != null) {
myPrimaryCaret.updateVisualPosition(); // repainting old primary caret's row background
}
- ((CaretImpl)e.getCaret()).updateVisualPosition(); // repainting caret region
+ updateCaretVisualPosition(e);
myPrimaryCaret = myCaretModel.getPrimaryCaret();
}
@Override
public void caretRemoved(CaretEvent e) {
- ((CaretImpl)e.getCaret()).updateVisualPosition(); // repainting caret region
+ updateCaretVisualPosition(e);
myPrimaryCaret = myCaretModel.getPrimaryCaret(); // repainting new primary caret's row background
myPrimaryCaret.updateVisualPosition();
}
@@ -548,7 +550,13 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
}
});
}
- updateHasTabsFlag(document.getImmutableCharSequence());
+ }
+
+ private static void updateCaretVisualPosition(CaretEvent e) {
+ CaretImpl caretImpl = ((CaretImpl)e.getCaret());
+ if (caretImpl != null) {
+ caretImpl.updateVisualPosition(); // repainting caret region
+ }
}
@NotNull
@@ -575,7 +583,10 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
myPrefixWidthInPixels = 0;
if (myPrefixText != null) {
for (char c : myPrefixText) {
- myPrefixWidthInPixels += EditorUtil.charWidth(c, myPrefixAttributes.getFontType(), this);
+ LOG.assertTrue(myPrefixAttributes != null);
+ if (myPrefixAttributes != null) {
+ myPrefixWidthInPixels += EditorUtil.charWidth(c, myPrefixAttributes.getFontType(), this);
+ }
}
}
mySoftWrapModel.recalculate();
@@ -791,6 +802,9 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
if (myConnection != null) {
myConnection.disconnect();
}
+ if (myDocument instanceof DocumentImpl) {
+ ((DocumentImpl)myDocument).giveUpTabTracking();
+ }
Disposer.dispose(myDisposable);
}
@@ -898,9 +912,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
new UiNotifyConnector(myEditorComponent, new Activatable.Adapter(){
@Override
public void showNotify() {
- if (myGutterNeedsUpdate) {
- updateGutterSize();
- }
+ myGutterComponent.updateSize();
}
});
@@ -1505,7 +1517,8 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
private final int[] myLastXOffsets = new int[myLastStartOffsets.length];
private final int[] myLastXs = new int[myLastStartOffsets.length];
private int myCurrentCachePosition;
- private int myLastCacheHits, myTotalRequests; // todo remove
+ private int myLastCacheHits;
+ private int myTotalRequests; // todo remove
private int getTabbedTextWidth(int startOffset, int targetColumn, int xOffset) {
int x = xOffset;
@@ -1621,7 +1634,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
@Override
public void repaint(final int startOffset, int endOffset) {
- if (!isShowing() || myScrollPane == null || myDocument.isInBulkUpdate()) {
+ if (!isShowing() || myDocument.isInBulkUpdate()) {
return;
}
@@ -1638,7 +1651,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
}
private boolean isShowing() {
- return myGutterComponent != null && myGutterComponent.isShowing();
+ return myGutterComponent.isShowing();
}
private void repaintToScreenBottom(int startLine) {
@@ -1679,9 +1692,6 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
}
private void bulkUpdateFinished() {
- if (myScrollPane == null) {
- return;
- }
clearTextWidthCache();
@@ -1700,7 +1710,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
if (isStickySelection()) {
setStickySelection(false);
}
- if (myDocument.isInBulkUpdate() || myScrollingModel == null) {
+ if (myDocument.isInBulkUpdate()) {
// Assuming that the job is done at bulk listener callback methods.
return;
}
@@ -1716,7 +1726,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
}
private void changedUpdate(DocumentEvent e) {
- if (myScrollPane == null || myDocument.isInBulkUpdate()) return;
+ if (myDocument.isInBulkUpdate()) return;
clearTextWidthCache();
mySelectionModel.removeBlockSelection();
@@ -1754,16 +1764,10 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
Point caretLocation = visualPositionToXY(getCaretModel().getVisualPosition());
int scrollOffset = caretLocation.y - myCaretUpdateVShift;
getScrollingModel().scrollVertically(scrollOffset);
- updateHasTabsFlag(e.getNewFragment());
}
- private void updateHasTabsFlag(@NotNull CharSequence newChars) {
- if (!hasTabs) {
- hasTabs = StringUtil.contains(newChars, 0, newChars.length(), '\t');
- }
- }
public boolean hasTabs() {
- return hasTabs;
+ return !(myDocument instanceof DocumentImpl) || ((DocumentImpl)myDocument).mightContainTabs();
}
public boolean isScrollToCaret() {
@@ -1784,24 +1788,12 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
}
private void updateGutterSize() {
- if (myGutterSizeUpdater != null) return;
- myGutterSizeUpdater = new Runnable() {
+ LaterInvocator.invokeLater(new Runnable() {
@Override
public void run() {
- if (!isDisposed()) {
- if (isShowing()) {
- myGutterComponent.updateSize();
- myGutterNeedsUpdate = false;
- }
- else {
- myGutterNeedsUpdate = true;
- }
- }
- myGutterSizeUpdater = null;
+ myGutterComponent.updateSize();
}
- };
-
- SwingUtilities.invokeLater(myGutterSizeUpdater);
+ });
}
void validateSize() {
@@ -1945,7 +1937,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
}
if (isReleased) {
- g.setColor(new Color(128, 255, 128));
+ g.setColor(new JBColor(new Color(128, 255, 128), new Color(128, 255, 128)));
g.fillRect(clip.x, clip.y, clip.width, clip.height);
return;
}
@@ -2239,7 +2231,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
myLastBackgroundColor = null;
int start = clipStartOffset;
- int end = clipEndOffset;
+
if (!myPurePaintingMode) {
getSoftWrapModel().registerSoftWrapsIfNecessary();
}
@@ -2250,7 +2242,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
return;
}
- IterationState iterationState = new IterationState(this, start, end, isPaintSelection());
+ IterationState iterationState = new IterationState(this, start, clipEndOffset, isPaintSelection());
TextAttributes attributes = iterationState.getMergedAttributes();
Color backColor = getBackgroundColor(attributes);
int fontType = attributes.getFontType();
@@ -2322,7 +2314,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
position.y += lineHeight;
start = lEnd;
}
- else if (collapsedFolderAt.getEndOffset() == end) {
+ else if (collapsedFolderAt.getEndOffset() == clipEndOffset) {
softWrap = mySoftWrapModel.getSoftWrap(collapsedFolderAt.getStartOffset());
if (softWrap != null) {
position.x = drawSoftWrapAwareBackground(
@@ -3677,19 +3669,16 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
return logicalToVisualPosition(logicalPos, true);
}
- // TODO den remove as soon as the problem is fixed.
- private final ThreadLocal<Integer> stackDepth = new ThreadLocal<Integer>();
-
- // TODO den remove as soon as the problem is fixed.
@Override
@NotNull
public VisualPosition logicalToVisualPosition(@NotNull LogicalPosition logicalPos, boolean softWrapAware) {
- stackDepth.set(0);
- return doLogicalToVisualPosition(logicalPos, softWrapAware);
+ return doLogicalToVisualPosition(logicalPos, softWrapAware,0);
}
@NotNull
- private VisualPosition doLogicalToVisualPosition(@NotNull LogicalPosition logicalPos, boolean softWrapAware) {
+ private VisualPosition doLogicalToVisualPosition(@NotNull LogicalPosition logicalPos, boolean softWrapAware,
+ // TODO den remove as soon as the problem is fixed.
+ int stackDepth) {
assertReadAccess();
if (!myFoldingModel.isFoldingEnabled() && !mySoftWrapModel.isSoftWrappingEnabled()) {
return new VisualPosition(logicalPos.line, logicalPos.column);
@@ -3703,25 +3692,12 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
offset = outermostCollapsed.getStartOffset();
LogicalPosition foldStart = offsetToLogicalPosition(offset);
// TODO den remove as soon as the problem is fixed.
- Integer depth = stackDepth.get();
- if (depth >= 0) {
- stackDepth.set(depth + 1);
- if (depth > 15) {
- LOG.error("Detected potential StackOverflowError at logical->visual position mapping. Given logical position: '" +
- logicalPos + "'. State: " + dumpState());
- stackDepth.set(-1);
- }
- }
- // TODO den remove as soon as the problem is fixed.
- try {
- return doLogicalToVisualPosition(foldStart, true);
- }
- finally {
- depth = stackDepth.get();
- if (depth > 0) {
- stackDepth.set(depth - 1);
- }
+ if (stackDepth > 15) {
+ LOG.error("Detected potential StackOverflowError at logical->visual position mapping. Given logical position: '" +
+ logicalPos + "'. State: " + dumpState());
+ stackDepth = -1;
}
+ return doLogicalToVisualPosition(foldStart, true, stackDepth+1);
}
else {
offset = outermostCollapsed.getEndOffset() + 3; // WTF?
@@ -3988,7 +3964,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
return false;
}
- if (e.getComponent() != myInitialMouseEvent.getComponent() || !e.getPoint().equals(myInitialMouseEvent.getPoint())) {
+ if (myInitialMouseEvent!= null && (e.getComponent() != myInitialMouseEvent.getComponent() || !e.getPoint().equals(myInitialMouseEvent.getPoint()))) {
myIgnoreMouseEventsConsecutiveToInitial = false;
myInitialMouseEvent = null;
return false;
@@ -4197,7 +4173,9 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
}
} else {
final LogicalPosition blockStart = selectionModel.hasBlockSelection() ? selectionModel.getBlockStart() : oldLogicalCaret;
- setBlockSelectionAndBlockActions(e, blockStart, getCaretModel().getLogicalPosition());
+ if (blockStart != null) {
+ setBlockSelectionAndBlockActions(e, blockStart, getCaretModel().getLogicalPosition());
+ }
}
}
else {
@@ -5002,7 +4980,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
}
void assertIsDispatchThread() {
- ApplicationManagerEx.getApplicationEx().assertIsDispatchThread();
+ ApplicationManager.getApplication().assertIsDispatchThread();
}
private static void assertReadAccess() {
@@ -5392,7 +5370,9 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
public void run() {
int docLength = doc.getTextLength();
ProperTextRange range = composedTextRange.intersection(new TextRange(0, docLength));
- doc.deleteString(range.getStartOffset(), range.getEndOffset());
+ if (range != null) {
+ doc.deleteString(range.getStartOffset(), range.getEndOffset());
+ }
}
});
}
@@ -6745,7 +6725,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
private class TablessBorder extends SideBorder {
private TablessBorder() {
- super(UIUtil.getBorderColor(), SideBorder.ALL);
+ super(JBColor.border(), SideBorder.ALL);
}
@Override
@@ -6769,7 +6749,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
public Insets getBorderInsets(Component c) {
Container splitters = SwingUtilities.getAncestorOfClass(EditorsSplitters.class, c);
boolean thereIsSomethingAbove = !SystemInfo.isMac || UISettings.getInstance().SHOW_MAIN_TOOLBAR || UISettings.getInstance().SHOW_NAVIGATION_BAR ||
- EditorImpl.this.myProject != null && !ToolWindowManagerEx.getInstanceEx(EditorImpl.this.myProject).getIdsOn(ToolWindowAnchor.TOP).isEmpty();
+ myProject != null && !ToolWindowManagerEx.getInstanceEx(myProject).getIdsOn(ToolWindowAnchor.TOP).isEmpty();
return splitters == null ? super.getBorderInsets(c) : new Insets(thereIsSomethingAbove ? 1 : 0, 0, 0, 0);
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java
index a2f45fe33857..6ec29e58dc0b 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java
@@ -36,6 +36,7 @@ import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.command.UndoConfirmationPolicy;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.actionSystem.DocCommandGroupId;
+import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.colors.EditorFontType;
import com.intellij.openapi.editor.ex.*;
import com.intellij.openapi.editor.markup.ErrorStripeRenderer;
@@ -45,7 +46,7 @@ import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.ui.popup.Balloon;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.ProperTextRange;
-import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.wm.ToolWindowAnchor;
import com.intellij.openapi.wm.ex.ToolWindowManagerEx;
import com.intellij.ui.*;
@@ -428,7 +429,7 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark
}
@Override
- public void paint(Graphics g) {
+ public void paint(@NotNull Graphics g) {
((ApplicationImpl)ApplicationManager.getApplication()).editorPaintStart();
final Rectangle bounds = getBounds();
@@ -437,7 +438,7 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark
errorIconBounds.y = bounds.height / 2 - errorIconBounds.height / 2;
try {
- if (UISettings.getInstance().PRESENTATION_MODE || SystemInfo.isMac) {
+ if (UISettings.getInstance().PRESENTATION_MODE || ButtonlessScrollBarUI.isMacOverlayScrollbarSupported()) {
g.setColor(getEditor().getColorsScheme().getDefaultBackground());
g.fillRect(0, 0, bounds.width, bounds.height);
@@ -493,7 +494,7 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark
}
@Override
- public void uninstallUI(JComponent c) {
+ public void uninstallUI(@NotNull JComponent c) {
super.uninstallUI(c);
myCachedTrack = null;
}
@@ -528,7 +529,7 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark
@Override
protected void paintThumb(Graphics g, JComponent c, Rectangle thumbBounds) {
- if (UISettings.getInstance().PRESENTATION_MODE || SystemInfo.isMac) {
+ if (UISettings.getInstance().PRESENTATION_MODE || ButtonlessScrollBarUI.isMacOverlayScrollbarSupported()) {
super.paintThumb(g, c, thumbBounds);
return;
}
@@ -565,13 +566,13 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark
@Override
protected int getThickness() {
- if (UISettings.getInstance().PRESENTATION_MODE || SystemInfo.isMac) return super.getThickness();
+ if (UISettings.getInstance().PRESENTATION_MODE || ButtonlessScrollBarUI.isMacOverlayScrollbarSupported()) return super.getThickness();
return super.getThickness() + (isMacOverlayScrollbar() ? 2 : 7);
}
@Override
protected void doPaintTrack(Graphics g, JComponent c, Rectangle bounds) {
- if (UISettings.getInstance().PRESENTATION_MODE || SystemInfo.isMac) {
+ if (UISettings.getInstance().PRESENTATION_MODE || ButtonlessScrollBarUI.isMacOverlayScrollbarSupported()) {
g.setColor(getEditor().getColorsScheme().getDefaultBackground());
g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height);
//return;
@@ -609,7 +610,9 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark
}
private void paintTrackBasement(Graphics g, Rectangle bounds) {
- if (UISettings.getInstance().PRESENTATION_MODE || SystemInfo.isMac) {
+ if (UISettings.getInstance().PRESENTATION_MODE || ButtonlessScrollBarUI.isMacOverlayScrollbarSupported()) {
+ g.setColor(EditorColorsManager.getInstance().getGlobalScheme().getDefaultBackground());
+ g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height);
return;
}
@@ -647,13 +650,13 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark
private void drawMarkup(final Graphics g, final int width, int startOffset, int endOffset, MarkupModelEx markup) {
final Queue<PositionedStripe> thinEnds = new PriorityQueue<PositionedStripe>(5, new Comparator<PositionedStripe>() {
@Override
- public int compare(PositionedStripe o1, PositionedStripe o2) {
+ public int compare(@NotNull PositionedStripe o1, @NotNull PositionedStripe o2) {
return o1.yEnd - o2.yEnd;
}
});
final Queue<PositionedStripe> wideEnds = new PriorityQueue<PositionedStripe>(5, new Comparator<PositionedStripe>() {
@Override
- public int compare(PositionedStripe o1, PositionedStripe o2) {
+ public int compare(@NotNull PositionedStripe o1, @NotNull PositionedStripe o2) {
return o1.yEnd - o2.yEnd;
}
});
@@ -757,12 +760,21 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark
boolean drawBottomDecoration) {
int x = isMirrored() ? 3 : 5;
int paintWidth = width;
+ boolean flatStyle = Registry.is("ide.new.markup.markers");
if (thinErrorStripeMark) {
paintWidth /= 2;
- paintWidth += 1;
+ paintWidth += flatStyle ? 0 : 1;
x = isMirrored() ? width + 2 : 0;
}
if (color == null) return;
+ Color darker = UIUtil.isUnderDarcula()? color : ColorUtil.shift(color, 0.75);
+
+ if (flatStyle) {
+ g.setColor(darker);
+ g.fillRect(x, yStart, paintWidth, yEnd - yStart + 1);
+ return;
+ }
+
g.setColor(color);
g.fillRect(x + 1, yStart, paintWidth - 2, yEnd - yStart + 1);
@@ -774,7 +786,6 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark
//top decoration
UIUtil.drawLine(g, x + 1, yStart, x + paintWidth - 2, yStart);
}
- Color darker = ColorUtil.shift(color, 0.75);
g.setColor(darker);
if (drawBottomDecoration) {
@@ -787,7 +798,7 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark
// mouse events
@Override
- public void mouseClicked(final MouseEvent e) {
+ public void mouseClicked(@NotNull final MouseEvent e) {
CommandProcessor.getInstance().executeCommand(myEditor.getProject(), new Runnable() {
@Override
public void run() {
@@ -801,11 +812,11 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark
}
@Override
- public void mousePressed(MouseEvent e) {
+ public void mousePressed(@NotNull MouseEvent e) {
}
@Override
- public void mouseReleased(MouseEvent e) {
+ public void mouseReleased(@NotNull MouseEvent e) {
}
private int getWidth() {
@@ -824,7 +835,7 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark
}
@Override
- public void mouseMoved(MouseEvent e) {
+ public void mouseMoved(@NotNull MouseEvent e) {
EditorImpl.MyScrollBar scrollBar = myEditor.getVerticalScrollBar();
int buttonHeight = scrollBar.getDecScrollButtonHeight();
int lineCount = getDocument().getLineCount() + myEditor.getSettings().getAdditionalLinesCount();
@@ -897,16 +908,16 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark
}
@Override
- public void mouseEntered(MouseEvent e) {
+ public void mouseEntered(@NotNull MouseEvent e) {
}
@Override
- public void mouseExited(MouseEvent e) {
+ public void mouseExited(@NotNull MouseEvent e) {
cancelMyToolTips(e, true);
}
@Override
- public void mouseDragged(MouseEvent e) {
+ public void mouseDragged(@NotNull MouseEvent e) {
cancelMyToolTips(e, true);
}
@@ -943,13 +954,15 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark
}
public void markDirtied(@NotNull ProperTextRange yPositions) {
- int start = Math.max(0, yPositions.getStartOffset() - myEditor.getLineHeight());
- int end = myEditorScrollbarTop + myEditorTargetHeight == 0 ? yPositions.getEndOffset() + myEditor.getLineHeight()
- : Math
- .min(myEditorScrollbarTop + myEditorTargetHeight, yPositions.getEndOffset() + myEditor.getLineHeight());
- ProperTextRange adj = new ProperTextRange(start, Math.max(end, start));
+ if (myDirtyYPositions != WHOLE_DOCUMENT) {
+ int start = Math.max(0, yPositions.getStartOffset() - myEditor.getLineHeight());
+ int end = myEditorScrollbarTop + myEditorTargetHeight == 0 ? yPositions.getEndOffset() + myEditor.getLineHeight()
+ : Math
+ .min(myEditorScrollbarTop + myEditorTargetHeight, yPositions.getEndOffset() + myEditor.getLineHeight());
+ ProperTextRange adj = new ProperTextRange(start, Math.max(end, start));
- myDirtyYPositions = myDirtyYPositions == null ? adj : myDirtyYPositions.union(adj);
+ myDirtyYPositions = myDirtyYPositions == null ? adj : myDirtyYPositions.union(adj);
+ }
myEditorScrollbarTop = 0;
myEditorSourceHeight = 0;
@@ -1137,7 +1150,7 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark
myHighlighters.add(rangeHighlighter);
}
Collections.sort(myHighlighters, new Comparator<RangeHighlighterEx>() {
- public int compare(RangeHighlighterEx ex1, RangeHighlighterEx ex2) {
+ public int compare(@NotNull RangeHighlighterEx ex1, @NotNull RangeHighlighterEx ex2) {
LogicalPosition startPos1 = myEditor.offsetToLogicalPosition(ex1.getAffectedAreaStartOffset());
LogicalPosition startPos2 = myEditor.offsetToLogicalPosition(ex2.getAffectedAreaStartOffset());
if (startPos1.line != startPos2.line) return 0;
@@ -1167,7 +1180,7 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark
}
@Override
- protected void paintComponent(Graphics g) {
+ protected void paintComponent(@NotNull Graphics g) {
if (myVisualLine ==-1) return;
Dimension size = getPreferredSize();
EditorGutterComponentEx gutterComponentEx = myEditor.getGutterComponentEx();
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/LazyRangeMarkerFactoryImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/LazyRangeMarkerFactoryImpl.java
new file mode 100644
index 000000000000..5a9c704173aa
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/LazyRangeMarkerFactoryImpl.java
@@ -0,0 +1,323 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.editor.impl;
+
+import com.intellij.codeStyle.CodeStyleFacade;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.EditorFactory;
+import com.intellij.openapi.editor.LazyRangeMarkerFactory;
+import com.intellij.openapi.editor.RangeMarker;
+import com.intellij.openapi.editor.event.DocumentAdapter;
+import com.intellij.openapi.editor.event.DocumentEvent;
+import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.UserDataHolderBase;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.containers.WeakList;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+public class LazyRangeMarkerFactoryImpl extends LazyRangeMarkerFactory {
+ private final Project myProject;
+ private static final Key<WeakList<LazyMarker>> LAZY_MARKERS_KEY = Key.create("LAZY_MARKERS_KEY");
+
+ public LazyRangeMarkerFactoryImpl(@NotNull Project project, @NotNull final FileDocumentManager fileDocumentManager) {
+ myProject = project;
+
+ EditorFactory.getInstance().getEventMulticaster().addDocumentListener(new DocumentAdapter() {
+ @Override
+ public void beforeDocumentChange(DocumentEvent e) {
+ transformRangeMarkers(e);
+ }
+
+ @Override
+ public void documentChanged(DocumentEvent e) {
+ transformRangeMarkers(e);
+ }
+
+ private void transformRangeMarkers(@NotNull DocumentEvent e) {
+ Document document = e.getDocument();
+ VirtualFile file = fileDocumentManager.getFile(document);
+ if (file == null) {
+ return;
+ }
+
+ WeakList<LazyMarker> lazyMarkers = getMarkers(file);
+ if (lazyMarkers == null) {
+ return;
+ }
+
+ List<LazyMarker> markers = lazyMarkers.toStrongList();
+ for (LazyMarker marker : markers) {
+ if (file.equals(marker.getFile())) {
+ marker.getOrCreateDelegate();
+ }
+ }
+ }
+ }, project);
+ }
+
+ static WeakList<LazyMarker> getMarkers(@NotNull VirtualFile file) {
+ return file.getUserData(LazyRangeMarkerFactoryImpl.LAZY_MARKERS_KEY);
+ }
+
+ private static void addToLazyMarkersList(@NotNull LazyMarker marker, @NotNull VirtualFile file) {
+ WeakList<LazyMarker> markers = getMarkers(file);
+
+ if (markers == null) {
+ markers = file.putUserDataIfAbsent(LAZY_MARKERS_KEY, new WeakList<LazyMarker>());
+ }
+ markers.add(marker);
+ }
+
+ private static void removeFromLazyMarkersList(@NotNull LazyMarker marker, @NotNull VirtualFile file) {
+ WeakList<LazyMarker> markers = getMarkers(file);
+
+ if (markers != null) {
+ markers.remove(marker);
+ }
+ }
+
+ @Override
+ @NotNull
+ public RangeMarker createRangeMarker(@NotNull final VirtualFile file, final int offset) {
+ return ApplicationManager.getApplication().runReadAction(new Computable<RangeMarker>() {
+ @Override
+ public RangeMarker compute() {
+ // even for already loaded document do not create range marker yet - wait until it really needed when e.g. user clicked to jump to OpenFileDescriptor
+ final LazyMarker marker = new OffsetLazyMarker(file, offset);
+ addToLazyMarkersList(marker, file);
+ return marker;
+ }
+ });
+ }
+
+ @Override
+ @NotNull
+ public RangeMarker createRangeMarker(@NotNull final VirtualFile file, final int line, final int column, final boolean persistent) {
+ return ApplicationManager.getApplication().runReadAction(new Computable<RangeMarker>() {
+ @Override
+ public RangeMarker compute() {
+ final Document document = FileDocumentManager.getInstance().getCachedDocument(file);
+ if (document != null) {
+ final int offset = calculateOffset(myProject, file, document, line, column);
+ return document.createRangeMarker(offset, offset, persistent);
+ }
+
+ final LazyMarker marker = new LineColumnLazyMarker(file, line, column);
+ addToLazyMarkersList(marker, file);
+ return marker;
+ }
+ });
+ }
+
+ abstract static class LazyMarker extends UserDataHolderBase implements RangeMarker {
+ protected RangeMarker myDelegate; // the real range marker which is created only when document is opened, or (this) which means it's disposed
+ protected final VirtualFile myFile;
+ protected final int myInitialOffset;
+
+ private LazyMarker(@NotNull VirtualFile file, int offset) {
+ myFile = file;
+ myInitialOffset = offset;
+ }
+
+ boolean isDelegated() {
+ return myDelegate != null;
+ }
+
+ @NotNull
+ public VirtualFile getFile() {
+ return myFile;
+ }
+
+ @Nullable
+ protected final RangeMarker getOrCreateDelegate() {
+ if (myDelegate == null) {
+ Document document = FileDocumentManager.getInstance().getDocument(myFile);
+ if (document == null) {
+ return null;
+ }
+ myDelegate = createDelegate(myFile, document);
+ removeFromLazyMarkersList(this, myFile);
+ }
+ return isDisposed() ? null : myDelegate;
+ }
+
+ @Nullable
+ protected abstract RangeMarker createDelegate(@NotNull VirtualFile file, @NotNull Document document);
+
+ @Override
+ @NotNull
+ public Document getDocument() {
+ RangeMarker delegate = getOrCreateDelegate();
+ if (delegate == null) {
+ //noinspection ConstantConditions
+ return FileDocumentManager.getInstance().getDocument(myFile);
+ }
+ return delegate.getDocument();
+ }
+
+ @Override
+ public int getStartOffset() {
+ return myDelegate == null || isDisposed() ? myInitialOffset : myDelegate.getStartOffset();
+ }
+
+ public boolean isDisposed() {
+ return myDelegate == this;
+ }
+
+
+ @Override
+ public int getEndOffset() {
+ return myDelegate == null || isDisposed() ? myInitialOffset : myDelegate.getEndOffset();
+ }
+
+ @Override
+ public boolean isValid() {
+ RangeMarker delegate = getOrCreateDelegate();
+ return delegate != null && !isDisposed() && delegate.isValid();
+ }
+
+ @Override
+ public void setGreedyToLeft(boolean greedy) {
+ getOrCreateDelegate().setGreedyToLeft(greedy);
+ }
+
+ @Override
+ public void setGreedyToRight(boolean greedy) {
+ getOrCreateDelegate().setGreedyToRight(greedy);
+ }
+
+ @Override
+ public boolean isGreedyToRight() {
+ return getOrCreateDelegate().isGreedyToRight();
+ }
+
+ @Override
+ public boolean isGreedyToLeft() {
+ return getOrCreateDelegate().isGreedyToLeft();
+ }
+
+ @Override
+ public void dispose() {
+ assert !isDisposed();
+ RangeMarker delegate = myDelegate;
+ if (delegate == null) {
+ removeFromLazyMarkersList(this, myFile);
+ myDelegate = this; // mark of disposed marker
+ }
+ else {
+ delegate.dispose();
+ }
+ }
+ }
+
+ private static class OffsetLazyMarker extends LazyMarker {
+ private OffsetLazyMarker(@NotNull VirtualFile file, int offset) {
+ super(file, offset);
+ }
+
+ @Override
+ public boolean isValid() {
+ RangeMarker delegate = myDelegate;
+ if (delegate == null) {
+ Document document = FileDocumentManager.getInstance().getDocument(myFile);
+ return document != null;
+ }
+
+ return super.isValid();
+ }
+
+ @Override
+ @NotNull
+ public RangeMarker createDelegate(@NotNull VirtualFile file, @NotNull final Document document) {
+ final int offset = Math.min(myInitialOffset, document.getTextLength());
+ return document.createRangeMarker(offset, offset);
+ }
+ }
+
+ private class LineColumnLazyMarker extends LazyMarker {
+ private final int myLine;
+ private final int myColumn;
+
+ private LineColumnLazyMarker(@NotNull VirtualFile file, int line, int column) {
+ super(file, -1);
+ myLine = line;
+ myColumn = column;
+ }
+
+ @Override
+ @Nullable
+ public RangeMarker createDelegate(@NotNull VirtualFile file, @NotNull Document document) {
+ if (document.getTextLength() == 0 && !(myLine == 0 && myColumn == 0)) {
+ return null;
+ }
+
+ int offset = calculateOffset(myProject, file, document, myLine, myColumn);
+ return document.createRangeMarker(offset, offset);
+ }
+
+ @Override
+ public boolean isValid() {
+ RangeMarker delegate = myDelegate;
+ if (delegate == null) {
+ Document document = FileDocumentManager.getInstance().getDocument(myFile);
+ return document != null && (document.getTextLength() != 0 || myLine == 0 && myColumn == 0);
+ }
+
+ return super.isValid();
+ }
+
+ @Override
+ public int getStartOffset() {
+ getOrCreateDelegate();
+ return super.getStartOffset();
+ }
+
+ @Override
+ public int getEndOffset() {
+ getOrCreateDelegate();
+ return super.getEndOffset();
+ }
+ }
+
+ private static int calculateOffset(@NotNull Project project, @NotNull VirtualFile file, @NotNull Document document, final int line, final int column) {
+ int offset;
+ if (line < document.getLineCount()) {
+ final int lineStart = document.getLineStartOffset(line);
+ final int lineEnd = document.getLineEndOffset(line);
+ final CharSequence docText = document.getCharsSequence();
+ final int tabSize = CodeStyleFacade.getInstance(project).getTabSize(file.getFileType());
+
+ offset = lineStart;
+ int col = 0;
+ while (offset < lineEnd && col < column) {
+ col += docText.charAt(offset) == '\t' ? tabSize : 1;
+ offset++;
+ }
+ }
+ else {
+ offset = document.getTextLength();
+ }
+ return offset;
+ }
+
+}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SelectionModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SelectionModelImpl.java
index 2f5a81153579..731d1e26a289 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SelectionModelImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SelectionModelImpl.java
@@ -567,7 +567,7 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi
@Override
public void copySelectionToClipboard() {
- CopyPasteSupport.copySelectionToClipboard(myEditor);
+ EditorCopyPasteHelper.getInstance().copySelectionToClipboard(myEditor);
}
@Override
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java
index 6f1b9820132b..d8b6697dc8d1 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java
@@ -303,14 +303,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi
if (!isSoftWrappingEnabled()) {
return 0;
}
- int result = 0;
- FoldingModel foldingModel = myEditor.getFoldingModel();
- for (SoftWrap softWrap : myStorage.getSoftWraps()) {
- if (!foldingModel.isOffsetCollapsed(softWrap.getStart())) {
- result++; // Assuming that soft wrap has single line feed all the time
- }
- }
- return result;
+ return myStorage.getSoftWraps().size(); // Assuming that soft wrap has single line feed all the time
}
/**
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/TrailingSpacesStripper.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/TrailingSpacesStripper.java
index a5c477facfb3..165ff5776756 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/TrailingSpacesStripper.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/TrailingSpacesStripper.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.intellij.openapi.fileEditor.impl;
+package com.intellij.openapi.editor.impl;
import com.intellij.ide.DataManager;
import com.intellij.injected.editor.DocumentWindow;
@@ -23,7 +23,6 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.ex.EditorSettingsExternalizable;
-import com.intellij.openapi.editor.impl.DocumentImpl;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileEditor.FileDocumentManagerAdapter;
import com.intellij.openapi.project.Project;
@@ -37,11 +36,12 @@ import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import java.awt.*;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Iterator;
import java.util.List;
+import java.util.Set;
public final class TrailingSpacesStripper extends FileDocumentManagerAdapter {
-
public static final Key<String> OVERRIDE_STRIP_TRAILING_SPACES_KEY = Key.create("OVERRIDE_TRIM_TRAILING_SPACES_KEY");
public static final Key<Boolean> OVERRIDE_ENSURE_NEWLINE_KEY = Key.create("OVERRIDE_ENSURE_NEWLINE_KEY");
@@ -61,7 +61,7 @@ public final class TrailingSpacesStripper extends FileDocumentManagerAdapter {
strip(document);
}
- private void strip(final Document document) {
+ private void strip(@NotNull final Document document) {
if (!document.isWritable()) return;
FileDocumentManager fileDocumentManager = FileDocumentManager.getInstance();
VirtualFile file = fileDocumentManager.getFile(document);
@@ -149,7 +149,7 @@ public final class TrailingSpacesStripper extends FileDocumentManagerAdapter {
((DocumentImpl)document).clearLineModificationFlagsExcept(caretLines);
}
- public static boolean stripIfNotCurrentLine(Document document, boolean inChangedLinesOnly) {
+ public static boolean stripIfNotCurrentLine(@NotNull Document document, boolean inChangedLinesOnly) {
if (document instanceof DocumentWindow) {
document = ((DocumentWindow)document).getDelegate();
}
@@ -168,10 +168,11 @@ public final class TrailingSpacesStripper extends FileDocumentManagerAdapter {
if (activeEditor != null && activeEditor.getCaretModel().supportsMultipleCarets()) {
List<Caret> carets = activeEditor.getCaretModel().getAllCarets();
List<VisualPosition> visualCarets = new ArrayList<VisualPosition>(carets.size());
- List<Integer> caretOffsets = new ArrayList<Integer>(carets.size());
- for (Caret caret : carets) {
+ int[] caretOffsets = new int[carets.size()];
+ for (int i = 0; i < carets.size(); i++) {
+ Caret caret = carets.get(i);
visualCarets.add(caret.getVisualPosition());
- caretOffsets.add(caret.getOffset());
+ caretOffsets[i] = caret.getOffset();
}
markAsNeedsStrippingLater = ((DocumentImpl)document).stripTrailingSpaces(activeEditor.getProject(), inChangedLinesOnly, isVirtualSpaceEnabled, caretOffsets);
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorTabbedContainer.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorTabbedContainer.java
index c2353d5db207..03b03faffe03 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorTabbedContainer.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorTabbedContainer.java
@@ -277,6 +277,8 @@ public final class EditorTabbedContainer implements Disposable, CloseAction.Clos
myTabs.getTabAt(index).setTooltipText(text);
}
+ public boolean isTitleShortened(int index) { return myTabs.getTabAt(index).isTitleShortened(); }
+
public void setBackgroundColorAt(final int index, final Color color) {
myTabs.getTabAt(index).setTabColor(color);
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java
index 3519ab6a1af4..06a3966ade1d 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java
@@ -34,6 +34,7 @@ import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx;
import com.intellij.openapi.fileTypes.FileTypes;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Splitter;
+import com.intellij.openapi.ui.ThreeComponentsSplitter;
import com.intellij.openapi.util.*;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
@@ -319,6 +320,16 @@ public class EditorWindow {
if (disposeIfNeeded && getTabCount() == 0) {
removeFromSplitter();
+ if (UISettings.getInstance().EDITOR_TAB_PLACEMENT == UISettings.TABS_NONE) {
+ final EditorsSplitters owner = getOwner();
+ if (owner != null) {
+ final ThreeComponentsSplitter splitter = UIUtil.getParentOfType(ThreeComponentsSplitter.class, owner);
+ if (splitter != null) {
+ splitter.revalidate();
+ splitter.repaint();
+ }
+ }
+ }
}
else {
myPanel.revalidate();
@@ -453,6 +464,10 @@ public class EditorWindow {
}
}
+ private boolean isTitleShortenedAt(int index) {
+ return myTabbedPane != null && myTabbedPane.isTitleShortened(index);
+ }
+
private void setBackgroundColorAt(final int index, final Color color) {
if (myTabbedPane != null) {
myTabbedPane.setBackgroundColorAt(index, color);
@@ -897,7 +912,9 @@ public class EditorWindow {
final int index = findEditorIndex(findFileComposite(file));
if (index != -1) {
setTitleAt(index, EditorTabbedContainer.calcTabTitle(getManager().getProject(), file));
- setToolTipTextAt(index, UISettings.getInstance().SHOW_TABS_TOOLTIPS ? getManager().getFileTooltipText(file) : null);
+ setToolTipTextAt(index, UISettings.getInstance().SHOW_TABS_TOOLTIPS || isTitleShortenedAt(index)
+ ? getManager().getFileTooltipText(file)
+ : null);
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java
index f396b1eed399..091ff1171157 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java
@@ -37,6 +37,7 @@ import com.intellij.openapi.editor.event.DocumentEvent;
import com.intellij.openapi.editor.ex.DocumentEx;
import com.intellij.openapi.editor.ex.EditorSettingsExternalizable;
import com.intellij.openapi.editor.impl.EditorFactoryImpl;
+import com.intellij.openapi.editor.impl.TrailingSpacesStripper;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.fileEditor.*;
import com.intellij.openapi.fileEditor.impl.text.TextEditorImpl;
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java
index e36a120d609b..c7fa51f770d1 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java
@@ -227,7 +227,7 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec
fm.doWhenFocusSettlesDown(run);
}
else {
- run.run();
+ UIUtil.invokeAndWaitIfNeeded(run);
}
return result;
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/NonProjectFileWritingAccessProvider.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/NonProjectFileWritingAccessProvider.java
index 69a91ec31970..b19b2aa3e943 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/NonProjectFileWritingAccessProvider.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/NonProjectFileWritingAccessProvider.java
@@ -16,7 +16,6 @@
package com.intellij.openapi.fileEditor.impl;
import com.intellij.ProjectTopics;
-import com.intellij.ide.IdeEventQueue;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.StorageScheme;
import com.intellij.openapi.components.impl.stores.IProjectStore;
@@ -30,6 +29,7 @@ import com.intellij.openapi.roots.ModuleRootEvent;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.NotNullLazyKey;
+import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.vfs.*;
import com.intellij.util.NotNullFunction;
import com.intellij.util.NullableFunction;
@@ -114,9 +114,7 @@ public class NonProjectFileWritingAccessProvider extends WritingAccessProvider {
if (deniedFiles.isEmpty()) return Collections.emptyList();
- final int savedEventCount = IdeEventQueue.getInstance().getEventCount();
UnlockOption unlockOption = askToUnlock(deniedFiles);
- IdeEventQueue.getInstance().setEventCount(savedEventCount);
if (unlockOption == null) return deniedFiles;
@@ -144,7 +142,9 @@ public class NonProjectFileWritingAccessProvider extends WritingAccessProvider {
}
private boolean isProjectFile(@NotNull VirtualFile file) {
- if (ProjectFileIndex.SERVICE.getInstance(myProject).isInContent(file)) return true;
+ ProjectFileIndex fileIndex = ProjectFileIndex.SERVICE.getInstance(myProject);
+ if (fileIndex.isInContent(file)) return true;
+ if (!Registry.is("ide.hide.excluded.files") && fileIndex.isExcluded(file) && !fileIndex.isUnderIgnored(file)) return true;
if (myProject instanceof ProjectEx) {
IProjectStore store = ((ProjectEx)myProject).getStateStore();
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorProvider.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorProvider.java
index 60b42f75c22c..690e7c7d2820 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorProvider.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorProvider.java
@@ -278,19 +278,22 @@ public class TextEditorProvider implements FileEditorProvider, DumbAware {
}
protected void setStateImpl(final Project project, final Editor editor, final TextEditorState state){
- if (editor.getCaretModel().supportsMultipleCarets()) {
- CaretModel caretModel = editor.getCaretModel();
- List<CaretState> states = new ArrayList<CaretState>(state.CARETS.length);
- for (TextEditorState.CaretState caretState : state.CARETS) {
- states.add(new CaretState(new LogicalPosition(caretState.LINE, caretState.COLUMN),
- new LogicalPosition(caretState.SELECTION_START_LINE, caretState.SELECTION_START_COLUMN),
- new LogicalPosition(caretState.SELECTION_END_LINE, caretState.SELECTION_END_COLUMN)));
+ if (state.CARETS != null) {
+ if (editor.getCaretModel().supportsMultipleCarets()) {
+ CaretModel caretModel = editor.getCaretModel();
+ List<CaretState> states = new ArrayList<CaretState>(state.CARETS.length);
+ for (TextEditorState.CaretState caretState : state.CARETS) {
+ states.add(new CaretState(new LogicalPosition(caretState.LINE, caretState.COLUMN),
+ new LogicalPosition(caretState.SELECTION_START_LINE, caretState.SELECTION_START_COLUMN),
+ new LogicalPosition(caretState.SELECTION_END_LINE, caretState.SELECTION_END_COLUMN)));
+ }
+ caretModel.setCaretsAndSelections(states);
+ }
+ else {
+ LogicalPosition pos = new LogicalPosition(state.CARETS[0].LINE, state.CARETS[0].COLUMN);
+ editor.getCaretModel().moveToLogicalPosition(pos);
+ editor.getSelectionModel().removeSelection();
}
- caretModel.setCaretsAndSelections(states);
- } else {
- LogicalPosition pos = new LogicalPosition(state.CARETS[0].LINE, state.CARETS[0].COLUMN);
- editor.getCaretModel().moveToLogicalPosition(pos);
- editor.getSelectionModel().removeSelection();
}
EditorEx editorEx = editor instanceof EditorEx ? (EditorEx)editor : null;
boolean preciselyScrollVertically =
diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeMouseEventDispatcher.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeMouseEventDispatcher.java
index 6c78ec12f9df..4b4d19136f01 100644
--- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeMouseEventDispatcher.java
+++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeMouseEventDispatcher.java
@@ -30,6 +30,7 @@ import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.openapi.wm.IdeFrame;
import com.intellij.openapi.wm.impl.FocusManagerImpl;
import com.intellij.openapi.wm.impl.IdeGlassPaneImpl;
+import com.intellij.util.ReflectionUtil;
import com.intellij.util.containers.HashMap;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.Nullable;
@@ -38,7 +39,6 @@ import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
-import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -230,12 +230,7 @@ public final class IdeMouseEventDispatcher {
}
private static void resetPopupTrigger(final MouseEvent e) {
- try {
- final Field popupTrigger = e.getClass().getDeclaredField("popupTrigger");
- popupTrigger.setAccessible(true);
- popupTrigger.set(e, false);
- }
- catch (Exception ignored) { }
+ ReflectionUtil.setField(MouseEvent.class, e, boolean.class, "popupTrigger", false);
}
/**
@@ -247,14 +242,7 @@ public final class IdeMouseEventDispatcher {
*/
public static boolean patchClickCount(final MouseEvent e) {
if (e.getClickCount() != 1 && e.getButton() > 3) {
- try {
- final Field clickCount = e.getClass().getDeclaredField("clickCount");
- clickCount.setAccessible(true);
- clickCount.set(e, 1);
- return true;
- }
- catch (Exception ignored) {
- }
+ ReflectionUtil.setField(MouseEvent.class, e, int.class, "clickCount", 1);
}
return false;
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/KeymapManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/KeymapManagerImpl.java
index 7b4f5a0371ba..7c65a805ee6c 100644
--- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/KeymapManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/KeymapManagerImpl.java
@@ -99,8 +99,8 @@ public class KeymapManagerImpl extends KeymapManagerEx implements PersistentStat
if (Registry.is("editor.add.carets.on.double.control.arrows")) {
ModifierKeyDoubleClickHandler.getInstance().registerAction(IdeActions.ACTION_EDITOR_CLONE_CARET_ABOVE, KeyEvent.VK_CONTROL, KeyEvent.VK_UP);
ModifierKeyDoubleClickHandler.getInstance().registerAction(IdeActions.ACTION_EDITOR_CLONE_CARET_BELOW, KeyEvent.VK_CONTROL, KeyEvent.VK_DOWN);
- ModifierKeyDoubleClickHandler.getInstance().registerAction(IdeActions.ACTION_EDITOR_MOVE_CARET_LEFT, KeyEvent.VK_CONTROL, KeyEvent.VK_LEFT);
- ModifierKeyDoubleClickHandler.getInstance().registerAction(IdeActions.ACTION_EDITOR_MOVE_CARET_RIGHT, KeyEvent.VK_CONTROL, KeyEvent.VK_RIGHT);
+ ModifierKeyDoubleClickHandler.getInstance().registerAction(IdeActions.ACTION_EDITOR_MOVE_CARET_LEFT_WITH_SELECTION, KeyEvent.VK_CONTROL, KeyEvent.VK_LEFT);
+ ModifierKeyDoubleClickHandler.getInstance().registerAction(IdeActions.ACTION_EDITOR_MOVE_CARET_RIGHT_WITH_SELECTION, KeyEvent.VK_CONTROL, KeyEvent.VK_RIGHT);
}
ourKeymapManagerInitialized = true;
diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ModifierKeyDoubleClickHandler.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ModifierKeyDoubleClickHandler.java
index 28536453b713..13a8aaecb724 100644
--- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ModifierKeyDoubleClickHandler.java
+++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ModifierKeyDoubleClickHandler.java
@@ -17,10 +17,10 @@ package com.intellij.openapi.keymap.impl;
import com.intellij.ide.DataManager;
import com.intellij.ide.IdeEventQueue;
-import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.ActionPlaces;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.actionSystem.ex.ActionManagerEx;
import com.intellij.openapi.keymap.KeymapManager;
import com.intellij.openapi.util.Clock;
import com.intellij.openapi.util.Couple;
@@ -39,6 +39,10 @@ import java.util.concurrent.atomic.AtomicLong;
/**
* Support for keyboard shortcuts like Control-double-click or Control-double-click+A
+ *
+ * Timings that are used in the implementation to detect double click were tuned for SearchEverywhere
+ * functionality (invoked on double Shift), so if you need to change them, please make sure
+ * SearchEverywhere behaviour remains intact.
*/
public class ModifierKeyDoubleClickHandler {
private static final ModifierKeyDoubleClickHandler INSTANCE = new ModifierKeyDoubleClickHandler();
@@ -121,7 +125,7 @@ public class ModifierKeyDoubleClickHandler {
return false;
} else if (ourPressed.first.get() && ourReleased.first.get() && ourPressed.second.get() && myActionKeyCode != -1) {
if (keyCode == myActionKeyCode) {
- if (event.getID() == KeyEvent.KEY_RELEASED) {
+ if (event.getID() == KeyEvent.KEY_PRESSED) {
run(keyEvent);
}
return true;
@@ -192,7 +196,7 @@ public class ModifierKeyDoubleClickHandler {
}
private void run(KeyEvent event) {
- final ActionManager actionManager = ActionManager.getInstance();
+ final ActionManagerEx actionManager = ActionManagerEx.getInstanceEx();
final AnAction action = actionManager.getAction(myActionId);
final AnActionEvent anActionEvent = new AnActionEvent(event,
DataManager.getInstance().getDataContext(IdeFocusManager.findInstance().getFocusOwner()),
@@ -200,7 +204,9 @@ public class ModifierKeyDoubleClickHandler {
action.getTemplatePresentation(),
actionManager,
0);
+ actionManager.fireBeforeActionPerformed(action, anActionEvent.getDataContext(), anActionEvent);
action.actionPerformed(anActionEvent);
+ actionManager.fireAfterActionPerformed(action, anActionEvent.getDataContext(), anActionEvent);
}
private boolean isActionBound() {
diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapPanel.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapPanel.java
index b99f19242fa9..ebb3686969f0 100644
--- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapPanel.java
+++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapPanel.java
@@ -393,7 +393,7 @@ public class KeymapPanel extends JPanel implements SearchableConfigurable, Confi
group.add(commonActionsManager.createExpandAllAction(treeExpander, myActionsTree.getTree()));
group.add(commonActionsManager.createCollapseAllAction(treeExpander, myActionsTree.getTree()));
- group.add(new AnAction("Edit Shortcut", "Edit Shortcut", AllIcons.Actions.Properties) {
+ group.add(new AnAction("Edit Shortcut", "Edit Shortcut", AllIcons.ToolbarDecorator.Edit) {
{
registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0)), myActionsTree.getTree());
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/ConfigurableBase.java b/platform/platform-impl/src/com/intellij/openapi/options/ConfigurableBase.java
index 104dc7b30ec7..d7c7dca2f19b 100644
--- a/platform/platform-impl/src/com/intellij/openapi/options/ConfigurableBase.java
+++ b/platform/platform-impl/src/com/intellij/openapi/options/ConfigurableBase.java
@@ -1,18 +1,64 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
package com.intellij.openapi.options;
+import org.jetbrains.annotations.Nls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
public abstract class ConfigurableBase<UI extends ConfigurableUi<S>, S> implements SearchableConfigurable, Configurable.NoScroll {
+ private final String id;
+ private final String displayName;
+ private final String helpTopic;
+
private UI ui;
+ protected ConfigurableBase(@NotNull String id, @NotNull String displayName, @Nullable String helpTopic) {
+ this.id = id;
+ this.displayName = displayName;
+ this.helpTopic = helpTopic;
+ }
+
+ @NotNull
+ @Override
+ public final String getId() {
+ return id;
+ }
+
+ @Nls
+ @Override
+ public final String getDisplayName() {
+ return displayName;
+ }
+
+ @Nullable
+ @Override
+ public final String getHelpTopic() {
+ return helpTopic;
+ }
+
@Nullable
@Override
public Runnable enableSearch(String option) {
return null;
}
+ @NotNull
protected abstract S getSettings();
@Override
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/ConfigurableUi.java b/platform/platform-impl/src/com/intellij/openapi/options/ConfigurableUi.java
index e454099318ea..0ecb19a7ce8e 100644
--- a/platform/platform-impl/src/com/intellij/openapi/options/ConfigurableUi.java
+++ b/platform/platform-impl/src/com/intellij/openapi/options/ConfigurableUi.java
@@ -1,3 +1,18 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
package com.intellij.openapi.options;
import org.jetbrains.annotations.NotNull;
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/SimpleConfigurable.java b/platform/platform-impl/src/com/intellij/openapi/options/SimpleConfigurable.java
new file mode 100644
index 000000000000..9812165932a2
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/openapi/options/SimpleConfigurable.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.options;
+
+import com.intellij.openapi.util.Getter;
+import com.intellij.util.ReflectionUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public final class SimpleConfigurable<UI extends ConfigurableUi<S>, S> extends ConfigurableBase<UI, S> {
+ private final Class<UI> uiClass;
+ private final Getter<S> settingsGetter;
+
+ private SimpleConfigurable(@NotNull String id, @NotNull String displayName, @Nullable String helpTopic, @NotNull Class<UI> uiClass, @NotNull Getter<S> settingsGetter) {
+ super(id, displayName, helpTopic);
+
+ this.uiClass = uiClass;
+ this.settingsGetter = settingsGetter;
+ }
+
+ public static <UI extends ConfigurableUi<S>, S> SimpleConfigurable<UI, S> create(@NotNull String id, @NotNull String displayName, @Nullable String helpTopic, @NotNull Class<UI> uiClass, @NotNull Getter<S> settingsGetter) {
+ return new SimpleConfigurable<UI, S>(id, displayName, helpTopic, uiClass, settingsGetter);
+ }
+
+ public static <UI extends ConfigurableUi<S>, S> SimpleConfigurable<UI, S> create(@NotNull String id, @NotNull String displayName, @NotNull Class<UI> uiClass, @NotNull Getter<S> settingsGetter) {
+ return create(id, displayName, id, uiClass, settingsGetter);
+ }
+
+ @NotNull
+ @Override
+ protected S getSettings() {
+ return settingsGetter.get();
+ }
+
+ @Override
+ protected UI createUi() {
+ return ReflectionUtil.newInstance(uiClass);
+ }
+} \ No newline at end of file
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/TabbedConfigurable.java b/platform/platform-impl/src/com/intellij/openapi/options/TabbedConfigurable.java
index 35b75fe7c8d2..47d3881ee815 100644
--- a/platform/platform-impl/src/com/intellij/openapi/options/TabbedConfigurable.java
+++ b/platform/platform-impl/src/com/intellij/openapi/options/TabbedConfigurable.java
@@ -33,6 +33,7 @@ public abstract class TabbedConfigurable extends CompositeConfigurable<Configura
myParent = parent;
}
+ @Override
public JComponent createComponent() {
myTabbedPane = new TabbedPaneWrapper(myParent);
createConfigurableTabs();
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditor.java b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditor.java
index 6ee4a1b947ef..07e5a93670e6 100644
--- a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditor.java
+++ b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditor.java
@@ -36,6 +36,7 @@ import com.intellij.openapi.ui.*;
import com.intellij.openapi.util.ActionCallback;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.EdtRunnable;
+import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.wm.IdeGlassPaneUtil;
import com.intellij.ui.DocumentAdapter;
@@ -366,6 +367,9 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat
myOwnDetails.setContent(myContentWrapper);
myOwnDetails.setBannerMinHeight(mySearchWrapper.getHeight());
myOwnDetails.setText(getBannerText(configurable));
+ if (Registry.is("ide.file.settings.order.new")) {
+ myOwnDetails.forProject(myTree.getConfigurableProject(configurable));
+ }
final ConfigurableContent content = myConfigurable2Content.get(current);
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsTree.java b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsTree.java
index 5524df2bb2cb..e0ab24815ece 100644
--- a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsTree.java
+++ b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsTree.java
@@ -308,7 +308,7 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl
myHandle.setOpaque(false);
content.add(myHandle, BorderLayout.WEST);
content.add(myComponent, BorderLayout.CENTER);
- myProjectIcon = new JLabel(" ", AllIcons.General.ProjectConfigurable, SwingConstants.LEFT);
+ myProjectIcon = new JLabel(" ", SwingConstants.LEFT);
myProjectIcon.setOpaque(true);
content.add(myProjectIcon, BorderLayout.EAST);
myRendererComponent.add(content, BorderLayout.CENTER);
@@ -407,32 +407,17 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl
Project project = getConfigurableProject(base);
if (project != null && Registry.is("ide.file.settings.order.new")) {
myProjectIcon.setBackground(selected ? getSelectionBackground() : getBackground());
+ myProjectIcon.setIcon(selected ? AllIcons.General.ProjectConfigurableSelected : AllIcons.General.ProjectConfigurable);
myProjectIcon.setVisible(true);
- tree.setToolTipText(OptionsBundle.message(project.isDefault()
+ myProjectIcon.setToolTipText(OptionsBundle.message(project.isDefault()
? "configurable.default.project.tooltip"
: "configurable.current.project.tooltip"));
} else {
myProjectIcon.setVisible(false);
- tree.setToolTipText(null);
}
return result;
}
- private Project getConfigurableProject(SimpleNode node) {
- if (node == null) {
- return null;
- }
- if (node instanceof EditorNode) {
- EditorNode editor = (EditorNode)node;
- Configurable configurable = editor.getConfigurable();
- if (configurable instanceof ConfigurableWrapper) {
- ConfigurableWrapper wrapper = (ConfigurableWrapper)configurable;
- return wrapper.getExtensionPoint().getProject();
- }
- }
- return getConfigurableProject(node.getParent());
- }
-
protected JComponent createItemComponent() {
myTextLabel = new ErrorLabel();
return myTextLabel;
@@ -642,6 +627,24 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl
}
@Override
+ public final String getToolTipText(MouseEvent event) {
+ if (event != null) {
+ Point point = event.getPoint();
+ Component component = getDeepestRendererComponentAt(point.x, point.y);
+ if (component instanceof JLabel) {
+ JLabel label = (JLabel)component;
+ if (label.getIcon() != null) {
+ String text = label.getToolTipText();
+ if (text != null) {
+ return text;
+ }
+ }
+ }
+ }
+ return super.getToolTipText(event);
+ }
+
+ @Override
protected boolean paintNodes() {
return false;
}
@@ -877,4 +880,27 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl
}
}
+
+ Project getConfigurableProject(Configurable configurable) {
+ if (configurable instanceof ConfigurableWrapper) {
+ ConfigurableWrapper wrapper = (ConfigurableWrapper)configurable;
+ return wrapper.getExtensionPoint().getProject();
+ }
+ return getConfigurableProject(myConfigurable2Node.get(configurable));
+ }
+
+ private static Project getConfigurableProject(SimpleNode node) {
+ if (node == null) {
+ return null;
+ }
+ if (node instanceof EditorNode) {
+ EditorNode editor = (EditorNode)node;
+ Configurable configurable = editor.getConfigurable();
+ if (configurable instanceof ConfigurableWrapper) {
+ ConfigurableWrapper wrapper = (ConfigurableWrapper)configurable;
+ return wrapper.getExtensionPoint().getProject();
+ }
+ }
+ return getConfigurableProject(node.getParent());
+ }
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java
index a393d937dcfb..27bb8eb5f245 100644
--- a/platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java
@@ -56,7 +56,10 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable{
private final ScheduledFuture<?> myCheckCancelledFuture;
public ProgressManagerImpl(Application application) {
- if (/*!application.isUnitTestMode() && */!DISABLED) {
+ if (DISABLED) {
+ myCheckCancelledFuture = null;
+ }
+ else {
myCheckCancelledFuture = JobScheduler.getScheduler().scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
@@ -65,9 +68,6 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable{
}
}, 0, 10, TimeUnit.MILLISECONDS);
}
- else {
- myCheckCancelledFuture = null;
- }
}
@Override
@@ -105,8 +105,8 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable{
private static class NonCancelableIndicator extends EmptyProgressIndicator implements NonCancelableSection {
private final ProgressIndicator myOld;
- private NonCancelableIndicator(ProgressIndicator old) {
- myOld = old;
+ private NonCancelableIndicator() {
+ myOld = myThreadIndicator.get();
}
@Override
@@ -124,16 +124,17 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable{
}
}
+ @NotNull
@Override
public final NonCancelableSection startNonCancelableSection() {
- NonCancelableIndicator nonCancelor = new NonCancelableIndicator(myThreadIndicator.get());
+ NonCancelableIndicator nonCancelor = new NonCancelableIndicator();
myThreadIndicator.set(nonCancelor);
return nonCancelor;
}
@Override
public void executeNonCancelableSection(@NotNull Runnable runnable) {
- executeProcessUnderProgress(runnable, new NonCancelableIndicator(getProgressIndicator()));
+ executeProcessUnderProgress(runnable, new NonCancelableIndicator());
}
@Override
diff --git a/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java b/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java
index 6ffa084931b4..d1abc0816845 100644
--- a/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java
@@ -49,6 +49,7 @@ import com.intellij.ui.components.JBLayeredPane;
import com.intellij.ui.mac.foundation.Foundation;
import com.intellij.ui.mac.foundation.ID;
import com.intellij.ui.mac.foundation.MacUtil;
+import com.intellij.util.ReflectionUtil;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -59,7 +60,6 @@ import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferStrategy;
import java.lang.ref.WeakReference;
-import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -887,18 +887,12 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer implements FocusTra
if (rootPane != null) { // Workaround for bug in native code to hold rootPane
try {
- Field field = rootPane.getClass().getDeclaredField("glassPane");
- field.setAccessible(true);
- field.set(rootPane, null);
+ ReflectionUtil.resetField(rootPane.getClass(), null, "glassPane");
+ ReflectionUtil.resetField(rootPane.getClass(), null, "contentPane");
- field = rootPane.getClass().getDeclaredField("contentPane");
- field.setAccessible(true);
- field.set(rootPane, null);
rootPane = null;
- field = Window.class.getDeclaredField("windowListener");
- field.setAccessible(true);
- field.set(this, null);
+ ReflectionUtil.resetField(Window.class, null, "windowListener");
}
catch (Exception ignored) {
}
@@ -906,9 +900,7 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer implements FocusTra
// http://bugs.sun.com/view_bug.do?bug_id=6614056
try {
- final Field field = Dialog.class.getDeclaredField("modalDialogs");
- field.setAccessible(true);
- final List<?> list = (List<?>)field.get(null);
+ final List<?> list = ReflectionUtil.getField(Dialog.class, null, null, "modalDialogs");
list.remove(this);
}
catch (final Exception ignored) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java
index 9dd3dd21f879..7e1c81ad2fbc 100755
--- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java
+++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java
@@ -618,12 +618,21 @@ public final class UpdateChecker {
Future<?> downloadThreadFuture = ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
public void run() {
try {
- URL requestUrl = new URL(url);
- if (!StandardFileSystems.FILE_PROTOCOL.equals(requestUrl.getProtocol())) {
- HttpConfigurable.getInstance().prepareURL(url);
- requestUrl = new URL(url + (url.contains("?") ? "&" : "?") + "build=" + ApplicationInfo.getInstance().getBuild().asString());
+ final String urlToCheck;
+ if (!StandardFileSystems.FILE_PROTOCOL.equals(new URL(url).getProtocol())) {
+ urlToCheck = url + (url.contains("?") ? "&" : "?") + "build=" + ApplicationInfo.getInstance().getBuild().asString();
+ } else {
+ urlToCheck = url;
}
- inputStreams[0] = requestUrl.openStream();
+
+ HttpURLConnection connection = ApplicationManager.getApplication() != null ?
+ HttpConfigurable.getInstance().openHttpConnection(urlToCheck) :
+ (HttpURLConnection)new URL(urlToCheck).openConnection();
+ connection.setReadTimeout(HttpConfigurable.CONNECTION_TIMEOUT);
+ connection.setConnectTimeout(HttpConfigurable.CONNECTION_TIMEOUT);
+ connection.connect();
+
+ inputStreams[0] = connection.getInputStream();
}
catch (IOException e) {
exception[0] = e;
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/HttpFileSystemBase.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/HttpFileSystemBase.java
index 7177138d1d9a..a2d32fd1307f 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/HttpFileSystemBase.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/HttpFileSystemBase.java
@@ -67,7 +67,9 @@ public abstract class HttpFileSystemBase extends HttpFileSystem {
@Override
@NotNull
public VirtualFile createChild(@NotNull VirtualFile parent, @NotNull String name, boolean isDirectory) {
- return getRemoteFileManager().getOrCreateFile((VirtualFileImpl)parent, Urls.newFromIdea(parent.getUrl() + '/' + name), parent.getPath() + '/' + name, isDirectory);
+ String parentPath = parent.getPath();
+ boolean hasEndSlash = parentPath.charAt(parentPath.length() - 1) == '/';
+ return getRemoteFileManager().getOrCreateFile((HttpVirtualFileImpl)parent, Urls.newFromIdea(parent.getUrl() + (hasEndSlash ? "" : '/') + name), parentPath + (hasEndSlash ? "" : '/') + name, isDirectory);
}
@Override
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/VirtualFileImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/HttpVirtualFileImpl.java
index ba49cfb5a690..a8a1a447d66c 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/VirtualFileImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/HttpVirtualFileImpl.java
@@ -35,7 +35,7 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
-class VirtualFileImpl extends HttpVirtualFile {
+class HttpVirtualFileImpl extends HttpVirtualFile {
private final HttpFileSystemBase myFileSystem;
@Nullable private final RemoteFileInfoImpl myFileInfo;
private FileType myInitialFileType;
@@ -45,7 +45,7 @@ class VirtualFileImpl extends HttpVirtualFile {
private List<VirtualFile> myChildren;
- VirtualFileImpl(@NotNull HttpFileSystemBase fileSystem, @Nullable VirtualFileImpl parent, String path, @Nullable RemoteFileInfoImpl fileInfo) {
+ HttpVirtualFileImpl(@NotNull HttpFileSystemBase fileSystem, @Nullable HttpVirtualFileImpl parent, String path, @Nullable RemoteFileInfoImpl fileInfo) {
if (parent != null) {
if (parent.myChildren == null) {
parent.myChildren = new SmartList<VirtualFile>();
@@ -63,7 +63,7 @@ class VirtualFileImpl extends HttpVirtualFile {
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
- VirtualFileImpl file = VirtualFileImpl.this;
+ HttpVirtualFileImpl file = HttpVirtualFileImpl.this;
FileDocumentManager.getInstance().reloadFiles(file);
if (!localFile.getFileType().equals(myInitialFileType)) {
FileContentUtilCore.reparseFiles(file);
@@ -135,8 +135,7 @@ class VirtualFileImpl extends HttpVirtualFile {
@Override
public VirtualFile getParent() {
- if (myParentPath == null) return null;
- return myFileSystem.findFileByPath(myParentPath, true);
+ return myParentPath == null ? null : myFileSystem.findFileByPath(myParentPath, true);
}
@Override
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/RemoteFileManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/RemoteFileManagerImpl.java
index b69c0befd376..904233a35cdf 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/RemoteFileManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/RemoteFileManagerImpl.java
@@ -17,7 +17,6 @@ package com.intellij.openapi.vfs.impl.http;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.util.Disposer;
-import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.ex.http.HttpVirtualFileListener;
import com.intellij.util.EventDispatcher;
@@ -35,7 +34,10 @@ import java.util.Map;
*/
public class RemoteFileManagerImpl extends RemoteFileManager implements Disposable {
private final LocalFileStorage myStorage;
- private final Map<Pair<Boolean, Url>, VirtualFileImpl> myRemoteFiles = new THashMap<Pair<Boolean, Url>, VirtualFileImpl>();
+
+ private final Map<Url, HttpVirtualFileImpl> remoteFiles = new THashMap<Url, HttpVirtualFileImpl>();
+ private final Map<Url, HttpVirtualFileImpl> remoteDirectories = new THashMap<Url, HttpVirtualFileImpl>();
+
private final EventDispatcher<HttpVirtualFileListener> myDispatcher = EventDispatcher.create(HttpVirtualFileListener.class);
private final List<RemoteContentProvider> myProviders = new ArrayList<RemoteContentProvider>();
private final DefaultRemoteContentProvider myDefaultRemoteContentProvider;
@@ -55,19 +57,19 @@ public class RemoteFileManagerImpl extends RemoteFileManager implements Disposab
return myDefaultRemoteContentProvider;
}
- public synchronized VirtualFileImpl getOrCreateFile(@Nullable VirtualFileImpl parent, @NotNull Url url, @NotNull String path, final boolean directory) {
- Pair<Boolean, Url> key = Pair.create(directory, url);
- VirtualFileImpl file = myRemoteFiles.get(key);
+ public synchronized HttpVirtualFileImpl getOrCreateFile(@Nullable HttpVirtualFileImpl parent, @NotNull Url url, @NotNull String path, final boolean directory) {
+ Map<Url, HttpVirtualFileImpl> cache = directory ? remoteDirectories : remoteFiles;
+ HttpVirtualFileImpl file = cache.get(url);
if (file == null) {
if (directory) {
- file = new VirtualFileImpl(getHttpFileSystem(url), parent, path, null);
+ file = new HttpVirtualFileImpl(getHttpFileSystem(url), parent, path, null);
}
else {
RemoteFileInfoImpl fileInfo = new RemoteFileInfoImpl(url, this);
- file = new VirtualFileImpl(getHttpFileSystem(url), parent, path, fileInfo);
+ file = new HttpVirtualFileImpl(getHttpFileSystem(url), parent, path, fileInfo);
fileInfo.addDownloadingListener(new MyDownloadingListener(file));
}
- myRemoteFiles.put(key, file);
+ cache.put(url, file);
}
return file;
}
@@ -133,9 +135,9 @@ public class RemoteFileManagerImpl extends RemoteFileManager implements Disposab
}
private class MyDownloadingListener extends FileDownloadingAdapter {
- private final VirtualFileImpl myFile;
+ private final HttpVirtualFileImpl myFile;
- public MyDownloadingListener(final VirtualFileImpl file) {
+ public MyDownloadingListener(final HttpVirtualFileImpl file) {
myFile = file;
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarHandler.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarHandler.java
index efaf84d08b8e..98c3884cc993 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarHandler.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/jar/JarHandler.java
@@ -22,6 +22,7 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.util.NotNullLazyValue;
+import com.intellij.openapi.util.ShutDownTracker;
import com.intellij.openapi.util.io.FileAttributes;
import com.intellij.openapi.util.io.FileSystemUtil;
import com.intellij.openapi.util.io.FileUtil;
@@ -30,6 +31,7 @@ import com.intellij.openapi.vfs.JarFileSystem;
import com.intellij.openapi.vfs.VfsBundle;
import com.intellij.openapi.vfs.impl.ZipHandler;
import com.intellij.openapi.vfs.newvfs.persistent.FSRecords;
+import com.intellij.openapi.vfs.newvfs.persistent.FlushingDaemon;
import com.intellij.util.io.DataExternalizer;
import com.intellij.util.io.EnumeratorStringDescriptor;
import com.intellij.util.io.IOUtil;
@@ -169,7 +171,6 @@ public class JarHandler extends ZipHandler {
info = new CacheLibraryInfo(mirrorFile.getName(), originalAttributes.lastModified, originalAttributes.length);
CacheLibraryInfo.ourCachedLibraryInfo.put(path, info);
- CacheLibraryInfo.ourCachedLibraryInfo.force();
return mirrorFile;
}
catch (IOException ex) {
@@ -260,6 +261,23 @@ public class JarHandler extends ZipHandler {
}
assert info != null;
ourCachedLibraryInfo = info;
+ FlushingDaemon.everyFiveSeconds(new Runnable() {
+ @Override
+ public void run() {
+ flushCachedLibraryInfos();
+ }
+ });
+
+ ShutDownTracker.getInstance().registerShutdownTask(new Runnable() {
+ @Override
+ public void run() {
+ flushCachedLibraryInfos();
+ }
+ });
+ }
+
+ private static void flushCachedLibraryInfos() {
+ if (ourCachedLibraryInfo.isDirty()) ourCachedLibraryInfo.force();
}
private CacheLibraryInfo(@NotNull String path, long time, long length) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/ex/IdeFocusTraversalPolicy.java b/platform/platform-impl/src/com/intellij/openapi/wm/ex/IdeFocusTraversalPolicy.java
index ba44d2b21d10..2ecb28327857 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/ex/IdeFocusTraversalPolicy.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/ex/IdeFocusTraversalPolicy.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,17 +19,15 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.impl.EditorComponentImpl;
import com.intellij.openapi.fileEditor.impl.EditorWindowHolder;
import com.intellij.openapi.util.Computable;
-import org.jetbrains.annotations.NonNls;
+import com.intellij.util.ReflectionUtil;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.text.JTextComponent;
import java.awt.*;
-import java.lang.reflect.Field;
public class IdeFocusTraversalPolicy extends LayoutFocusTraversalPolicyExt {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.wm.ex.IdeFocusTraversalPolicy");
- @NonNls private static final String FOCUS_TRAVERSAL_POLICY_FIELD = "focusTraversalPolicy";
protected Component getDefaultComponentImpl(Container focusCycleRoot) {
if (!(focusCycleRoot instanceof JComponent)) {
@@ -103,15 +101,7 @@ public class IdeFocusTraversalPolicy extends LayoutFocusTraversalPolicyExt {
}
private static FocusTraversalPolicy getFocusTraversalPolicyAwtImpl(final JComponent component) {
- try {
- final Field field = Container.class.getDeclaredField(FOCUS_TRAVERSAL_POLICY_FIELD);
- field.setAccessible(true);
- return (FocusTraversalPolicy)field.get(component);
- }
- catch (Exception e) {
- LOG.error(e);
- return null;
- }
+ return ReflectionUtil.getField(Container.class, component, FocusTraversalPolicy.class, "focusTraversalPolicy");
}
protected final boolean accept(final Component aComponent) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeGlassPaneImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeGlassPaneImpl.java
index 83696e07c7f8..71f964504102 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeGlassPaneImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeGlassPaneImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,8 +20,9 @@ import com.intellij.ide.IdeTooltipManager;
import com.intellij.ide.dnd.DnDAware;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.ui.Divider;
import com.intellij.openapi.ui.Painter;
-import com.intellij.openapi.ui.Splitter;
import com.intellij.openapi.ui.impl.GlassPaneDialogWrapperPeer;
import com.intellij.openapi.ui.popup.Balloon;
import com.intellij.openapi.ui.popup.JBPopupFactory;
@@ -42,6 +43,8 @@ import java.util.List;
public class IdeGlassPaneImpl extends JPanel implements IdeGlassPaneEx, IdeEventQueue.EventDispatcher, Painter.Listener {
+ private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.wm.impl.IdeGlassPaneImpl");
+
private final List<EventListener> myMouseListeners = new ArrayList<EventListener>();
private final Set<EventListener> mySortedMouseListeners = new TreeSet<EventListener>(new Comparator<EventListener>() {
@Override
@@ -360,9 +363,12 @@ public class IdeGlassPaneImpl extends JPanel implements IdeGlassPaneEx, IdeEvent
}
else {
cursor = Cursor.getDefaultCursor();
- getRootPane().setCursor(cursor);
-
-
+ JRootPane rootPane = getRootPane();
+ if (rootPane != null) {
+ rootPane.setCursor(cursor);
+ } else {
+ LOG.warn("Root pane is null. Event: " + e);
+ }
restoreLastComponent(null);
myLastOriginalCursor = null;
myLastCursorComponent = null;
@@ -375,7 +381,7 @@ public class IdeGlassPaneImpl extends JPanel implements IdeGlassPaneEx, IdeEvent
private boolean canProcessCursorFor(Component target) {
if (target instanceof JMenu ||
target instanceof JMenuItem ||
- target instanceof Splitter.Divider ||
+ target instanceof Divider ||
target instanceof JSeparator ||
(target instanceof JEditorPane && ((JEditorPane)target).getEditorKit() instanceof HTMLEditorKit)) {
return false;
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeadlessManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeadlessManagerImpl.java
index d6e1d9994500..8b78b1632f79 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeadlessManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeadlessManagerImpl.java
@@ -27,9 +27,11 @@ import com.intellij.openapi.actionSystem.ActionGroup;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.DataProvider;
import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.ui.popup.Balloon;
import com.intellij.openapi.util.ActionCallback;
+import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.wm.*;
@@ -41,7 +43,7 @@ import com.intellij.ui.content.ContentFactory;
import com.intellij.ui.content.ContentManager;
import com.intellij.ui.content.ContentManagerListener;
import com.intellij.util.ArrayUtil;
-import org.jetbrains.annotations.NonNls;
+import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -50,12 +52,18 @@ import javax.swing.event.HyperlinkListener;
import java.awt.*;
import java.awt.event.InputEvent;
import java.beans.PropertyChangeListener;
-import java.util.ArrayList;
-import java.util.Collections;
+import java.util.*;
import java.util.List;
@SuppressWarnings({"ConstantConditions"})
public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx {
+ private final Map<String, ToolWindow> myToolWindows = new HashMap<String, ToolWindow>();
+ private final Project myProject;
+
+ public ToolWindowHeadlessManagerImpl(Project project) {
+ myProject = project;
+ }
+
@Override
public boolean canShowNotification(@NotNull String toolWindowId) {
return false;
@@ -65,7 +73,184 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx {
public void notifyByBalloon(@NotNull final String toolWindowId, @NotNull final MessageType type, @NotNull final String htmlBody) {
}
- public static final ToolWindow HEADLESS_WINDOW = new ToolWindowEx() {
+ private ToolWindow doRegisterToolWindow(final String id, @Nullable Disposable parentDisposable) {
+ MockToolWindow tw = new MockToolWindow(myProject);
+ myToolWindows.put(id, tw);
+ if (parentDisposable != null) {
+ Disposer.register(parentDisposable, new Disposable() {
+ @Override
+ public void dispose() {
+ unregisterToolWindow(id);
+ }
+ });
+ }
+ return tw;
+ }
+
+ @Override
+ public ToolWindow registerToolWindow(@NotNull String id,
+ @NotNull JComponent component,
+ @NotNull ToolWindowAnchor anchor,
+ Disposable parentDisposable,
+ boolean canWorkInDumbMode) {
+ return doRegisterToolWindow(id, parentDisposable);
+ }
+
+ @Override
+ public ToolWindow registerToolWindow(@NotNull String id, @NotNull JComponent component, @NotNull ToolWindowAnchor anchor) {
+ return doRegisterToolWindow(id, null);
+ }
+
+ @Override
+ public ToolWindow registerToolWindow(@NotNull String id,
+ @NotNull JComponent component,
+ @NotNull ToolWindowAnchor anchor,
+ Disposable parentDisposable,
+ boolean canWorkInDumbMode,
+ boolean canCloseContents) {
+ return doRegisterToolWindow(id, parentDisposable);
+ }
+
+ @Override
+ public ToolWindow registerToolWindow(@NotNull String id,
+ @NotNull JComponent component,
+ @NotNull ToolWindowAnchor anchor,
+ Disposable parentDisposable) {
+ return doRegisterToolWindow(id, parentDisposable);
+ }
+
+ @Override
+ public ToolWindow registerToolWindow(@NotNull final String id, final boolean canCloseContent, @NotNull final ToolWindowAnchor anchor) {
+ return doRegisterToolWindow(id, null);
+ }
+
+ @Override
+ public ToolWindow registerToolWindow(@NotNull final String id,
+ final boolean canCloseContent,
+ @NotNull final ToolWindowAnchor anchor,
+ final boolean secondary) {
+ return doRegisterToolWindow(id, null);
+ }
+
+ @Override
+ public ToolWindow registerToolWindow(@NotNull final String id, final boolean canCloseContent, @NotNull final ToolWindowAnchor anchor,
+ final Disposable parentDisposable, final boolean dumbAware) {
+ return doRegisterToolWindow(id, parentDisposable);
+ }
+
+ @Override
+ public void unregisterToolWindow(@NotNull String id) {
+ myToolWindows.remove(id);
+ }
+
+ @Override
+ public void activateEditorComponent() {
+ }
+
+ @Override
+ public boolean isEditorComponentActive() {
+ return false;
+ }
+
+ @Override
+ public String[] getToolWindowIds() {
+ return ArrayUtil.EMPTY_STRING_ARRAY;
+ }
+
+ @Override
+ public String getActiveToolWindowId() {
+ return null;
+ }
+
+ @Override
+ public ToolWindow getToolWindow(String id) {
+ return myToolWindows.get(id);
+ }
+
+ @Override
+ public void invokeLater(Runnable runnable) {
+ }
+
+ @Override
+ public IdeFocusManager getFocusManager() {
+ return IdeFocusManagerHeadless.INSTANCE;
+ }
+
+ @Override
+ public void notifyByBalloon(@NotNull final String toolWindowId,
+ @NotNull final MessageType type,
+ @NotNull final String text,
+ @Nullable final Icon icon,
+ @Nullable final HyperlinkListener listener) {
+ }
+
+ @Override
+ public Balloon getToolWindowBalloon(String id) {
+ return null;
+ }
+
+ @Override
+ public void initToolWindow(ToolWindowEP bean) {
+
+ }
+
+ @Override
+ public void addToolWindowManagerListener(@NotNull ToolWindowManagerListener l) {
+
+ }
+
+ @Override
+ public void removeToolWindowManagerListener(@NotNull ToolWindowManagerListener l) {
+ }
+
+ @Override
+ public String getLastActiveToolWindowId() {
+ return null;
+ }
+
+ @Override
+ public String getLastActiveToolWindowId(Condition<JComponent> condition) {
+ return null;
+ }
+
+ @Override
+ public DesktopLayout getLayout() {
+ return new DesktopLayout();
+ }
+
+ @Override
+ public void setLayoutToRestoreLater(DesktopLayout layout) {
+ }
+
+ @Override
+ public DesktopLayout getLayoutToRestoreLater() {
+ return new DesktopLayout();
+ }
+
+ @Override
+ public void setLayout(@NotNull DesktopLayout layout) {
+ }
+
+ @Override
+ public void clearSideStack() {
+ }
+
+ @Override
+ public void hideToolWindow(@NotNull final String id, final boolean hideSide) {
+ }
+
+ @Override
+ public List<String> getIdsOn(@NotNull final ToolWindowAnchor anchor) {
+ return new ArrayList<String>();
+ }
+
+ public static class MockToolWindow implements ToolWindowEx {
+ ContentManager myContentManager = new MockContentManager();
+
+ public MockToolWindow(@NotNull Project project) {
+ Disposer.register(project, myContentManager);
+ }
+
@Override
public boolean isActive() {
return false;
@@ -206,7 +391,7 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx {
@Override
public ContentManager getContentManager() {
- return MOCK_CONTENT_MANAGER;
+ return myContentManager;
}
@Override
@@ -270,9 +455,9 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx {
public boolean isUseLastFocusedOnActivation() {
return false;
}
- };
+ }
- @NonNls private static final ContentManager MOCK_CONTENT_MANAGER = new ContentManager() {
+ private static class MockContentManager implements ContentManager {
private final List<Content> myContents = new ArrayList<Content>();
private Content mySelected;
@@ -284,27 +469,33 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx {
@Override
public void addContent(@NotNull final Content content) {
+ myContents.add(content);
+ if (mySelected == null) mySelected = content;
}
@Override
public void addContent(@NotNull Content content, int order) {
myContents.add(order, content);
+ if (mySelected == null) mySelected = content;
}
@Override
public void addContent(@NotNull final Content content, final Object constraints) {
+ addContent(content);
}
@Override
- public void addContentManagerListener(@NotNull final ContentManagerListener l) {
+ public void addSelectedContent(@NotNull final Content content) {
+ addContent(content);
+ setSelectedContent(content);
}
@Override
- public void addDataProvider(@NotNull final DataProvider provider) {
+ public void addContentManagerListener(@NotNull final ContentManagerListener l) {
}
@Override
- public void addSelectedContent(@NotNull final Content content) {
+ public void addDataProvider(@NotNull final DataProvider provider) {
}
@Override
@@ -319,6 +510,9 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx {
@Override
public Content findContent(final String displayName) {
+ for (Content each : myContents) {
+ if (each.getDisplayName().equals(displayName)) return each;
+ }
return null;
}
@@ -359,18 +553,24 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx {
@Override
public Content getContent(final JComponent component) {
+ Content[] contents = getContents();
+ for (Content content : contents) {
+ if (Comparing.equal(component, content.getComponent())) {
+ return content;
+ }
+ }
return null;
}
@Override
@Nullable
public Content getContent(final int index) {
- return null;
+ return myContents.get(index);
}
@Override
public int getContentCount() {
- return 0;
+ return myContents.size();
}
@Override
@@ -381,7 +581,7 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx {
@Override
public int getIndexOfContent(final Content content) {
- return -1;
+ return myContents.indexOf(content);
}
@Override
@@ -393,35 +593,37 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx {
@Override
@NotNull
public Content[] getSelectedContents() {
- return new Content[0];
+ return mySelected != null ? new Content[]{mySelected} : new Content[0];
}
@Override
public boolean isSelected(@NotNull final Content content) {
- return false;
+ return content == mySelected;
}
@Override
public void removeAllContents(final boolean dispose) {
for (int i = myContents.size() - 1; i >= 0; i--) {
Content content = myContents.get(i);
- removeContent(content, true);
+ removeContent(content, dispose);
}
mySelected = null;
}
@Override
public boolean removeContent(@NotNull final Content content, final boolean dispose) {
- Disposer.dispose(content);
+ if (dispose) Disposer.dispose(content);
+ boolean result = myContents.remove(content);
if (mySelected == content) {
- mySelected = null;
+ mySelected = ContainerUtil.getFirstItem(myContents);
}
- return myContents.remove(content);
+ return result;
}
@NotNull
@Override
public ActionCallback removeContent(@NotNull Content content, boolean dispose, boolean trackFocus, boolean implicitFocus) {
+ removeContent(content, dispose);
return new ActionCallback.Done();
}
@@ -451,33 +653,36 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx {
@NotNull
@Override
public ActionCallback setSelectedContentCB(@NotNull Content content) {
+ setSelectedContent(content);
return new ActionCallback.Done();
}
@Override
public void setSelectedContent(@NotNull final Content content, final boolean requestFocus) {
+ setSelectedContent(content);
}
@NotNull
@Override
public ActionCallback setSelectedContentCB(@NotNull final Content content, final boolean requestFocus) {
- return new ActionCallback.Done();
+ return setSelectedContentCB(content);
}
@Override
public void setSelectedContent(@NotNull Content content, boolean requestFocus, boolean forcedFocus) {
+ setSelectedContent(content);
}
@NotNull
@Override
public ActionCallback setSelectedContentCB(@NotNull final Content content, final boolean requestFocus, final boolean forcedFocus) {
- return new ActionCallback.Done();
+ return setSelectedContentCB(content);
}
@NotNull
@Override
public ActionCallback setSelectedContent(@NotNull Content content, boolean requestFocus, boolean forcedFocus, boolean implicit) {
- return new ActionCallback.Done();
+ return setSelectedContentCB(content);
}
@NotNull
@@ -506,161 +711,4 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx {
public ContentFactory getFactory() {
return ServiceManager.getService(ContentFactory.class);
}
- };
-
- @Override
- public ToolWindow registerToolWindow(@NotNull String id,
- @NotNull JComponent component,
- @NotNull ToolWindowAnchor anchor,
- Disposable parentDisposable,
- boolean canWorkInDumbMode) {
- return HEADLESS_WINDOW;
- }
-
- @Override
- public ToolWindow registerToolWindow(@NotNull String id, @NotNull JComponent component, @NotNull ToolWindowAnchor anchor) {
- return HEADLESS_WINDOW;
- }
-
- @Override
- public ToolWindow registerToolWindow(@NotNull String id,
- @NotNull JComponent component,
- @NotNull ToolWindowAnchor anchor,
- Disposable parentDisposable,
- boolean canWorkInDumbMode,
- boolean canCloseContents) {
- return HEADLESS_WINDOW;
- }
-
- @Override
- public ToolWindow registerToolWindow(@NotNull String id,
- @NotNull JComponent component,
- @NotNull ToolWindowAnchor anchor,
- Disposable parentDisposable) {
- return HEADLESS_WINDOW;
- }
-
- @Override
- public ToolWindow registerToolWindow(@NotNull final String id, final boolean canCloseContent, @NotNull final ToolWindowAnchor anchor) {
- return HEADLESS_WINDOW;
- }
-
- @Override
- public ToolWindow registerToolWindow(@NotNull final String id,
- final boolean canCloseContent,
- @NotNull final ToolWindowAnchor anchor,
- final boolean secondary) {
- return HEADLESS_WINDOW;
- }
-
- @Override
- public ToolWindow registerToolWindow(@NotNull final String id, final boolean canCloseContent, @NotNull final ToolWindowAnchor anchor,
- final Disposable parentDisposable, final boolean dumbAware) {
- return HEADLESS_WINDOW;
- }
-
- @Override
- public void unregisterToolWindow(@NotNull String id) {
- }
-
- @Override
- public void activateEditorComponent() {
- }
-
- @Override
- public boolean isEditorComponentActive() {
- return false;
- }
-
- @Override
- public String[] getToolWindowIds() {
- return ArrayUtil.EMPTY_STRING_ARRAY;
- }
-
- @Override
- public String getActiveToolWindowId() {
- return null;
- }
-
- @Override
- public ToolWindow getToolWindow(String id) {
- return HEADLESS_WINDOW;
- }
-
- @Override
- public void invokeLater(Runnable runnable) {
- }
-
- @Override
- public IdeFocusManager getFocusManager() {
- return IdeFocusManagerHeadless.INSTANCE;
- }
-
- @Override
- public void notifyByBalloon(@NotNull final String toolWindowId,
- @NotNull final MessageType type,
- @NotNull final String text,
- @Nullable final Icon icon,
- @Nullable final HyperlinkListener listener) {
- }
-
- @Override
- public Balloon getToolWindowBalloon(String id) {
- return null;
- }
-
- @Override
- public void initToolWindow(ToolWindowEP bean) {
-
- }
-
- @Override
- public void addToolWindowManagerListener(@NotNull ToolWindowManagerListener l) {
-
- }
-
- @Override
- public void removeToolWindowManagerListener(@NotNull ToolWindowManagerListener l) {
- }
-
- @Override
- public String getLastActiveToolWindowId() {
- return null;
- }
-
- @Override
- public String getLastActiveToolWindowId(Condition<JComponent> condition) {
- return null;
- }
-
- @Override
- public DesktopLayout getLayout() {
- return new DesktopLayout();
- }
-
- @Override
- public void setLayoutToRestoreLater(DesktopLayout layout) {
- }
-
- @Override
- public DesktopLayout getLayoutToRestoreLater() {
- return new DesktopLayout();
- }
-
- @Override
- public void setLayout(@NotNull DesktopLayout layout) {
- }
-
- @Override
- public void clearSideStack() {
- }
-
- @Override
- public void hideToolWindow(@NotNull final String id, final boolean hideSide) {
- }
-
- @Override
- public List<String> getIdsOn(@NotNull final ToolWindowAnchor anchor) {
- return new ArrayList<String>();
- }
-}
+ }}
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/X11UiUtil.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/X11UiUtil.java
index 6c6bcd137949..120579bcb809 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/X11UiUtil.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/X11UiUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,9 +16,11 @@
package com.intellij.openapi.wm.impl;
import com.intellij.Patches;
+import com.intellij.execution.util.ExecUtil;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.registry.Registry;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.wm.IdeFrame;
import com.intellij.openapi.wm.WindowManager;
import org.jetbrains.annotations.Nullable;
@@ -29,6 +31,8 @@ import java.awt.*;
import java.awt.peer.ComponentPeer;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import static com.intellij.util.ArrayUtil.newLongArray;
import static com.intellij.util.containers.ContainerUtil.newHashSet;
@@ -254,11 +258,17 @@ public class X11UiUtil {
setWM("MARCO_WM", "METACITY_WM");
}
else if ("awesome".equals(wmName)) {
- setWM("SAWFISH_WM");
+ String version = getAwesomeWMVersion();
+ if (StringUtil.compareVersionNumbers(version, "3.5") >= 0) {
+ setWM("SAWFISH_WM");
+ }
+ else if (version != null) {
+ setWM("OTHER_NONREPARENTING_WM", "LG3D_WM");
+ }
}
}
- catch (Throwable e) {
- LOG.warn(e);
+ catch (Throwable t) {
+ LOG.warn(t);
}
}
@@ -273,6 +283,7 @@ public class X11UiUtil {
if (id != null) {
field(xwmClass, "awt_wmgr").set(null, id);
field(xwmClass, "WMID").set(xwm, id);
+ LOG.info("impersonated WM: " + wmConstant);
break;
}
}
@@ -281,6 +292,23 @@ public class X11UiUtil {
}
}
+ @Nullable
+ private static String getAwesomeWMVersion() {
+ try {
+ String version = ExecUtil.execAndReadLine("awesome", "--version");
+ if (version != null) {
+ Matcher m = Pattern.compile("awesome v([0-9.]+)").matcher(version);
+ if (m.find()) {
+ return m.group(1);
+ }
+ }
+ }
+ catch (Throwable t) {
+ LOG.warn(t);
+ }
+ return null;
+ }
+
// full-screen support
public static boolean isFullScreenSupported() {
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/commands/RequestFocusInEditorComponentCmd.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/commands/RequestFocusInEditorComponentCmd.java
index 7a772e7aed34..2c681856a328 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/commands/RequestFocusInEditorComponentCmd.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/commands/RequestFocusInEditorComponentCmd.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,11 +19,13 @@
*/
package com.intellij.openapi.wm.impl.commands;
+import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileEditor.impl.EditorWindow;
import com.intellij.openapi.fileEditor.impl.EditorWithProviderComposite;
import com.intellij.openapi.fileEditor.impl.EditorsSplitters;
import com.intellij.openapi.util.ActionCallback;
import com.intellij.openapi.util.Expirable;
+import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.openapi.wm.impl.FloatingDecorator;
import com.intellij.openapi.wm.impl.IdeFrameImpl;
@@ -44,10 +46,16 @@ public final class RequestFocusInEditorComponentCmd extends FinalizableCommand{
private final IdeFocusManager myFocusManager;
private final Expirable myTimestamp;
+ private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.wm.impl.commands.RequestFocusInEditorComponentCmd");
+
public RequestFocusInEditorComponentCmd(@NotNull final EditorsSplitters splitters, IdeFocusManager
focusManager, final Runnable finishCallBack, boolean forced){
super(finishCallBack);
+ boolean shouldLogFocuses = Registry.is("ide.log.focuses");
+ if (shouldLogFocuses) {
+ LOG.info(new Exception());
+ }
myComponent = null;
final EditorWindow window = splitters.getCurrentWindow();
if (window != null) {
@@ -94,7 +102,8 @@ public final class RequestFocusInEditorComponentCmd extends FinalizableCommand{
}
if(myComponent != null){
- myFocusManager.requestFocus(myComponent, myForced).notifyWhenDone(myDoneCallback).doWhenDone(new Runnable() {
+ final boolean forced = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() == null;
+ myFocusManager.requestFocus(myComponent, myForced || forced).notifyWhenDone(myDoneCallback).doWhenDone(new Runnable() {
public void run() {
// if owner is active window or it has active child window which isn't floating decorator then
// don't bring owner window to font. If we will make toFront every time then it's possible
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/RecentProjectPanel.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/RecentProjectPanel.java
index 9140fc200a77..82dba7430827 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/RecentProjectPanel.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/RecentProjectPanel.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -186,14 +186,11 @@ public class RecentProjectPanel extends JPanel {
private String getTitle2Text(ReopenProjectAction action, JComponent pathLabel) {
String fullText = action.getProjectPath();
- int labelWidth = pathLabel.getWidth();
if (fullText == null || fullText.length() == 0) return " ";
- String home = SystemProperties.getUserHome();
- if (FileUtil.startsWith(fullText, home)) {
- fullText = "~" + fullText.substring(home.length());
- }
+ fullText = FileUtil.getLocationRelativeToUserHome(fullText, false);
+ int labelWidth = pathLabel.getWidth();
if (pathLabel.getFontMetrics(pathLabel.getFont()).stringWidth(fullText) > labelWidth) {
return myPathShortener.getShortPath(action);
}
diff --git a/platform/platform-impl/src/com/intellij/remote/RemoteConnectionCredentialsWrapper.java b/platform/platform-impl/src/com/intellij/remote/RemoteConnectionCredentialsWrapper.java
index e31b067e5d79..8d85ae106c44 100644
--- a/platform/platform-impl/src/com/intellij/remote/RemoteConnectionCredentialsWrapper.java
+++ b/platform/platform-impl/src/com/intellij/remote/RemoteConnectionCredentialsWrapper.java
@@ -116,11 +116,24 @@ public class RemoteConnectionCredentialsWrapper {
return new IllegalStateException("Unknown connection type"); //TODO
}
- public void copyTo(RemoteConnectionCredentialsWrapper copy) {
+ public void copyTo(final RemoteConnectionCredentialsWrapper copy) {
copy.myCredentialsTypeHolder = new UserDataHolderBase();
- copy.setPlainSshCredentials(getPlainSshCredentials());
- copy.setVagrantConnectionType(getVagrantCredentials());
- copy.setWebDeploymentCredentials(getWebDeploymentCredentials());
+ switchType(new RemoteSdkConnectionAcceptor() {
+ @Override
+ public void ssh(@NotNull RemoteCredentialsHolder cred) {
+ copy.setPlainSshCredentials(getPlainSshCredentials());
+ }
+
+ @Override
+ public void vagrant(@NotNull VagrantBasedCredentialsHolder cred) {
+ copy.setVagrantConnectionType(getVagrantCredentials());
+ }
+
+ @Override
+ public void deployment(@NotNull WebDeploymentCredentialsHolder cred) {
+ copy.setWebDeploymentCredentials(getWebDeploymentCredentials());
+ }
+ });
}
public String getId() {
diff --git a/platform/platform-impl/src/com/intellij/remote/VagrantSupport.java b/platform/platform-impl/src/com/intellij/remote/VagrantSupport.java
index a5ebae6fe567..9e2b60a54416 100644
--- a/platform/platform-impl/src/com/intellij/remote/VagrantSupport.java
+++ b/platform/platform-impl/src/com/intellij/remote/VagrantSupport.java
@@ -21,6 +21,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.Consumer;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -43,6 +44,10 @@ public abstract class VagrantSupport {
@NotNull
public abstract RemoteCredentials getVagrantSettings(@NotNull Project project, String vagrantFolder);
+ public abstract void getVagrantSettingsAsync(@Nullable Project project,
+ @NotNull String vagrantFolder,
+ @NotNull Consumer<RemoteCredentials> onSuccess);
+
@NotNull
public abstract RemoteCredentials getCredentials(@NotNull String folder) throws IOException;
diff --git a/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java b/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java
index 4e65063e7939..d8b204cfd76c 100644
--- a/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java
+++ b/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java
@@ -223,6 +223,7 @@ public abstract class AbstractExpandableItemsHandler<KeyType, ComponentType exte
if (selected == null
|| !myComponent.isEnabled()
|| !myComponent.isShowing()
+ || !myComponent.getVisibleRect().intersects(getVisibleRect(selected))
|| !myComponent.isFocusOwner() && !processIfUnfocused
|| isPopup()) {
hideHint();
diff --git a/platform/platform-impl/src/com/intellij/ui/AppUIUtil.java b/platform/platform-impl/src/com/intellij/ui/AppUIUtil.java
index 50a7ebbca92b..2a7d44d017bd 100644
--- a/platform/platform-impl/src/com/intellij/ui/AppUIUtil.java
+++ b/platform/platform-impl/src/com/intellij/ui/AppUIUtil.java
@@ -29,6 +29,7 @@ import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.wm.ToolWindowManager;
import com.intellij.util.PlatformUtils;
+import com.intellij.util.ReflectionUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -38,7 +39,6 @@ import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.io.InputStream;
-import java.lang.reflect.Field;
import java.net.URL;
import java.util.List;
import java.util.Locale;
@@ -111,9 +111,7 @@ public class AppUIUtil {
final Toolkit toolkit = Toolkit.getDefaultToolkit();
final Class<? extends Toolkit> aClass = toolkit.getClass();
if ("sun.awt.X11.XToolkit".equals(aClass.getName())) {
- final Field awtAppClassName = aClass.getDeclaredField("awtAppClassName");
- awtAppClassName.setAccessible(true);
- awtAppClassName.set(toolkit, getFrameClass());
+ ReflectionUtil.setField(aClass, toolkit, null, "awtAppClassName", getFrameClass());
}
}
catch (Exception ignore) { }
diff --git a/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java b/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java
index c6c209ed4b88..513d5cedb2ab 100644
--- a/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java
+++ b/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java
@@ -200,8 +200,7 @@ public class BalloonImpl implements Balloon, IdeTooltip.Ui {
if (cmp == myCloseRec) return true;
if (UIUtil.isDescendingFrom(cmp, myComp)) return true;
if (myComp == null || !myComp.isShowing()) return false;
- Rectangle rectangleOnScreen = new Rectangle(myComp.getLocationOnScreen(), myComp.getSize());
- return rectangleOnScreen.contains(target.getScreenPoint());
+ return myComp.contains(target.getScreenPoint().x, target.getScreenPoint().y);
}
public boolean isMovingForward(RelativePoint target) {
@@ -614,7 +613,7 @@ public class BalloonImpl implements Balloon, IdeTooltip.Ui {
myComp.setBorder(new EmptyBorder(borderSize, borderSize, borderSize, borderSize));
myLayeredPane.add(myComp);
- myLayeredPane.setLayer(myComp, getLayer());
+ myLayeredPane.setLayer(myComp, getLayer(), 0); // the second balloon must be over the first one
myPosition.updateBounds(this);
if (myBlockClicks) {
myComp.addMouseListener(new MouseAdapter() {
diff --git a/platform/platform-impl/src/com/intellij/ui/CheckboxTree.java b/platform/platform-impl/src/com/intellij/ui/CheckboxTree.java
index c91be65978c1..1443a9303e39 100644
--- a/platform/platform-impl/src/com/intellij/ui/CheckboxTree.java
+++ b/platform/platform-impl/src/com/intellij/ui/CheckboxTree.java
@@ -15,8 +15,6 @@
*/
package com.intellij.ui;
-import java.awt.event.KeyEvent;
-
/**
* User: lex
* Date: Sep 18, 2003
@@ -56,11 +54,4 @@ public class CheckboxTree extends CheckboxTreeBase {
protected void installSpeedSearch() {
new TreeSpeedSearch(this);
}
-
-
- protected boolean isToggleEvent(KeyEvent e) {
- return super.isToggleEvent(e) && !SpeedSearchBase.hasActiveSpeedSearch(this);
- }
-
-
}
diff --git a/platform/platform-impl/src/com/intellij/ui/CheckboxTreeTable.java b/platform/platform-impl/src/com/intellij/ui/CheckboxTreeTable.java
new file mode 100644
index 000000000000..369dd0cc1803
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/ui/CheckboxTreeTable.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2000-2012 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.ui;
+
+import com.intellij.ui.dualView.TreeTableView;
+import com.intellij.ui.treeStructure.treetable.ListTreeTableModelOnColumns;
+import com.intellij.ui.treeStructure.treetable.TreeTableTree;
+import com.intellij.util.EventDispatcher;
+import com.intellij.util.ui.ColumnInfo;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author nik
+ */
+public class CheckboxTreeTable extends TreeTableView {
+ private final EventDispatcher<CheckboxTreeListener> myEventDispatcher;
+
+ public CheckboxTreeTable(CheckedTreeNode root, CheckboxTree.CheckboxTreeCellRenderer renderer, final ColumnInfo[] columns) {
+ super(new ListTreeTableModelOnColumns(root, columns));
+ final TreeTableTree tree = getTree();
+ myEventDispatcher = EventDispatcher.create(CheckboxTreeListener.class);
+ CheckboxTreeHelper helper = new CheckboxTreeHelper(CheckboxTreeHelper.DEFAULT_POLICY, myEventDispatcher);
+ helper.initTree(tree, this, renderer);
+ tree.setSelectionRow(0);
+ }
+
+ public void addCheckboxTreeListener(@NotNull CheckboxTreeListener listener) {
+ myEventDispatcher.addListener(listener);
+ }
+
+ public <T> T[] getCheckedNodes(final Class<T> nodeType) {
+ return CheckboxTreeHelper.getCheckedNodes(nodeType, null, getTree().getModel());
+ }
+}
diff --git a/platform/platform-impl/src/com/intellij/ui/JBTabsPaneImpl.java b/platform/platform-impl/src/com/intellij/ui/JBTabsPaneImpl.java
index 39c8aaf41ace..d5fc8dcca1ba 100644
--- a/platform/platform-impl/src/com/intellij/ui/JBTabsPaneImpl.java
+++ b/platform/platform-impl/src/com/intellij/ui/JBTabsPaneImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,7 +20,8 @@ import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.ui.tabs.*;
-import com.intellij.ui.tabs.impl.JBTabsImpl;
+import com.intellij.ui.tabs.impl.JBEditorTabs;
+import com.intellij.ui.tabs.impl.TabLabel;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -38,7 +39,45 @@ public class JBTabsPaneImpl implements TabbedPane, SwingConstants {
private final CopyOnWriteArraySet<ChangeListener> myListeners = new CopyOnWriteArraySet<ChangeListener>();
public JBTabsPaneImpl(@Nullable Project project, int tabPlacement, @NotNull Disposable parent) {
- myTabs = new JBTabsImpl(project, ActionManager.getInstance(), project == null ? null : IdeFocusManager.getInstance(project), parent);
+ myTabs = new JBEditorTabs(project, ActionManager.getInstance(), project == null ? null : IdeFocusManager.getInstance(project), parent) {
+ @Override
+ public boolean isAlphabeticalMode() {
+ return false;
+ }
+
+ @Override
+ protected void doPaintBackground(Graphics2D g2d, Rectangle clip) {
+ super.doPaintBackground(g2d, clip);
+ if (getTabsPosition() == JBTabsPosition.top && isSingleRow()) {
+ int maxOffset = 0;
+ int maxLength = 0;
+
+ for (int i = getVisibleInfos().size() - 1; i >= 0; i--) {
+ TabInfo visibleInfo = getVisibleInfos().get(i);
+ TabLabel tabLabel = myInfo2Label.get(visibleInfo);
+ Rectangle r = tabLabel.getBounds();
+ if (r.width == 0 || r.height == 0) continue;
+ maxOffset = r.x + r.width;
+ maxLength = r.height;
+ break;
+ }
+
+ maxOffset++;
+ g2d.setPaint(UIUtil.getPanelBackground());
+ g2d.fillRect(clip.x + maxOffset, clip.y, clip.width - maxOffset, clip.y + maxLength - TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT);
+ g2d.setPaint(new JBColor(Gray._181, UIUtil.getPanelBackground()));
+ g2d.drawLine(clip.x + maxOffset, clip.y + maxLength - TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT, clip.x + clip.width, clip.y + maxLength - TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT);
+ g2d.setPaint(UIUtil.getPanelBackground());
+ g2d.drawLine(clip.x, clip.y + maxLength, clip.width, clip.y + maxLength);
+ }
+ }
+
+ @Override
+ protected void paintSelectionAndBorder(Graphics2D g2d) {
+ super.paintSelectionAndBorder(g2d);
+ }
+ };
+
myTabs.addListener(new TabsListener.Adapter() {
@Override
public void selectionChanged(TabInfo oldSelection, TabInfo newSelection) {
diff --git a/platform/platform-impl/src/com/intellij/ui/SplitterWithSecondHideable.java b/platform/platform-impl/src/com/intellij/ui/SplitterWithSecondHideable.java
index 99c41b52cbea..e219b778f44d 100644
--- a/platform/platform-impl/src/com/intellij/ui/SplitterWithSecondHideable.java
+++ b/platform/platform-impl/src/com/intellij/ui/SplitterWithSecondHideable.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,6 +16,7 @@
package com.intellij.ui;
import com.intellij.icons.AllIcons;
+import com.intellij.openapi.ui.Divider;
import com.intellij.openapi.ui.PseudoSplitter;
import com.intellij.openapi.ui.Splitter;
import com.intellij.openapi.vcs.changes.RefreshablePanel;
@@ -41,7 +42,7 @@ public abstract class SplitterWithSecondHideable {
private final boolean myVertical;
private final OnOffListener<Integer> myListener;
private final JPanel myFictivePanel;
- private Splitter.Divider mySuperDivider;
+ private Splitter.DividerImpl mySuperDivider;
private float myPreviousProportion;
public SplitterWithSecondHideable(final boolean vertical,
@@ -185,7 +186,7 @@ public abstract class SplitterWithSecondHideable {
return vertical ? myTitledSeparator.getHeight() : myTitledSeparator.getWidth();
}
- class MyDivider extends Divider {
+ class MyDivider extends DividerImpl {
@Override
public void processMouseMotionEvent(MouseEvent e) {
super.processMouseMotionEvent(e);
diff --git a/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java b/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java
index 78802ccdf6bb..e50403abef45 100644
--- a/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java
+++ b/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java
@@ -162,6 +162,25 @@ public class AbstractPopup implements JBPopup {
private UiActivity myActivityKey;
private Disposable myProjectDisposable;
+ private volatile State myState = State.NEW;
+
+ private enum State {NEW, INIT, SHOWING, SHOWN, CANCEL, DISPOSE}
+
+ private void debugState(String message, State... states) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(hashCode() + " - " + message);
+ if (!ApplicationManager.getApplication().isDispatchThread()) {
+ LOG.debug("unexpected thread");
+ }
+ for (State state : states) {
+ if (state == myState) {
+ return;
+ }
+ }
+ LOG.debug(new IllegalStateException("myState=" + myState));
+ }
+ }
+
AbstractPopup() { }
AbstractPopup init(Project project,
@@ -302,6 +321,8 @@ public class AbstractPopup implements JBPopup {
}
myKeyEventHandler = keyEventHandler;
+ debugState("popup initialized", State.NEW);
+ myState = State.INIT;
return this;
}
@@ -582,10 +603,18 @@ public class AbstractPopup implements JBPopup {
@Override
public void cancel(InputEvent e) {
+ if (myState == State.CANCEL || myState == State.DISPOSE) {
+ return;
+ }
+ debugState("cancel popup", State.SHOWN);
+ myState = State.CANCEL;
+
if (isDisposed()) return;
if (myPopup != null) {
if (!canClose()) {
+ debugState("cannot cancel popup", State.CANCEL);
+ myState = State.SHOWN;
return;
}
storeDimensionSize(myContent.getSize());
@@ -610,8 +639,13 @@ public class AbstractPopup implements JBPopup {
}
if (myInStack) {
- myFocusTrackback.setForcedRestore(!myOk && myFocusable);
- myFocusTrackback.restoreFocus();
+ if (myFocusTrackback != null) {
+ myFocusTrackback.setForcedRestore(!myOk && myFocusable);
+ myFocusTrackback.restoreFocus();
+ }
+ else if (LOG.isDebugEnabled()) {
+ LOG.debug("cancel before show @ " + Thread.currentThread());
+ }
}
@@ -664,6 +698,9 @@ public class AbstractPopup implements JBPopup {
assert ApplicationManager.getApplication().isDispatchThread();
+ debugState("show popup", State.INIT);
+ myState = State.SHOWING;
+
installWindowHook(this);
installProjectDisposer();
addActivity();
@@ -673,6 +710,8 @@ public class AbstractPopup implements JBPopup {
final boolean shouldShow = beforeShow();
if (!shouldShow) {
removeActivity();
+ debugState("rejected to show popup", State.SHOWING);
+ myState = State.INIT;
return;
}
@@ -758,10 +797,11 @@ public class AbstractPopup implements JBPopup {
PopupComponent.Factory factory = getFactory(myForcedHeavyweight || myResizable, forcedDialog);
myNativePopup = factory.isNativePopup();
Component popupOwner = myOwner;
- if (popupOwner instanceof RootPaneContainer) {
+ if (popupOwner instanceof RootPaneContainer && !(popupOwner instanceof IdeFrame && !Registry.is("popup.fix.ide.frame.owner"))) {
// JDK uses cached heavyweight popup for a window ancestor
RootPaneContainer root = (RootPaneContainer)popupOwner;
popupOwner = root.getRootPane();
+ LOG.debug("popup owner fixed for JDK cache");
}
if (LOG.isDebugEnabled()) {
LOG.debug("expected preferred size: " + myContent.getPreferredSize());
@@ -957,6 +997,8 @@ public class AbstractPopup implements JBPopup {
}
});
}
+ debugState("popup shown", State.SHOWING);
+ myState = State.SHOWN;
}
public void focusPreferredComponent() {
@@ -1232,6 +1274,16 @@ public class AbstractPopup implements JBPopup {
@Override
public void dispose() {
+ if (myState == State.SHOWN) {
+ LOG.debug("shown popup must be cancelled");
+ cancel();
+ }
+ if (myState == State.DISPOSE) {
+ return;
+ }
+ debugState("dispose popup", State.INIT, State.CANCEL);
+ myState = State.DISPOSE;
+
if (myDisposed) {
return;
}
@@ -1480,8 +1532,8 @@ public class AbstractPopup implements JBPopup {
@Override
public Dimension getSize() {
if (myPopup != null) {
- final Window popupWindow = SwingUtilities.windowForComponent(myContent);
- return popupWindow.getSize();
+ final Window popupWindow = getContentWindow(myContent);
+ return (popupWindow == null) ? myForcedSize : popupWindow.getSize();
} else {
return myForcedSize;
}
@@ -1491,7 +1543,8 @@ public class AbstractPopup implements JBPopup {
public void moveToFitScreen() {
if (myPopup == null) return;
- final Window popupWindow = SwingUtilities.windowForComponent(myContent);
+ final Window popupWindow = getContentWindow(myContent);
+ if (popupWindow == null) return;
Rectangle bounds = popupWindow.getBounds();
ScreenUtil.moveRectangleToFitTheScreen(bounds);
@@ -1501,7 +1554,8 @@ public class AbstractPopup implements JBPopup {
public static Window setSize(JComponent content, final Dimension size) {
- final Window popupWindow = SwingUtilities.windowForComponent(content);
+ final Window popupWindow = getContentWindow(content);
+ if (popupWindow == null) return null;
Insets insets = content.getInsets();
if (insets != null) {
size.width += insets.left + insets.right;
diff --git a/platform/platform-impl/src/com/intellij/ui/popup/OurHeavyWeightPopup.java b/platform/platform-impl/src/com/intellij/ui/popup/OurHeavyWeightPopup.java
new file mode 100644
index 000000000000..2a79368f65bb
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/ui/popup/OurHeavyWeightPopup.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.ui.popup;
+
+import com.intellij.openapi.util.registry.Registry;
+
+import javax.swing.Popup;
+import java.awt.Component;
+import java.awt.GraphicsEnvironment;
+
+/**
+ * @author Sergey Malenkov
+ */
+public final class OurHeavyWeightPopup extends Popup {
+ public OurHeavyWeightPopup(Component owner, Component content, int x, int y) {
+ super(owner, content, x, y);
+ }
+
+ public static boolean isEnabled() {
+ return !GraphicsEnvironment.isHeadless() && Registry.is("our.heavy.weight.popup");
+ }
+}
diff --git a/platform/platform-impl/src/com/intellij/ui/popup/PopupComponent.java b/platform/platform-impl/src/com/intellij/ui/popup/PopupComponent.java
index 301758511612..1670491b91bf 100644
--- a/platform/platform-impl/src/com/intellij/ui/popup/PopupComponent.java
+++ b/platform/platform-impl/src/com/intellij/ui/popup/PopupComponent.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -58,6 +58,9 @@ public interface PopupComponent {
class AwtHeavyweight implements Factory {
public PopupComponent getPopup(Component owner, Component content, int x, int y, JBPopup jbPopup) {
+ if (OurHeavyWeightPopup.isEnabled()) {
+ return new AwtPopupWrapper(new OurHeavyWeightPopup(owner, content, x, y), jbPopup);
+ }
final PopupFactory factory = PopupFactory.getSharedInstance();
final int oldType = PopupUtil.getPopupType(factory);
@@ -172,7 +175,7 @@ public interface PopupComponent {
myJBPopup = jbPopup;
if (SystemInfo.isMac && UIUtil.isUnderAquaLookAndFeel()) {
- final Component c = (Component)ReflectionUtil.getField(Popup.class, myPopup, Component.class, "component");
+ final Component c = ReflectionUtil.getField(Popup.class, myPopup, Component.class, "component");
c.setBackground(UIUtil.getPanelBackground());
}
}
@@ -220,7 +223,7 @@ public interface PopupComponent {
}
public Window getWindow() {
- final Component c = (Component)ReflectionUtil.getField(Popup.class, myPopup, Component.class, "component");
+ final Component c = ReflectionUtil.getField(Popup.class, myPopup, Component.class, "component");
return c instanceof JWindow ? (JWindow)c : null;
}
diff --git a/platform/platform-impl/src/com/intellij/util/ui/SwingHelper.java b/platform/platform-impl/src/com/intellij/util/ui/SwingHelper.java
index ac4c1b12373c..35719ca9366b 100644
--- a/platform/platform-impl/src/com/intellij/util/ui/SwingHelper.java
+++ b/platform/platform-impl/src/com/intellij/util/ui/SwingHelper.java
@@ -1,3 +1,18 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
package com.intellij.util.ui;
import com.intellij.ide.BrowserUtil;
@@ -48,7 +63,7 @@ public class SwingHelper {
* stacked vertically each on another in a given order.
*
* @param childAlignmentX Component.LEFT_ALIGNMENT, Component.CENTER_ALIGNMENT or Component.RIGHT_ALIGNMENT
- * @param children children components
+ * @param children children components
* @return created panel
*/
@NotNull
@@ -76,7 +91,7 @@ public class SwingHelper {
* stacked each on another in a given order.
*
* @param childAlignmentY Component.TOP_ALIGNMENT, Component.CENTER_ALIGNMENT or Component.BOTTOM_ALIGNMENT
- * @param children children components
+ * @param children children components
* @return created panel
*/
@NotNull
@@ -98,10 +113,11 @@ public class SwingHelper {
for (Component child : children) {
panel.add(child, childAlignment);
if (child instanceof JComponent) {
- JComponent jChild = (JComponent) child;
+ JComponent jChild = (JComponent)child;
if (verticalOrientation) {
jChild.setAlignmentX(childAlignment);
- } else {
+ }
+ else {
jChild.setAlignmentY(childAlignment);
}
}
@@ -259,20 +275,7 @@ public class SwingHelper {
textFieldWithHistory.addPopupMenuListener(new PopupMenuListener() {
@Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
- List<String> newHistory = historyProvider.produce();
- Set<String> newHistorySet = ContainerUtil.newHashSet(newHistory);
- List<String> oldHistory = textFieldWithHistory.getHistory();
- List<String> mergedHistory = ContainerUtil.newArrayList();
- for (String item : oldHistory) {
- if (!newHistorySet.contains(item)) {
- mergedHistory.add(item);
- }
- }
- mergedHistory.addAll(newHistory);
- textFieldWithHistory.setHistory(mergedHistory);
-
- setLongestAsPrototype(textFieldWithHistory, mergedHistory);
-
+ setHistory(textFieldWithHistory, historyProvider.produce(), true);
// one-time initialization
textFieldWithHistory.removePopupMenuListener(this);
}
@@ -287,11 +290,35 @@ public class SwingHelper {
});
}
+ public static void setHistory(@NotNull TextFieldWithHistory textFieldWithHistory,
+ @NotNull List<String> history,
+ boolean mergeWithPrevHistory) {
+ Set<String> newHistorySet = ContainerUtil.newHashSet(history);
+ List<String> prevHistory = textFieldWithHistory.getHistory();
+ List<String> mergedHistory = ContainerUtil.newArrayList();
+ if (mergeWithPrevHistory) {
+ for (String item : prevHistory) {
+ if (!newHistorySet.contains(item)) {
+ mergedHistory.add(item);
+ }
+ }
+ }
+ else {
+ String currentText = textFieldWithHistory.getText();
+ if (StringUtil.isNotEmpty(currentText) && !newHistorySet.contains(currentText)) {
+ mergedHistory.add(currentText);
+ }
+ }
+ mergedHistory.addAll(history);
+ textFieldWithHistory.setHistory(mergedHistory);
+ setLongestAsPrototype(textFieldWithHistory, mergedHistory);
+ }
+
private static void setLongestAsPrototype(@NotNull JComboBox comboBox, @NotNull List<String> variants) {
Object prototypeDisplayValue = comboBox.getPrototypeDisplayValue();
String prototypeDisplayValueStr = null;
if (prototypeDisplayValue instanceof String) {
- prototypeDisplayValueStr = (String) prototypeDisplayValue;
+ prototypeDisplayValueStr = (String)prototypeDisplayValue;
}
else if (prototypeDisplayValue != null) {
return;
@@ -413,15 +440,38 @@ public class SwingHelper {
return textPane;
}
- public static void setHtml(@NotNull JEditorPane editorPane, @NotNull String bodyInnerHtml) {
+ public static void setHtml(@NotNull JEditorPane editorPane,
+ @NotNull String bodyInnerHtml,
+ @Nullable Color foregroundColor) {
String html = String.format(
"<html><head>%s</head><body>%s</body></html>",
- UIUtil.getCssFontDeclaration(editorPane.getFont(), null, null, null),
+ UIUtil.getCssFontDeclaration(editorPane.getFont(), foregroundColor, null, null),
bodyInnerHtml
);
editorPane.setText(html);
}
+ @NotNull
+ public static TextFieldWithHistoryWithBrowseButton createTextFieldWithHistoryWithBrowseButton(@Nullable Project project,
+ @NotNull String browseDialogTitle,
+ @NotNull FileChooserDescriptor fileChooserDescriptor,
+ @Nullable NotNullProducer<List<String>> historyProvider) {
+ TextFieldWithHistoryWithBrowseButton textFieldWithHistoryWithBrowseButton = new TextFieldWithHistoryWithBrowseButton();
+ TextFieldWithHistory textFieldWithHistory = textFieldWithHistoryWithBrowseButton.getChildComponent();
+ textFieldWithHistory.setHistorySize(-1);
+ textFieldWithHistory.setMinimumAndPreferredWidth(0);
+ if (historyProvider != null) {
+ addHistoryOnExpansion(textFieldWithHistory, historyProvider);
+ }
+ installFileCompletionAndBrowseDialog(
+ project,
+ textFieldWithHistoryWithBrowseButton,
+ browseDialogTitle,
+ fileChooserDescriptor
+ );
+ return textFieldWithHistoryWithBrowseButton;
+ }
+
private static class CopyLinkAction extends AnAction {
private final String myUrl;
diff --git a/platform/platform-impl/src/org/jetbrains/io/BuiltInServer.java b/platform/platform-impl/src/org/jetbrains/io/BuiltInServer.java
index a7d09ab548f2..7310b936246d 100644
--- a/platform/platform-impl/src/org/jetbrains/io/BuiltInServer.java
+++ b/platform/platform-impl/src/org/jetbrains/io/BuiltInServer.java
@@ -170,7 +170,7 @@ public class BuiltInServer implements Disposable {
@Override
protected boolean process(ChannelHandlerContext context, FullHttpRequest request, QueryStringDecoder urlDecoder) throws IOException {
- return (request.getMethod() == HttpMethod.POST || request.getMethod() == HttpMethod.OPTIONS) &&
+ return (request.method() == HttpMethod.POST || request.method() == HttpMethod.OPTIONS) &&
XmlRpcServer.SERVICE.getInstance().process(urlDecoder.path(), request, context, handlers);
}
}
diff --git a/platform/platform-impl/src/org/jetbrains/io/PortUnificationServerHandler.java b/platform/platform-impl/src/org/jetbrains/io/PortUnificationServerHandler.java
index 3f88327d3d28..1dbf57785dac 100644
--- a/platform/platform-impl/src/org/jetbrains/io/PortUnificationServerHandler.java
+++ b/platform/platform-impl/src/org/jetbrains/io/PortUnificationServerHandler.java
@@ -113,7 +113,7 @@ class PortUnificationServerHandler extends Decoder {
@Override
public void write(ChannelHandlerContext context, Object message, ChannelPromise promise) throws Exception {
if (message instanceof HttpResponse) {
-// BuiltInServer.LOG.debug("OUT HTTP:\n" + message);
+ //BuiltInServer.LOG.debug("OUT HTTP:\n" + message);
HttpResponse response = (HttpResponse)message;
BuiltInServer.LOG.debug("OUT HTTP: " + response.status().code() + " " + response.headers().get(CONTENT_TYPE));
}
diff --git a/platform/platform-resources-en/src/messages/ActionsBundle.properties b/platform/platform-resources-en/src/messages/ActionsBundle.properties
index 1c05af27102c..47c4cef92207 100644
--- a/platform/platform-resources-en/src/messages/ActionsBundle.properties
+++ b/platform/platform-resources-en/src/messages/ActionsBundle.properties
@@ -596,6 +596,8 @@ action.MemberPushDown.text=Pu_sh Members Down...
action.MemberPushDown.description=Push class members down to directly inheriting subclasses
action.InheritanceToDelegation.text=Replace _Inheritance with Delegation...
action.InheritanceToDelegation.description=Replace inheritance with delegation
+action.RenameFile.text=Rename File...
+action.RenameFile.description=Rename selected file
action.Inline.text=I_nline...
action.Inline.description=Inline the selected method or variable
action.AnonymousToInner.text=Convert Anon_ymous to Inner...
@@ -1014,8 +1016,8 @@ action.Vcs.ShowDiffAction.text=Show Changes
action.Vcs.ShowDiffAction.description=Show changes
action.Vcs.RollbackChanges.text=Rollback Changes
action.Vcs.RollbackChanges.description=Rollback changes
-action.RollbackLineStatusChanges.text=Rollback
-action.RollbackLineStatusChanges.description=Rollback selected local changes
+action.Vcs.RollbackChangedLines.text=Rollback
+action.Vcs.RollbackChangedLines.description=Rollback changes in selected lines
action.Vcs.EditSourceAction.text=Edit Source
action.Vcs.EditSourceAction.description=Edit source
action.Vcs.ExcludeAction.text=Exclude from Commit
diff --git a/platform/platform-resources-en/src/messages/ApplicationBundle.properties b/platform/platform-resources-en/src/messages/ApplicationBundle.properties
index bbd737afedf1..5d539357ca3d 100644
--- a/platform/platform-resources-en/src/messages/ApplicationBundle.properties
+++ b/platform/platform-resources-en/src/messages/ApplicationBundle.properties
@@ -360,6 +360,7 @@ label.collapse.by.default=Collapse by default:
checkbox.show.code.folding.outline=Show code folding outline
group.tab.appearance=Tab Appearance
editbox.tab.limit=Tab limit:
+editbox.tab.title.limit=Tab title limit:
combobox.editor.tab.placement=Placement:
checkbox.editor.tabs.in.single.row=Show tabs in single row
checkbox.editor.tabs.show.close.button=Show "close" button on editor tabs
diff --git a/platform/platform-resources-en/src/messages/CommonBundle.properties b/platform/platform-resources-en/src/messages/CommonBundle.properties
index 46750d536a06..1fbbd0a61f57 100644
--- a/platform/platform-resources-en/src/messages/CommonBundle.properties
+++ b/platform/platform-resources-en/src/messages/CommonBundle.properties
@@ -31,7 +31,6 @@ action.close=&Close
action.help=Help
action.rerun=Rerun
button.reset=&Reset
-button.reset.to.default=&Reset to Default
button.delete=Delete
button.copy=Copy...
button.close=&Close
diff --git a/platform/platform-resources-en/src/messages/DiffBundle.properties b/platform/platform-resources-en/src/messages/DiffBundle.properties
index 598cc9714697..aafd6884a3d6 100644
--- a/platform/platform-resources-en/src/messages/DiffBundle.properties
+++ b/platform/platform-resources-en/src/messages/DiffBundle.properties
@@ -67,6 +67,8 @@ merge.partial.diff.action.name.0.1=Compare left and middle panel contents
merge.partial.diff.action.name.1.2=Compare middle and right panel contents
merge.dialog.exit.without.applying.changes.confirmation.message=Are you sure you want to exit without applying changes?
cancel.visual.merge.dialog.title=Cancel Visual Merge
+merge.dialog.apply.partially.resolved.changes.confirmation.message=There are {0, choice, 0#|1#one change|2#{0, number} changes}{0, choice, 0#|1#'{1, choice, 0#|1# and }'}{1, choice, 0#|1#one conflict|2#{1, number} conflicts} left unprocessed.\nAre you sure you want to save changes and finish merging?
+apply.partially.resolved.merge.dialog.title=Apply Changes
merge.all.changes.have.processed.save.and.finish.confirmation.text=All changes have been processed.\nWould you like to save changes and finish merging?
all.changes.processed.dialog.title=All Changes Processed
merge.save.and.finish.button=Save and &Finish
diff --git a/platform/platform-resources-en/src/messages/FindBundle.properties b/platform/platform-resources-en/src/messages/FindBundle.properties
index 293d013fe8d6..8a857db74fd0 100644
--- a/platform/platform-resources-en/src/messages/FindBundle.properties
+++ b/platform/platform-resources-en/src/messages/FindBundle.properties
@@ -29,6 +29,7 @@ find.open.in.new.tab.checkbox=Open in new ta&b
find.options.group=Options
find.options.search.for.text.occurences.checkbox=Search for text &occurrences
find.options.skip.results.tab.with.one.usage.checkbox=S&kip results tab with one usage
+find.options.skip.results.tab.with.one.occurrence.checkbox=S&kip results tab when only one occurrence is found
find.options.include.overloaded.methods.checkbox=Include o&verloaded methods
find.scope.label=&Scope
find.searched.elements.have.been.changed.error=Searched elements have been changed.\nCannot search for usages.
@@ -69,6 +70,14 @@ find.text.to.find.label=Text to &find:
find.replace.with.label=Replace &with:
find.filter.file.name.group=File name filter
find.filter.file.mask.checkbox=File m&ask(s)
+find.context.combo.label=Conte&xt:
+find.context.anywhere.scope.label=anywhere
+find.context.in.comments.scope.label=in comments
+find.context.in.literals.scope.label=in string literals
+find.context.except.literals.scope.label=except string literals
+find.context.except.comments.scope.label=except comments
+find.context.except.comments.and.literals.scope.label=except comments and string literals
+
find.directory.not.found.error=Directory {0} is not found
find.invalid.regular.expression.error=Bad pattern \"{0}\": {1}
find.empty.match.regular.expression.error=Regular expression matches empty string
diff --git a/platform/platform-resources-en/src/messages/VcsBundle.properties b/platform/platform-resources-en/src/messages/VcsBundle.properties
index 3d34252c9c7a..573cff8e6261 100644
--- a/platform/platform-resources-en/src/messages/VcsBundle.properties
+++ b/platform/platform-resources-en/src/messages/VcsBundle.properties
@@ -308,7 +308,7 @@ changes.action.rollback.custom.title={0} Changes
changes.action.rollback.nothing=Nothing to {0}
changes.dialog.editchangelist.error.already.exists=A changelist named ''{0}'' already exists
error.adding.files.prompt=The following problems have occurred when adding the files:
-error.adding.files.title=Error adding files
+error.adding.files.title=Error Adding Files
column.name.revision.list.committer=User
column.name.revision.list.number=Number
column.name.revision.list.description=Description
diff --git a/platform/platform-resources-en/src/messages/XDebuggerBundle.properties b/platform/platform-resources-en/src/messages/XDebuggerBundle.properties
index 878c814e4764..058e446bc896 100644
--- a/platform/platform-resources-en/src/messages/XDebuggerBundle.properties
+++ b/platform/platform-resources-en/src/messages/XDebuggerBundle.properties
@@ -3,6 +3,8 @@ xdebugger.colors.page.name=Debugger
debugger.configurable.display.name=Debugger
debugger.dataViews.display.name=Data Views
debugger.stepping.display.name=Stepping
+# suppress inspection "UnusedProperty"
+debugger.hotswap.display.name=HotSwap
xdebugger.default.content.title=Debug
xdebugger.debugger.tab.title=Debugger
diff --git a/platform/platform-resources-en/src/messages/XmlBundle.properties b/platform/platform-resources-en/src/messages/XmlBundle.properties
index 70e26de6ffeb..7343727c5b72 100644
--- a/platform/platform-resources-en/src/messages/XmlBundle.properties
+++ b/platform/platform-resources-en/src/messages/XmlBundle.properties
@@ -233,3 +233,6 @@ start.browser.with.js.debugger=with &JavaScript debugger
javascript.debugger.settings.choose.file.title=Select
javascript.debugger.settings.choose.file.subtitle=Select file to debug JavaScript in
+
+setting.value.builtin.server.port.label=Built-in server &port:
+setting.value.can.accept.external.connections=Can accept &external connections \ No newline at end of file
diff --git a/platform/platform-resources/src/META-INF/PlatformExtensions.xml b/platform/platform-resources/src/META-INF/PlatformExtensions.xml
index 1f40bacf983c..7aa76abcd4f8 100644
--- a/platform/platform-resources/src/META-INF/PlatformExtensions.xml
+++ b/platform/platform-resources/src/META-INF/PlatformExtensions.xml
@@ -57,6 +57,9 @@
<applicationService serviceInterface="com.intellij.openapi.fileEditor.impl.EditorEmptyTextPainter"
serviceImplementation="com.intellij.openapi.fileEditor.impl.EditorEmptyTextPainter" />
+ <applicationService serviceInterface="com.intellij.openapi.editor.EditorCopyPasteHelper"
+ serviceImplementation="com.intellij.openapi.editor.impl.EditorCopyPasteHelperImpl" />
+
<applicationService serviceImplementation="com.intellij.openapi.options.ex.IdeConfigurablesGroup"/>
<applicationService serviceInterface="com.intellij.diagnostic.ErrorReportConfigurable"
@@ -190,7 +193,8 @@
<projectService serviceInterface="com.intellij.openapi.vcs.VcsFileListenerContextHelper"
serviceImplementation="com.intellij.openapi.vcs.VcsFileListenerContextHelper"/>
- <projectService serviceImplementation="com.intellij.openapi.editor.LazyRangeMarkerFactory"/>
+ <projectService serviceInterface="com.intellij.openapi.editor.LazyRangeMarkerFactory"
+ serviceImplementation="com.intellij.openapi.editor.impl.LazyRangeMarkerFactoryImpl"/>
<!-- General -->
<applicationConfigurable groupId="appearance" key="title.general" bundle="messages.IdeBundle" id="preferences.general" instance="com.intellij.ide.GeneralSettingsConfigurable"/>
diff --git a/platform/platform-resources/src/META-INF/XmlPlugin.xml b/platform/platform-resources/src/META-INF/XmlPlugin.xml
index 9a737df77ef6..525ea3c94540 100644
--- a/platform/platform-resources/src/META-INF/XmlPlugin.xml
+++ b/platform/platform-resources/src/META-INF/XmlPlugin.xml
@@ -89,6 +89,10 @@
</extensionPoint>
<extensionPoint name="xml.undefinedElementFixProvider" interface="com.intellij.xml.XmlUndefinedElementFixProvider"/>
+
+ <extensionPoint qualifiedName="org.jetbrains.webServerPathHandler" interface="org.jetbrains.builtInWebServer.WebServerPathHandler"/>
+ <extensionPoint qualifiedName="org.jetbrains.webServerFileHandler" interface="org.jetbrains.builtInWebServer.WebServerFileHandler"/>
+ <extensionPoint qualifiedName="org.jetbrains.webServerRootsProvider" interface="org.jetbrains.builtInWebServer.WebServerRootsProvider"/>
</extensionPoints>
<project-components>
@@ -530,8 +534,21 @@
<applicationConfigurable groupId="tools" instance="com.intellij.ide.browsers.BrowserSettings" id="reference.settings.ide.settings.web.browsers"
key="browsers.settings" bundle="messages.IdeBundle"/>
<lang.inspectionSuppressor language="XML" implementationClass="com.intellij.codeInspection.XmlInspectionSuppressor"/>
+
+ <httpRequestHandler implementation="org.jetbrains.builtInWebServer.BuiltInWebServer"/>
+ <webBrowserUrlProvider implementation="org.jetbrains.builtInWebServer.BuiltInWebBrowserUrlProvider"/>
+
+ <customPortServerManager implementation="org.jetbrains.builtInWebServer.BuiltInServerOptions$MyCustomPortServerManager"/>
+ <xdebugger.configurableProvider implementation="org.jetbrains.builtInWebServer.BuiltInServerOptions$BuiltInServerDebuggerConfigurableProvider"/>
+
+ <exportable serviceInterface="org.jetbrains.builtInWebServer.BuiltInServerOptions"/>
+ <applicationService serviceInterface="org.jetbrains.builtInWebServer.BuiltInServerOptions" serviceImplementation="org.jetbrains.builtInWebServer.BuiltInServerOptions"/>
+ <projectService serviceInterface="org.jetbrains.builtInWebServer.WebServerPathToFileManager" serviceImplementation="org.jetbrains.builtInWebServer.WebServerPathToFileManager"/>
</extensions>
<extensions defaultExtensionNs="org.jetbrains">
<urlOpener implementation="com.intellij.ide.browsers.impl.DefaultUrlOpener" order="last"/>
+ <webServerPathHandler implementation="org.jetbrains.builtInWebServer.DefaultWebServerPathHandler"/>
+ <webServerFileHandler implementation="org.jetbrains.builtInWebServer.BuiltInWebServer$StaticFileHandler" order="last"/>
+ <webServerRootsProvider implementation="org.jetbrains.builtInWebServer.DefaultWebServerRootsProvider"/>
</extensions>
</idea-plugin>
diff --git a/platform/platform-resources/src/META-INF/xdebugger.xml b/platform/platform-resources/src/META-INF/xdebugger.xml
index 68111b8eb7b2..4b03978f9473 100644
--- a/platform/platform-resources/src/META-INF/xdebugger.xml
+++ b/platform/platform-resources/src/META-INF/xdebugger.xml
@@ -10,6 +10,7 @@
<extensionPoint name="xdebugger.settings" interface="com.intellij.xdebugger.settings.XDebuggerSettings"/>
<extensionPoint name="xdebugger.breakpointType" interface="com.intellij.xdebugger.breakpoints.XBreakpointType"/>
<extensionPoint name="xdebugger.debuggerSupport" interface="com.intellij.xdebugger.impl.DebuggerSupport"/>
+ <extensionPoint name="xdebugger.configurableProvider" interface="com.intellij.xdebugger.settings.DebuggerConfigurableProvider"/>
</extensionPoints>
<extensions defaultExtensionNs="com.intellij">
@@ -29,11 +30,12 @@
<projectService serviceInterface="com.intellij.xdebugger.impl.XDebuggerHistoryManager"
serviceImplementation="com.intellij.xdebugger.impl.XDebuggerHistoryManager"/>
- <applicationConfigurable groupId="build" dynamic="true" key="debugger.configurable.display.name" bundle="messages.XDebuggerBundle" provider="com.intellij.xdebugger.impl.settings.DebuggerConfigurableProvider"/>
+ <applicationConfigurable groupId="build" dynamic="true" key="debugger.configurable.display.name" bundle="messages.XDebuggerBundle" instance="com.intellij.xdebugger.impl.settings.DebuggerConfigurable"/>
<customizableActionGroupProvider implementation="com.intellij.xdebugger.impl.ui.XDebugTabCustomizableActionGroupProvider"/>
<xdebugger.debuggerSupport implementation="com.intellij.xdebugger.impl.XDebuggerSupport" order="first"/>
+ <xdebugger.configurableProvider implementation="com.intellij.xdebugger.impl.settings.XDebuggerConfigurableProvider" order="first"/>
<executor implementation="com.intellij.execution.executors.DefaultDebugExecutor" order="first,after run"/>
</extensions>
diff --git a/platform/platform-resources/src/brokenPlugins.txt b/platform/platform-resources/src/brokenPlugins.txt
index 438c23f2ffd2..57b863fb916b 100644
--- a/platform/platform-resources/src/brokenPlugins.txt
+++ b/platform/platform-resources/src/brokenPlugins.txt
@@ -1,15 +1,14 @@
// This file contains list of broken plugins.
// Each line contains plugin ID and list of versions that are broken.
// If plugin name or version contains a space you can quote it like in command line.
-
-NodeJS 138.921 138.447 138.172 138.317 138.21 138.35 138.96 138.85 136.1205 134.1276 134.1163 134.1145 134.1081 134.1039 134.985 134.680 134.31 134.307 134.262 134.198 134.125 136.1141
-com.jetbrains.php 136.1768 136.1672 134.1456 133.982 133.679 133.51 133.326 131.98 131.374 131.332 131.235 131.205 130.1639 130.1481 130.1176 129.91 129.814 129.672 129.362 127.67 127.100 126.334 123.66 122.875 121.62 121.390 121.215 121.12
+NodeJS 138.937 138.1013 138.921 138.447 138.172 138.317 138.21 138.35 138.96 138.85 136.1205 134.1276 134.1163 134.1145 134.1081 134.1039 134.985 134.680 134.31 134.307 134.262 134.198 134.125 136.1141
+com.jetbrains.php 138.826 136.1768 136.1672 134.1456 133.982 133.679 133.51 133.326 131.98 131.374 131.332 131.235 131.205 130.1639 130.1481 130.1176 129.91 129.814 129.672 129.362 127.67 127.100 126.334 123.66 122.875 121.62 121.390 121.215 121.12
com.jetbrains.lang.ejs 131.17 131.12
com.jetbrains.twig 133.51 130.1639
-org.jetbrains.plugins.ruby 6.0.0.20140207 6.5.2.20140512 7.0.0.20140704
-Pythonid 3.1
+org.jetbrains.plugins.ruby 6.0.0.20140207 6.5.2.20140512 7.0.0.20140704 7.0.0.20140707
+Pythonid 3.1 4.0.25
Karma 138.21 134.1163 134.1039 134.686 134.31
-org.intellij.scala 0.32.593 0.32.562 0.32.558 0.32.550 0.32.520 0.32.512
+org.intellij.scala 0.40.20 0.40.18 0.40.16 0.32.593 0.32.562 0.32.558 0.32.550 0.32.520 0.32.512
org.jetbrains.kannotator 0.2.420
org.jetbrains.kotlin 0.7.1360 0.7.1376 0.8.7
SBT 1.0.0 1.1.0 1.2.0 1.3.0 1.3.1 1.4.0 1.5.0
diff --git a/platform/platform-resources/src/idea/Keymap_Default.xml b/platform/platform-resources/src/idea/Keymap_Default.xml
index 58d6f3a76d27..3508b1d0112e 100644
--- a/platform/platform-resources/src/idea/Keymap_Default.xml
+++ b/platform/platform-resources/src/idea/Keymap_Default.xml
@@ -506,6 +506,9 @@
<action id="EditorPasteFromX11">
<mouse-shortcut keystroke="button2"/>
</action>
+ <action id="Vcs.RollbackChangedLines">
+ <keyboard-shortcut first-keystroke="control alt Z"/>
+ </action>
<action id="GotoNextError">
<keyboard-shortcut first-keystroke="F2"/>
diff --git a/platform/platform-resources/src/idea/Keymap_EclipseMac.xml b/platform/platform-resources/src/idea/Keymap_EclipseMac.xml
index dc1dcb5e66ec..f35e24c776b0 100644
--- a/platform/platform-resources/src/idea/Keymap_EclipseMac.xml
+++ b/platform/platform-resources/src/idea/Keymap_EclipseMac.xml
@@ -312,6 +312,10 @@
<keyboard-shortcut first-keystroke="meta 3"/>
</action>
+ <action id="Vcs.RollbackChangedLines">
+ <keyboard-shortcut first-keystroke="control shift alt Z"/>
+ </action>
+
<action id="ActivateProjectToolWindow"/>
<action id="ActivateFavoritesToolWindow"/>
<action id="ActivateFindToolWindow">
diff --git a/platform/platform-resources/src/idea/PlatformActions.xml b/platform/platform-resources/src/idea/PlatformActions.xml
index 9cebd282ded6..869a8a754886 100644
--- a/platform/platform-resources/src/idea/PlatformActions.xml
+++ b/platform/platform-resources/src/idea/PlatformActions.xml
@@ -563,7 +563,6 @@
</group>
<group id="DiffPanel.Toolbar">
- <reference ref="$Copy"/>
<reference ref="PreviousDiff"/>
<reference ref="NextDiff"/>
<separator/>
diff --git a/platform/platform-resources/src/idea/VcsActions.xml b/platform/platform-resources/src/idea/VcsActions.xml
index dc15f19282bf..5496ab6bf3e7 100644
--- a/platform/platform-resources/src/idea/VcsActions.xml
+++ b/platform/platform-resources/src/idea/VcsActions.xml
@@ -265,7 +265,7 @@
<add-to-group group-id="CloseEditorsGroup" anchor="before" relative-to-action="CloseAllUnpinnedEditors"/>
</action>
- <action id="RollbackLineStatusChanges" class="com.intellij.openapi.vcs.ex.RollbackLineStatusAction">
+ <action id="Vcs.RollbackChangedLines" class="com.intellij.openapi.vcs.ex.RollbackLineStatusAction" icon="AllIcons.Actions.Reset">
</action>
<action id="WelcomeScreen.GetFromVcs" class="com.intellij.openapi.wm.impl.welcomeScreen.GetFromVcsAction"
diff --git a/platform/platform-tests/testSrc/com/intellij/codeInsight/actions/ReformatFilesWithFiltersTest.java b/platform/platform-tests/testSrc/com/intellij/codeInsight/actions/ReformatFilesWithFiltersTest.java
index a90148799f5d..dbc05f849a49 100644
--- a/platform/platform-tests/testSrc/com/intellij/codeInsight/actions/ReformatFilesWithFiltersTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/codeInsight/actions/ReformatFilesWithFiltersTest.java
@@ -202,42 +202,22 @@ public class ReformatFilesWithFiltersTest extends LightPlatformTestCase {
TestFileStructure fileTree = new TestFileStructure(getModule(), myWorkingDirectory);
fileTree.createDirectoryAndMakeItCurrent("src");
- PsiFile java2 = fileTree.addTestFile("Test2.java", "empty content");
+ PsiFile java2 = fileTree.addTestFile("Test2.tj", "empty content");
PsiFile php2 = fileTree.addTestFile("Pair2.php", "empty content");
PsiFile js2 = fileTree.addTestFile("Pair2.js", "empty content");
PsiDirectory test = fileTree.createDirectoryAndMakeItCurrent("test");
- PsiFile testJava1 = fileTree.addTestFile("testJava1.java", "empty content");
+ PsiFile testJava1 = fileTree.addTestFile("testJava1.tj", "empty content");
PsiFile testPhp1 = fileTree.addTestFile("testPhp1.php", "empty content");
PsiFile testJs1 = fileTree.addTestFile("testJs1.js", "empty content");
GlobalSearchScope testScope = directoryScope(test, true);
- Logger logger = Logger.getInstance(getClass());
- logFiles(logger, "Previously formatted files: ", myMockCodeStyleManager.getFormattedFiles());
-
- reformatWithRearrange(myWorkingDirectory, testScope);
- logFiles(logger, "Currently formatted files: ", myMockCodeStyleManager.getFormattedFiles());
- logFiles(logger, "Should be formatted", ContainerUtil.newArrayList(testJava1, testPhp1, testJs1));
-
- assertWasFormatted(testJava1, testPhp1, testJs1);
- assertWasNotFormatted(java2, php2, js2);
-
reformatAndOptimize(myWorkingDirectory, testScope);
assertWasFormatted(testJava1, testPhp1, testJs1);
assertWasNotFormatted(java2, php2, js2);
}
- private void logFiles(Logger log, String message, Collection<PsiFile> files) {
- StringBuilder builder;
- builder = new StringBuilder();
- builder.append(message).append('\n');
- for (PsiFile file : files) {
- builder.append(file).append('\n');
- }
- log.info(builder.toString());
- }
-
public void assertWasFormatted(PsiFile... files) {
final Set<PsiFile> formattedFiles = myMockCodeStyleManager.getFormattedFiles();
for (PsiFile file : files) {
diff --git a/platform/platform-tests/testSrc/com/intellij/history/core/PathsTest.java b/platform/platform-tests/testSrc/com/intellij/history/core/PathsTest.java
index 32f5ec2eb16e..f8bc13e05aed 100644
--- a/platform/platform-tests/testSrc/com/intellij/history/core/PathsTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/history/core/PathsTest.java
@@ -103,6 +103,11 @@ public class PathsTest extends LocalHistoryTestCase {
assertEquals(array("/", "foo"), ContainerUtil.collect(Paths.split("/foo").iterator()));
assertEquals(array("/"), ContainerUtil.collect(Paths.split("/").iterator()));
assertEquals(array("c:", "foo", "bar"), ContainerUtil.collect(Paths.split("c:/foo/bar").iterator()));
+
+ assertEquals(array("//"), ContainerUtil.collect(Paths.split("//").iterator()));
+ assertEquals(array("//foo"), ContainerUtil.collect(Paths.split("//foo").iterator()));
+ assertEquals(array("//foo"), ContainerUtil.collect(Paths.split("//foo/").iterator()));
+ assertEquals(array("//foo", "bar"), ContainerUtil.collect(Paths.split("//foo/bar").iterator()));
}
@Test
diff --git a/platform/platform-tests/testSrc/com/intellij/lang/PsiBuilderQuickTest.java b/platform/platform-tests/testSrc/com/intellij/lang/PsiBuilderQuickTest.java
index 5a47fdf4c5f3..db833c2d8f3e 100644
--- a/platform/platform-tests/testSrc/com/intellij/lang/PsiBuilderQuickTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/lang/PsiBuilderQuickTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,16 +18,14 @@ package com.intellij.lang;
import com.intellij.lang.impl.PsiBuilderImpl;
import com.intellij.lexer.Lexer;
import com.intellij.lexer.LexerBase;
+import com.intellij.openapi.fileTypes.PlainTextParserDefinition;
import com.intellij.openapi.project.Project;
-import com.intellij.psi.FileViewProvider;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiFile;
import com.intellij.psi.TokenType;
import com.intellij.psi.impl.DebugUtil;
import com.intellij.psi.impl.source.tree.ASTStructure;
import com.intellij.psi.tree.*;
-import com.intellij.testFramework.LightPlatformTestCase;
-import com.intellij.testFramework.PlatformTestCase;
+import com.intellij.testFramework.LightPlatformLangTestCase;
+import com.intellij.testFramework.PlatformTestUtil;
import com.intellij.util.ThreeState;
import com.intellij.util.diff.DiffTree;
import com.intellij.util.diff.DiffTreeChangeBuilder;
@@ -36,12 +34,9 @@ import com.intellij.util.diff.ShallowNodeComparator;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.PrintStream;
import java.util.List;
-public class PsiBuilderQuickTest extends LightPlatformTestCase {
+public class PsiBuilderQuickTest extends LightPlatformLangTestCase {
private static final IFileElementType ROOT = new IFileElementType("ROOT", Language.ANY);
private static final IElementType LETTER = new IElementType("LETTER", Language.ANY);
@@ -57,11 +52,6 @@ public class PsiBuilderQuickTest extends LightPlatformTestCase {
private static final TokenSet WHITESPACE_SET = TokenSet.create(TokenType.WHITE_SPACE);
private static final TokenSet COMMENT_SET = TokenSet.create(COMMENT);
- @SuppressWarnings("JUnitTestCaseWithNonTrivialConstructors")
- public PsiBuilderQuickTest() {
- PlatformTestCase.initPlatformLangPrefix();
- }
-
public void testPlain() {
doTest("a<<b",
new Parser() {
@@ -428,15 +418,8 @@ public class PsiBuilderQuickTest extends LightPlatformTestCase {
" PsiElement(OTHER)('}')\n");
}
- private abstract static class MyLazyElementType extends ILazyParseableElementType implements ILightLazyParseableElementType {
- protected MyLazyElementType(@NonNls String debugName) {
- super(debugName, Language.ANY);
- }
- }
-
public void testLightChameleon() {
final IElementType CHAMELEON_2 = new MyChameleon2Type();
-
final IElementType CHAMELEON_1 = new MyChameleon1Type(CHAMELEON_2);
doTest("ab{12[.?]}cd{x}",
@@ -478,60 +461,26 @@ public class PsiBuilderQuickTest extends LightPlatformTestCase {
" PsiElement(OTHER)('}')\n");
}
- @SuppressWarnings("ConstantConditions")
- private static PsiBuilderImpl createBuilder(CharSequence text) {
- ParserDefinition parserDefinition = new ParserDefinition() {
- @NotNull
- @Override
- public Lexer createLexer(Project project) {
- return new MyTestLexer();
- }
-
- @Override
- public PsiParser createParser(Project project) {
- return null;
- }
-
- @Override
- public IFileElementType getFileNodeType() {
- return null;
- }
-
- @NotNull
- @Override
- public TokenSet getWhitespaceTokens() {
- return WHITESPACE_SET;
- }
-
- @NotNull
- @Override
- public TokenSet getCommentTokens() {
- return COMMENT_SET;
- }
-
- @NotNull
- @Override
- public TokenSet getStringLiteralElements() {
- return null;
- }
-
- @NotNull
- @Override
- public PsiElement createElement(ASTNode node) {
- return null;
- }
-
- @Override
- public PsiFile createFile(FileViewProvider viewProvider) {
- return null;
- }
-
- @Override
- public SpaceRequirements spaceExistanceTypeBetweenTokens(ASTNode left, ASTNode right) {
- return null;
- }
- };
- return new PsiBuilderImpl(getProject(), null, parserDefinition, parserDefinition.createLexer(getProject()), null, text, null, null);
+ public void testEndMarkersOverlapping() {
+ doTest("a ",
+ new Parser() {
+ @Override
+ public void parse(PsiBuilder builder) {
+ PsiBuilder.Marker e1 = builder.mark();
+ PsiBuilder.Marker e2 = builder.mark();
+ builder.advanceLexer();
+ e2.done(OTHER);
+ e2.setCustomEdgeTokenBinders(null, WhitespacesBinders.GREEDY_RIGHT_BINDER);
+ e1.done(OTHER);
+ e1.setCustomEdgeTokenBinders(null, WhitespacesBinders.DEFAULT_RIGHT_BINDER);
+ assertTrue(builder.eof());
+ }
+ },
+ "Element(ROOT)\n" +
+ " Element(OTHER)\n" +
+ " Element(OTHER)\n" +
+ " PsiElement(LETTER)('a')\n" +
+ " PsiWhiteSpace(' ')\n");
}
private interface Parser {
@@ -594,75 +543,44 @@ public class PsiBuilderQuickTest extends LightPlatformTestCase {
}
private static void doFailTest(@NonNls final String text, final Parser parser, @NonNls final String expected) {
- final PrintStream std = System.err;
- //noinspection IOResourceOpenedButNotSafelyClosed
- System.setErr(new PrintStream(new NullStream()));
- try {
- try {
- ParserDefinition parserDefinition = new ParserDefinition() {
- @NotNull
- @Override
- public Lexer createLexer(Project project) {
- return null;
- }
-
- @Override
- public PsiParser createParser(Project project) {
- return null;
- }
-
- @Override
- public IFileElementType getFileNodeType() {
- return null;
- }
-
- @NotNull
- @Override
- public TokenSet getWhitespaceTokens() {
- return TokenSet.EMPTY;
- }
-
- @NotNull
- @Override
- public TokenSet getCommentTokens() {
- return TokenSet.EMPTY;
- }
-
- @NotNull
- @Override
- public TokenSet getStringLiteralElements() {
- return null;
- }
-
- @NotNull
- @Override
- public PsiElement createElement(ASTNode node) {
- return null;
- }
-
- @Override
- public PsiFile createFile(FileViewProvider viewProvider) {
- return null;
- }
-
- @Override
- public SpaceRequirements spaceExistanceTypeBetweenTokens(ASTNode left, ASTNode right) {
- return null;
- }
- };
- final PsiBuilder builder = PsiBuilderFactory.getInstance().createBuilder(parserDefinition, new MyTestLexer(),text);
- builder.setDebugMode(true);
- parser.parse(builder);
- builder.getLightTree();
- fail("should fail");
+ PlatformTestUtil.withStdErrSuppressed(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ PsiBuilder builder = PsiBuilderFactory.getInstance().createBuilder(new PlainTextParserDefinition(), new MyTestLexer(), text);
+ builder.setDebugMode(true);
+ parser.parse(builder);
+ builder.getLightTree();
+ fail("should fail");
+ }
+ catch (AssertionError e) {
+ assertEquals(expected, e.getMessage());
+ }
+ }
+ });
+ }
+
+ private static PsiBuilderImpl createBuilder(CharSequence text) {
+ ParserDefinition parserDefinition = new PlainTextParserDefinition() {
+ @NotNull
+ @Override
+ public Lexer createLexer(Project project) {
+ return new MyTestLexer();
}
- catch (AssertionError e) {
- assertEquals(expected, e.getMessage());
+
+ @NotNull
+ @Override
+ public TokenSet getWhitespaceTokens() {
+ return WHITESPACE_SET;
}
- }
- finally {
- System.setErr(std);
- }
+
+ @NotNull
+ @Override
+ public TokenSet getCommentTokens() {
+ return COMMENT_SET;
+ }
+ };
+ return new PsiBuilderImpl(getProject(), null, parserDefinition, parserDefinition.createLexer(getProject()), null, text, null, null);
}
private static class MyTestLexer extends LexerBase {
@@ -719,9 +637,10 @@ public class PsiBuilderQuickTest extends LightPlatformTestCase {
}
}
- private static class NullStream extends OutputStream {
- @Override
- public void write(final int b) throws IOException { }
+ private abstract static class MyLazyElementType extends ILazyParseableElementType implements ILightLazyParseableElementType {
+ protected MyLazyElementType(@NonNls String debugName) {
+ super(debugName, Language.ANY);
+ }
}
private static class MyChameleon1Type extends MyLazyElementType {
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/EditorCloneCaretAboveBelowTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/EditorCloneCaretAboveBelowTest.java
new file mode 100644
index 000000000000..2d73640ff655
--- /dev/null
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/EditorCloneCaretAboveBelowTest.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.editor.actions;
+
+import com.intellij.openapi.actionSystem.IdeActions;
+import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase;
+
+public class EditorCloneCaretAboveBelowTest extends LightPlatformCodeInsightFixtureTestCase {
+ public void testStoringDesiredXPosition() {
+ init("long line<caret>\n" +
+ "line\n" +
+ "long line\n" +
+ "very long line");
+ cloneCaretBelow();
+ checkResult("long line<caret>\n" +
+ "line<caret>\n" +
+ "long line\n" +
+ "very long line");
+ cloneCaretBelow();
+ checkResult("long line<caret>\n" +
+ "line<caret>\n" +
+ "long line<caret>\n" +
+ "very long line");
+ cloneCaretBelow();
+ checkResult("long line<caret>\n" +
+ "line<caret>\n" +
+ "long line<caret>\n" +
+ "very long<caret> line");
+ }
+
+ public void testCloneAndMove() {
+ init("long line<caret>\n" +
+ "line\n" +
+ "long line");
+ cloneCaretBelow();
+ moveCaretDown();
+ checkResult("long line\n" +
+ "line<caret>\n" +
+ "long line<caret>");
+ }
+
+ public void testCloneBelowAndAbove() {
+ init("line\n" +
+ "<caret>li<caret>ne\n" +
+ "line");
+ cloneCaretBelow();
+ checkResult("line\n" +
+ "<caret>li<caret>ne\n" +
+ "<caret>li<caret>ne");
+ cloneCaretAbove();
+ checkResult("line\n" +
+ "<caret>li<caret>ne\n" +
+ "line");
+ cloneCaretAbove();
+ checkResult("<caret>li<caret>ne\n" +
+ "<caret>li<caret>ne\n" +
+ "line");
+ cloneCaretBelow();
+ checkResult("line\n" +
+ "<caret>li<caret>ne\n" +
+ "line");
+ }
+
+ public void testCloneWithSelection() {
+ init("long <selection>line<caret></selection>\n" +
+ "line\n" +
+ "long line");
+ cloneCaretBelow();
+ checkResult("long <selection>line<caret></selection>\n" +
+ "line\n" +
+ "long <selection>line<caret></selection>");
+ }
+
+ private void cloneCaretBelow() {
+ myFixture.performEditorAction(IdeActions.ACTION_EDITOR_CLONE_CARET_BELOW);
+ }
+
+ private void cloneCaretAbove() {
+ myFixture.performEditorAction(IdeActions.ACTION_EDITOR_CLONE_CARET_ABOVE);
+ }
+
+ private void moveCaretDown() {
+ myFixture.performEditorAction(IdeActions.ACTION_EDITOR_MOVE_CARET_DOWN);
+ }
+
+ private void init(String text) {
+ myFixture.configureByText(getTestName(false) + ".txt", text);
+ }
+
+ private void checkResult(String text) {
+ myFixture.checkResult(text);
+ }
+}
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/AbstractEditorTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/AbstractEditorTest.java
index 5dd8bbb8c424..fd774b5e817d 100644
--- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/AbstractEditorTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/AbstractEditorTest.java
@@ -34,6 +34,7 @@ import java.util.Arrays;
import java.util.List;
import java.util.Scanner;
import java.util.regex.MatchResult;
+import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static org.junit.Assert.assertArrayEquals;
@@ -94,6 +95,20 @@ public abstract class AbstractEditorTest extends LightPlatformCodeInsightTestCas
));
}
+ protected static void foldOccurrences(String textToFoldRegexp, final String placeholder) {
+ final Matcher matcher = Pattern.compile(textToFoldRegexp).matcher(myEditor.getDocument().getCharsSequence());
+ myEditor.getFoldingModel().runBatchFoldingOperation(new Runnable() {
+ @Override
+ public void run() {
+ while(matcher.find()) {
+ FoldRegion foldRegion = myEditor.getFoldingModel().addFoldRegion(matcher.start(), matcher.end(), placeholder);
+ assertNotNull(foldRegion);
+ foldRegion.setExpanded(false);
+ }
+ }
+ });
+ }
+
/**
* Setups document of the {@link #getEditor() current editor} according to the given text that is expected to contain
* information about document lines obtained from the {@link DocumentImpl#dumpState()}.
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorImplTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorImplTest.java
index 5a9d4da33219..aff78b0b1d27 100644
--- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorImplTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorImplTest.java
@@ -16,6 +16,7 @@
package com.intellij.openapi.editor.impl;
import com.intellij.codeInsight.folding.CodeFoldingManager;
+import com.intellij.openapi.actionSystem.IdeActions;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.VisualPosition;
import com.intellij.testFramework.EditorTestUtil;
@@ -65,6 +66,29 @@ public class EditorImplTest extends AbstractEditorTest {
verifySoftWrapPositions(58, 93);
}
+ public void testCorrectVisibleLineCountCalculation() throws Exception {
+ init("line containing FOLDED_REGION\n" +
+ "next <caret>line\n" +
+ "last line");
+ foldOccurrences("FOLDED_REGION", "...");
+ EditorTestUtil.configureSoftWraps(myEditor, 16); // wrap right at folded region start
+ verifySoftWrapPositions(16);
+
+ executeAction(IdeActions.ACTION_EDITOR_MOVE_CARET_DOWN);
+ checkResultByText("line containing FOLDED_REGION\n" +
+ "next line\n" +
+ "last <caret>line");
+ }
+
+ public void testInsertingFirstTab() throws Exception {
+ init(" <caret>space-indented line");
+ EditorTestUtil.configureSoftWraps(myEditor, 100);
+ myEditor.getSettings().setUseTabCharacter(true);
+
+ executeAction(IdeActions.ACTION_EDITOR_TAB);
+ checkResultByText(" \t<caret>space-indented line");
+ }
+
private void init(String text) throws IOException {
configureFromFileText(getTestName(false) + ".txt", text);
}
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/RangeMarkerTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/RangeMarkerTest.java
index 9f3484b35deb..d11847af849a 100644
--- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/RangeMarkerTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/RangeMarkerTest.java
@@ -34,6 +34,7 @@ import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.ThrowableComputable;
import com.intellij.openapi.util.Trinity;
import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.intellij.psi.impl.PsiDocumentManagerImpl;
@@ -44,6 +45,7 @@ import com.intellij.testFramework.PlatformTestUtil;
import com.intellij.testFramework.Timings;
import com.intellij.util.CommonProcessors;
import com.intellij.util.ThrowableRunnable;
+import com.intellij.util.containers.WeakList;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -1077,13 +1079,13 @@ public class RangeMarkerTest extends LightPlatformTestCase {
public void testRangeHighlighterLinesInRangeForLongLinePerformance() throws Exception {
final int N = 50000;
- Document document = EditorFactory.getInstance().createDocument(StringUtil.repeatSymbol('x', 2*N));
+ Document document = EditorFactory.getInstance().createDocument(StringUtil.repeatSymbol('x', 2 * N));
final MarkupModelEx markupModel = (MarkupModelEx)DocumentMarkupModel.forDocument(document, ourProject, true);
for (int i=0; i<N-1;i++) {
markupModel.addRangeHighlighter(2*i, 2*i+1, 0, null, HighlighterTargetArea.EXACT_RANGE);
}
- markupModel.addRangeHighlighter(N/2, N/2+1, 0, null, HighlighterTargetArea.LINES_IN_RANGE);
+ markupModel.addRangeHighlighter(N / 2, N / 2 + 1, 0, null, HighlighterTargetArea.LINES_IN_RANGE);
PlatformTestUtil.startPerformanceTest("slow highlighters lookup", (int)(N*Math.log(N)/1000), new ThrowableRunnable() {
@Override
@@ -1107,6 +1109,42 @@ public class RangeMarkerTest extends LightPlatformTestCase {
RangeHighlighter line = markupModel.addRangeHighlighter(4, 5, 0, null, HighlighterTargetArea.LINES_IN_RANGE);
List<RangeHighlighter> list = new ArrayList<RangeHighlighter>();
markupModel.processRangeHighlightersOverlappingWith(2, 9, new CommonProcessors.CollectProcessor<RangeHighlighter>(list));
- assertEquals(Arrays.asList(line,exact), list);
+ assertEquals(Arrays.asList(line, exact), list);
+ }
+
+ public void testLazyRangeMarkers() {
+ psiFile = createFile("x.txt", "xxx");
+
+ LazyRangeMarkerFactoryImpl factory = (LazyRangeMarkerFactoryImpl)LazyRangeMarkerFactory.getInstance(getProject());
+ VirtualFile virtualFile = psiFile.getVirtualFile();
+ LazyRangeMarkerFactoryImpl.LazyMarker marker = (LazyRangeMarkerFactoryImpl.LazyMarker)factory.createRangeMarker(virtualFile, 0);
+ WeakList<LazyRangeMarkerFactoryImpl.LazyMarker> markers = LazyRangeMarkerFactoryImpl.getMarkers(virtualFile);
+ assertSame(marker, assertOneElement(markers));
+
+ assertFalse(marker.isDelegated());
+ assertTrue(marker.isValid());
+ assertEquals(0, marker.getStartOffset());
+ assertFalse(marker.isDelegated());
+
+ marker.dispose();
+ assertFalse(marker.isValid());
+ assertEmpty(LazyRangeMarkerFactoryImpl.getMarkers(virtualFile));
+
+
+ marker = (LazyRangeMarkerFactoryImpl.LazyMarker)factory.createRangeMarker(virtualFile, 0);
+ assertFalse(marker.isDelegated());
+ assertTrue(marker.isValid());
+ assertEquals(0, marker.getStartOffset());
+ assertFalse(marker.isDelegated());
+
+ Document document = marker.getDocument();
+ document.insertString(2, "yyy");
+ assertTrue(marker.isDelegated());
+ assertTrue(marker.isValid());
+ assertEquals(0, marker.getStartOffset());
+
+ assertEmpty(LazyRangeMarkerFactoryImpl.getMarkers(virtualFile));
+ marker.dispose();
+ assertEmpty(LazyRangeMarkerFactoryImpl.getMarkers(virtualFile));
}
}
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/StripTrailingSpacesTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/StripTrailingSpacesTest.java
index abfef7cf0657..285aadbef402 100644
--- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/StripTrailingSpacesTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/StripTrailingSpacesTest.java
@@ -13,15 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.intellij.openapi.editor;
+package com.intellij.openapi.editor.impl;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.impl.ApplicationImpl;
import com.intellij.openapi.command.WriteCommandAction;
+import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.ex.DocumentEx;
import com.intellij.openapi.editor.ex.EditorSettingsExternalizable;
import com.intellij.openapi.fileEditor.FileDocumentManager;
-import com.intellij.openapi.fileEditor.impl.TrailingSpacesStripper;
import com.intellij.testFramework.LightPlatformCodeInsightTestCase;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/NonProjectFileAccessTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/NonProjectFileAccessTest.java
index e517799165e2..06594d2352bf 100644
--- a/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/NonProjectFileAccessTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/NonProjectFileAccessTest.java
@@ -245,7 +245,7 @@ public class NonProjectFileAccessTest extends HeavyFileEditorManagerTestCase {
assertNotNull(NonProjectFileWritingAccessProvider.getAccessStatus(getProject(), nonProjectFile1));
assertNull(NonProjectFileWritingAccessProvider.getAccessStatus(getProject(), nonProjectFile2));
- PsiTestUtil.removeContentEntry(myModule, contextRoot);
+ PsiTestUtil.removeContentEntry(myModule, contextRoot.getFile());
// do not add notification panel until access is requested
assertNotNull(NonProjectFileWritingAccessProvider.getAccessStatus(getProject(), nonProjectFile1));
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/keymap/impl/ModifierKeyDoubleClickHandlerTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/keymap/impl/ModifierKeyDoubleClickHandlerTest.java
index 490aa294974d..96d85c122624 100644
--- a/platform/platform-tests/testSrc/com/intellij/openapi/keymap/impl/ModifierKeyDoubleClickHandlerTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/keymap/impl/ModifierKeyDoubleClickHandlerTest.java
@@ -118,6 +118,16 @@ public class ModifierKeyDoubleClickHandlerTest extends LightPlatformTestCase {
release();
}
+ public void testRepeatedInvocationOnKeyHold() {
+ press();
+ release();
+ press();
+ key(2);
+ assertInvocationCounts(0, 0, 2);
+ release();
+ assertInvocationCounts(0, 0, 2);
+ }
+
public void assertInvocationCounts(int shiftKeyCount, int shiftShiftCount, int shiftShiftKeyCount) {
assertEquals(shiftKeyCount, myShiftKeyActionInvocationCount);
assertEquals(shiftShiftCount, myShiftShiftActionInvocationCount);
@@ -143,18 +153,24 @@ public class ModifierKeyDoubleClickHandlerTest extends LightPlatformTestCase {
}
private void key() {
- IdeEventQueue.getInstance().dispatchEvent(new KeyEvent(myComponent,
- KeyEvent.KEY_PRESSED,
- Clock.getTime(),
- InputEvent.SHIFT_MASK,
- KeyEvent.VK_BACK_SPACE,
- '\b'));
- IdeEventQueue.getInstance().dispatchEvent(new KeyEvent(myComponent,
- KeyEvent.KEY_TYPED,
- Clock.getTime(),
- InputEvent.SHIFT_MASK,
- 0,
- '\b'));
+ key(1);
+ }
+
+ private void key(int repeat) {
+ for (int i = 0; i < repeat; i++) {
+ IdeEventQueue.getInstance().dispatchEvent(new KeyEvent(myComponent,
+ KeyEvent.KEY_PRESSED,
+ Clock.getTime(),
+ InputEvent.SHIFT_MASK,
+ KeyEvent.VK_BACK_SPACE,
+ '\b'));
+ IdeEventQueue.getInstance().dispatchEvent(new KeyEvent(myComponent,
+ KeyEvent.KEY_TYPED,
+ Clock.getTime(),
+ InputEvent.SHIFT_MASK,
+ 0,
+ '\b'));
+ }
IdeEventQueue.getInstance().dispatchEvent(new KeyEvent(myComponent,
KeyEvent.KEY_RELEASED,
Clock.getTime(),
diff --git a/platform/projectModel-api/src/com/intellij/openapi/roots/ProjectFileIndex.java b/platform/projectModel-api/src/com/intellij/openapi/roots/ProjectFileIndex.java
index b06cf065fd95..17a7abc2a694 100644
--- a/platform/projectModel-api/src/com/intellij/openapi/roots/ProjectFileIndex.java
+++ b/platform/projectModel-api/src/com/intellij/openapi/roots/ProjectFileIndex.java
@@ -131,6 +131,7 @@ public interface ProjectFileIndex extends FileIndex {
/**
* @deprecated name of this method may be confusing. If you want to check if the file is excluded or ignored use {@link #isExcluded(com.intellij.openapi.vfs.VirtualFile)}.
* If you want to check if the file is ignored use {@link com.intellij.openapi.fileTypes.FileTypeRegistry#isFileIgnored(com.intellij.openapi.vfs.VirtualFile)}.
+ * If you want to check if the file or one of its parents is ignored use {@link #isUnderIgnored(com.intellij.openapi.vfs.VirtualFile)}.
*/
@Deprecated
boolean isIgnored(@NotNull VirtualFile file);
@@ -143,4 +144,13 @@ public interface ProjectFileIndex extends FileIndex {
* @return true if <code>file</code> is excluded or ignored, false otherwise.
*/
boolean isExcluded(@NotNull VirtualFile file);
+
+ /**
+ * Checks if the specified file or directory is located under project roots but the file itself or one of its parent directories is ignored
+ * by {@link com.intellij.openapi.fileTypes.FileTypeRegistry#isFileIgnored(com.intellij.openapi.vfs.VirtualFile)}).
+ *
+ * @param file the file to check.
+ * @return true if <code>file</code> is ignored, false otherwise.
+ */
+ boolean isUnderIgnored(@NotNull VirtualFile file);
}
diff --git a/platform/projectModel-impl/src/com/intellij/ide/projectView/impl/ProjectRootsUtil.java b/platform/projectModel-impl/src/com/intellij/ide/projectView/impl/ProjectRootsUtil.java
index 7acb0fb12243..7b436b53c8d6 100644
--- a/platform/projectModel-impl/src/com/intellij/ide/projectView/impl/ProjectRootsUtil.java
+++ b/platform/projectModel-impl/src/com/intellij/ide/projectView/impl/ProjectRootsUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -41,21 +41,21 @@ public class ProjectRootsUtil {
return directoryFile.equals(fileIndex.getSourceRootForFile(directoryFile));
}
- public static boolean isInSource(final PsiDirectory directory) {
+ public static boolean isInSource(@NotNull PsiDirectory directory) {
return isInSource(directory.getVirtualFile(), directory.getProject());
}
- public static boolean isInSource(final VirtualFile directoryFile, final Project project) {
+ public static boolean isInSource(@NotNull VirtualFile directoryFile, @NotNull Project project) {
final ProjectFileIndex projectFileIndex = ProjectRootManager.getInstance(project).getFileIndex();
return projectFileIndex.isInSourceContent(directoryFile);
}
- public static boolean isInTestSource(final VirtualFile directoryFile, final Project project) {
+ public static boolean isInTestSource(@NotNull VirtualFile directoryFile, @NotNull Project project) {
final ProjectFileIndex projectFileIndex = ProjectRootManager.getInstance(project).getFileIndex();
return projectFileIndex.isInTestSourceContent(directoryFile);
}
- public static boolean isModuleSourceRoot(@NotNull VirtualFile virtualFile, final @NotNull Project project) {
+ public static boolean isModuleSourceRoot(@NotNull VirtualFile virtualFile, @NotNull final Project project) {
return getModuleSourceRoot(virtualFile, project) != null;
}
@@ -66,7 +66,7 @@ public class ProjectRootsUtil {
return module != null && !module.isDisposed() ? findSourceFolder(module, root) : null;
}
- public static boolean isLibraryRoot(final VirtualFile directoryFile, final Project project) {
+ public static boolean isLibraryRoot(@NotNull VirtualFile directoryFile, @NotNull Project project) {
final ProjectFileIndex projectFileIndex = ProjectRootManager.getInstance(project).getFileIndex();
if (projectFileIndex.isInLibraryClasses(directoryFile)) {
final VirtualFile parent = directoryFile.getParent();
diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/OrderEnumerationHandler.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/OrderEnumerationHandler.java
index 83984e11a80b..7a62c35d0390 100644
--- a/platform/projectModel-impl/src/com/intellij/openapi/roots/OrderEnumerationHandler.java
+++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/OrderEnumerationHandler.java
@@ -18,6 +18,7 @@ package com.intellij.openapi.roots;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -65,4 +66,12 @@ public abstract class OrderEnumerationHandler {
@NotNull Collection<String> urls) {
return false;
}
+
+ public boolean addCustomModuleRoots(@NotNull OrderRootType type,
+ @NotNull ModuleRootModel rootModel,
+ @NotNull Collection<String> result,
+ boolean includeProduction,
+ boolean includeTests) {
+ return false;
+ }
}
diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryIndex.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryIndex.java
index 9fdd8e09a57d..e87d3c749b10 100644
--- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryIndex.java
+++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryIndex.java
@@ -17,23 +17,23 @@
package com.intellij.openapi.roots.impl;
import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.OrderEntry;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Query;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import org.jetbrains.annotations.TestOnly;
import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
+import java.util.List;
+
public abstract class DirectoryIndex {
public static DirectoryIndex getInstance(Project project) {
assert !project.isDefault() : "Must not call DirectoryIndex for default project";
return ServiceManager.getService(project, DirectoryIndex.class);
}
- @TestOnly
- public abstract void checkConsistency();
-
/**
* The same as {@link #getInfoForFile} but works only for directories or file roots and returns {@code null} for directories
* which aren't included in project content or libraries
@@ -62,4 +62,13 @@ public abstract class DirectoryIndex {
public boolean isInitialized() {
return true;
}
+
+ @NotNull
+ public abstract OrderEntry[] getOrderEntries(@NotNull DirectoryInfo info);
+
+ @Nullable
+ abstract OrderEntry findOrderEntryWithOwnerModule(@NotNull DirectoryInfo info, @NotNull Module ownerModule);
+
+ @NotNull
+ abstract List<OrderEntry> findAllOrderEntriesWithOwnerModule(@NotNull DirectoryInfo info, @NotNull Module ownerModule);
}
diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexExcludePolicy.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexExcludePolicy.java
index b31519ccb4a2..61838f51ac1d 100644
--- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexExcludePolicy.java
+++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexExcludePolicy.java
@@ -17,7 +17,6 @@
package com.intellij.openapi.roots.impl;
import com.intellij.openapi.extensions.ExtensionPointName;
-import com.intellij.openapi.module.Module;
import com.intellij.openapi.roots.ModuleRootModel;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.pointers.VirtualFilePointer;
@@ -29,10 +28,9 @@ import org.jetbrains.annotations.NotNull;
public interface DirectoryIndexExcludePolicy {
ExtensionPointName<DirectoryIndexExcludePolicy> EP_NAME = ExtensionPointName.create("com.intellij.directoryIndexExcludePolicy");
- boolean isExcludeRoot(VirtualFile file);
- boolean isExcludeRootForModule(@NotNull Module module, final VirtualFile file);
@NotNull
VirtualFile[] getExcludeRootsForProject();
+
@NotNull
VirtualFilePointer[] getExcludeRootsForModule(@NotNull ModuleRootModel rootModel);
}
diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryInfo.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryInfo.java
index 87448a584a23..cd5fbd7d5867 100644
--- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryInfo.java
+++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryInfo.java
@@ -17,13 +17,8 @@
package com.intellij.openapi.roots.impl;
import com.intellij.openapi.module.Module;
-import com.intellij.openapi.roots.OrderEntry;
import com.intellij.openapi.vfs.VirtualFile;
-import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import org.jetbrains.annotations.TestOnly;
-
-import java.util.List;
public abstract class DirectoryInfo {
/**
@@ -61,16 +56,4 @@ public abstract class DirectoryInfo {
@Nullable
public abstract Module getModule();
-
- @NotNull
- public abstract OrderEntry[] getOrderEntries();
-
- @Nullable
- abstract OrderEntry findOrderEntryWithOwnerModule(@NotNull Module ownerModule);
-
- @NotNull
- abstract List<OrderEntry> findAllOrderEntriesWithOwnerModule(@NotNull Module ownerModule);
-
- @TestOnly
- abstract void assertConsistency();
}
diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryInfoImpl.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryInfoImpl.java
index 0be339bf3c5f..1c3ca4f2ff8d 100644
--- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryInfoImpl.java
+++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryInfoImpl.java
@@ -16,34 +16,16 @@
package com.intellij.openapi.roots.impl;
import com.intellij.openapi.module.Module;
-import com.intellij.openapi.roots.OrderEntry;
-import com.intellij.openapi.roots.OrderRootType;
-import com.intellij.openapi.roots.RootPolicy;
-import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import org.jetbrains.annotations.TestOnly;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
/**
* @author nik
*/
-public abstract class DirectoryInfoImpl extends DirectoryInfo {
- public static final Comparator<OrderEntry> BY_OWNER_MODULE = new Comparator<OrderEntry>() {
- @Override
- public int compare(OrderEntry o1, OrderEntry o2) {
- String name1 = o1.getOwnerModule().getName();
- String name2 = o2.getOwnerModule().getName();
- return name1.compareTo(name2);
- }
- };
+public class DirectoryInfoImpl extends DirectoryInfo {
public static final int MAX_ROOT_TYPE_ID = Byte.MAX_VALUE;
+ private final VirtualFile myRoot;//original project root for which this information is calculated
private final Module module; // module to which content it belongs or null
private final VirtualFile libraryClassRoot; // class root in library
private final VirtualFile contentRoot;
@@ -53,8 +35,9 @@ public abstract class DirectoryInfoImpl extends DirectoryInfo {
private final boolean myExcluded;
private final byte mySourceRootTypeId;
- DirectoryInfoImpl(Module module, VirtualFile contentRoot, VirtualFile sourceRoot, VirtualFile libraryClassRoot,
+ DirectoryInfoImpl(@NotNull VirtualFile root, Module module, VirtualFile contentRoot, VirtualFile sourceRoot, VirtualFile libraryClassRoot,
boolean inModuleSource, boolean inLibrarySource, boolean isExcluded, int sourceRootTypeId) {
+ myRoot = root;
this.module = module;
this.libraryClassRoot = libraryClassRoot;
this.contentRoot = contentRoot;
@@ -74,30 +57,12 @@ public abstract class DirectoryInfoImpl extends DirectoryInfo {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
- DirectoryInfoImpl info = (DirectoryInfoImpl)o;
-
- return mySourceRootTypeId == info.mySourceRootTypeId &&
- myInModuleSource == info.myInModuleSource &&
- myInLibrarySource == info.myInLibrarySource &&
- myExcluded == info.myExcluded &&
- Comparing.equal(contentRoot, info.contentRoot) &&
- Comparing.equal(libraryClassRoot, info.libraryClassRoot) &&
- Comparing.equal(module, info.module) &&
- Arrays.equals(getOrderEntries(), info.getOrderEntries()) &&
- Comparing.equal(sourceRoot, info.sourceRoot);
+ return myRoot.equals(((DirectoryInfoImpl)o).myRoot);
}
@Override
public int hashCode() {
- int result = module != null ? module.hashCode() : 0;
- result = 31 * result + (libraryClassRoot != null ? libraryClassRoot.hashCode() : 0);
- result = 31 * result + (contentRoot != null ? contentRoot.hashCode() : 0);
- result = 31 * result + (sourceRoot != null ? sourceRoot.hashCode() : 0);
- result = 31 * result + (myInModuleSource ? 1 : 0);
- result = 31 * result + (myInLibrarySource ? 1 : 0);
- result = 31 * result + (myExcluded ? 1 : 0);
- result = 31 * result + (int)mySourceRootTypeId;
- return result;
+ return myRoot.hashCode();
}
@SuppressWarnings({"HardCodedStringLiteral"})
@@ -111,98 +76,9 @@ public abstract class DirectoryInfoImpl extends DirectoryInfo {
", libraryClassRoot=" + getLibraryClassRoot() +
", contentRoot=" + getContentRoot() +
", sourceRoot=" + getSourceRoot() +
- ", orderEntries=" + Arrays.toString(getOrderEntries()) +
"}";
}
- @NotNull
- private static OrderEntry createFakeOrderEntry(@NotNull final Module ownerModule) {
- return new OrderEntry() {
- @NotNull
- @Override
- public VirtualFile[] getFiles(OrderRootType type) {
- throw new IncorrectOperationException();
- }
-
- @NotNull
- @Override
- public String[] getUrls(OrderRootType rootType) {
- throw new IncorrectOperationException();
- }
-
- @NotNull
- @Override
- public String getPresentableName() {
- throw new IncorrectOperationException();
- }
-
- @Override
- public boolean isValid() {
- throw new IncorrectOperationException();
- }
-
- @NotNull
- @Override
- public Module getOwnerModule() {
- return ownerModule;
- }
-
- @Override
- public <R> R accept(RootPolicy<R> policy, @Nullable R initialValue) {
- throw new IncorrectOperationException();
- }
-
- @Override
- public int compareTo(@NotNull OrderEntry o) {
- throw new IncorrectOperationException();
- }
-
- @Override
- public boolean isSynthetic() {
- throw new IncorrectOperationException();
- }
- };
- }
-
- @Nullable
- OrderEntry findOrderEntryWithOwnerModule(@NotNull Module ownerModule) {
- OrderEntry[] entries = getOrderEntries();
- if (entries.length < 10) {
- for (OrderEntry entry : entries) {
- if (entry.getOwnerModule() == ownerModule) return entry;
- }
- return null;
- }
- int index = Arrays.binarySearch(entries, createFakeOrderEntry(ownerModule), BY_OWNER_MODULE);
- return index < 0 ? null : entries[index];
- }
-
- @NotNull
- List<OrderEntry> findAllOrderEntriesWithOwnerModule(@NotNull Module ownerModule) {
- OrderEntry[] entries = getOrderEntries();
- if (entries.length == 1) {
- OrderEntry entry = entries[0];
- return entry.getOwnerModule() == ownerModule ? Arrays.asList(entries) : Collections.<OrderEntry>emptyList();
- }
- int index = Arrays.binarySearch(entries, createFakeOrderEntry(ownerModule), BY_OWNER_MODULE);
- if (index < 0) {
- return Collections.emptyList();
- }
- int firstIndex = index;
- while (firstIndex-1 >= 0 && entries[firstIndex-1].getOwnerModule() == ownerModule) {
- firstIndex--;
- }
- int lastIndex = index+1;
- while (lastIndex < entries.length && entries[lastIndex].getOwnerModule() == ownerModule) {
- lastIndex++;
- }
-
- OrderEntry[] subArray = new OrderEntry[lastIndex - firstIndex];
- System.arraycopy(entries, firstIndex, subArray, 0, lastIndex - firstIndex);
-
- return Arrays.asList(subArray);
- }
-
public boolean isInProject() {
return !isExcluded();
}
@@ -241,15 +117,12 @@ public abstract class DirectoryInfoImpl extends DirectoryInfo {
return module;
}
- @TestOnly
- void assertConsistency() {
- OrderEntry[] entries = getOrderEntries();
- for (int i=1; i<entries.length; i++) {
- assert BY_OWNER_MODULE.compare(entries[i-1], entries[i]) <= 0;
- }
- }
-
public int getSourceRootTypeId() {
return mySourceRootTypeId;
}
+
+ @NotNull
+ public VirtualFile getRoot() {
+ return myRoot;
+ }
}
diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ModuleFileIndexImpl.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ModuleFileIndexImpl.java
index 3b5ea4fa1610..8140a3c15211 100644
--- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ModuleFileIndexImpl.java
+++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ModuleFileIndexImpl.java
@@ -79,12 +79,12 @@ public class ModuleFileIndexImpl extends FileIndexBase implements ModuleFileInde
@Override
@NotNull
public List<OrderEntry> getOrderEntriesForFile(@NotNull VirtualFile fileOrDir) {
- return getInfoForFileOrDirectory(fileOrDir).findAllOrderEntriesWithOwnerModule(myModule);
+ return myDirectoryIndex.findAllOrderEntriesWithOwnerModule(getInfoForFileOrDirectory(fileOrDir), myModule);
}
@Override
public OrderEntry getOrderEntryForFile(@NotNull VirtualFile fileOrDir) {
- return getInfoForFileOrDirectory(fileOrDir).findOrderEntryWithOwnerModule(myModule);
+ return myDirectoryIndex.findOrderEntryWithOwnerModule(getInfoForFileOrDirectory(fileOrDir), myModule);
}
@Override
diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/NonProjectDirectoryInfo.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/NonProjectDirectoryInfo.java
index 7937f08fc7b4..ce09ec2fb819 100644
--- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/NonProjectDirectoryInfo.java
+++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/NonProjectDirectoryInfo.java
@@ -16,14 +16,9 @@
package com.intellij.openapi.roots.impl;
import com.intellij.openapi.module.Module;
-import com.intellij.openapi.roots.OrderEntry;
import com.intellij.openapi.vfs.VirtualFile;
-import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import java.util.Collections;
-import java.util.List;
-
/**
* @author nik
*/
@@ -53,22 +48,6 @@ class NonProjectDirectoryInfo extends DirectoryInfo {
return false;
}
- @NotNull
- @Override
- public OrderEntry[] getOrderEntries() {
- return OrderEntry.EMPTY_ARRAY;
- }
-
- @Nullable
- OrderEntry findOrderEntryWithOwnerModule(@NotNull Module ownerModule) {
- return null;
- }
-
- @NotNull
- List<OrderEntry> findAllOrderEntriesWithOwnerModule(@NotNull Module ownerModule) {
- return Collections.emptyList();
- }
-
@Override
public String toString() {
return "DirectoryInfo: " + myDebugName;
@@ -118,9 +97,6 @@ class NonProjectDirectoryInfo extends DirectoryInfo {
return null;
}
- void assertConsistency() {
- }
-
public int getSourceRootTypeId() {
return 0;
}
diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/OrderEnumeratorBase.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/OrderEnumeratorBase.java
index 61a6aee9315b..b13df0560292 100644
--- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/OrderEnumeratorBase.java
+++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/OrderEnumeratorBase.java
@@ -356,6 +356,38 @@ abstract class OrderEnumeratorBase extends OrderEnumerator implements OrderEnume
return false;
}
+ boolean addCustomRootsForModule(OrderRootType type,
+ ModuleRootModel rootModel,
+ Collection<VirtualFile> result,
+ boolean includeProduction,
+ boolean includeTests) {
+ for (OrderEnumerationHandler handler : myCustomHandlers) {
+ final List<String> urls = new ArrayList<String>();
+ final boolean added = handler.addCustomModuleRoots(type, rootModel, urls, includeProduction, includeTests);
+ for (String url : urls) {
+ ContainerUtil.addIfNotNull(VirtualFileManager.getInstance().findFileByUrl(url), result);
+ }
+
+ if (added) return true;
+ }
+ return false;
+ }
+
+ boolean addCustomRootUrlsForModule(OrderRootType type,
+ ModuleRootModel rootModel,
+ Collection<String> result,
+ boolean includeProduction,
+ boolean includeTests) {
+ for (OrderEnumerationHandler handler : myCustomHandlers) {
+ final List<String> urls = new ArrayList<String>();
+ final boolean added = handler.addCustomModuleRoots(type, rootModel, urls, includeProduction, includeTests);
+ result.addAll(urls);
+
+ if (added) return true;
+ }
+ return false;
+ }
+
@Override
public boolean isRuntimeOnly() {
return myRuntimeOnly;
diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/OrderRootsEnumeratorImpl.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/OrderRootsEnumeratorImpl.java
index ea5742cce176..fb9a75176255 100644
--- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/OrderRootsEnumeratorImpl.java
+++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/OrderRootsEnumeratorImpl.java
@@ -240,6 +240,7 @@ public class OrderRootsEnumeratorImpl implements OrderRootsEnumerator {
}
}
}
+ myOrderEnumerator.addCustomRootsForModule(type, rootModel, result, includeProduction, includeTests);
}
private void collectModuleRootsUrls(OrderRootType type,
diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectFileIndexFacade.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectFileIndexFacade.java
index 0bb65c600083..e15763716280 100644
--- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectFileIndexFacade.java
+++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectFileIndexFacade.java
@@ -69,6 +69,11 @@ public class ProjectFileIndexFacade extends FileIndexFacade {
return myFileIndex.isExcluded(file);
}
+ @Override
+ public boolean isUnderIgnored(@NotNull VirtualFile file) {
+ return myFileIndex.isUnderIgnored(file);
+ }
+
@Nullable
@Override
public Module getModuleForFile(@NotNull VirtualFile file) {
diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectFileIndexImpl.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectFileIndexImpl.java
index acb6598f55c8..e2417193149e 100644
--- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectFileIndexImpl.java
+++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectFileIndexImpl.java
@@ -85,6 +85,11 @@ public class ProjectFileIndexImpl extends FileIndexBase implements ProjectFileIn
}
@Override
+ public boolean isUnderIgnored(@NotNull VirtualFile file) {
+ return getInfoForFileOrDirectory(file).isIgnored();
+ }
+
+ @Override
public Module getModuleForFile(@NotNull VirtualFile file) {
if (file instanceof VirtualFileWindow) file = ((VirtualFileWindow)file).getDelegate();
DirectoryInfo info = getInfoForFileOrDirectory(file);
@@ -95,7 +100,7 @@ public class ProjectFileIndexImpl extends FileIndexBase implements ProjectFileIn
@Override
@NotNull
public List<OrderEntry> getOrderEntriesForFile(@NotNull VirtualFile file) {
- return Arrays.asList(getInfoForFileOrDirectory(file).getOrderEntries());
+ return Arrays.asList(myDirectoryIndex.getOrderEntries(getInfoForFileOrDirectory(file)));
}
@Override
diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerImpl.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerImpl.java
index 85a098341e4e..8e80670b1f76 100644
--- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerImpl.java
+++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerImpl.java
@@ -131,8 +131,7 @@ public class ProjectRootManagerImpl extends ProjectRootManagerEx implements Proj
return (ProjectRootManagerImpl)getInstance(project);
}
- public ProjectRootManagerImpl(Project project,
- DirectoryIndex directoryIndex) {
+ public ProjectRootManagerImpl(Project project) {
myProject = project;
myRootsCache = new OrderRootsCache(project);
}
@@ -143,8 +142,6 @@ public class ProjectRootManagerImpl extends ProjectRootManagerEx implements Proj
return ProjectFileIndex.SERVICE.getInstance(myProject);
}
- private final Map<ModuleRootListener, MessageBusConnection> myListenerAdapters = new HashMap<ModuleRootListener, MessageBusConnection>();
-
@Override
@NotNull
public List<String> getContentRootUrls() {
diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/RootIndex.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/RootIndex.java
index ca68cee3d061..eb04fb6c103e 100644
--- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/RootIndex.java
+++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/RootIndex.java
@@ -25,13 +25,16 @@ import com.intellij.openapi.roots.*;
import com.intellij.openapi.roots.impl.libraries.LibraryEx;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.LowMemoryWatcher;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.newvfs.events.VFileEvent;
import com.intellij.util.CollectionQuery;
+import com.intellij.util.EmptyQuery;
import com.intellij.util.Query;
+import com.intellij.util.containers.ConcurrentHashSet;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import gnu.trove.TObjectIntHashMap;
@@ -41,7 +44,15 @@ import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
import java.util.*;
-public class RootIndex extends DirectoryIndex {
+public class RootIndex {
+ public static final Comparator<OrderEntry> BY_OWNER_MODULE = new Comparator<OrderEntry>() {
+ @Override
+ public int compare(OrderEntry o1, OrderEntry o2) {
+ String name1 = o1.getOwnerModule().getName();
+ String name2 = o2.getOwnerModule().getName();
+ return name1.compareTo(name2);
+ }
+ };
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.roots.impl.RootIndex");
private final Set<VirtualFile> myProjectExcludedRoots = ContainerUtil.newHashSet();
@@ -54,11 +65,20 @@ public class RootIndex extends DirectoryIndex {
};
private final Map<String, List<VirtualFile>> myDirectoriesByPackageNameCache = ContainerUtil.newConcurrentMap();
+ private final Set<String> myNonExistentPackages = new ConcurrentHashSet<String>();
private final InfoCache myInfoCache;
private final List<JpsModuleSourceRootType<?>> myRootTypes = ContainerUtil.newArrayList();
private final TObjectIntHashMap<JpsModuleSourceRootType<?>> myRootTypeId = new TObjectIntHashMap<JpsModuleSourceRootType<?>>();
@NotNull private final Project myProject;
private volatile Map<VirtualFile, OrderEntry[]> myOrderEntries;
+ @SuppressWarnings("UnusedDeclaration")
+ private final LowMemoryWatcher myLowMemoryWatcher = LowMemoryWatcher.register(new Runnable() {
+ @Override
+ public void run() {
+ myNonExistentPackages.clear();
+ }
+ });
+
// made public for Upsource
public RootIndex(@NotNull Project project, @NotNull InfoCache cache) {
@@ -145,7 +165,6 @@ public class RootIndex extends DirectoryIndex {
}
}
}
-
}
}
}
@@ -171,7 +190,8 @@ public class RootIndex extends DirectoryIndex {
if (orderEntry instanceof ModuleOrderEntry) {
final Module depModule = ((ModuleOrderEntry)orderEntry).getModule();
if (depModule != null) {
- VirtualFile[] importedClassRoots = OrderEnumerator.orderEntries(depModule).exportedOnly().recursively().classes().usingCache().getRoots();
+ VirtualFile[] importedClassRoots =
+ OrderEnumerator.orderEntries(depModule).exportedOnly().recursively().classes().usingCache().getRoots();
for (VirtualFile importedClassRoot : importedClassRoots) {
depEntries.putValue(importedClassRoot, orderEntry);
}
@@ -197,7 +217,9 @@ public class RootIndex extends DirectoryIndex {
Set<VirtualFile> allRoots = rootInfo.getAllRoots();
for (VirtualFile file : allRoots) {
List<VirtualFile> hierarchy = getHierarchy(file, allRoots, rootInfo);
- result.put(file, hierarchy == null ? OrderEntry.EMPTY_ARRAY : calcOrderEntries(rootInfo, depEntries, libClassRootEntries, libSourceRootEntries, hierarchy));
+ result.put(file, hierarchy == null
+ ? OrderEntry.EMPTY_ARRAY
+ : calcOrderEntries(rootInfo, depEntries, libClassRootEntries, libSourceRootEntries, hierarchy));
}
myOrderEntries = result;
return result;
@@ -211,7 +233,8 @@ public class RootIndex extends DirectoryIndex {
@Nullable VirtualFile libraryClassRoot = info.findLibraryRootInfo(hierarchy, false);
@Nullable VirtualFile librarySourceRoot = info.findLibraryRootInfo(hierarchy, true);
Set<OrderEntry> orderEntries = ContainerUtil.newLinkedHashSet();
- orderEntries.addAll(info.getLibraryOrderEntries(hierarchy, libraryClassRoot, librarySourceRoot, libClassRootEntries, libSourceRootEntries));
+ orderEntries
+ .addAll(info.getLibraryOrderEntries(hierarchy, libraryClassRoot, librarySourceRoot, libClassRootEntries, libSourceRootEntries));
for (VirtualFile root : hierarchy) {
orderEntries.addAll(depEntries.get(root));
}
@@ -224,12 +247,11 @@ public class RootIndex extends DirectoryIndex {
}
OrderEntry[] array = orderEntries.toArray(new OrderEntry[orderEntries.size()]);
- Arrays.sort(array, DirectoryInfoImpl.BY_OWNER_MODULE);
+ Arrays.sort(array, BY_OWNER_MODULE);
return array;
}
- @Override
public void checkConsistency() {
for (VirtualFile file : myProjectExcludedRoots) {
assert file.exists() : file.getPath() + " does not exist";
@@ -247,21 +269,14 @@ public class RootIndex extends DirectoryIndex {
int id = myRootTypes.size();
if (id > DirectoryInfoImpl.MAX_ROOT_TYPE_ID) {
- LOG.error("Too many different types of module source roots (" + id + ") registered: " + myRootTypes);
+ LOG.error("Too many different types of module source roots (" + id + ") registered: " + myRootTypes);
}
myRootTypes.add(rootType);
myRootTypeId.put(rootType, id);
return id;
}
- @Override
- public DirectoryInfo getInfoForDirectory(@NotNull VirtualFile dir) {
- DirectoryInfo info = getInfoForFile(dir);
- return info.isInProject() ? info : null;
- }
-
@NotNull
- @Override
public DirectoryInfo getInfoForFile(@NotNull VirtualFile file) {
if (!file.isValid()) {
return NonProjectDirectoryInfo.INVALID;
@@ -314,28 +329,41 @@ public class RootIndex extends DirectoryIndex {
return info;
}
- @Override
@NotNull
public Query<VirtualFile> getDirectoriesByPackageName(@NotNull final String packageName, final boolean includeLibrarySources) {
List<VirtualFile> result = myDirectoriesByPackageNameCache.get(packageName);
if (result == null) {
+ if (myNonExistentPackages.contains(packageName)) return EmptyQuery.getEmptyQuery();
+
result = ContainerUtil.newSmartList();
-
+
if (StringUtil.isNotEmpty(packageName) && !StringUtil.startsWithChar(packageName, '.')) {
- String shortName = StringUtil.getShortName(packageName);
- for (VirtualFile parentDir : getDirectoriesByPackageName(StringUtil.getPackageName(packageName), true)) {
- VirtualFile child = parentDir.findChild(shortName);
- if (child != null && child.isDirectory() && getInfoForFile(child).isInProject()
- && packageName.equals(getPackageName(child))) {
- result.add(child);
+ int i = packageName.lastIndexOf('.');
+ while (true) {
+ String shortName = packageName.substring(i + 1);
+ String parentPackage = i > 0 ? packageName.substring(0, i) : "";
+ for (VirtualFile parentDir : getDirectoriesByPackageName(parentPackage, true)) {
+ VirtualFile child = parentDir.findChild(shortName);
+ if (child != null && child.isDirectory() && getInfoForFile(child).isInProject()
+ && packageName.equals(getPackageName(child))) {
+ result.add(child);
+ }
}
+ if (i < 0) break;
+ i = packageName.lastIndexOf('.', i - 1);
}
}
- result.addAll(myPackagePrefixRoots.get(packageName));
+ for (VirtualFile file : myPackagePrefixRoots.get(packageName)) {
+ if (file.isDirectory()) {
+ result.add(file);
+ }
+ }
if (!result.isEmpty()) {
myDirectoriesByPackageNameCache.put(packageName, result);
+ } else {
+ myNonExistentPackages.add(packageName);
}
}
@@ -351,7 +379,6 @@ public class RootIndex extends DirectoryIndex {
return new CollectionQuery<VirtualFile>(result);
}
- @Override
@Nullable
public String getPackageName(@NotNull final VirtualFile dir) {
if (dir.isDirectory()) {
@@ -380,7 +407,6 @@ public class RootIndex extends DirectoryIndex {
return parentPackageName.isEmpty() ? subdirName : parentPackageName + "." + subdirName;
}
- @Override
@Nullable
public JpsModuleSourceRootType<?> getSourceRootType(@NotNull DirectoryInfo directoryInfo) {
return myRootTypes.get(directoryInfo.getSourceRootTypeId());
@@ -487,8 +513,9 @@ public class RootIndex extends DirectoryIndex {
if (source && libraryOrSdkSources.contains(root) &&
(!sourceOfLibraries.containsKey(root) || !librariesToIgnore.containsAll(sourceOfLibraries.get(root)))) {
return root;
- } else if (!source && libraryOrSdkClasses.contains(root) &&
- (!classOfLibraries.containsKey(root) || !librariesToIgnore.containsAll(classOfLibraries.get(root)))) {
+ }
+ else if (!source && libraryOrSdkClasses.contains(root) &&
+ (!classOfLibraries.containsKey(root) || !librariesToIgnore.containsAll(classOfLibraries.get(root)))) {
return root;
}
}
@@ -569,8 +596,11 @@ public class RootIndex extends DirectoryIndex {
}
}
+
@NotNull
- private Pair<DirectoryInfo, String> calcDirectoryInfo(@NotNull final VirtualFile root, @NotNull final List<VirtualFile> hierarchy, @NotNull RootInfo info) {
+ private static Pair<DirectoryInfo, String> calcDirectoryInfo(@NotNull final VirtualFile root,
+ @NotNull final List<VirtualFile> hierarchy,
+ @NotNull RootInfo info) {
VirtualFile moduleContentRoot = info.findModuleRootInfo(hierarchy);
VirtualFile libraryClassRoot = info.findLibraryRootInfo(hierarchy, false);
VirtualFile librarySourceRoot = info.findLibraryRootInfo(hierarchy, true);
@@ -590,23 +620,26 @@ public class RootIndex extends DirectoryIndex {
int typeId = moduleSourceRoot != null ? info.rootTypeId.get(moduleSourceRoot) : 0;
Module module = parentModuleForExcluded != null ? parentModuleForExcluded : info.contentRootOf.get(moduleContentRoot);
- DirectoryInfo directoryInfo = new DirectoryInfoImpl(module, moduleContentRoot, sourceRoot, libraryClassRoot, inModuleSources, inLibrarySource,
- parentModuleForExcluded != null, typeId) {
- @NotNull
- @Override
- public OrderEntry[] getOrderEntries() {
- OrderEntry[] entries = RootIndex.this.getOrderEntries().get(root);
- return entries == null ? OrderEntry.EMPTY_ARRAY : entries;
- }
- };
+ DirectoryInfo directoryInfo =
+ new DirectoryInfoImpl(root, module, moduleContentRoot, sourceRoot, libraryClassRoot, inModuleSources, inLibrarySource,
+ parentModuleForExcluded != null, typeId);
String packagePrefix = info.calcPackagePrefix(root, hierarchy, moduleContentRoot, libraryClassRoot, librarySourceRoot);
return Pair.create(directoryInfo, packagePrefix);
}
-
+
+ @NotNull
+ public OrderEntry[] getOrderEntries(@NotNull DirectoryInfo info) {
+ if (!(info instanceof DirectoryInfoImpl)) return OrderEntry.EMPTY_ARRAY;
+ OrderEntry[] entries = this.getOrderEntries().get(((DirectoryInfoImpl)info).getRoot());
+ return entries == null ? OrderEntry.EMPTY_ARRAY : entries;
+ }
+
public interface InfoCache {
- @Nullable DirectoryInfo getCachedInfo(@NotNull VirtualFile dir);
- void cacheInfo(@NotNull VirtualFile dir, @NotNull DirectoryInfo info);
+ @Nullable
+ DirectoryInfo getCachedInfo(@NotNull VirtualFile dir);
+
+ void cacheInfo(@NotNull VirtualFile dir, @NotNull DirectoryInfo info);
}
-} \ No newline at end of file
+}
diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/RootModelImpl.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/RootModelImpl.java
index 8ece843b5972..540bfe290645 100644
--- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/RootModelImpl.java
+++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/RootModelImpl.java
@@ -213,6 +213,8 @@ public class RootModelImpl extends RootModelBase implements ModifiableRootModel
LOG.assertTrue(myContent.contains(entry));
if (entry instanceof RootModelComponentBase) {
Disposer.dispose((RootModelComponentBase)entry);
+ RootModelImpl entryModel = ((RootModelComponentBase)entry).getRootModel();
+ LOG.assertTrue(entryModel == this, "Removing from " + this + " content entry obtained from " + entryModel);
}
myContent.remove(entry);
}
@@ -731,6 +733,15 @@ public class RootModelImpl extends RootModelBase implements ModifiableRootModel
return myModuleRootManager.getRootModel();
}
+ @Override
+ public String toString() {
+ return "RootModelImpl{" +
+ "module=" + getModule().getName() +
+ ", writable=" + myWritable +
+ ", disposed=" + myDisposed +
+ '}';
+ }
+
@Nullable
@Override
public <T> T getModuleExtension(@NotNull final Class<T> klass) {
diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/libraries/LibraryImpl.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/libraries/LibraryImpl.java
index 7a8e9ca01922..fa901849867f 100644
--- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/libraries/LibraryImpl.java
+++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/libraries/LibraryImpl.java
@@ -522,10 +522,8 @@ public class LibraryImpl extends TraceableDisposable implements LibraryEx.Modifi
private boolean isUnderRoots(@NotNull String url) {
for (VirtualFilePointerContainer container : myRoots.values()) {
- for (String rootUrl : container.getUrls()) {
- if (VfsUtilCore.isEqualOrAncestor(rootUrl, url)) {
- return true;
- }
+ if (VfsUtilCore.isUnder(url, Arrays.asList(container.getUrls()))) {
+ return true;
}
}
return false;
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ServerConnectionManagerImpl.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ServerConnectionManagerImpl.java
index f12e646a72b9..8ed6e68b1915 100644
--- a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ServerConnectionManagerImpl.java
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ServerConnectionManagerImpl.java
@@ -20,8 +20,6 @@ import java.util.Map;
*/
public class ServerConnectionManagerImpl extends ServerConnectionManager {
- private static final int POLL_DEPLOYMENTS_DELAY = 2000;
-
private final Map<RemoteServer<?>, ServerConnection> myConnections = new HashMap<RemoteServer<?>, ServerConnection>();
private final ServerConnectionEventDispatcher myEventDispatcher = new ServerConnectionEventDispatcher();
@@ -34,29 +32,10 @@ public class ServerConnectionManagerImpl extends ServerConnectionManager {
connection = doCreateConnection(server, this);
myConnections.put(server, connection);
myEventDispatcher.fireConnectionCreated(connection);
- pollDeployments(connection);
}
return connection;
}
- private void pollDeployments(final ServerConnection connection) {
- connection.computeDeployments(new Runnable() {
-
- @Override
- public void run() {
- new Alarm().addRequest(new Runnable() {
-
- @Override
- public void run() {
- if (connection == getConnection(connection.getServer())) {
- pollDeployments(connection);
- }
- }
- }, POLL_DEPLOYMENTS_DELAY, ModalityState.any());
- }
- });
- }
-
@NotNull
@Override
public <C extends ServerConfiguration> ServerConnection createTemporaryConnection(@NotNull RemoteServer<C> server) {
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/ServersToolWindowContent.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/ServersToolWindowContent.java
index 7a1f27f3b8ee..8a46887be6cf 100644
--- a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/ServersToolWindowContent.java
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/ServersToolWindowContent.java
@@ -6,6 +6,7 @@ import com.intellij.ide.util.treeView.AbstractTreeNode;
import com.intellij.ide.util.treeView.NodeDescriptor;
import com.intellij.ide.util.treeView.NodeRenderer;
import com.intellij.ide.util.treeView.TreeVisitor;
+import com.intellij.openapi.application.ModalityState;
import com.intellij.remoteServer.impl.runtime.ui.tree.ServersTreeStructure;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.*;
@@ -13,7 +14,6 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Splitter;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Disposer;
-import com.intellij.openapi.util.EmptyRunnable;
import com.intellij.remoteServer.configuration.RemoteServer;
import com.intellij.remoteServer.impl.runtime.log.LoggingHandlerImpl;
import com.intellij.remoteServer.impl.runtime.ui.tree.DeploymentNode;
@@ -28,6 +28,7 @@ import com.intellij.ui.ScrollPaneFactory;
import com.intellij.ui.SideBorder;
import com.intellij.ui.components.panels.Wrapper;
import com.intellij.ui.treeStructure.Tree;
+import com.intellij.util.Alarm;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -56,6 +57,8 @@ public class ServersToolWindowContent extends JPanel implements Disposable {
private static final String MESSAGE_CARD = "message";
private static final String EMPTY_SELECTION_MESSAGE = "Select a server or deployment in the tree to view details";
+ private static final int POLL_DEPLOYMENTS_DELAY = 2000;
+
private final Tree myTree;
private final CardLayout myPropertiesPanelLayout;
private final JPanel myPropertiesPanel;
@@ -188,6 +191,7 @@ public class ServersToolWindowContent extends JPanel implements Disposable {
@Override
public void onConnectionCreated(@NotNull ServerConnection<?> connection) {
getBuilder().queueUpdate();
+ pollDeployments(connection);
}
@Override
@@ -210,6 +214,24 @@ public class ServersToolWindowContent extends JPanel implements Disposable {
}
}
+ private static void pollDeployments(final ServerConnection connection) {
+ connection.computeDeployments(new Runnable() {
+
+ @Override
+ public void run() {
+ new Alarm().addRequest(new Runnable() {
+
+ @Override
+ public void run() {
+ if (connection == ServerConnectionManager.getInstance().getConnection(connection.getServer())) {
+ pollDeployments(connection);
+ }
+ }
+ }, POLL_DEPLOYMENTS_DELAY, ModalityState.any());
+ }
+ });
+ }
+
private JComponent createToolbar() {
DefaultActionGroup group = new DefaultActionGroup();
group.add(ActionManager.getInstance().getAction(SERVERS_TOOL_WINDOW_TOOLBAR));
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudAccountSelectionEditor.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudAccountSelectionEditor.java
index fa4355eb356c..5a3d150daf57 100644
--- a/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudAccountSelectionEditor.java
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudAccountSelectionEditor.java
@@ -15,9 +15,6 @@
*/
package com.intellij.remoteServer.util;
-import com.intellij.execution.RunManagerEx;
-import com.intellij.execution.RunnerAndConfigurationSettings;
-import com.intellij.execution.configurations.ConfigurationType;
import com.intellij.ide.DataManager;
import com.intellij.ide.actions.ShowSettingsUtilImpl;
import com.intellij.ide.util.projectWizard.WizardContext;
@@ -25,11 +22,8 @@ import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.module.Module;
-import com.intellij.openapi.module.ModulePointer;
-import com.intellij.openapi.module.ModulePointerManager;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.options.ex.SingleConfigurableEditor;
-import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.ComboBox;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.util.Condition;
@@ -38,12 +32,7 @@ import com.intellij.openapi.util.Ref;
import com.intellij.remoteServer.ServerType;
import com.intellij.remoteServer.configuration.RemoteServer;
import com.intellij.remoteServer.configuration.RemoteServersManager;
-import com.intellij.remoteServer.configuration.ServerConfiguration;
-import com.intellij.remoteServer.configuration.deployment.DeploymentConfiguration;
import com.intellij.remoteServer.impl.configuration.RemoteServerConfigurable;
-import com.intellij.remoteServer.impl.configuration.deployment.DeployToServerConfigurationType;
-import com.intellij.remoteServer.impl.configuration.deployment.DeployToServerRunConfiguration;
-import com.intellij.remoteServer.impl.configuration.deployment.ModuleDeploymentSourceImpl;
import com.intellij.util.Consumer;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.hash.HashMap;
@@ -224,52 +213,7 @@ public class CloudAccountSelectionEditor {
if (account == null) {
return;
}
- createRunConfiguration(account, module, configuration);
- }
-
- public static <SC extends ServerConfiguration, DC extends DeploymentConfiguration>
- DeployToServerRunConfiguration<SC, DC> createRunConfiguration(RemoteServer<SC> account, Module module, DC deploymentConfiguration) {
-
- Project project = module.getProject();
-
- String accountName = account.getName();
-
- String name = generateRunConfigurationName(accountName, module.getName());
-
- final RunManagerEx runManager = RunManagerEx.getInstanceEx(project);
- final RunnerAndConfigurationSettings runSettings
- = runManager.createRunConfiguration(name, getRunConfigurationType(account.getType()).getConfigurationFactories()[0]);
-
- final DeployToServerRunConfiguration<SC, DC> result = (DeployToServerRunConfiguration<SC, DC>)runSettings.getConfiguration();
-
- result.setServerName(accountName);
-
- final ModulePointer modulePointer = ModulePointerManager.getInstance(project).create(module);
- result.setDeploymentSource(new ModuleDeploymentSourceImpl(modulePointer));
-
- result.setDeploymentConfiguration(deploymentConfiguration);
-
- runManager.addConfiguration(runSettings, false);
- runManager.setSelectedConfiguration(runSettings);
-
- return result;
- }
-
- private static DeployToServerConfigurationType getRunConfigurationType(ServerType<?> cloudType) {
- String id = DeployToServerConfigurationType.getId(cloudType);
- for (ConfigurationType configurationType : ConfigurationType.CONFIGURATION_TYPE_EP.getExtensions()) {
- if (configurationType instanceof DeployToServerConfigurationType) {
- DeployToServerConfigurationType deployConfigurationType = (DeployToServerConfigurationType)configurationType;
- if (deployConfigurationType.getId().equals(id)) {
- return deployConfigurationType;
- }
- }
- }
- return null;
- }
-
- private static String generateRunConfigurationName(String serverName, String moduleName) {
- return CloudBundle.getText("run.configuration.name", serverName, moduleName);
+ CloudRunConfigurationUtil.createRunConfiguration(account, module, configuration);
}
private static class AccountItem {
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudRunConfigurationUtil.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudRunConfigurationUtil.java
new file mode 100644
index 000000000000..a717571a7ca6
--- /dev/null
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudRunConfigurationUtil.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.remoteServer.util;
+
+import com.intellij.execution.RunManagerEx;
+import com.intellij.execution.RunnerAndConfigurationSettings;
+import com.intellij.execution.configuration.ConfigurationFactoryEx;
+import com.intellij.execution.configurations.ConfigurationFactory;
+import com.intellij.execution.configurations.ConfigurationType;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModulePointer;
+import com.intellij.openapi.module.ModulePointerManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.remoteServer.ServerType;
+import com.intellij.remoteServer.configuration.RemoteServer;
+import com.intellij.remoteServer.configuration.ServerConfiguration;
+import com.intellij.remoteServer.configuration.deployment.DeploymentConfiguration;
+import com.intellij.remoteServer.configuration.deployment.DeploymentSource;
+import com.intellij.remoteServer.impl.configuration.deployment.DeployToServerConfigurationType;
+import com.intellij.remoteServer.impl.configuration.deployment.DeployToServerRunConfiguration;
+import com.intellij.remoteServer.impl.configuration.deployment.ModuleDeploymentSourceImpl;
+
+
+public class CloudRunConfigurationUtil {
+
+ public static <SC extends ServerConfiguration, DC extends DeploymentConfiguration>
+ DeployToServerRunConfiguration<SC, DC> createRunConfiguration(RemoteServer<SC> account, Module module, DC deploymentConfiguration) {
+ final ModulePointer modulePointer = ModulePointerManager.getInstance(module.getProject()).create(module);
+ DeploymentSource deploymentSource = new ModuleDeploymentSourceImpl(modulePointer);
+ return createRunConfiguration(account, module, deploymentSource, deploymentConfiguration);
+ }
+
+ public static <SC extends ServerConfiguration, DC extends DeploymentConfiguration>
+ DeployToServerRunConfiguration<SC, DC> createRunConfiguration(RemoteServer<SC> account,
+ Module module,
+ DeploymentSource deploymentSource,
+ DC deploymentConfiguration) {
+ Project project = module.getProject();
+
+ String accountName = account.getName();
+
+ String name = generateRunConfigurationName(accountName, module.getName());
+
+ final RunManagerEx runManager = RunManagerEx.getInstanceEx(project);
+ ConfigurationFactory configurationFactory = getRunConfigurationType(account.getType()).getConfigurationFactories()[0];
+ final RunnerAndConfigurationSettings runSettings = runManager.createRunConfiguration(name, configurationFactory);
+
+ final DeployToServerRunConfiguration<SC, DC> result = (DeployToServerRunConfiguration<SC, DC>)runSettings.getConfiguration();
+
+ result.setServerName(accountName);
+
+ result.setDeploymentSource(deploymentSource);
+
+ result.setDeploymentConfiguration(deploymentConfiguration);
+
+ ((ConfigurationFactoryEx)configurationFactory).onNewConfigurationCreated(runSettings.getConfiguration());
+
+ runManager.addConfiguration(runSettings, false);
+ runManager.setSelectedConfiguration(runSettings);
+
+ return result;
+ }
+
+ private static DeployToServerConfigurationType getRunConfigurationType(ServerType<?> cloudType) {
+ String id = DeployToServerConfigurationType.getId(cloudType);
+ for (ConfigurationType configurationType : ConfigurationType.CONFIGURATION_TYPE_EP.getExtensions()) {
+ if (configurationType instanceof DeployToServerConfigurationType) {
+ DeployToServerConfigurationType deployConfigurationType = (DeployToServerConfigurationType)configurationType;
+ if (deployConfigurationType.getId().equals(id)) {
+ return deployConfigurationType;
+ }
+ }
+ }
+ return null;
+ }
+
+ private static String generateRunConfigurationName(String serverName, String moduleName) {
+ return CloudBundle.getText("run.configuration.name", serverName, moduleName);
+ }
+}
diff --git a/platform/script-debugger/backend/src/org/jetbrains/debugger/Breakpoint.java b/platform/script-debugger/backend/src/org/jetbrains/debugger/Breakpoint.java
index 41b6a35b5e8d..f2180d66a069 100755
--- a/platform/script-debugger/backend/src/org/jetbrains/debugger/Breakpoint.java
+++ b/platform/script-debugger/backend/src/org/jetbrains/debugger/Breakpoint.java
@@ -24,11 +24,6 @@ public abstract class Breakpoint {
@NotNull
public abstract BreakpointTarget getTarget();
- /**
- * Returns line number of the breakpoint. As source is changed (typically with LiveEdit feature,
- * and particularly by calling {@link ScriptManager#setSourceOnRemote}) this value
- * may become stale.
- */
public abstract int getLine();
/**
diff --git a/platform/script-debugger/backend/src/org/jetbrains/debugger/DebugEventAdapter.java b/platform/script-debugger/backend/src/org/jetbrains/debugger/DebugEventAdapter.java
index 51cf25e1aefb..10a2444fc834 100644
--- a/platform/script-debugger/backend/src/org/jetbrains/debugger/DebugEventAdapter.java
+++ b/platform/script-debugger/backend/src/org/jetbrains/debugger/DebugEventAdapter.java
@@ -26,7 +26,7 @@ public abstract class DebugEventAdapter implements DebugEventListener {
}
@Override
- public void scriptContentChanged(Script newScript) {
+ public void scriptContentChanged(@NotNull Script newScript) {
}
@Override
diff --git a/platform/script-debugger/backend/src/org/jetbrains/debugger/DebugEventListener.java b/platform/script-debugger/backend/src/org/jetbrains/debugger/DebugEventListener.java
index 5b73448d39c7..a8038bed8f41 100755
--- a/platform/script-debugger/backend/src/org/jetbrains/debugger/DebugEventListener.java
+++ b/platform/script-debugger/backend/src/org/jetbrains/debugger/DebugEventListener.java
@@ -50,7 +50,7 @@ public interface DebugEventListener extends EventListener {
/**
* Reports that script source has been altered in remote VM.
*/
- void scriptContentChanged(Script newScript);
+ void scriptContentChanged(@NotNull Script newScript);
/**
* Reports a navigation event on the target.
diff --git a/platform/script-debugger/backend/src/org/jetbrains/debugger/VmBase.java b/platform/script-debugger/backend/src/org/jetbrains/debugger/VmBase.java
index befe4221e011..b2ebd332c623 100644
--- a/platform/script-debugger/backend/src/org/jetbrains/debugger/VmBase.java
+++ b/platform/script-debugger/backend/src/org/jetbrains/debugger/VmBase.java
@@ -19,6 +19,7 @@ public abstract class VmBase implements Vm {
return evaluateContext;
}
+ @NotNull
protected abstract EvaluateContext computeEvaluateContext();
@NotNull
diff --git a/platform/script-debugger/backend/src/org/jetbrains/debugger/sourcemap/SourceMapDecoder.java b/platform/script-debugger/backend/src/org/jetbrains/debugger/sourcemap/SourceMapDecoder.java
index 431a1156ae89..c033a6979f09 100644
--- a/platform/script-debugger/backend/src/org/jetbrains/debugger/sourcemap/SourceMapDecoder.java
+++ b/platform/script-debugger/backend/src/org/jetbrains/debugger/sourcemap/SourceMapDecoder.java
@@ -135,6 +135,10 @@ public final class SourceMapDecoder {
}
List<String> sources = readSources(sourcesReader, sourceRoot);
+ if (sources.isEmpty()) {
+ // empty map, meteor can report such ugly maps
+ return null;
+ }
@SuppressWarnings("unchecked")
List<MappingEntry>[] reverseMappingsBySourceUrl = new List[sources.size()];
diff --git a/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/LazyVariablesGroup.java b/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/LazyVariablesGroup.java
index e558f4ba91ab..25b8b3e11ee5 100644
--- a/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/LazyVariablesGroup.java
+++ b/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/LazyVariablesGroup.java
@@ -21,24 +21,24 @@ public final class LazyVariablesGroup extends XValueGroup {
private final ObjectValue value;
- private final int start;
- private final int end;
+ private final int startInclusive;
+ private final int endInclusive;
private final VariableContext context;
private final ValueType componentType;
private final boolean sparse;
- public LazyVariablesGroup(@NotNull ObjectValue value, int start, int end, @NotNull VariableContext context) {
- this(value, start, end, context, null, true);
+ public LazyVariablesGroup(@NotNull ObjectValue value, int startInclusive, int endInclusive, @NotNull VariableContext context) {
+ this(value, startInclusive, endInclusive, context, null, true);
}
- public LazyVariablesGroup(@NotNull ObjectValue value, int start, int end, @NotNull VariableContext context, @Nullable ValueType componentType, boolean sparse) {
- super(String.format("[%,d \u2026 %,d]", start, end));
+ public LazyVariablesGroup(@NotNull ObjectValue value, int startInclusive, int endInclusive, @NotNull VariableContext context, @Nullable ValueType componentType, boolean sparse) {
+ super(String.format("[%,d \u2026 %,d]", startInclusive, endInclusive));
this.value = value;
- this.start = start;
- this.end = end;
+ this.startInclusive = startInclusive;
+ this.endInclusive = endInclusive;
this.context = context;
@@ -51,18 +51,17 @@ public final class LazyVariablesGroup extends XValueGroup {
node.setAlreadySorted(true);
int bucketThreshold = XCompositeNode.MAX_CHILDREN_TO_SHOW;
- int size = end - start;
- if (!sparse && size > bucketThreshold) {
- node.addChildren(XValueChildrenList.topGroups(computeNotSparseGroups(value, context, start, end, bucketThreshold)), true);
+ if (!sparse && (endInclusive - startInclusive) > bucketThreshold) {
+ node.addChildren(XValueChildrenList.topGroups(computeNotSparseGroups(value, context, startInclusive, endInclusive + 1, bucketThreshold)), true);
return;
}
- value.getIndexedProperties(start, end + 1, bucketThreshold, new VariableView.ObsolescentIndexedVariablesConsumer(node) {
+ value.getIndexedProperties(startInclusive, endInclusive + 1, bucketThreshold, new VariableView.ObsolescentIndexedVariablesConsumer(node) {
@Override
public void consumeRanges(@Nullable int[] ranges) {
if (ranges == null) {
XValueChildrenList groupList = new XValueChildrenList();
- addGroups(value, GROUP_FACTORY, groupList, start, end, XCompositeNode.MAX_CHILDREN_TO_SHOW, context);
+ addGroups(value, GROUP_FACTORY, groupList, startInclusive, endInclusive, XCompositeNode.MAX_CHILDREN_TO_SHOW, context);
node.addChildren(groupList, true);
}
else {
@@ -78,12 +77,12 @@ public final class LazyVariablesGroup extends XValueGroup {
}
@NotNull
- public static List<XValueGroup> computeNotSparseGroups(@NotNull ObjectValue value, @NotNull VariableContext context, int from, int to, int bucketThreshold) {
- int size = to - from;
+ public static List<XValueGroup> computeNotSparseGroups(@NotNull ObjectValue value, @NotNull VariableContext context, int fromInclusive, int toExclusive, int bucketThreshold) {
+ int size = toExclusive - fromInclusive;
int bucketSize = (int)Math.pow(bucketThreshold, Math.ceil(Math.log(size) / Math.log(bucketThreshold)) - 1);
List<XValueGroup> groupList = new ArrayList<XValueGroup>((int)Math.ceil(size / bucketSize));
- for (; from < to; from += bucketSize) {
- groupList.add(new LazyVariablesGroup(value, from, from + (Math.min(bucketSize, to - from) - 1), context, ValueType.NUMBER, false));
+ for (; fromInclusive < toExclusive; fromInclusive += bucketSize) {
+ groupList.add(new LazyVariablesGroup(value, fromInclusive, fromInclusive + (Math.min(bucketSize, toExclusive - fromInclusive) - 1), context, ValueType.NUMBER, false));
}
return groupList;
}
diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/BoxableType.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/BoxableType.java
index 8c7175962c76..3f4b8ea839ac 100644
--- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/BoxableType.java
+++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/BoxableType.java
@@ -2,6 +2,7 @@ package org.jetbrains.protocolReader;
abstract class BoxableType {
static final BoxableType STRING = new StandaloneType(new NamePath("String"), "writeString");
+ static final BoxableType ANY_STRING = new StandaloneType(new NamePath("String"), "writeString");
static final BoxableType INT = new StandaloneType(new NamePath("int"), "writeInt");
static final BoxableType LONG = new StandaloneType(new NamePath("long"), "writeLong");
static final BoxableType NUMBER = new StandaloneType(new NamePath("double"), "writeDouble");
diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ClassScope.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ClassScope.java
index 6b27866492a4..31ba16f3438c 100644
--- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ClassScope.java
+++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ClassScope.java
@@ -20,10 +20,6 @@ abstract class ClassScope {
return contextNamespace.getLastComponent();
}
- String getFullName() {
- return contextNamespace.getFullText();
- }
-
NamePath getClassContextNamespace() {
return contextNamespace;
}
diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/DomainGenerator.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/DomainGenerator.java
index b74c73e28e1a..6798629e835c 100644
--- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/DomainGenerator.java
+++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/DomainGenerator.java
@@ -153,7 +153,7 @@ class DomainGenerator {
}
@Override
- public <T extends ItemDescriptor> QualifiedTypeData resolveType(T typedObject) {
+ public <T extends ItemDescriptor> TypeDescriptor resolveType(T typedObject) {
throw new UnsupportedOperationException();
}
@@ -162,8 +162,7 @@ class DomainGenerator {
throw new UnsupportedOperationException();
}
};
- QualifiedTypeData itemTypeData = generator.resolveType(items, resolveAndGenerateScope);
- BoxableType itemBoxableType = itemTypeData.getJavaType();
+ BoxableType itemBoxableType = generator.resolveType(items, resolveAndGenerateScope).getType();
final BoxableType arrayType = new ListType(itemBoxableType);
StandaloneTypeBinding.Target target = new StandaloneTypeBinding.Target() {
@@ -178,7 +177,7 @@ class DomainGenerator {
});
}
- StandaloneTypeBinding createStandaloneObjectInputTypeBinding(final ProtocolMetaModel.StandaloneType type, final List<ProtocolMetaModel.ObjectProperty> properties) {
+ StandaloneTypeBinding createStandaloneObjectInputTypeBinding(@NotNull final ProtocolMetaModel.StandaloneType type, @Nullable final List<ProtocolMetaModel.ObjectProperty> properties) {
final String name = type.id();
final NamePath fullTypeName = generator.getNaming().inputValue.getFullName(domain.domain(), name);
generator.jsonProtocolParserClassNames.add(fullTypeName.getFullText());
@@ -198,10 +197,12 @@ class DomainGenerator {
out.doc(type.description());
}
- out.append("@org.chromium.protocolReader.JsonType").newLine();
+ out.append("@org.jetbrains.jsonProtocol.JsonType").newLine();
out.append("public interface ").append(className.getLastComponent()).openBlock();
InputClassScope classScope = new InputClassScope(DomainGenerator.this, className);
- classScope.generateStandaloneTypeBody(out, properties);
+ if (properties != null) {
+ classScope.generateDeclarationBody(out, properties);
+ }
classScope.writeAdditionalMembers(out);
out.closeBlock();
fileUpdater.update();
@@ -309,16 +310,18 @@ class DomainGenerator {
fileUpdater.update();
}
- private void generateJsonProtocolInterface(TextOutput out, String className, String description, List<ProtocolMetaModel.Parameter> parameters, TextOutConsumer additionalMembersText) throws IOException {
+ private void generateJsonProtocolInterface(TextOutput out, String className, String description, List<ProtocolMetaModel.Parameter> parameters, TextOutConsumer additionalMembersText) {
if (description != null) {
out.doc(description);
}
- out.append("@org.chromium.protocolReader.JsonType").newLine().append("public interface ").append(className).openBlock();
+ out.append("@org.jetbrains.jsonProtocol.JsonType").newLine().append("public interface ").append(className).openBlock();
InputClassScope classScope = new InputClassScope(this, new NamePath(className, new NamePath(ClassNameScheme.getPackageName(generator.getNaming().inputPackage, domain.domain()))));
if (additionalMembersText != null) {
classScope.addMember(additionalMembersText);
}
- classScope.generateMainJsonProtocolInterfaceBody(out, parameters);
+ if (parameters != null) {
+ classScope.generateDeclarationBody(out, parameters);
+ }
classScope.writeAdditionalMembers(out);
out.closeBlock();
}
diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/Generator.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/Generator.java
index e545f0280f81..b02905ad51ad 100644
--- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/Generator.java
+++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/Generator.java
@@ -114,92 +114,61 @@ class Generator {
fileSet.deleteOtherFiles();
}
- QualifiedTypeData resolveType(final ItemDescriptor typedObject, final ResolveAndGenerateScope scope) {
- UnqualifiedTypeData unqualifiedType = switchByType(typedObject, new TypeVisitor<UnqualifiedTypeData>() {
+ TypeDescriptor resolveType(@NotNull final ItemDescriptor typedObject, @NotNull final ResolveAndGenerateScope scope) {
+ final boolean optional = typedObject instanceof ItemDescriptor.Named && ((ItemDescriptor.Named)typedObject).optional();
+ return switchByType(typedObject, new TypeVisitor<TypeDescriptor>() {
@Override
- public UnqualifiedTypeData visitRef(String refName) {
- return new UnqualifiedTypeData(resolveRefType(scope.getDomainName(), refName, scope.getTypeDirection()));
+ public TypeDescriptor visitRef(String refName) {
+ return new TypeDescriptor(resolveRefType(scope.getDomainName(), refName, scope.getTypeDirection()), optional);
}
@Override
- public UnqualifiedTypeData visitBoolean() {
- return UnqualifiedTypeData.BOOLEAN;
+ public TypeDescriptor visitBoolean() {
+ return new TypeDescriptor(BoxableType.BOOLEAN, optional);
}
@Override
- public UnqualifiedTypeData visitEnum(List<String> enumConstants) {
+ public TypeDescriptor visitEnum(List<String> enumConstants) {
assert scope instanceof MemberScope;
- return new UnqualifiedTypeData(((MemberScope)scope).generateEnum(typedObject.description(), enumConstants));
+ return new TypeDescriptor(((MemberScope)scope).generateEnum(typedObject.description(), enumConstants), optional);
}
@Override
- public UnqualifiedTypeData visitString() {
- return UnqualifiedTypeData.STRING;
+ public TypeDescriptor visitString() {
+ return new TypeDescriptor(BoxableType.STRING, optional);
}
@Override
- public UnqualifiedTypeData visitInteger() {
- return UnqualifiedTypeData.INT;
+ public TypeDescriptor visitInteger() {
+ return new TypeDescriptor(BoxableType.INT, optional);
}
@Override
- public UnqualifiedTypeData visitNumber() {
- return UnqualifiedTypeData.NUMBER;
+ public TypeDescriptor visitNumber() {
+ return new TypeDescriptor(BoxableType.NUMBER, optional);
}
@Override
- public UnqualifiedTypeData visitMap() {
- return UnqualifiedTypeData.MAP;
+ public TypeDescriptor visitMap() {
+ return new TypeDescriptor(BoxableType.MAP, optional);
}
@Override
- public UnqualifiedTypeData visitArray(ArrayItemType items) {
- return new UnqualifiedTypeData(new ListType(scope.resolveType(items).getJavaType()));
+ public TypeDescriptor visitArray(ArrayItemType items) {
+ BoxableType type = scope.resolveType(items).getType();
+ return new TypeDescriptor(new ListType(type), optional, false, type == BoxableType.ANY_STRING);
}
@Override
- public UnqualifiedTypeData visitObject(List<ObjectProperty> properties) {
- return new UnqualifiedTypeData(scope.generateNestedObject(typedObject.description(), properties), false);
+ public TypeDescriptor visitObject(List<ObjectProperty> properties) {
+ return new TypeDescriptor(scope.generateNestedObject(typedObject.description(), properties), optional);
}
@Override
- public UnqualifiedTypeData visitUnknown() {
- return UnqualifiedTypeData.ANY;
+ public TypeDescriptor visitUnknown() {
+ return new TypeDescriptor(BoxableType.STRING, optional, false, true);
}
});
-
- return unqualifiedType.getQualifiedType(typedObject instanceof ItemDescriptor.Named && ((ItemDescriptor.Named)typedObject).optional());
- }
-
- private static class UnqualifiedTypeData {
- private final BoxableType typeRef;
- private final boolean nullable;
- private final boolean asRawString;
-
- UnqualifiedTypeData(BoxableType typeRef) {
- this(typeRef, false);
- }
-
- UnqualifiedTypeData(BoxableType typeRef, boolean nullable) {
- this(typeRef, nullable, false);
- }
-
- UnqualifiedTypeData(BoxableType typeRef, boolean nullable, boolean asRawString) {
- this.typeRef = typeRef;
- this.nullable = nullable;
- this.asRawString = asRawString;
- }
-
- QualifiedTypeData getQualifiedType(boolean optional) {
- return new QualifiedTypeData(typeRef, optional, nullable, asRawString);
- }
-
- static final UnqualifiedTypeData BOOLEAN = new UnqualifiedTypeData(BoxableType.BOOLEAN, false);
- static final UnqualifiedTypeData STRING = new UnqualifiedTypeData(BoxableType.STRING, false);
- static final UnqualifiedTypeData INT = new UnqualifiedTypeData(BoxableType.INT, false);
- static final UnqualifiedTypeData MAP = new UnqualifiedTypeData(BoxableType.MAP, false);
- static final UnqualifiedTypeData NUMBER = new UnqualifiedTypeData(BoxableType.NUMBER, false);
- static final UnqualifiedTypeData ANY = new UnqualifiedTypeData(BoxableType.STRING, false, true);
}
private void generateParserInterfaceList() throws IOException {
@@ -274,11 +243,11 @@ class Generator {
return typeMap.resolve(domainName, shortName, direction);
}
- static String generateMethodNameSubstitute(String originalName, TextOutput out) {
+ static String generateMethodNameSubstitute(@NotNull String originalName, @NotNull TextOutput out) {
if (!BAD_METHOD_NAMES.contains(originalName)) {
return originalName;
}
- out.append("@org.chromium.protocolReader.JsonField(jsonLiteralName=\"").append(originalName).append("\")").newLine();
+ out.append("@org.jetbrains.jsonProtocol.JsonField(jsonLiteralName=\"").append(originalName).append("\")").newLine();
return "get" + Character.toUpperCase(originalName.charAt(0)) + originalName.substring(1);
}
diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/InputClassScope.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/InputClassScope.java
index 9411f4d25db1..99c95d8f5ae3 100644
--- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/InputClassScope.java
+++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/InputClassScope.java
@@ -1,8 +1,9 @@
package org.jetbrains.protocolReader;
-import org.jetbrains.jsonProtocol.ProtocolMetaModel;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jsonProtocol.ItemDescriptor.Named;
+import org.jetbrains.jsonProtocol.ProtocolMetaModel.ObjectProperty;
-import java.io.IOException;
import java.util.List;
class InputClassScope extends ClassScope {
@@ -10,36 +11,20 @@ class InputClassScope extends ClassScope {
super(generator, namePath);
}
- public void generateMainJsonProtocolInterfaceBody(TextOutput out, List<ProtocolMetaModel.Parameter> parameters) throws IOException {
- if (parameters != null) {
- for (ProtocolMetaModel.Parameter parameter : parameters) {
- if (parameter.description() != null) {
- out.doc(parameter.description());
- }
-
- String methodName = Generator.generateMethodNameSubstitute(getName(parameter), out);
- QualifiedTypeData paramTypeData = newMemberScope(getName(parameter)).resolveType(parameter);
- paramTypeData.writeAnnotations(out);
- out.append(paramTypeData.getJavaType().getShortText(getClassContextNamespace())).space().append(methodName).append("();").newLine();
+ void generateDeclarationBody(@NotNull TextOutput out, @NotNull List<? extends Named> list) {
+ for (int i = 0, n = list.size(); i < n; i++) {
+ Named named = list.get(i);
+ if (named.description() != null) {
+ out.doc(named.description());
}
- }
- }
-
- void generateStandaloneTypeBody(TextOutput out, List<ProtocolMetaModel.ObjectProperty> properties) throws IOException {
- if (properties != null) {
- for (ProtocolMetaModel.ObjectProperty objectProperty : properties) {
- String propertyName = getName(objectProperty);
- if (objectProperty.description() != null) {
- out.doc(objectProperty.description());
- }
-
- String methodName = Generator.generateMethodNameSubstitute(propertyName, out);
- MemberScope memberScope = newMemberScope(propertyName);
- QualifiedTypeData propertyTypeData = memberScope.resolveType(objectProperty);
- propertyTypeData.writeAnnotations(out);
-
- out.append(propertyTypeData.getJavaType().getShortText(getClassContextNamespace()) + ' ' + methodName + "();").newLine();
+ String name = getName(named);
+ String declarationName = Generator.generateMethodNameSubstitute(name, out);
+ TypeDescriptor typeDescriptor = new InputMemberScope(name).resolveType(named);
+ typeDescriptor.writeAnnotations(out);
+ out.append(typeDescriptor.getType().getShortText(getClassContextNamespace())).space().append(declarationName).append("();");
+ if (i != (n - 1)) {
+ out.newLine().newLine();
}
}
}
@@ -49,10 +34,6 @@ class InputClassScope extends ClassScope {
return TypeData.Direction.INPUT;
}
- private MemberScope newMemberScope(String memberName) {
- return new InputMemberScope(memberName);
- }
-
class InputMemberScope extends MemberScope {
InputMemberScope(String memberName) {
super(InputClassScope.this, memberName);
@@ -72,28 +53,28 @@ class InputClassScope extends ClassScope {
}
@Override
- public BoxableType generateNestedObject(final String description, final List<ProtocolMetaModel.ObjectProperty> propertyList) {
+ public BoxableType generateNestedObject(final String description, final List<ObjectProperty> propertyList) {
final String objectName = Generator.capitalizeFirstChar(getMemberName());
addMember(new TextOutConsumer() {
@Override
public void append(TextOutput out) {
out.newLine().doc(description);
if (propertyList == null) {
- out.append("@org.chromium.protocolReader.JsonType(allowsOtherProperties=true)").newLine();
+ out.append("@org.jetbrains.jsonProtocol.JsonType(allowsOtherProperties=true)").newLine();
out.append("public interface ").append(objectName).append(" extends org.jetbrains.jsonProtocol.JsonObjectBased").openBlock();
}
else {
- out.append("@org.chromium.protocolReader.JsonType").newLine();
+ out.append("@org.jetbrains.jsonProtocol.JsonType").newLine();
out.append("public interface ").append(objectName).openBlock();
- for (ProtocolMetaModel.ObjectProperty property : propertyList) {
+ for (ObjectProperty property : propertyList) {
out.doc(property.description());
String methodName = Generator.generateMethodNameSubstitute(getName(property), out);
- MemberScope memberScope = newMemberScope(getName(property));
- QualifiedTypeData propertyTypeData = memberScope.resolveType(property);
+ MemberScope memberScope = new InputMemberScope(getName(property));
+ TypeDescriptor propertyTypeData = memberScope.resolveType(property);
propertyTypeData.writeAnnotations(out);
- out.append(propertyTypeData.getJavaType().getShortText(getClassContextNamespace()) + ' ' + methodName + "();").newLine();
+ out.append(propertyTypeData.getType().getShortText(getClassContextNamespace()) + ' ' + methodName + "();").newLine();
}
}
out.closeBlock();
diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/MemberScope.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/MemberScope.java
index 21de2ca3b228..78a83a9127ca 100644
--- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/MemberScope.java
+++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/MemberScope.java
@@ -19,7 +19,7 @@ abstract class MemberScope implements ResolveAndGenerateScope {
}
@Override
- public <T extends ItemDescriptor> QualifiedTypeData resolveType(T typedObject) {
+ public <T extends ItemDescriptor> TypeDescriptor resolveType(T typedObject) {
return classScope.generator.generator.resolveType(typedObject, this);
}
diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/MyCreateStandaloneTypeBindingVisitorBase.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/MyCreateStandaloneTypeBindingVisitorBase.java
index e867bf924eaa..90b7068e8cb5 100644
--- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/MyCreateStandaloneTypeBindingVisitorBase.java
+++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/MyCreateStandaloneTypeBindingVisitorBase.java
@@ -60,7 +60,7 @@ class MyCreateStandaloneTypeBindingVisitorBase extends CreateStandaloneTypeBindi
}
@Override
- public <T extends ItemDescriptor> QualifiedTypeData resolveType(T typedObject) {
+ public <T extends ItemDescriptor> TypeDescriptor resolveType(T typedObject) {
throw new UnsupportedOperationException();
}
@@ -68,7 +68,7 @@ class MyCreateStandaloneTypeBindingVisitorBase extends CreateStandaloneTypeBindi
public BoxableType generateNestedObject(String description, List<ProtocolMetaModel.ObjectProperty> properties) {
return context.generateNestedObject("Item", description, properties);
}
- }).getJavaType());
+ }).getType());
}
}, generator.generator.getNaming().outputTypedef, TypeData.Direction.OUTPUT);
}
diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/OutputClassScope.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/OutputClassScope.java
index fa7f4f18740f..f88a55d7a039 100644
--- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/OutputClassScope.java
+++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/OutputClassScope.java
@@ -19,8 +19,8 @@ class OutputClassScope extends ClassScope {
return;
}
- List<P> mandatoryParameters = new ArrayList<P>();
- List<P> optionalParameters = new ArrayList<P>();
+ List<P> mandatoryParameters = new ArrayList<>();
+ List<P> optionalParameters = new ArrayList<>();
for (P parameter : parameters) {
if (parameter.optional()) {
optionalParameters.add(parameter);
@@ -34,8 +34,8 @@ class OutputClassScope extends ClassScope {
generateConstructor(out, mandatoryParameters, null);
if (mandatoryParameters.size() == 1) {
P parameter = mandatoryParameters.get(0);
- QualifiedTypeData typeData = new OutputMemberScope(getName(parameter)).resolveType(parameter);
- if (typeData.getJavaType().getFullText().equals("int[]")) {
+ TypeDescriptor typeData = new OutputMemberScope(getName(parameter)).resolveType(parameter);
+ if (typeData.getType().getFullText().equals("int[]")) {
BoxableType[] types = new BoxableType[mandatoryParameters.size()];
types[0] = new ListType(BoxableType.INT) {
@Override
@@ -94,7 +94,7 @@ class OutputClassScope extends ClassScope {
out.append("/**").newLine().append(" * @param v ").append(parameter.description()).newLine().append(" */").newLine();
}
- CharSequence type = new OutputMemberScope(parameter.name()).resolveType(parameter).getJavaType().getShortText(getClassContextNamespace());
+ CharSequence type = new OutputMemberScope(parameter.name()).resolveType(parameter).getType().getShortText(getClassContextNamespace());
if (type.equals(JsonReaderEx.class.getCanonicalName())) {
type = "String";
}
@@ -131,9 +131,10 @@ class OutputClassScope extends ClassScope {
mandatoryParameterTypes = new BoxableType[mandatoryParameters.size()];
}
for (int i = 0, length = mandatoryParameterTypes.length; i < length; i++) {
+ assert mandatoryParameterTypes != null;
if (mandatoryParameterTypes[i] == null) {
P parameter = mandatoryParameters.get(i);
- mandatoryParameterTypes[i] = new OutputMemberScope(parameter.name()).resolveType(parameter).getJavaType();
+ mandatoryParameterTypes[i] = new OutputMemberScope(parameter.name()).resolveType(parameter).getType();
}
}
@@ -144,6 +145,7 @@ class OutputClassScope extends ClassScope {
out.comma();
}
+ assert mandatoryParameterTypes != null;
out.append(mandatoryParameterTypes[i].getShortText(getClassContextNamespace()));
out.space().append(parameter.name());
needComa = true;
@@ -152,6 +154,7 @@ class OutputClassScope extends ClassScope {
for (int i = 0, size = mandatoryParameters.size(); i < size; i++) {
P parameter = mandatoryParameters.get(i);
out.newLine();
+ assert mandatoryParameterTypes != null;
appendWriteValueInvocation(out, parameter, parameter.name(), mandatoryParameterTypes[i]);
}
out.closeBlock();
@@ -159,7 +162,7 @@ class OutputClassScope extends ClassScope {
private void appendWriteValueInvocation(TextOutput out, ItemDescriptor.Named parameter, String valueRefName, @Nullable BoxableType type) {
if (type == null) {
- type = new OutputMemberScope(parameter.name()).resolveType(parameter).getJavaType();
+ type = new OutputMemberScope(parameter.name()).resolveType(parameter).getType();
}
boolean blockOpened = false;
@@ -188,7 +191,7 @@ class OutputClassScope extends ClassScope {
}
// todo CallArgument (we should allow write null as value)
out.append(parameter.name().equals("value") && type.getWriteMethodName().equals("writeString") ? "writeNullableString" : type.getWriteMethodName()).append("(");
- out.quoute(parameter.name()).comma().append(valueRefName).append(");");
+ out.quote(parameter.name()).comma().append(valueRefName).append(");");
if (blockOpened) {
out.closeBlock();
}
diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ParserRootInterfaceItem.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ParserRootInterfaceItem.java
index e3e8049c1b6d..e84c641ff9c3 100644
--- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ParserRootInterfaceItem.java
+++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ParserRootInterfaceItem.java
@@ -18,7 +18,7 @@ class ParserRootInterfaceItem implements Comparable<ParserRootInterfaceItem> {
}
void writeCode(TextOutput out) throws IOException {
- out.append("@org.chromium.protocolReader.JsonParseMethod").newLine();
+ out.append("@org.jetbrains.jsonProtocol.JsonParseMethod").newLine();
out.append("public abstract ").append(fullName).space();
appendReadMethodName(out);
out.append("(").append(Util.JSON_READER_PARAMETER_DEF).append(")").semi().newLine();
diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ResolveAndGenerateScope.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ResolveAndGenerateScope.java
index 8f117d02ab95..c43c9ff7deff 100644
--- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ResolveAndGenerateScope.java
+++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/ResolveAndGenerateScope.java
@@ -9,7 +9,7 @@ interface ResolveAndGenerateScope {
String getDomainName();
TypeData.Direction getTypeDirection();
- <T extends ItemDescriptor> QualifiedTypeData resolveType(T typedObject);
+ <T extends ItemDescriptor> TypeDescriptor resolveType(T typedObject);
BoxableType generateNestedObject(String description,
List<ProtocolMetaModel.ObjectProperty> properties);
diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TypeData.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TypeData.java
index 0ab11a07c352..7fbc5f6c2cad 100644
--- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TypeData.java
+++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TypeData.java
@@ -4,6 +4,21 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.jsonProtocol.ProtocolMetaModel;
class TypeData {
+ public static final StandaloneTypeBinding ANY = new StandaloneTypeBinding() {
+ @Override
+ public BoxableType getJavaType() {
+ return BoxableType.ANY_STRING;
+ }
+
+ @Override
+ public void generate() {
+ }
+
+ @Override
+ public Direction getDirection() {
+ return null;
+ }
+ };
private final String name;
private Input input;
@@ -119,21 +134,7 @@ class TypeData {
};
}
else if (name.equals("any")) {
- return new StandaloneTypeBinding() {
- @Override
- public BoxableType getJavaType() {
- return BoxableType.STRING;
- }
-
- @Override
- public void generate() {
- }
-
- @Override
- public Direction getDirection() {
- return null;
- }
- };
+ return ANY;
}
throw new RuntimeException();
@@ -164,21 +165,7 @@ class TypeData {
};
}
else if (name.equals("any")) {
- return new StandaloneTypeBinding() {
- @Override
- public BoxableType getJavaType() {
- return BoxableType.STRING;
- }
-
- @Override
- public void generate() {
- }
-
- @Override
- public Direction getDirection() {
- return null;
- }
- };
+ return ANY;
}
throw new RuntimeException();
diff --git a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/QualifiedTypeData.java b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TypeDescriptor.java
index a4ccd0b3c49f..d142e8bdf6d5 100644
--- a/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/QualifiedTypeData.java
+++ b/platform/script-debugger/protocol/protocol-model-generator/src/org/jetbrains/protocolReader/TypeDescriptor.java
@@ -1,13 +1,19 @@
package org.jetbrains.protocolReader;
-class QualifiedTypeData {
- private final BoxableType typeRef;
+import org.jetbrains.annotations.NotNull;
+
+class TypeDescriptor {
+ private final BoxableType type;
private final boolean optional;
private final boolean nullable;
private final boolean asRawString;
- QualifiedTypeData(BoxableType typeRef, boolean optional, boolean nullable, boolean asRawString) {
- this.typeRef = typeRef;
+ TypeDescriptor(@NotNull BoxableType type, boolean optional) {
+ this(type, optional, false, false);
+ }
+
+ TypeDescriptor(@NotNull BoxableType type, boolean optional, boolean nullable, boolean asRawString) {
+ this.type = type;
this.optional = optional;
this.nullable = nullable;
this.asRawString = asRawString;
@@ -17,13 +23,14 @@ class QualifiedTypeData {
return nullable;
}
- BoxableType getJavaType() {
- return typeRef;
+ @NotNull
+ BoxableType getType() {
+ return type;
}
- void writeAnnotations(TextOutput out) {
+ void writeAnnotations(@NotNull TextOutput out) {
if (optional || asRawString) {
- out.append("@org.chromium.protocolReader.JsonField(");
+ out.append("@org.jetbrains.jsonProtocol.JsonField(");
if (optional) {
out.append("optional=true");
}
@@ -37,7 +44,7 @@ class QualifiedTypeData {
}
if (isNullable()) {
- out.append("@org.chromium.protocolReader.JsonNullable").newLine();
+ out.append("@org.jetbrains.jsonProtocol.JsonNullable").newLine();
}
}
}
diff --git a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonField.java b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonField.java
index 5dfa26ca057a..3b960b8636a9 100644
--- a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonField.java
+++ b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonField.java
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-package org.chromium.protocolReader;
+package org.jetbrains.jsonProtocol;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
@@ -25,6 +25,7 @@ public @interface JsonField {
// read any primitive value as String (true as true, number as string - don't try to parse)
boolean allowAnyPrimitiveValue() default false;
+
boolean allowAnyPrimitiveValueAndMap() default false;
boolean optional() default false;
diff --git a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonNullable.java b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonNullable.java
index bbaa82a1b2c5..8e88ab4eb2b4 100644
--- a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonNullable.java
+++ b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonNullable.java
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-package org.chromium.protocolReader;
+package org.jetbrains.jsonProtocol;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
diff --git a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonOptionalField.java b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonOptionalField.java
index a2ede4854bf5..92c9cd978700 100644
--- a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonOptionalField.java
+++ b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonOptionalField.java
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-package org.chromium.protocolReader;
+package org.jetbrains.jsonProtocol;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
diff --git a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonParseMethod.java b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonParseMethod.java
index c964e8057018..8016b9b59539 100644
--- a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonParseMethod.java
+++ b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonParseMethod.java
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-package org.chromium.protocolReader;
+package org.jetbrains.jsonProtocol;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
diff --git a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonReaders.java b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonReaders.java
index aa1d19f1bad2..056e4dc6b78f 100644
--- a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonReaders.java
+++ b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonReaders.java
@@ -234,7 +234,7 @@ public final class JsonReaders {
return list;
}
- public static List<String> readListOfPrimitive(JsonReaderEx reader) {
+ public static List<String> readRawStringArray(JsonReaderEx reader) {
reader.beginArray();
if (!reader.hasNext()) {
reader.endArray();
diff --git a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonSubtype.java b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonSubtype.java
index f104d74943cd..b40d4a1b7687 100644
--- a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonSubtype.java
+++ b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonSubtype.java
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-package org.chromium.protocolReader;
+package org.jetbrains.jsonProtocol;
/**
* A base interface for JSON subtype interface. This inheritance serves 2 purposes:
diff --git a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonSubtypeCasting.java b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonSubtypeCasting.java
index 05275511e407..cc59fed74eac 100644
--- a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonSubtypeCasting.java
+++ b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonSubtypeCasting.java
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-package org.chromium.protocolReader;
+package org.jetbrains.jsonProtocol;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
diff --git a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonType.java b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonType.java
index 62e2c8c12118..79dc453ac9fb 100644
--- a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/chromium/protocolReader/JsonType.java
+++ b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/JsonType.java
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-package org.chromium.protocolReader;
+package org.jetbrains.jsonProtocol;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
diff --git a/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/FieldProcessor.java b/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/FieldProcessor.java
index eabc8d8e4337..111e58caa3a6 100644
--- a/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/FieldProcessor.java
+++ b/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/FieldProcessor.java
@@ -1,6 +1,9 @@
package org.jetbrains.protocolReader;
-import org.chromium.protocolReader.*;
+import org.jetbrains.jsonProtocol.JsonField;
+import org.jetbrains.jsonProtocol.JsonNullable;
+import org.jetbrains.jsonProtocol.JsonOptionalField;
+import org.jetbrains.jsonProtocol.JsonSubtypeCasting;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
diff --git a/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/InterfaceReader.java b/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/InterfaceReader.java
index f80b8c54bb42..cc4e2566f4dd 100644
--- a/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/InterfaceReader.java
+++ b/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/InterfaceReader.java
@@ -1,10 +1,10 @@
package org.jetbrains.protocolReader;
import gnu.trove.THashSet;
-import org.chromium.protocolReader.JsonField;
-import org.chromium.protocolReader.JsonSubtype;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.io.JsonReaderEx;
+import org.jetbrains.jsonProtocol.JsonField;
+import org.jetbrains.jsonProtocol.JsonSubtype;
import org.jetbrains.jsonProtocol.StringIntPair;
import java.lang.annotation.RetentionPolicy;
@@ -249,7 +249,7 @@ class InterfaceReader {
argumentType = wildcard.getUpperBounds()[0];
}
}
- return new ArrayReader(getFieldTypeParser(argumentType, false, false, null), true, declaredNullable);
+ return new ArrayReader(getFieldTypeParser(argumentType, false, false, method), true, declaredNullable);
}
else if (parameterizedType.getRawType() == Map.class) {
return declaredNullable ? NULLABLE_MAP_PARSER : MAP_PARSER;
diff --git a/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/ReaderRoot.java b/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/ReaderRoot.java
index a76971dc5da7..7914a5103ac6 100644
--- a/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/ReaderRoot.java
+++ b/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/ReaderRoot.java
@@ -2,7 +2,7 @@ package org.jetbrains.protocolReader;
import org.jetbrains.io.JsonReaderEx;
import gnu.trove.THashSet;
-import org.chromium.protocolReader.JsonParseMethod;
+import org.jetbrains.jsonProtocol.JsonParseMethod;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
diff --git a/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/TextOutput.java b/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/TextOutput.java
index cd5afa1c27ff..77d4bd1e275f 100644
--- a/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/TextOutput.java
+++ b/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/TextOutput.java
@@ -9,7 +9,7 @@ public class TextOutput {
private int identLevel;
private final static int indentGranularity = 2;
private char[][] indents = {EMPTY_CHARS};
- private boolean justNewlined;
+ private boolean justNewLined;
private final StringBuilder out;
public TextOutput(StringBuilder out) {
@@ -41,7 +41,7 @@ public class TextOutput {
public TextOutput newLine() {
out.append('\n');
- justNewlined = true;
+ justNewLined = true;
return this;
}
@@ -122,14 +122,14 @@ public class TextOutput {
return append("/**").newLine().append(" * ").append(description).newLine().append(" */").newLine();
}
- public TextOutput quoute(CharSequence s) {
+ public TextOutput quote(CharSequence s) {
return append('"').append(s).append('"');
}
public void maybeIndent() {
- if (justNewlined) {
+ if (justNewLined) {
out.append(indents[identLevel]);
- justNewlined = false;
+ justNewLined = false;
}
}
}
diff --git a/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/ValueReader.java b/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/ValueReader.java
index 7ef6b3e0fc82..442167687b40 100644
--- a/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/ValueReader.java
+++ b/platform/script-debugger/protocol/protocol-reader/src/org/jetbrains/protocolReader/ValueReader.java
@@ -1,7 +1,3 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
package org.jetbrains.protocolReader;
import org.jetbrains.annotations.Nullable;
@@ -51,7 +47,7 @@ abstract class ValueReader {
out.append("name");
}
else {
- out.quoute(fieldName);
+ out.quote(fieldName);
}
}
}
diff --git a/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ItemDescriptor.java b/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ItemDescriptor.java
index 26dbd72d058e..d6f5afcfbe27 100644
--- a/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ItemDescriptor.java
+++ b/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ItemDescriptor.java
@@ -1,7 +1,5 @@
package org.jetbrains.jsonProtocol;
-import org.chromium.protocolReader.JsonOptionalField;
-
import java.util.List;
public interface ItemDescriptor {
diff --git a/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ProtocolMetaModel.java b/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ProtocolMetaModel.java
index c08c50c108aa..a4aeeec15d37 100644
--- a/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ProtocolMetaModel.java
+++ b/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ProtocolMetaModel.java
@@ -1,9 +1,5 @@
package org.jetbrains.jsonProtocol;
-import org.chromium.protocolReader.JsonField;
-import org.chromium.protocolReader.JsonOptionalField;
-import org.chromium.protocolReader.JsonType;
-
import java.util.List;
/**
diff --git a/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ProtocolSchemaReader.java b/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ProtocolSchemaReader.java
index 50aeebbbdf1e..aafe735409fd 100644
--- a/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ProtocolSchemaReader.java
+++ b/platform/script-debugger/protocol/schema-reader-generator/src/org/jetbrains/jsonProtocol/ProtocolSchemaReader.java
@@ -5,7 +5,6 @@
package org.jetbrains.jsonProtocol;
import org.jetbrains.io.JsonReaderEx;
-import org.chromium.protocolReader.JsonParseMethod;
import org.jetbrains.jsonProtocol.ProtocolMetaModel.Root;
import java.io.IOException;
diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/GeneralToSMTRunnerEventsConvertor.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/GeneralToSMTRunnerEventsConvertor.java
index 8532b9aa4084..b77acd9c03ee 100644
--- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/GeneralToSMTRunnerEventsConvertor.java
+++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/GeneralToSMTRunnerEventsConvertor.java
@@ -273,7 +273,11 @@ public class GeneralToSMTRunnerEventsConvertor extends GeneralTestEventsProcesso
public void onTestFailure(@NotNull final TestFailedEvent testFailedEvent) {
addToInvokeLater(new Runnable() {
public void run() {
- final String testName = ObjectUtils.assertNotNull(testFailedEvent.getName());
+ final String testName = testFailedEvent.getName();
+ if (testName == null) {
+ logProblem("No test name specified in " + testFailedEvent);
+ return;
+ }
final String localizedMessage = testFailedEvent.getLocalizedFailureMessage();
final String stackTrace = testFailedEvent.getStacktrace();
final boolean isTestError = testFailedEvent.isTestError();
diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/states/SuiteInProgressState.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/states/SuiteInProgressState.java
index d454ae03bf4c..5d4cf5472204 100644
--- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/states/SuiteInProgressState.java
+++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/states/SuiteInProgressState.java
@@ -18,6 +18,7 @@ package com.intellij.execution.testframework.sm.runner.states;
import org.jetbrains.annotations.NotNull;
import com.intellij.execution.testframework.sm.runner.SMTestProxy;
+import java.util.ArrayList;
import java.util.List;
/**
@@ -42,7 +43,7 @@ public class SuiteInProgressState extends TestInProgressState {
}
//Test suit fails if any of its tests fails
- final List<? extends SMTestProxy> children = mySuiteProxy.getChildren();
+ final List<? extends SMTestProxy> children = new ArrayList<SMTestProxy>(mySuiteProxy.getChildren());
for (SMTestProxy child : children) {
if (child.isDefect()) {
myDefectFound = true;
diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/CompiledPattern.java b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/CompiledPattern.java
index 565f80ac01ce..70c1cdccd03e 100644
--- a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/CompiledPattern.java
+++ b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/CompiledPattern.java
@@ -82,7 +82,7 @@ public abstract class CompiledPattern {
public boolean isRealTypedVar(PsiElement element) {
if (element!=null && element.getTextLength()>0) {
String str = getTypedVarString(element);
- if (str.length()==0) {
+ if (str == null || str.length()==0) {
return false;
}
return isTypedVar( str );
diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/PatternCompiler.java b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/PatternCompiler.java
index e290ebb70793..6dba855121cb 100644
--- a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/PatternCompiler.java
+++ b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/PatternCompiler.java
@@ -272,12 +272,8 @@ public class PatternCompiler {
element.accept(new PsiRecursiveElementWalkingVisitor() {
@Override
- public void visitElement(PsiElement element) {
- super.visitElement(element);
-
- if (!(element instanceof PsiErrorElement)) {
- return;
- }
+ public void visitErrorElement(PsiErrorElement element) {
+ super.visitErrorElement(element);
final int startOffset = element.getTextRange().getStartOffset();
diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/EditVarConstraintsDialog.java b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/EditVarConstraintsDialog.java
index 368240ff50be..f82ad12e5f4f 100644
--- a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/EditVarConstraintsDialog.java
+++ b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/EditVarConstraintsDialog.java
@@ -22,7 +22,6 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.ComponentWithBrowseButton;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
-import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
@@ -36,8 +35,6 @@ import com.intellij.structuralsearch.plugin.replace.ReplaceOptions;
import com.intellij.structuralsearch.plugin.replace.ui.ReplaceConfiguration;
import com.intellij.ui.ComboboxWithBrowseButton;
import com.intellij.ui.EditorTextField;
-import com.intellij.ui.components.labels.LinkLabel;
-import com.intellij.ui.components.labels.LinkListener;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -46,7 +43,6 @@ import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
-import javax.swing.text.BadLocationException;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
@@ -117,7 +113,7 @@ class EditVarConstraintsDialog extends DialogWrapper {
withinCombo.getComboBox().setEditable(true);
withinCombo.getButton().addActionListener(new ActionListener() {
- public void actionPerformed(final ActionEvent e) {
+ public void actionPerformed(@NotNull final ActionEvent e) {
final SelectTemplateDialog dialog = new SelectTemplateDialog(project, false, false);
dialog.show();
if (dialog.getExitCode() == OK_EXIT_CODE) {
@@ -191,7 +187,7 @@ class EditVarConstraintsDialog extends DialogWrapper {
new ListSelectionListener() {
boolean rollingBackSelection;
- public void valueChanged(ListSelectionEvent e) {
+ public void valueChanged(@NotNull ListSelectionEvent e) {
if (e.getValueIsAdjusting()) return;
if (rollingBackSelection) {
rollingBackSelection=false;
@@ -212,7 +208,7 @@ class EditVarConstraintsDialog extends DialogWrapper {
parameterList.setCellRenderer(
new DefaultListCellRenderer() {
- public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
+ public Component getListCellRendererComponent(@NotNull JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
String name = ((Variable)value).getName();
if (Configuration.CONTEXT_VAR_NAME.equals(name)) name = SSRBundle.message("complete.match.variable.name");
if (isReplacementVariable(name)) {
@@ -226,7 +222,7 @@ class EditVarConstraintsDialog extends DialogWrapper {
maxoccursUnlimited.addChangeListener(new MyChangeListener(maxoccurs, true));
customScriptCode.getButton().addActionListener(new ActionListener() {
- public void actionPerformed(final ActionEvent e) {
+ public void actionPerformed(@NotNull final ActionEvent e) {
final EditScriptDialog dialog = new EditScriptDialog(project, customScriptCode.getChildComponent().getText());
dialog.show();
if (dialog.getExitCode() == OK_EXIT_CODE) {
@@ -505,18 +501,7 @@ class EditVarConstraintsDialog extends DialogWrapper {
formalArgType = createRegexComponent();
customScriptCode = new ComponentWithBrowseButton<EditorTextField>(createScriptComponent(), null);
- myRegExHelpLabel = new LinkLabel(SSRBundle.message("regular.expression.help.label"), null, new LinkListener() {
- public void linkSelected(LinkLabel aSource, Object aLinkData) {
- try {
- final JBPopup helpPopup = RegExHelpPopup.createRegExHelpPopup();
- helpPopup.showInCenterOf(mainForm);
- }
- catch (BadLocationException e) {
- LOG.info(e);
- }
- }
- });
-
+ myRegExHelpLabel = RegExHelpPopup.createRegExLink(SSRBundle.message("regular.expression.help.label"), regexp, LOG);
myRegExHelpLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 5));
}
@@ -559,7 +544,7 @@ class EditVarConstraintsDialog extends DialogWrapper {
inverted = _inverted;
}
- public void stateChanged(ChangeEvent e) {
+ public void stateChanged(@NotNull ChangeEvent e) {
final JCheckBox jCheckBox = (JCheckBox)e.getSource();
component.setEnabled(inverted ^ jCheckBox.isSelected());
}
diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/SubstitutionShortInfoHandler.java b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/SubstitutionShortInfoHandler.java
index 32f1302336f3..ecdccbe0e40b 100644
--- a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/SubstitutionShortInfoHandler.java
+++ b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/SubstitutionShortInfoHandler.java
@@ -1,6 +1,6 @@
package com.intellij.structuralsearch.plugin.ui;
-import com.intellij.codeInsight.hint.TooltipGroup;
+import com.intellij.codeInsight.hint.TooltipController;
import com.intellij.codeInsight.template.impl.TemplateImplUtil;
import com.intellij.codeInsight.template.impl.Variable;
import com.intellij.openapi.editor.Document;
@@ -11,7 +11,6 @@ import com.intellij.openapi.util.Key;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
-import java.util.Iterator;
/**
* Created by IntelliJ IDEA.
@@ -21,7 +20,6 @@ import java.util.Iterator;
* To change this template use File | Settings | File Templates.
*/
public class SubstitutionShortInfoHandler implements DocumentListener, EditorMouseMotionListener, CaretListener {
- private static final TooltipGroup SS_INFO_TOOLTIP_GROUP = new TooltipGroup("SS_INFO_TOOLTIP_GROUP", 0);
private long modificationTimeStamp;
private final ArrayList<Variable> variables = new ArrayList<Variable>();
@@ -63,9 +61,7 @@ public class SubstitutionShortInfoHandler implements DocumentListener, EditorMou
String varname = elements.subSequence(start + 1, end).toString();
Variable foundVar = null;
- for(Iterator<Variable> i=variables.iterator();i.hasNext();) {
- final Variable var = i.next();
-
+ for (final Variable var : variables) {
if (var.getName().equals(varname)) {
foundVar = var;
break;
@@ -79,7 +75,10 @@ public class SubstitutionShortInfoHandler implements DocumentListener, EditorMou
}
if (text.length() > 0) {
- UIUtil.showTooltip(editor, start, end, text, SS_INFO_TOOLTIP_GROUP);
+ UIUtil.showTooltip(editor, start, end + 1, text);
+ }
+ else {
+ TooltipController.getInstance().cancelTooltips();
}
}
diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/UIUtil.java b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/UIUtil.java
index aa3ca82725b0..e2c16bfbc355 100644
--- a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/UIUtil.java
+++ b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/UIUtil.java
@@ -15,17 +15,14 @@ import com.intellij.openapi.editor.colors.EditorColors;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.ex.EditorEx;
-import com.intellij.openapi.fileEditor.FileEditorManager;
-import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.psi.*;
import com.intellij.structuralsearch.*;
import com.intellij.structuralsearch.plugin.StructuralReplaceAction;
import com.intellij.structuralsearch.plugin.StructuralSearchAction;
import com.intellij.structuralsearch.plugin.replace.ui.ReplaceConfiguration;
-import com.intellij.structuralsearch.plugin.util.SmartPsiPointer;
+import com.intellij.ui.HintHint;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -41,6 +38,7 @@ import java.awt.*;
public class UIUtil {
static Key<SubstitutionShortInfoHandler> LISTENER_KEY = Key.create("sslistener.key");
private static final String MODIFY_EDITOR_CONTENT = SSRBundle.message("modify.editor.content.command.name");
+ private static final TooltipGroup SS_INFO_TOOLTIP_GROUP = new TooltipGroup("SS_INFO_TOOLTIP_GROUP", 0);
@NonNls private static final String SS_GROUP = "structuralsearchgroup";
@NotNull
@@ -191,18 +189,6 @@ public class UIUtil {
buf.append(str);
}
- public static void navigate(PsiElement result) {
- FileEditorManager.getInstance(result.getProject()).openTextEditor(
- new OpenFileDescriptor(result.getProject(), result.getContainingFile().getVirtualFile(), result.getTextOffset()), true);
- }
-
- public static void navigate(MatchResult result) {
- final SmartPsiPointer ref = result.getMatchRef();
-
- FileEditorManager.getInstance(ref.getProject())
- .openTextEditor(new OpenFileDescriptor(ref.getProject(), ref.getFile(), ref.getOffset()), true);
- }
-
public static void invokeAction(Configuration config, SearchContext context) {
if (config instanceof SearchConfiguration) {
StructuralSearchAction.triggerAction(config, context);
@@ -212,22 +198,27 @@ public class UIUtil {
}
}
- static void showTooltip(@NotNull Editor editor, final int start, int end, @NotNull String text, @NotNull TooltipGroup group) {
- Rectangle visibleArea = editor.getScrollingModel().getVisibleArea();
- Point top = editor.logicalPositionToXY(editor.offsetToLogicalPosition(start));
+ static void showTooltip(@NotNull Editor editor, final int start, int end, @NotNull String text) {
+ final Rectangle visibleArea = editor.getScrollingModel().getVisibleArea();
+ final Point left = editor.logicalPositionToXY(editor.offsetToLogicalPosition(start));
final int documentLength = editor.getDocument().getTextLength();
if (end >= documentLength) end = documentLength;
- Point bottom = editor.logicalPositionToXY(editor.offsetToLogicalPosition(end));
+ final Point right = editor.logicalPositionToXY(editor.offsetToLogicalPosition(end));
- Point bestPoint = new Point(top.x, bottom.y + editor.getLineHeight());
+ final Point bestPoint = new Point(left.x + (right.x - left.x) / 2, right.y + editor.getLineHeight() / 2);
- if (!visibleArea.contains(bestPoint)) {
- int defaultOffset = editor.logicalPositionToOffset(editor.xyToLogicalPosition(new Point(0, 0)));
- bestPoint = editor.logicalPositionToXY(editor.offsetToLogicalPosition(defaultOffset));
+ if (visibleArea.x > bestPoint.x) {
+ bestPoint.x = visibleArea.x;
+ }
+ else if (visibleArea.x + visibleArea.width < bestPoint.x) {
+ bestPoint.x = visibleArea.x + visibleArea.width - 5;
}
- Point p = SwingUtilities.convertPoint(editor.getContentComponent(), bestPoint, editor.getComponent().getRootPane().getLayeredPane());
- TooltipController.getInstance().showTooltip(editor, p, text, false, group);
+ final Point p = SwingUtilities.convertPoint(editor.getContentComponent(), bestPoint,
+ editor.getComponent().getRootPane().getLayeredPane());
+ final HintHint hint = new HintHint(editor, bestPoint).setAwtTooltip(true).setHighlighterType(true)
+ .setCalloutShift(editor.getLineHeight() / 2 - 1);
+ TooltipController.getInstance().showTooltip(editor, p, text, visibleArea.width, false, SS_INFO_TOOLTIP_GROUP, hint);
}
public static void updateHighlighter(Editor editor, StructuralSearchProfile profile) {
diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/UsageViewContext.java b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/UsageViewContext.java
index afd2ae1b029d..a55a16d4c379 100644
--- a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/UsageViewContext.java
+++ b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/UsageViewContext.java
@@ -1,13 +1,13 @@
package com.intellij.structuralsearch.plugin.ui;
import com.intellij.navigation.ItemPresentation;
-import com.intellij.openapi.actionSystem.*;
+import com.intellij.openapi.actionSystem.ActionManager;
+import com.intellij.openapi.actionSystem.KeyboardShortcut;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
-import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.structuralsearch.SSRBundle;
import com.intellij.structuralsearch.plugin.replace.ui.ReplaceCommand;
import com.intellij.usages.*;
@@ -81,7 +81,7 @@ public class UsageViewContext {
protected void configureActions() {}
- private class MyUsageTarget implements ConfigurableUsageTarget,ItemPresentation, TypeSafeDataProvider {
+ private class MyUsageTarget implements ConfigurableUsageTarget,ItemPresentation {
private final String myPresentableText;
MyUsageTarget(String str) {
@@ -179,12 +179,5 @@ public class UsageViewContext {
public String getLongDescriptiveName() {
return _getPresentableText();
}
-
- @Override
- public void calcData(DataKey key, DataSink sink) {
- if (key == UsageView.USAGE_SCOPE) {
- sink.put(UsageView.USAGE_SCOPE, GlobalSearchScope.allScope(mySearchContext.getProject()));
- }
- }
}
}
diff --git a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralReplaceTest.java b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralReplaceTest.java
index de9b668be4d3..fe1b6e09d99f 100644
--- a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralReplaceTest.java
+++ b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralReplaceTest.java
@@ -1809,6 +1809,35 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase {
);
}
+ public void testUseStaticImport() {
+ final String in = "class X {{ Math.abs(-1); }}";
+ final String what = "Math.abs('a)";
+ final String by = "Math.abs($a$)";
+ options.setToUseStaticImport(true);
+
+ final String expected = "import static java.lang.Math.abs;class X {{ abs(-1); }}";
+ assertEquals("Replacing with static import", expected, replacer.testReplace(in, what, by, options, true));
+ }
+
+ public void testUseStaticStarImport() {
+ final String in = "class ImportTest {{\n" +
+ " Math.abs(-0.5);\n" +
+ " Math.sin(0.5);\n" +
+ " Math.max(1, 2);\n" +
+ "}}";
+ final String what = "Math.'m('a*)";
+ final String by = "Math.$m$($a$)";
+ options.setToUseStaticImport(true);
+
+ // depends on default setting being equal to 3 for names count to use import on demand
+ final String expected = "import static java.lang.Math.*;class ImportTest {{\n" +
+ " abs(-0.5);\n" +
+ " sin(0.5);\n" +
+ " max(1,2);\n" +
+ "}}";
+ assertEquals("Replacing with static star import", expected, replacer.testReplace(in, what, by, options, true));
+ }
+
public void testReformatAndShortenClassRefPerformance() throws IOException {
final String testName = getTestName(false);
final String ext = "java";
diff --git a/platform/testFramework/src/com/intellij/FileSetTestCase.java b/platform/testFramework/src/com/intellij/FileSetTestCase.java
index ba2afa2f8d86..d89e175a52c2 100644
--- a/platform/testFramework/src/com/intellij/FileSetTestCase.java
+++ b/platform/testFramework/src/com/intellij/FileSetTestCase.java
@@ -16,6 +16,7 @@ import com.intellij.util.ArrayUtil;
import junit.framework.TestSuite;
import java.io.File;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
@@ -80,6 +81,10 @@ public abstract class FileSetTestCase extends TestSuite {
}
}
+ protected String loadFile(File testFile) throws IOException {
+ return FileUtil.loadFile(testFile);
+ }
+
protected String getDelimiter() {
return "---";
}
@@ -116,7 +121,7 @@ public abstract class FileSetTestCase extends TestSuite {
@Override
protected void runTest() throws Throwable {
- String content = FileUtil.loadFile(myTestFile);
+ String content = loadFile(myTestFile);
assertNotNull(content);
List<String> input = new ArrayList<String>();
diff --git a/platform/testFramework/src/com/intellij/GroupBasedTestClassFilter.java b/platform/testFramework/src/com/intellij/GroupBasedTestClassFilter.java
index 3fa50dec3032..f7a84c0470d9 100644
--- a/platform/testFramework/src/com/intellij/GroupBasedTestClassFilter.java
+++ b/platform/testFramework/src/com/intellij/GroupBasedTestClassFilter.java
@@ -56,7 +56,7 @@ public class GroupBasedTestClassFilter extends TestClassesFilter {
private final List<Pattern> myTestGroupPatterns;
private boolean myContainsAllExcludeDefinedGroup;
- private GroupBasedTestClassFilter(Map<String, List<String>> filters, List<String> testGroupNames) {
+ public GroupBasedTestClassFilter(Map<String, List<String>> filters, List<String> testGroupNames) {
//empty group means all patterns from each defined group should be excluded
myContainsAllExcludeDefinedGroup = containsAllExcludeDefinedGroup(testGroupNames);
@@ -120,6 +120,10 @@ public class GroupBasedTestClassFilter extends TestClassesFilter {
*/
@NotNull
public static TestClassesFilter createOn(@NotNull Reader reader, @NotNull List<String> testGroupNames) throws IOException {
+ return new GroupBasedTestClassFilter(readGroups(reader), testGroupNames);
+ }
+
+ public static Map<String, List<String>> readGroups(Reader reader) throws IOException {
Map<String, List<String>> groupNameToPatternsMap = new HashMap<String, List<String>>();
String currentGroupName = "";
@@ -137,8 +141,7 @@ public class GroupBasedTestClassFilter extends TestClassesFilter {
groupNameToPatternsMap.get(currentGroupName).add(line);
}
}
-
- return new GroupBasedTestClassFilter(groupNameToPatternsMap, testGroupNames);
+ return groupNameToPatternsMap;
}
/**
diff --git a/platform/testFramework/src/com/intellij/TestCaseLoader.java b/platform/testFramework/src/com/intellij/TestCaseLoader.java
index 5d11e48548b8..a01070363482 100644
--- a/platform/testFramework/src/com/intellij/TestCaseLoader.java
+++ b/platform/testFramework/src/com/intellij/TestCaseLoader.java
@@ -62,15 +62,24 @@ public class TestCaseLoader {
System.out.println("Using patterns: [" + patterns +"]");
}
else {
- URL excludedStream = StringUtil.isEmpty(classFilterName) ? null : getClass().getClassLoader().getResource(classFilterName);
- if (excludedStream != null) {
- TestClassesFilter filter;
+ List<URL> groupingFileUrls = Collections.emptyList();
+ if (!StringUtil.isEmpty(classFilterName)) {
try {
- List<String> testGroupNames = StringUtil.split(System.getProperty(TARGET_TEST_GROUP, "").trim(), ";");
- InputStreamReader reader = new InputStreamReader(excludedStream.openStream());
+ groupingFileUrls = Collections.list(getClass().getClassLoader().getResources(classFilterName));
+ }
+ catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ List<String> testGroupNames = StringUtil.split(System.getProperty(TARGET_TEST_GROUP, "").trim(), ";");
+ Map<String, List<String>> groups = new LinkedHashMap<String, List<String>>();
+
+ for (URL fileUrl : groupingFileUrls) {
+ try {
+ InputStreamReader reader = new InputStreamReader(fileUrl.openStream());
try {
- filter = GroupBasedTestClassFilter.createOn(reader, testGroupNames);
- System.out.println("Using test groups: " + testGroupNames);
+ groups.putAll(GroupBasedTestClassFilter.readGroups(reader));
}
finally {
reader.close();
@@ -78,14 +87,17 @@ public class TestCaseLoader {
}
catch (IOException e) {
e.printStackTrace();
- filter = TestClassesFilter.ALL_CLASSES;
- System.out.println("Using all classes");
+ System.err.println("Failed to load test groups from " + fileUrl);
}
- myTestClassesFilter = filter;
}
- else {
- myTestClassesFilter = TestClassesFilter.ALL_CLASSES;
+
+ if (groups.isEmpty()) {
System.out.println("Using all classes");
+ myTestClassesFilter = TestClassesFilter.ALL_CLASSES;
+ }
+ else {
+ System.out.println("Using test groups: " + testGroupNames);
+ myTestClassesFilter = new GroupBasedTestClassFilter(groups, testGroupNames);
}
}
}
diff --git a/platform/testFramework/src/com/intellij/testFramework/LightPlatformCodeInsightTestCase.java b/platform/testFramework/src/com/intellij/testFramework/LightPlatformCodeInsightTestCase.java
index 24e4074ed4ee..3c1f96113532 100644
--- a/platform/testFramework/src/com/intellij/testFramework/LightPlatformCodeInsightTestCase.java
+++ b/platform/testFramework/src/com/intellij/testFramework/LightPlatformCodeInsightTestCase.java
@@ -35,10 +35,10 @@ import com.intellij.openapi.editor.actionSystem.EditorActionManager;
import com.intellij.openapi.editor.ex.util.EditorUtil;
import com.intellij.openapi.editor.impl.DocumentImpl;
import com.intellij.openapi.editor.impl.EditorImpl;
+import com.intellij.openapi.editor.impl.TrailingSpacesStripper;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
-import com.intellij.openapi.fileEditor.impl.TrailingSpacesStripper;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.ThrowableComputable;
diff --git a/platform/testFramework/src/com/intellij/testFramework/PlatformTestUtil.java b/platform/testFramework/src/com/intellij/testFramework/PlatformTestUtil.java
index 0c46f14b98e0..307fb65e5ef1 100644
--- a/platform/testFramework/src/com/intellij/testFramework/PlatformTestUtil.java
+++ b/platform/testFramework/src/com/intellij/testFramework/PlatformTestUtil.java
@@ -44,6 +44,7 @@ import com.intellij.openapi.vfs.VirtualFileFilter;
import com.intellij.openapi.vfs.ex.temp.TempFileSystem;
import com.intellij.util.Alarm;
import com.intellij.util.ArrayUtil;
+import com.intellij.util.ReflectionUtil;
import com.intellij.util.ThrowableRunnable;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashMap;
@@ -62,11 +63,8 @@ import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;
import java.awt.*;
import java.awt.event.InvocationEvent;
-import java.io.File;
-import java.io.IOException;
-import java.io.StringWriter;
+import java.io.*;
import java.lang.ref.SoftReference;
-import java.lang.reflect.Field;
import java.nio.charset.Charset;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
@@ -823,9 +821,24 @@ public class PlatformTestUtil {
}
private static void patchSystemFileEncoding(String encoding) throws NoSuchFieldException, IllegalAccessException {
- Field charset = Charset.class.getDeclaredField("defaultCharset");
- charset.setAccessible(true);
- charset.set(Charset.class, null);
+ ReflectionUtil.resetField(Charset.class, Charset.class, "defaultCharset");
System.setProperty("file.encoding", encoding);
}
+
+ public static void withStdErrSuppressed(@NotNull Runnable r) {
+ PrintStream std = System.err;
+ System.setErr(new PrintStream(NULL));
+ try {
+ r.run();
+ }
+ finally {
+ System.setErr(std);
+ }
+ }
+
+ @SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
+ private static final OutputStream NULL = new OutputStream() {
+ @Override
+ public void write(int b) throws IOException { }
+ };
}
diff --git a/platform/testFramework/src/com/intellij/testFramework/PsiTestUtil.java b/platform/testFramework/src/com/intellij/testFramework/PsiTestUtil.java
index 0f746d43c6ca..3960159e5bb4 100644
--- a/platform/testFramework/src/com/intellij/testFramework/PsiTestUtil.java
+++ b/platform/testFramework/src/com/intellij/testFramework/PsiTestUtil.java
@@ -220,11 +220,11 @@ public class PsiTestUtil {
return entry;
}
- public static void removeContentEntry(Module module, final ContentEntry e) {
+ public static void removeContentEntry(Module module, final VirtualFile contentRoot) {
ModuleRootModificationUtil.updateModel(module, new Consumer<ModifiableRootModel>() {
@Override
public void consume(ModifiableRootModel model) {
- model.removeContentEntry(e);
+ model.removeContentEntry(findContentEntryWithAssertion(model, contentRoot));
}
});
}
diff --git a/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java b/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java
index fa752b4643b0..6deda3d4b70a 100644
--- a/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java
+++ b/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java
@@ -570,8 +570,12 @@ public abstract class UsefulTestCase extends TestCase {
public static <T> T assertOneElement(Collection<T> collection) {
Assert.assertNotNull(collection);
- Assert.assertEquals(toString(collection), 1, collection.size());
- return collection.iterator().next();
+ Iterator<T> iterator = collection.iterator();
+ String toString = toString(collection);
+ Assert.assertTrue(toString, iterator.hasNext());
+ T t = iterator.next();
+ Assert.assertFalse(toString, iterator.hasNext());
+ return t;
}
public static <T> T assertOneElement(T[] ts) {
diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/CodeInsightTestFixture.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/CodeInsightTestFixture.java
index e721401a82ba..a309f9acda8f 100644
--- a/platform/testFramework/src/com/intellij/testFramework/fixtures/CodeInsightTestFixture.java
+++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/CodeInsightTestFixture.java
@@ -463,7 +463,7 @@ public interface CodeInsightTestFixture extends IdeaProjectTestFixture {
void type(final char c);
- void type(final String s);
+ void type(@NotNull String s);
void performEditorAction(@NotNull String actionId);
diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/HeavyIdeaTestFixture.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/HeavyIdeaTestFixture.java
index 490d2c3ff05b..57e78061cc3c 100644
--- a/platform/testFramework/src/com/intellij/testFramework/fixtures/HeavyIdeaTestFixture.java
+++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/HeavyIdeaTestFixture.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@ package com.intellij.testFramework.fixtures;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import java.io.IOException;
@@ -25,5 +26,5 @@ import java.io.IOException;
* @author peter
*/
public interface HeavyIdeaTestFixture extends IdeaProjectTestFixture {
- PsiFile addFileToProject(@NonNls String rootPath, @NonNls String relativePath, @NonNls String fileText) throws IOException;
+ PsiFile addFileToProject(@NonNls @NotNull String rootPath, @NonNls @NotNull String relativePath, @NonNls @NotNull String fileText) throws IOException;
}
diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java
index 4857acd2d328..449b1bacf8e9 100644
--- a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java
+++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java
@@ -146,7 +146,6 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig
private final TempDirTestFixture myTempDirFixture;
protected final IdeaProjectTestFixture myProjectFixture;
- @NonNls private static final String XXX = "XXX";
private final FileTreeAccessFilter myJavaFilesFilter = new FileTreeAccessFilter();
private boolean myAllowDirt;
private boolean myCaresAboutInjection = true;
@@ -369,7 +368,7 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig
private long collectAndCheckHighlightings(final boolean checkWarnings,
final boolean checkInfos,
final boolean checkWeakWarnings,
- final VirtualFile[] files) {
+ @NotNull VirtualFile[] files) {
final List<Trinity<PsiFile, Editor, ExpectedHighlightingData>> datas =
ContainerUtil.map2List(files, new Function<VirtualFile, Trinity<PsiFile, Editor, ExpectedHighlightingData>>() {
@Override
@@ -787,12 +786,13 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig
});
}
+ @NotNull
private DataContext getEditorDataContext() {
return ((EditorEx)myEditor).getDataContext();
}
@Override
- public void type(String s) {
+ public void type(@NotNull String s) {
for (int i = 0; i < s.length(); i++) {
type(s.charAt(i));
}
@@ -804,7 +804,7 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig
_performEditorAction(actionId);
}
- private boolean _performEditorAction(String actionId) {
+ private boolean _performEditorAction(@NotNull String actionId) {
final DataContext dataContext = getEditorDataContext();
final ActionManagerEx managerEx = ActionManagerEx.getInstanceEx();
@@ -948,7 +948,7 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig
private static void addGutterIconRenderer(final GutterMark renderer,
final int offset,
- SortedMap<Integer, List<GutterMark>> result) {
+ @NotNull SortedMap<Integer, List<GutterMark>> result) {
if (renderer == null) return;
List<GutterMark> renderers = result.get(offset);
@@ -965,7 +965,7 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig
return addFileToProject(getTempDirPath(), relativePath, fileText);
}
- protected PsiFile addFileToProject(final String rootPath, final String relativePath, final String fileText) {
+ protected PsiFile addFileToProject(@NotNull final String rootPath, @NotNull final String relativePath, @NotNull final String fileText) {
return new WriteCommandAction<PsiFile>(getProject()) {
@Override
protected void run(@NotNull Result<PsiFile> result) throws Throwable {
@@ -1377,7 +1377,7 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig
return PsiDocumentManager.getInstance(getProject()).getDocument(file);
}
- private PsiFile configureByFileInner(@NonNls String filePath) {
+ private PsiFile configureByFileInner(@NonNls @NotNull String filePath) {
assertInitialized();
final VirtualFile file = copyFileToProject(filePath);
return configureByFileInner(file);
@@ -1401,7 +1401,7 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig
return configureInner(copy, SelectionAndCaretMarkupLoader.fromFile(copy));
}
- private PsiFile configureInner(@NotNull final VirtualFile copy, final SelectionAndCaretMarkupLoader loader) {
+ private PsiFile configureInner(@NotNull final VirtualFile copy, @NotNull final SelectionAndCaretMarkupLoader loader) {
assertInitialized();
new WriteCommandAction.Simple(getProject()) {
@Override
@@ -1459,13 +1459,17 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig
}
@Nullable
- private Editor createEditor(VirtualFile file) {
+ private Editor createEditor(@NotNull VirtualFile file) {
final Project project = getProject();
final FileEditorManager instance = FileEditorManager.getInstance(project);
if (file.getFileType().isBinary()) {
return null;
}
- return instance.openTextEditor(new OpenFileDescriptor(project, file, 0), false);
+ Editor editor = instance.openTextEditor(new OpenFileDescriptor(project, file), false);
+ if (editor != null) {
+ editor.getCaretModel().moveToOffset(0);
+ }
+ return editor;
}
private long collectAndCheckHighlighting(boolean checkWarnings, boolean checkInfos, boolean checkWeakWarnings) throws Exception {
@@ -1487,14 +1491,14 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig
//to initialize caches
if (!DumbService.isDumb(project)) {
- CacheManager.SERVICE.getInstance(project).getFilesWithWord(XXX, UsageSearchContext.IN_COMMENTS, GlobalSearchScope.allScope(project), true);
+ CacheManager.SERVICE.getInstance(project).getFilesWithWord("XXX", UsageSearchContext.IN_COMMENTS, GlobalSearchScope.allScope(project), true);
}
- List<HighlightInfo> infos;
final long start = System.currentTimeMillis();
((PsiManagerImpl)PsiManager.getInstance(project)).setAssertOnFileLoadingFilter(myJavaFilesFilter, myTestRootDisposable);
// ProfilingUtil.startCPUProfiling();
+ List<HighlightInfo> infos;
try {
infos = doHighlighting();
removeDuplicatedRangesForInjected(infos);
@@ -1510,7 +1514,7 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig
return elapsed;
}
- private static void removeDuplicatedRangesForInjected(List<HighlightInfo> infos) {
+ private static void removeDuplicatedRangesForInjected(@NotNull List<HighlightInfo> infos) {
Collections.sort(infos, new Comparator<HighlightInfo>() {
@Override
public int compare(HighlightInfo o1, HighlightInfo o2) {
@@ -1582,7 +1586,7 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig
throw exception;
}
- public static void ensureIndexesUpToDate(Project project) {
+ public static void ensureIndexesUpToDate(@NotNull Project project) {
if (!DumbService.isDumb(project)) {
FileBasedIndex.getInstance().ensureUpToDate(StubUpdatingIndex.INDEX_ID, project, null);
FileBasedIndex.getInstance().ensureUpToDate(TodoIndex.NAME, project, null);
@@ -1625,6 +1629,7 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig
});
}
+ @NotNull
public static List<IntentionAction> getAvailableIntentions(@NotNull final Editor editor, @NotNull final PsiFile file) {
return ApplicationManager.getApplication().runReadAction(new Computable<List<IntentionAction>>() {
@Override
@@ -1634,6 +1639,7 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig
});
}
+ @NotNull
private static List<IntentionAction> doGetAvailableIntentions(@NotNull Editor editor, @NotNull PsiFile file) {
ShowIntentionsPass.IntentionsInfo intentions = new ShowIntentionsPass.IntentionsInfo();
ShowIntentionsPass.getActionsToShow(editor, file, intentions, -1);
@@ -1681,15 +1687,17 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig
myJavaFilesFilter.allowTreeAccessForAllFiles();
}
- static class SelectionAndCaretMarkupLoader {
+ private static class SelectionAndCaretMarkupLoader {
final String filePath;
final String newFileText;
final EditorTestUtil.CaretAndSelectionState caretState;
- static SelectionAndCaretMarkupLoader fromFile(String path, String charset) throws IOException {
+ @NotNull
+ static SelectionAndCaretMarkupLoader fromFile(@NotNull String path, String charset) throws IOException {
return new SelectionAndCaretMarkupLoader(StringUtil.convertLineSeparators(FileUtil.loadFile(new File(path), charset)), path);
}
+ @NotNull
static SelectionAndCaretMarkupLoader fromFile(@NotNull VirtualFile file) {
final String text;
try {
@@ -1701,11 +1709,12 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig
return new SelectionAndCaretMarkupLoader(StringUtil.convertLineSeparators(text), file.getPath());
}
- static SelectionAndCaretMarkupLoader fromText(String text) {
+ @NotNull
+ static SelectionAndCaretMarkupLoader fromText(@NotNull String text) {
return new SelectionAndCaretMarkupLoader(text, null);
}
- private SelectionAndCaretMarkupLoader(String fileText, String filePath) {
+ private SelectionAndCaretMarkupLoader(@NotNull String fileText, String filePath) {
this.filePath = filePath;
final Document document = EditorFactory.getInstance().createDocument(fileText);
caretState = EditorTestUtil.extractCaretAndSelectionMarkers(document);
@@ -1735,11 +1744,10 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig
}
- @SuppressWarnings("ConstantConditions")
private void checkResult(@NotNull String expectedFile,
final boolean stripTrailingSpaces,
- final SelectionAndCaretMarkupLoader loader,
- String actualText) {
+ @NotNull SelectionAndCaretMarkupLoader loader,
+ @NotNull String actualText) {
assertInitialized();
Project project = getProject();
Editor editor = getEditor();
@@ -1773,7 +1781,8 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig
EditorTestUtil.verifyCaretAndSelectionState(editor, loader.caretState, expectedFile);
}
- private String stripTrailingSpaces(String actualText) {
+ @NotNull
+ private String stripTrailingSpaces(@NotNull String actualText) {
final Document document = EditorFactory.getInstance().createDocument(actualText);
((DocumentImpl)document).stripTrailingSpaces(getProject());
actualText = document.getText();
@@ -1824,6 +1833,7 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig
}
}
+ @NotNull
public String getFoldingDescription(boolean withCollapseStatus) {
CodeFoldingManager.getInstance(getProject()).buildInitialFoldings(myEditor);
@@ -1849,7 +1859,7 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig
return result.toString();
}
- private void testFoldingRegions(final String verificationFileName, boolean doCheckCollapseStatus) {
+ private void testFoldingRegions(@NotNull String verificationFileName, boolean doCheckCollapseStatus) {
String expectedContent;
try {
expectedContent = FileUtil.loadFile(new File(verificationFileName));
diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/HeavyIdeaTestFixtureImpl.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/HeavyIdeaTestFixtureImpl.java
index 4adc2aa57cef..27a45cbfe99e 100644
--- a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/HeavyIdeaTestFixtureImpl.java
+++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/HeavyIdeaTestFixtureImpl.java
@@ -235,7 +235,7 @@ class HeavyIdeaTestFixtureImpl extends BaseFixture implements HeavyIdeaTestFixtu
}
@Override
- public PsiFile addFileToProject(@NonNls String rootPath, @NonNls final String relativePath, @NonNls final String fileText) throws IOException {
+ public PsiFile addFileToProject(@NotNull @NonNls String rootPath, @NotNull @NonNls final String relativePath, @NotNull @NonNls final String fileText) throws IOException {
final VirtualFile dir = VfsUtil.createDirectories(rootPath + "/" + PathUtil.getParentPath(relativePath));
final VirtualFile[] virtualFile = new VirtualFile[1];
diff --git a/platform/testFramework/src/com/intellij/util/io/TestFileSystemBuilder.java b/platform/testFramework/src/com/intellij/util/io/TestFileSystemBuilder.java
index da7dc5cfa162..9ee314d52b8d 100644
--- a/platform/testFramework/src/com/intellij/util/io/TestFileSystemBuilder.java
+++ b/platform/testFramework/src/com/intellij/util/io/TestFileSystemBuilder.java
@@ -1,5 +1,7 @@
package com.intellij.util.io;
+import org.jetbrains.annotations.NotNull;
+
/**
* @author nik
*/
@@ -12,6 +14,7 @@ public class TestFileSystemBuilder {
myParent = parent;
}
+ @NotNull
public TestFileSystemItem build() {
TestFileSystemBuilder builder = this;
while (builder.myParent != null) {
@@ -20,23 +23,27 @@ public class TestFileSystemBuilder {
return builder.myItem;
}
+ @NotNull
public TestFileSystemBuilder dir(String name) {
final TestFileSystemItem item = new TestFileSystemItem(name, false, true);
myItem.addChild(item);
return new TestFileSystemBuilder(item, this);
}
+ @NotNull
public TestFileSystemBuilder archive(String name) {
final TestFileSystemItem item = new TestFileSystemItem(name, true, false);
myItem.addChild(item);
return new TestFileSystemBuilder(item, this);
}
+ @NotNull
public TestFileSystemBuilder file(String name) {
myItem.addChild(new TestFileSystemItem(name, false, false));
return this;
}
+ @NotNull
public TestFileSystemBuilder file(String name, String content) {
myItem.addChild(new TestFileSystemItem(name, false, false, content));
return this;
@@ -46,6 +53,7 @@ public class TestFileSystemBuilder {
return myParent;
}
+ @NotNull
public static TestFileSystemBuilder fs() {
return new TestFileSystemBuilder(new TestFileSystemItem("root", false, true), null);
}
diff --git a/platform/testFramework/testSrc/com/intellij/openapi/keymap/KeymapsTestCase.java b/platform/testFramework/testSrc/com/intellij/openapi/keymap/KeymapsTestCase.java
index 86958eee3461..4375701bc62c 100644
--- a/platform/testFramework/testSrc/com/intellij/openapi/keymap/KeymapsTestCase.java
+++ b/platform/testFramework/testSrc/com/intellij/openapi/keymap/KeymapsTestCase.java
@@ -82,6 +82,7 @@ public abstract class KeymapsTestCase extends PlatformTestCase {
{ "alt DOWN", "ShowContent", "MethodDown"},
{ "alt F1", "SelectIn", "ProjectViewChangeView"},
{ "alt INSERT", "FileChooser.NewFolder", "Generate", "NewElement"},
+ { "control F10", "javaee.UpdateRunningApplication", "liveedit.UpdateRunningApplication"},
{ "control 1", "FileChooser.GotoHome", "GotoBookmark1", "DuplicatesForm.SendToLeft"},
{ "control 2", "FileChooser.GotoProject", "GotoBookmark2", "DuplicatesForm.SendToRight"},
{ "control 3", "GotoBookmark3", "FileChooser.GotoModule"},
@@ -238,7 +239,7 @@ public abstract class KeymapsTestCase extends PlatformTestCase {
{ "TAB", "EditorChooseLookupItemReplace", "NextTemplateVariable", "NextParameter", "EditorIndentSelection", "EditorTab", "NextTemplateParameter"},
{ "alt DOWN", "ShowContent", "MoveStatementDown"},
{ "alt HOME", "ViewNavigationBar", "ShowNavBar"},
- { "control F10", "ShowPopupMenu", "javaee.UpdateRunningApplication"},
+ { "control F10", "ShowPopupMenu", "javaee.UpdateRunningApplication", "liveedit.UpdateRunningApplication"},
{ "control F11", "Rerun", "ToggleBookmarkWithMnemonic"},
{ "control D", "CompareDirs", "EditorDeleteLine", "CompareTwoFiles", "SendEOF", "FileChooser.GotoDesktop"},
{ "control N", "ShowPopupMenu", "FileChooser.NewFolder"},
diff --git a/platform/testFramework/testSrc/com/intellij/testFramework/vcs/MockChangeListManager.java b/platform/testFramework/testSrc/com/intellij/testFramework/vcs/MockChangeListManager.java
index b3557238124f..263c25b184b8 100644
--- a/platform/testFramework/testSrc/com/intellij/testFramework/vcs/MockChangeListManager.java
+++ b/platform/testFramework/testSrc/com/intellij/testFramework/vcs/MockChangeListManager.java
@@ -271,6 +271,11 @@ public class MockChangeListManager extends ChangeListManagerEx {
}
@Override
+ public void addDirectoryToIgnoreImplicitly(@NotNull String path) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
public void setFilesToIgnore(IgnoredFileBean... ignoredFiles) {
throw new UnsupportedOperationException();
}
diff --git a/platform/usageView/src/com/intellij/usages/ChunkExtractor.java b/platform/usageView/src/com/intellij/usages/ChunkExtractor.java
index 930321fc61d5..dbbaeb48b72f 100644
--- a/platform/usageView/src/com/intellij/usages/ChunkExtractor.java
+++ b/platform/usageView/src/com/intellij/usages/ChunkExtractor.java
@@ -19,9 +19,7 @@ import com.intellij.injected.editor.DocumentWindow;
import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.lexer.Lexer;
import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.editor.HighlighterColors;
-import com.intellij.openapi.editor.RangeMarker;
+import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.colors.TextAttributesKey;
import com.intellij.openapi.editor.markup.TextAttributes;
@@ -39,11 +37,14 @@ import com.intellij.psi.tree.IElementType;
import com.intellij.reference.SoftReference;
import com.intellij.usageView.UsageTreeColors;
import com.intellij.usageView.UsageTreeColorsScheme;
+import com.intellij.usages.impl.SyntaxHighlighterOverEditorHighlighter;
+import com.intellij.usages.impl.rules.UsageType;
import com.intellij.util.Processor;
import com.intellij.util.containers.FactoryMap;
import com.intellij.util.text.CharArrayUtil;
import com.intellij.util.text.StringFactory;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.awt.*;
import java.lang.ref.WeakReference;
@@ -64,9 +65,7 @@ public class ChunkExtractor {
private final Document myDocument;
private long myDocumentStamp;
- private final SyntaxHighlighter myHighlighter;
-
- private final Lexer myLexer;
+ private final SyntaxHighlighterOverEditorHighlighter myHighlighter;
private abstract static class WeakFactory<T> {
private WeakReference<T> myRef;
@@ -119,11 +118,10 @@ public class ChunkExtractor {
myDocument = PsiDocumentManager.getInstance(project).getDocument(file);
LOG.assertTrue(myDocument != null);
final FileType fileType = file.getFileType();
- final SyntaxHighlighter highlighter = SyntaxHighlighterFactory.getSyntaxHighlighter(fileType, project, file.getVirtualFile());
- myHighlighter = highlighter == null ? new PlainSyntaxHighlighter() : highlighter;
- myLexer = myHighlighter.getHighlightingLexer();
- myLexer.start(myDocument.getCharsSequence());
- myDocumentStamp = myDocument.getModificationStamp();
+ SyntaxHighlighter highlighter = SyntaxHighlighterFactory.getSyntaxHighlighter(fileType, project, file.getVirtualFile());
+ highlighter = highlighter == null ? new PlainSyntaxHighlighter() : highlighter;
+ myHighlighter = new SyntaxHighlighterOverEditorHighlighter(highlighter, file.getVirtualFile(), project);
+ myDocumentStamp = -1;
}
public static int getStartOffset(final List<RangeMarker> rangeMarkers) {
@@ -194,18 +192,21 @@ public class ChunkExtractor {
int end,
boolean selectUsageWithBold,
@NotNull List<TextChunk> result) {
- final Lexer lexer = myLexer;
- final SyntaxHighlighter highlighter = myHighlighter;
+ final Lexer lexer = myHighlighter.getHighlightingLexer();
+ final SyntaxHighlighterOverEditorHighlighter highlighter = myHighlighter;
LOG.assertTrue(start <= end);
int i = StringUtil.indexOf(chars, '\n', start, end);
if (i != -1) end = i;
- if (lexer.getTokenStart() > start || myDocumentStamp != myDocument.getModificationStamp()) {
- lexer.start(chars);
+ if (myDocumentStamp != myDocument.getModificationStamp()) {
+ highlighter.restart(chars);
myDocumentStamp = myDocument.getModificationStamp();
+ } else if(lexer.getTokenStart() > start) {
+ highlighter.resetPosition(0); // todo restart from nearest position with initial state
}
+
boolean isBeginning = true;
for(;lexer.getTokenType() != null; lexer.advance()) {
@@ -218,8 +219,10 @@ public class ChunkExtractor {
hiEnd = Math.min(hiEnd, end);
if (hiStart >= hiEnd) { continue; }
- String text = chars.subSequence(hiStart, hiEnd).toString();
- if (isBeginning && text.trim().isEmpty()) continue;
+ if (isBeginning) {
+ String text = chars.subSequence(hiStart, hiEnd).toString();
+ if(text.trim().isEmpty()) continue;
+ }
isBeginning = false;
IElementType tokenType = lexer.getTokenType();
TextAttributesKey[] tokenHighlights = highlighter.getTokenHighlights(tokenType);
@@ -234,7 +237,7 @@ public class ChunkExtractor {
@NotNull final CharSequence chars,
int hiStart,
final int hiEnd,
- @NotNull TextAttributesKey[] tokenHighlights,
+ @NotNull final TextAttributesKey[] tokenHighlights,
final boolean selectUsageWithBold,
@NotNull final List<TextChunk> result) {
final TextAttributes originalAttrs = convertAttributes(tokenHighlights);
@@ -249,8 +252,12 @@ public class ChunkExtractor {
int usageStart = segment.getStartOffset();
int usageEnd = segment.getEndOffset();
if (rangeIntersect(lastOffset[0], hiEnd, usageStart, usageEnd)) {
- addChunk(chars, lastOffset[0], Math.max(lastOffset[0], usageStart), originalAttrs, false, result);
- addChunk(chars, Math.max(lastOffset[0], usageStart), Math.min(hiEnd, usageEnd), originalAttrs, selectUsageWithBold, result);
+ addChunk(chars, lastOffset[0], Math.max(lastOffset[0], usageStart), originalAttrs, false, null, result);
+
+ UsageType usageType = isHighlightedAsString(tokenHighlights)
+ ? UsageType.LITERAL_USAGE
+ : isHighlightedAsComment(tokenHighlights) ? UsageType.COMMENT_USAGE : null;
+ addChunk(chars, Math.max(lastOffset[0], usageStart), Math.min(hiEnd, usageEnd), originalAttrs, selectUsageWithBold, usageType, result);
lastOffset[0] = usageEnd;
if (usageEnd > hiEnd) {
return false;
@@ -260,8 +267,40 @@ public class ChunkExtractor {
}
});
if (lastOffset[0] < hiEnd) {
- addChunk(chars, lastOffset[0], hiEnd, originalAttrs, false, result);
+ addChunk(chars, lastOffset[0], hiEnd, originalAttrs, false, null, result);
+ }
+ }
+
+ public static boolean isHighlightedAsComment(TextAttributesKey... keys) {
+ for (TextAttributesKey key : keys) {
+ if (key == DefaultLanguageHighlighterColors.DOC_COMMENT ||
+ key == SyntaxHighlighterColors.DOC_COMMENT ||
+ key == DefaultLanguageHighlighterColors.LINE_COMMENT ||
+ key == SyntaxHighlighterColors.LINE_COMMENT ||
+ key == DefaultLanguageHighlighterColors.BLOCK_COMMENT ||
+ key == SyntaxHighlighterColors.JAVA_BLOCK_COMMENT
+ ) {
+ return true;
+ }
+ final TextAttributesKey fallbackAttributeKey = key.getFallbackAttributeKey();
+ if (fallbackAttributeKey != null && isHighlightedAsComment(fallbackAttributeKey)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static boolean isHighlightedAsString(TextAttributesKey... keys) {
+ for (TextAttributesKey key : keys) {
+ if (key == DefaultLanguageHighlighterColors.STRING || key == SyntaxHighlighterColors.STRING) {
+ return true;
+ }
+ final TextAttributesKey fallbackAttributeKey = key.getFallbackAttributeKey();
+ if (fallbackAttributeKey != null && isHighlightedAsString(fallbackAttributeKey)) {
+ return true;
+ }
}
+ return false;
}
private static void addChunk(@NotNull CharSequence chars,
@@ -269,13 +308,14 @@ public class ChunkExtractor {
int end,
@NotNull TextAttributes originalAttrs,
boolean bold,
+ @Nullable UsageType usageType,
@NotNull List<TextChunk> result) {
if (start >= end) return;
TextAttributes attrs = bold
? TextAttributes.merge(originalAttrs, new TextAttributes(null, null, null, null, Font.BOLD))
: originalAttrs;
- result.add(new TextChunk(attrs, StringFactory.createShared(CharArrayUtil.fromSequence(chars, start, end))));
+ result.add(new TextChunk(attrs, StringFactory.createShared(CharArrayUtil.fromSequence(chars, start, end)), usageType));
}
private static boolean rangeIntersect(int s1, int e1, int s2, int e2) {
diff --git a/platform/usageView/src/com/intellij/usages/FindUsagesProcessPresentation.java b/platform/usageView/src/com/intellij/usages/FindUsagesProcessPresentation.java
index d608303eec09..2248182a3c5c 100644
--- a/platform/usageView/src/com/intellij/usages/FindUsagesProcessPresentation.java
+++ b/platform/usageView/src/com/intellij/usages/FindUsagesProcessPresentation.java
@@ -20,6 +20,7 @@ import com.intellij.openapi.util.Factory;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.ArrayList;
@@ -41,6 +42,7 @@ public class FindUsagesProcessPresentation {
private Factory<ProgressIndicator> myProgressIndicatorFactory;
private Collection<PsiFile> myLargeFiles;
private boolean myShowFindOptionsPrompt = true;
+ private Runnable mySearchWithProjectFiles;
public FindUsagesProcessPresentation(@NotNull UsageViewPresentation presentation) {
myUsageViewPresentation = presentation;
@@ -80,6 +82,15 @@ public class FindUsagesProcessPresentation {
myProgressIndicatorFactory = progressIndicatorFactory;
}
+ @Nullable
+ public Runnable searchIncludingProjectFileUsages() {
+ return mySearchWithProjectFiles;
+ }
+
+ public void projectFileUsagesFound(@NotNull Runnable searchWithProjectFiles) {
+ mySearchWithProjectFiles = searchWithProjectFiles;
+ }
+
public void setLargeFilesWereNotScanned(@NotNull Collection<PsiFile> largeFiles) {
myLargeFiles = largeFiles;
}
diff --git a/platform/usageView/src/com/intellij/usages/TextChunk.java b/platform/usageView/src/com/intellij/usages/TextChunk.java
index e1c3345d41da..e74debdb97fb 100644
--- a/platform/usageView/src/com/intellij/usages/TextChunk.java
+++ b/platform/usageView/src/com/intellij/usages/TextChunk.java
@@ -18,17 +18,25 @@ package com.intellij.usages;
import com.intellij.openapi.editor.markup.AttributesFlyweight;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.ui.SimpleTextAttributes;
+import com.intellij.usages.impl.rules.UsageType;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
public class TextChunk {
public static final TextChunk[] EMPTY_ARRAY = new TextChunk[0];
private final AttributesFlyweight myAttributes;
private final String myText;
+ private final UsageType myType;
public TextChunk(@NotNull TextAttributes attributes, @NotNull String text) {
+ this(attributes, text, null);
+ }
+
+ public TextChunk(@NotNull TextAttributes attributes, @NotNull String text, @Nullable UsageType type) {
myAttributes = attributes.getFlyweight();
myText = text;
+ myType = type;
}
@NotNull
@@ -45,6 +53,10 @@ public class TextChunk {
return getText();
}
+ public @Nullable UsageType getType() {
+ return myType;
+ }
+
@NotNull
public SimpleTextAttributes getSimpleAttributesIgnoreBackground() {
SimpleTextAttributes simples = SimpleTextAttributes.fromTextAttributes(getAttributes());
diff --git a/platform/usageView/src/com/intellij/usages/UsageInfo2UsageAdapter.java b/platform/usageView/src/com/intellij/usages/UsageInfo2UsageAdapter.java
index aaccbfffbe18..418890ce17d9 100644
--- a/platform/usageView/src/com/intellij/usages/UsageInfo2UsageAdapter.java
+++ b/platform/usageView/src/com/intellij/usages/UsageInfo2UsageAdapter.java
@@ -38,11 +38,9 @@ import com.intellij.reference.SoftReference;
import com.intellij.ui.SimpleTextAttributes;
import com.intellij.usageView.UsageInfo;
import com.intellij.usageView.UsageViewBundle;
+import com.intellij.usages.impl.rules.UsageType;
import com.intellij.usages.rules.*;
-import com.intellij.util.ArrayUtil;
-import com.intellij.util.IncorrectOperationException;
-import com.intellij.util.NotNullFunction;
-import com.intellij.util.Processor;
+import com.intellij.util.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -79,7 +77,8 @@ public class UsageInfo2UsageAdapter implements UsageInModule,
private final int myLineNumber;
private final int myOffset;
protected Icon myIcon;
- private Reference<TextChunk[]> myTextChunks; // allow to be gced and recreated on-demand because it requires a lot of memory
+ private volatile Reference<TextChunk[]> myTextChunks; // allow to be gced and recreated on-demand because it requires a lot of memory
+ private volatile UsageType myUsageType;
public UsageInfo2UsageAdapter(@NotNull final UsageInfo usageInfo) {
myUsageInfo = usageInfo;
@@ -336,7 +335,7 @@ public class UsageInfo2UsageAdapter implements UsageInModule,
UsageInfo[] merged = ArrayUtil.mergeArrays(getMergedInfos(), u2.getMergedInfos());
myMergedUsageInfos = merged.length == 1 ? merged[0] : merged;
Arrays.sort(getMergedInfos(), BY_NAVIGATION_OFFSET);
- initChunks();
+ myTextChunks = null; // chunks will be rebuilt lazily (IDEA-126048)
return true;
}
@@ -493,4 +492,44 @@ public class UsageInfo2UsageAdapter implements UsageInModule,
public String getTooltipText() {
return myUsageInfo.getTooltipText();
}
+
+ public @Nullable UsageType getUsageType() {
+ UsageType usageType = myUsageType;
+
+ if (usageType == null) {
+ usageType = UsageType.UNCLASSIFIED;
+ PsiFile file = getPsiFile();
+
+ if (file != null) {
+ ChunkExtractor extractor = ChunkExtractor.getExtractor(file);
+ Segment segment = getFirstSegment();
+
+ if (segment != null) {
+ Document document = PsiDocumentManager.getInstance(getProject()).getDocument(file);
+
+ if (document != null) {
+ SmartList<TextChunk> chunks = new SmartList<TextChunk>();
+ extractor.createTextChunks(
+ this,
+ document.getCharsSequence(),
+ segment.getStartOffset(),
+ segment.getEndOffset(),
+ false,
+ chunks
+ );
+
+ for(TextChunk chunk:chunks) {
+ UsageType chunkUsageType = chunk.getType();
+ if (chunkUsageType != null) {
+ usageType = chunkUsageType;
+ break;
+ }
+ }
+ }
+ }
+ }
+ myUsageType = usageType;
+ }
+ return usageType;
+ }
}
diff --git a/platform/usageView/src/com/intellij/usages/impl/SearchForUsagesRunnable.java b/platform/usageView/src/com/intellij/usages/impl/SearchForUsagesRunnable.java
index 8b065b30d167..170d1802eee4 100644
--- a/platform/usageView/src/com/intellij/usages/impl/SearchForUsagesRunnable.java
+++ b/platform/usageView/src/com/intellij/usages/impl/SearchForUsagesRunnable.java
@@ -19,6 +19,7 @@ import com.intellij.find.FindManager;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.KeyboardShortcut;
import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.ApplicationNamesInfo;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.colors.CodeInsightColors;
@@ -71,6 +72,7 @@ class SearchForUsagesRunnable implements Runnable {
@NonNls private static final String FIND_OPTIONS_HREF_TARGET = "FindOptions";
@NonNls private static final String SEARCH_IN_PROJECT_HREF_TARGET = "SearchInProject";
@NonNls private static final String LARGE_FILES_HREF_TARGET = "LargeFiles";
+ @NonNls private static final String SHOW_PROJECT_FILE_OCCURRENCES_HREF_TARGET = "SHOW_PROJECT_FILE_OCCURRENCES";
private final AtomicInteger myUsageCountWithoutDefinition = new AtomicInteger(0);
private final AtomicReference<Usage> myFirstUsage = new AtomicReference<Usage>();
@NotNull
@@ -80,7 +82,7 @@ class SearchForUsagesRunnable implements Runnable {
private final UsageTarget[] mySearchFor;
private final Factory<UsageSearcher> mySearcherFactory;
private final FindUsagesProcessPresentation myProcessPresentation;
- @NotNull private final SearchScope mySearchScope;
+ @NotNull private final SearchScope mySearchScopeToWarnOfFallingOutOf;
private final UsageViewManager.UsageViewStateListener myListener;
private final UsageViewManagerImpl myUsageViewManager;
private final AtomicInteger myOutOfScopeUsages = new AtomicInteger();
@@ -92,7 +94,7 @@ class SearchForUsagesRunnable implements Runnable {
@NotNull UsageTarget[] searchFor,
@NotNull Factory<UsageSearcher> searcherFactory,
@NotNull FindUsagesProcessPresentation processPresentation,
- @NotNull SearchScope scope,
+ @NotNull SearchScope searchScopeToWarnOfFallingOutOf,
@Nullable UsageViewManager.UsageViewStateListener listener) {
myProject = project;
myUsageViewRef = usageViewRef;
@@ -100,7 +102,7 @@ class SearchForUsagesRunnable implements Runnable {
mySearchFor = searchFor;
mySearcherFactory = searcherFactory;
myProcessPresentation = processPresentation;
- mySearchScope = scope;
+ mySearchScopeToWarnOfFallingOutOf = searchScopeToWarnOfFallingOutOf;
myListener = listener;
myUsageViewManager = usageViewManager;
}
@@ -135,25 +137,43 @@ class SearchForUsagesRunnable implements Runnable {
+ UsageViewBundle.message("large.files.were.ignored", largeFiles.size()) + "</a>)";
resultLines.add(shortMessage);
- resultListener = new HyperlinkAdapter(){
- @Override
- protected void hyperlinkActivated(HyperlinkEvent e) {
- if (e.getDescription().equals(LARGE_FILES_HREF_TARGET)) {
- String detailedMessage = detailedLargeFilesMessage(largeFiles);
- List<String> strings = new ArrayList<String>(lines);
- strings.add(detailedMessage);
- ToolWindowManager.getInstance(project).notifyByBalloon(ToolWindowId.FIND, info, wrapInHtml(strings), AllIcons.Actions.Find, listener);
- }
- else if (listener != null) {
- listener.hyperlinkUpdate(e);
- }
+ resultListener = addHrefHandling(resultListener, LARGE_FILES_HREF_TARGET, new Runnable() {
+ public void run() {
+ String detailedMessage = detailedLargeFilesMessage(largeFiles);
+ List<String> strings = new ArrayList<String>(lines);
+ strings.add(detailedMessage);
+ //noinspection SSBasedInspection
+ ToolWindowManager.getInstance(project).notifyByBalloon(ToolWindowId.FIND, info, wrapInHtml(strings), AllIcons.Actions.Find, listener);
}
- };
+ });
}
+ Runnable searchIncludingProjectFileUsages = processPresentation.searchIncludingProjectFileUsages();
+ if (searchIncludingProjectFileUsages != null) {
+ resultLines.add("Occurrences in " + ApplicationNamesInfo.getInstance().getProductName() + " project files are skipped. " +
+ "<a href='" + SHOW_PROJECT_FILE_OCCURRENCES_HREF_TARGET + "'>Include them</a>");
+ resultListener = addHrefHandling(resultListener, SHOW_PROJECT_FILE_OCCURRENCES_HREF_TARGET, searchIncludingProjectFileUsages);
+ }
+
+ //noinspection SSBasedInspection
ToolWindowManager.getInstance(project).notifyByBalloon(ToolWindowId.FIND, info, wrapInHtml(resultLines), AllIcons.Actions.Find, resultListener);
}
+ private static HyperlinkListener addHrefHandling(@Nullable final HyperlinkListener listener,
+ @NotNull final String hrefTarget, @NotNull final Runnable handler) {
+ return new HyperlinkAdapter() {
+ @Override
+ protected void hyperlinkActivated(HyperlinkEvent e) {
+ if (e.getDescription().equals(hrefTarget)) {
+ handler.run();
+ }
+ else if (listener != null) {
+ listener.hyperlinkUpdate(e);
+ }
+ }
+ };
+ }
+
@NotNull
private static String wrapInHtml(@NotNull List<String> strings) {
return XmlStringUtil.wrapInHtml(StringUtil.join(strings, "<br>"));
@@ -319,7 +339,7 @@ class SearchForUsagesRunnable implements Runnable {
ProgressIndicator indicator = ProgressWrapper.unwrap(ProgressManager.getInstance().getProgressIndicator());
if (indicator != null && indicator.isCanceled()) return false;
- if (!UsageViewManagerImpl.isInScope(usage, mySearchScope)) {
+ if (!UsageViewManagerImpl.isInScope(usage, mySearchScopeToWarnOfFallingOutOf)) {
myOutOfScopeUsages.incrementAndGet();
return true;
}
@@ -389,7 +409,7 @@ class SearchForUsagesRunnable implements Runnable {
List<String> lines = new ArrayList<String>();
lines.add(StringUtil.escapeXml(message));
if (myOutOfScopeUsages.get() != 0) {
- lines.add(UsageViewManagerImpl.outOfScopeMessage(myOutOfScopeUsages.get(), mySearchScope));
+ lines.add(UsageViewManagerImpl.outOfScopeMessage(myOutOfScopeUsages.get(), mySearchScopeToWarnOfFallingOutOf));
}
if (myProcessPresentation.isShowFindOptionsPrompt()) {
lines.add(createOptionsHtml(mySearchFor));
@@ -432,7 +452,7 @@ class SearchForUsagesRunnable implements Runnable {
lines.add("Only one usage found.");
if (myOutOfScopeUsages.get() != 0) {
- lines.add(UsageViewManagerImpl.outOfScopeMessage(myOutOfScopeUsages.get(), mySearchScope));
+ lines.add(UsageViewManagerImpl.outOfScopeMessage(myOutOfScopeUsages.get(), mySearchScopeToWarnOfFallingOutOf));
}
lines.add(createOptionsHtml(mySearchFor));
MessageType type = myOutOfScopeUsages.get() == 0 ? MessageType.INFO : MessageType.WARNING;
@@ -456,11 +476,13 @@ class SearchForUsagesRunnable implements Runnable {
hyperlinkListener = null;
}
else {
- lines = Arrays.asList(UsageViewManagerImpl.outOfScopeMessage(myOutOfScopeUsages.get(), mySearchScope), createSearchInProjectHtml());
+ lines = Arrays.asList(UsageViewManagerImpl.outOfScopeMessage(myOutOfScopeUsages.get(), mySearchScopeToWarnOfFallingOutOf), createSearchInProjectHtml());
hyperlinkListener = createSearchInProjectListener();
}
- if (!myProcessPresentation.getLargeFiles().isEmpty() || myOutOfScopeUsages.get() != 0) {
+ if (!myProcessPresentation.getLargeFiles().isEmpty() ||
+ myOutOfScopeUsages.get() != 0 ||
+ myProcessPresentation.searchIncludingProjectFileUsages() != null) {
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
diff --git a/platform/usageView/src/com/intellij/usages/impl/SyntaxHighlighterOverEditorHighlighter.java b/platform/usageView/src/com/intellij/usages/impl/SyntaxHighlighterOverEditorHighlighter.java
new file mode 100644
index 000000000000..04690cc6fa20
--- /dev/null
+++ b/platform/usageView/src/com/intellij/usages/impl/SyntaxHighlighterOverEditorHighlighter.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.usages.impl;
+
+import com.intellij.lexer.LayeredLexer;
+import com.intellij.lexer.Lexer;
+import com.intellij.openapi.editor.colors.TextAttributesKey;
+import com.intellij.openapi.editor.ex.util.LayeredHighlighterIterator;
+import com.intellij.openapi.editor.ex.util.LayeredLexerEditorHighlighter;
+import com.intellij.openapi.editor.highlighter.EditorHighlighter;
+import com.intellij.openapi.editor.highlighter.EditorHighlighterFactory;
+import com.intellij.openapi.editor.highlighter.HighlighterIterator;
+import com.intellij.openapi.fileTypes.PlainSyntaxHighlighter;
+import com.intellij.openapi.fileTypes.PlainTextFileType;
+import com.intellij.openapi.fileTypes.SyntaxHighlighter;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.impl.search.LexerEditorHighlighterLexer;
+import com.intellij.psi.tree.IElementType;
+import org.jetbrains.annotations.NotNull;
+
+/**
+* Created by Maxim.Mossienko on 7/31/2014.
+*/
+public class SyntaxHighlighterOverEditorHighlighter implements SyntaxHighlighter {
+ private final Lexer lexer;
+ private LayeredHighlighterIterator layeredHighlighterIterator = null;
+ private final SyntaxHighlighter highlighter;
+
+ public SyntaxHighlighterOverEditorHighlighter(SyntaxHighlighter _highlighter, VirtualFile file, Project project) {
+ if (file.getFileType() == PlainTextFileType.INSTANCE) { // optimization for large files, PlainTextSyntaxHighlighterFactory is slow
+ highlighter = new PlainSyntaxHighlighter();
+ lexer = highlighter.getHighlightingLexer();
+ } else {
+ highlighter = _highlighter;
+ LayeredLexer.ourDisableLayersFlag.set(Boolean.TRUE);
+ EditorHighlighter editorHighlighter = EditorHighlighterFactory.getInstance().createEditorHighlighter(project, file);
+
+ try {
+ if (editorHighlighter instanceof LayeredLexerEditorHighlighter) {
+ lexer = new LexerEditorHighlighterLexer(editorHighlighter, false);
+ }
+ else {
+ lexer = highlighter.getHighlightingLexer();
+ }
+ }
+ finally {
+ LayeredLexer.ourDisableLayersFlag.set(null);
+ }
+ }
+ }
+
+ @NotNull
+ @Override
+ public Lexer getHighlightingLexer() {
+ return lexer;
+ }
+
+ @NotNull
+ @Override
+ public TextAttributesKey[] getTokenHighlights(IElementType tokenType) {
+ final SyntaxHighlighter activeSyntaxHighlighter =
+ layeredHighlighterIterator != null ? layeredHighlighterIterator.getActiveSyntaxHighlighter() : highlighter;
+ return activeSyntaxHighlighter.getTokenHighlights(tokenType);
+ }
+
+ public void restart(@NotNull CharSequence text) {
+ lexer.start(text);
+
+ if (lexer instanceof LexerEditorHighlighterLexer) {
+ HighlighterIterator iterator = ((LexerEditorHighlighterLexer)lexer).getHighlighterIterator();
+ if (iterator instanceof LayeredHighlighterIterator) {
+ layeredHighlighterIterator = (LayeredHighlighterIterator)iterator;
+ } else {
+ layeredHighlighterIterator = null;
+ }
+ }
+ }
+
+ public void resetPosition(int startOffset) {
+ if (lexer instanceof LexerEditorHighlighterLexer) {
+ ((LexerEditorHighlighterLexer)lexer).resetPosition(startOffset);
+
+ HighlighterIterator iterator = ((LexerEditorHighlighterLexer)lexer).getHighlighterIterator();
+ if (iterator instanceof LayeredHighlighterIterator) {
+ layeredHighlighterIterator = (LayeredHighlighterIterator)iterator;
+ } else {
+ layeredHighlighterIterator = null;
+ }
+ } else {
+ CharSequence text = lexer.getBufferSequence();
+ lexer.start(text, startOffset, text.length());
+ }
+ }
+}
diff --git a/platform/usageView/src/com/intellij/usages/impl/UsageViewManagerImpl.java b/platform/usageView/src/com/intellij/usages/impl/UsageViewManagerImpl.java
index 6d7ce9c07a14..b9fc77295d62 100644
--- a/platform/usageView/src/com/intellij/usages/impl/UsageViewManagerImpl.java
+++ b/platform/usageView/src/com/intellij/usages/impl/UsageViewManagerImpl.java
@@ -33,9 +33,8 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.ToolWindow;
import com.intellij.openapi.wm.ToolWindowId;
import com.intellij.openapi.wm.ToolWindowManager;
-import com.intellij.psi.search.GlobalSearchScope;
-import com.intellij.psi.search.LocalSearchScope;
-import com.intellij.psi.search.SearchScope;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.search.*;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.ui.content.Content;
import com.intellij.usageView.UsageViewBundle;
@@ -122,23 +121,23 @@ public class UsageViewManagerImpl extends UsageViewManager {
@NotNull final UsageViewPresentation presentation,
@NotNull final FindUsagesProcessPresentation processPresentation,
@Nullable final UsageViewStateListener listener) {
- final SearchScope searchScope = getSearchScope(searchFor);
+ final SearchScope searchScope = getMaxSearchScopeToWarnOfFallingOutOf(searchFor);
return doSearchAndShow(searchFor, searcherFactory, presentation, processPresentation, listener, searchScope);
}
- UsageView doSearchAndShow(@NotNull final UsageTarget[] searchFor,
+ private UsageView doSearchAndShow(@NotNull final UsageTarget[] searchFor,
@NotNull final Factory<UsageSearcher> searcherFactory,
@NotNull final UsageViewPresentation presentation,
@NotNull final FindUsagesProcessPresentation processPresentation,
@Nullable final UsageViewStateListener listener,
- @NotNull final SearchScope searchScope) {
+ @NotNull final SearchScope searchScopeToWarnOfFallingOutOf) {
final AtomicReference<UsageViewImpl> usageViewRef = new AtomicReference<UsageViewImpl>();
Task.Backgroundable task = new Task.Backgroundable(myProject, getProgressTitle(presentation), true, new SearchInBackgroundOption()) {
@Override
public void run(@NotNull final ProgressIndicator indicator) {
new SearchForUsagesRunnable(UsageViewManagerImpl.this, UsageViewManagerImpl.this.myProject, usageViewRef, presentation, searchFor, searcherFactory,
- processPresentation, searchScope, listener).run();
+ processPresentation, searchScopeToWarnOfFallingOutOf, listener).run();
}
@NotNull
@@ -159,7 +158,7 @@ public class UsageViewManagerImpl extends UsageViewManager {
}
@NotNull
- private SearchScope getSearchScope(@NotNull UsageTarget[] searchFor) {
+ private SearchScope getMaxSearchScopeToWarnOfFallingOutOf(@NotNull UsageTarget[] searchFor) {
UsageTarget target = searchFor[0];
if (target instanceof TypeSafeDataProvider) {
final SearchScope[] scope = new SearchScope[1];
@@ -171,7 +170,7 @@ public class UsageViewManagerImpl extends UsageViewManager {
});
return scope[0];
}
- return GlobalSearchScope.projectScope(myProject);
+ return GlobalSearchScope.allScope(myProject); // by default do not warn of falling out of scope
}
@Override
@@ -262,10 +261,27 @@ public class UsageViewManagerImpl extends UsageViewManager {
}
public static boolean isInScope(@NotNull Usage usage, @NotNull SearchScope searchScope) {
- VirtualFile file = usage instanceof UsageInFile ? ((UsageInFile)usage).getFile() : usage instanceof PsiElementUsage ? PsiUtilCore
- .getVirtualFile(((PsiElementUsage)usage).getElement()) : null;
- return file != null && (searchScope instanceof LocalSearchScope
- ? ((LocalSearchScope)searchScope).isInScope(file) : ((GlobalSearchScope)searchScope).contains(file));
+ PsiElement element = null;
+ VirtualFile file = usage instanceof UsageInFile ? ((UsageInFile)usage).getFile() :
+ usage instanceof PsiElementUsage ? PsiUtilCore.getVirtualFile(element = ((PsiElementUsage)usage).getElement()) : null;
+ if (file != null) {
+ return isFileInScope(file, searchScope);
+ }
+ else if(element != null) {
+ return searchScope instanceof EverythingGlobalScope ||
+ searchScope instanceof ProjectScopeImpl ||
+ searchScope instanceof ProjectAndLibrariesScope;
+ }
+ return false;
+ }
+
+ private static boolean isFileInScope(@NotNull VirtualFile file, @NotNull SearchScope searchScope) {
+ if (searchScope instanceof LocalSearchScope) {
+ return ((LocalSearchScope)searchScope).isInScope(file);
+ }
+ else {
+ return ((GlobalSearchScope)searchScope).contains(file);
+ }
}
@NotNull
diff --git a/platform/usageView/src/com/intellij/usages/impl/rules/UsageTypeGroupingRule.java b/platform/usageView/src/com/intellij/usages/impl/rules/UsageTypeGroupingRule.java
index b182bc31bceb..8d1de0bc06e3 100644
--- a/platform/usageView/src/com/intellij/usages/impl/rules/UsageTypeGroupingRule.java
+++ b/platform/usageView/src/com/intellij/usages/impl/rules/UsageTypeGroupingRule.java
@@ -19,6 +19,7 @@ import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.vcs.FileStatus;
import com.intellij.psi.PsiComment;
import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.usages.*;
import com.intellij.usages.rules.PsiElementUsage;
@@ -42,7 +43,13 @@ public class UsageTypeGroupingRule implements UsageGroupingRuleEx {
if (usage instanceof PsiElementUsage) {
PsiElementUsage elementUsage = (PsiElementUsage)usage;
- UsageType usageType = getUsageType(elementUsage.getElement(), targets);
+ PsiElement element = elementUsage.getElement();
+ UsageType usageType = getUsageType(element, targets);
+
+ if (usageType == null && element instanceof PsiFile && elementUsage instanceof UsageInfo2UsageAdapter) {
+ usageType = ((UsageInfo2UsageAdapter)elementUsage).getUsageType();
+ }
+
if (usageType != null) return new UsageTypeGroup(usageType);
if (usage instanceof ReadWriteAccessUsage) {
diff --git a/platform/usageView/usageView.iml b/platform/usageView/usageView.iml
index e3943e442779..d69cf73e8a0c 100644
--- a/platform/usageView/usageView.iml
+++ b/platform/usageView/usageView.iml
@@ -9,6 +9,7 @@
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="lang-api" />
<orderEntry type="module" module-name="core-impl" />
+ <orderEntry type="module" module-name="editor-ui-ex" />
</component>
</module>
diff --git a/platform/platform-resources-en/src/misc/registry.properties b/platform/util/resources/misc/registry.properties
index 0f430e0fee58..bbda04a2461a 100644
--- a/platform/platform-resources-en/src/misc/registry.properties
+++ b/platform/util/resources/misc/registry.properties
@@ -316,6 +316,7 @@ diff.patience.alg=false
svn.use.terminal=false
svn.use.incoming.optimization=false
+svn.executable.locale=C.UTF-8
completion.enable.relevant.method.chain.suggestions=false
ide.mac.message.sheets.java.emulation=false
@@ -366,6 +367,12 @@ editor.richcopy.strip.indents=true
allow.dialog.based.popups=true
allow.dialog.based.popups.description=Allows to use a JDialog as popup toplevel
+popup.fix.ide.frame.owner=false
+popup.fix.ide.frame.owner.description=Uses correct owner for IdeFrame, but can break some popups
+
+our.heavy.weight.popup=false
+our.heavy.weight.popup.description=Disables HeavyWeightPopup cache in Swing
+
focus.fix.lost.cursor=true
focus.fix.lost.cursor.description=See IDEA-79312
@@ -384,7 +391,7 @@ console.too.much.text.buffer.ratio.description=Used for disabling of console pro
when there is too much of text to process.\n\
The ratio is used against the console cycle buffer size (idea.cycle.buffer.size/theRatio=maxTextLength).
ide.file.settings.order.new=false
-ide.new.project.settings=false
+ide.new.project.settings=true
ide.new.project.settings.description=Temporary key for new project settings dialog UI
commonjs.complete.required.filename.with.extension=false
@@ -392,4 +399,10 @@ commonjs.complete.required.filename.with.extension.description=If checked, requi
fix.jdk7.alt.shortcuts=true
-fix.jdk7.alt.shortcuts.description=Allow to use alt for shortcuts on MacOSX with jdk7+ \ No newline at end of file
+fix.jdk7.alt.shortcuts.description=Allow to use alt for shortcuts on MacOSX with jdk7+
+
+ide.new.markup.markers=true
+ide.new.markup.markers.description=New error stripe markers
+
+spy.js.realtime.evaluation=false
+spy.js.realtime.evaluation.description=Enables spy-js autocomplete and realtime evaluation
diff --git a/platform/util/src/com/intellij/icons/AllIcons.java b/platform/util/src/com/intellij/icons/AllIcons.java
index db897fd8c52d..be3f4f212072 100644
--- a/platform/util/src/com/intellij/icons/AllIcons.java
+++ b/platform/util/src/com/intellij/icons/AllIcons.java
@@ -74,6 +74,7 @@ public class AllIcons {
public static final Icon Forward = IconLoader.getIcon("/actions/forward.png"); // 16x16
public static final Icon GC = IconLoader.getIcon("/actions/gc.png"); // 16x16
public static final Icon Get = IconLoader.getIcon("/actions/get.png"); // 16x16
+ public static final Icon GroupByFile = IconLoader.getIcon("/actions/GroupByFile.png"); // 16x16
public static final Icon GroupByMethod = IconLoader.getIcon("/actions/groupByMethod.png"); // 16x16
public static final Icon GroupByModule = IconLoader.getIcon("/actions/GroupByModule.png"); // 16x16
public static final Icon GroupByModuleGroup = IconLoader.getIcon("/actions/GroupByModuleGroup.png"); // 16x16
@@ -459,6 +460,8 @@ public class AllIcons {
public static final Icon PluginManager = IconLoader.getIcon("/general/pluginManager.png"); // 32x32
public static final Icon Progress = IconLoader.getIcon("/general/progress.png"); // 8x10
public static final Icon ProjectConfigurable = IconLoader.getIcon("/general/projectConfigurable.png"); // 9x9
+ public static final Icon ProjectConfigurableBanner = IconLoader.getIcon("/general/projectConfigurableBanner.png"); // 9x9
+ public static final Icon ProjectConfigurableSelected = IconLoader.getIcon("/general/projectConfigurableSelected.png"); // 9x9
public static final Icon ProjectSettings = IconLoader.getIcon("/general/projectSettings.png"); // 16x16
public static final Icon ProjectStructure = IconLoader.getIcon("/general/projectStructure.png"); // 16x16
public static final Icon ProjectTab = IconLoader.getIcon("/general/projectTab.png"); // 16x16
diff --git a/plugins/properties/resources/icons/PropertiesIcons.java b/platform/util/src/com/intellij/openapi/ui/Divider.java
index 156d14467707..1b2b6b1a3d6a 100644
--- a/plugins/properties/resources/icons/PropertiesIcons.java
+++ b/platform/util/src/com/intellij/openapi/ui/Divider.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,20 +13,22 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package icons;
-
-import com.intellij.openapi.util.IconLoader;
+package com.intellij.openapi.ui;
import javax.swing.*;
+import java.awt.*;
/**
- * NOTE THIS FILE IS AUTO-GENERATED
- * DO NOT EDIT IT BY HAND, run build/scripts/icons.gant instead
+ * @author Konstantin Bulenkov
*/
-public class PropertiesIcons {
- private static Icon load(String path) {
- return IconLoader.getIcon(path, PropertiesIcons.class);
+public abstract class Divider extends JPanel {
+ public Divider(LayoutManager layout) {
+ super(layout);
}
- public static final Icon XmlProperties = load("/icons/xmlProperties.png"); // 16x16
+ public abstract void setResizeEnabled(boolean resizeEnabled);
+
+ public abstract void setSwitchOrientationEnabled(boolean switchOrientationEnabled);
+
+ public abstract void setOrientation(boolean vertical);
}
diff --git a/platform/util/src/com/intellij/openapi/ui/Splitter.java b/platform/util/src/com/intellij/openapi/ui/Splitter.java
index 44d2317088c6..71a026702563 100644
--- a/platform/util/src/com/intellij/openapi/ui/Splitter.java
+++ b/platform/util/src/com/intellij/openapi/ui/Splitter.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -177,7 +177,7 @@ public class Splitter extends JPanel {
}
protected Divider createDivider() {
- return new Divider();
+ return new DividerImpl();
}
@Override
@@ -481,12 +481,12 @@ public class Splitter extends JPanel {
return myDivider;
}
- public class Divider extends JPanel {
+ public class DividerImpl extends Divider {
private boolean myResizeEnabled;
private boolean mySwitchOrientationEnabled;
protected Point myPoint;
- public Divider() {
+ public DividerImpl() {
super(new GridBagLayout());
myResizeEnabled = true;
mySwitchOrientationEnabled = false;
@@ -496,7 +496,7 @@ public class Splitter extends JPanel {
setOrientation(myVerticalSplit);
}
- private void setOrientation(boolean isVerticalSplit) {
+ public void setOrientation(boolean isVerticalSplit) {
removeAll();
setCursor(isVertical() ?
diff --git a/platform/util/src/com/intellij/openapi/util/io/FileUtil.java b/platform/util/src/com/intellij/openapi/util/io/FileUtil.java
index 0f95577cf2b5..cfcbe7967d35 100644
--- a/platform/util/src/com/intellij/openapi/util/io/FileUtil.java
+++ b/platform/util/src/com/intellij/openapi/util/io/FileUtil.java
@@ -1255,10 +1255,15 @@ public class FileUtil extends FileUtilRt {
}
@Contract("null -> null")
- public static String getLocationRelativeToUserHome(@Nullable final String path) {
+ public static String getLocationRelativeToUserHome(@Nullable String path) {
+ return getLocationRelativeToUserHome(path, true);
+ }
+
+ @Contract("null,_ -> null")
+ public static String getLocationRelativeToUserHome(@Nullable String path, boolean unixOnly) {
if (path == null) return null;
- if (SystemInfo.isUnix) {
+ if (SystemInfo.isUnix || !unixOnly) {
final File projectDir = new File(path);
final File userHomeDir = new File(SystemProperties.getUserHome());
if (isAncestor(userHomeDir, projectDir, true)) {
diff --git a/platform/util/src/com/intellij/openapi/util/io/win32/IdeaWin32.java b/platform/util/src/com/intellij/openapi/util/io/win32/IdeaWin32.java
index 3484d0625d37..586668af3864 100644
--- a/platform/util/src/com/intellij/openapi/util/io/win32/IdeaWin32.java
+++ b/platform/util/src/com/intellij/openapi/util/io/win32/IdeaWin32.java
@@ -35,7 +35,7 @@ public class IdeaWin32 {
static {
IdeaWin32 instance = null;
- if (SystemInfo.isWin2kOrNewer) {
+ if (SystemInfo.isWin2kOrNewer && Boolean.parseBoolean(System.getProperty("idea.use.native.fs.for.win", "true"))) {
try {
UrlClassLoader.loadPlatformLibrary("IdeaWin32");
instance = new IdeaWin32();
diff --git a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java
index 7ee904c1f344..bc37f673bb03 100644
--- a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java
+++ b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java
@@ -923,6 +923,10 @@ public class StringUtil extends StringUtilRt {
}
}
+ public static String defaultIfEmpty(@Nullable String value, String defaultValue) {
+ return isEmpty(value) ? defaultValue : value;
+ }
+
@Contract("null -> false")
public static boolean isNotEmpty(@Nullable String s) {
return s != null && !s.isEmpty();
@@ -2513,10 +2517,9 @@ public class StringUtil extends StringUtilRt {
public static String shortenTextWithEllipsis(@NotNull final String text,
final int maxLength,
final int suffixLength,
- boolean useEllipsisSymbol) {
+ @NotNull String symbol) {
final int textLength = text.length();
if (textLength > maxLength) {
- String symbol = useEllipsisSymbol ? "\u2026" : "...";
final int prefixLength = maxLength - suffixLength - symbol.length();
assert prefixLength > 0;
return text.substring(0, prefixLength) + symbol + text.substring(textLength - suffixLength);
@@ -2527,6 +2530,15 @@ public class StringUtil extends StringUtilRt {
}
@NotNull
+ public static String shortenTextWithEllipsis(@NotNull final String text,
+ final int maxLength,
+ final int suffixLength,
+ boolean useEllipsisSymbol) {
+ String symbol = useEllipsisSymbol ? "\u2026" : "...";
+ return shortenTextWithEllipsis(text, maxLength, suffixLength, symbol);
+ }
+
+ @NotNull
public static String shortenPathWithEllipsis(@NotNull final String path, final int maxLength, boolean useEllipsisSymbol) {
return shortenTextWithEllipsis(path, maxLength, (int)(maxLength * 0.7), useEllipsisSymbol);
}
@@ -2650,6 +2662,63 @@ public class StringUtil extends StringUtilRt {
return s.startsWith(smallPart.toLowerCase()) && bigPart.toLowerCase().startsWith(s);
}
+ public static String getShortened(String s, int maxWidth) {
+ int length = s.length();
+ if (isEmpty(s) || length <= maxWidth) return s;
+ ArrayList<String> words = new ArrayList<String>();
+
+ StringBuilder builder = new StringBuilder();
+ for (int i = 0; i < length; i++) {
+ char ch = s.charAt(i);
+
+ if (i == length - 1) {
+ builder.append(ch);
+ words.add(builder.toString());
+ builder.delete(0, builder.length());
+ continue;
+ }
+
+ if (i > 0 && (ch == '/' || ch == '\\' || ch == '.' || Character.isUpperCase(ch))) {
+ words.add(builder.toString());
+ builder.delete(0, builder.length());
+ }
+ builder.append(ch);
+ }
+ for (int i = 0; i < words.size(); i++) {
+ String word = words.get(i);
+ if (i < words.size() - 1 && word.length() == 1) {
+ words.remove(i);
+ words.set(i, word + words.get(i));
+ }
+ }
+
+ int removedLength = 0;
+
+ String toPaste = "...";
+ int index;
+ while (true) {
+ index = Math.max(0, (words.size() - 1) / 2);
+ String aWord = words.get(index);
+ words.remove(index);
+ int toCut = length - removedLength - maxWidth + 3;
+ if (words.size() < 2 || (toCut < aWord.length() - 2 && removedLength == 0)) {
+ int pos = (aWord.length() - toCut) / 2;
+ toPaste = aWord.substring(0, pos) + "..." + aWord.substring(pos+toCut);
+ break;
+ }
+ removedLength += aWord.length();
+ if (length - removedLength <= maxWidth - 3) {
+ break;
+ }
+ }
+ for (int i = 0; i < words.size(); i++) {
+ String word = words.get(i);
+ if (i == index || words.size() == 1) builder.append(toPaste);
+ builder.append(word);
+ }
+ return builder.toString().replaceAll("\\.{4,}", "...");
+ }
+
/**
* Expirable CharSequence. Very useful to control external library execution time,
* i.e. when java.util.regex.Pattern match goes out of control.
diff --git a/platform/util/src/com/intellij/ui/JBColor.java b/platform/util/src/com/intellij/ui/JBColor.java
index d2b4a3bd7623..3669e725610d 100644
--- a/platform/util/src/com/intellij/ui/JBColor.java
+++ b/platform/util/src/com/intellij/ui/JBColor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,7 +15,9 @@
*/
package com.intellij.ui;
+import com.intellij.util.NotNullProducer;
import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NotNull;
import java.awt.*;
import java.awt.color.ColorSpace;
@@ -32,6 +34,7 @@ public class JBColor extends Color {
private static volatile boolean DARK = UIUtil.isUnderDarcula();
private final Color darkColor;
+ private final NotNullProducer<Color> func;
public JBColor(int rgb, int darkRGB) {
this(new Color(rgb), new Color(darkRGB));
@@ -42,6 +45,13 @@ public class JBColor extends Color {
darkColor = dark;
//noinspection AssignmentToStaticFieldFromInstanceMethod
DARK = UIUtil.isUnderDarcula(); //Double check. Sometimes DARK != isDarcula() after dialogs appear on splash screen
+ func = null;
+ }
+
+ public JBColor(NotNullProducer<Color> function) {
+ super(0);
+ darkColor = null;
+ func = function;
}
public static void setDark(boolean dark) {
@@ -52,99 +62,142 @@ public class JBColor extends Color {
return darkColor;
}
+ Color getColor() {
+ if (func != null) {
+ return func.produce();
+ } else {
+ return DARK ? getDarkVariant() : this;
+ }
+ }
+
@Override
public int getRed() {
- return DARK ? getDarkVariant().getRed() : super.getRed();
+ final Color c = getColor();
+ return c == this ? super.getRed() : c.getRed();
}
@Override
public int getGreen() {
- return DARK ? getDarkVariant().getGreen() : super.getGreen();
+ final Color c = getColor();
+ return c == this ? super.getGreen() : c.getGreen();
}
@Override
public int getBlue() {
- return DARK ? getDarkVariant().getBlue() : super.getBlue();
+ final Color c = getColor();
+ return c == this ? super.getBlue() : c.getBlue();
}
@Override
public int getAlpha() {
- return DARK ? getDarkVariant().getAlpha() : super.getAlpha();
+ final Color c = getColor();
+ return c == this ? super.getAlpha() : c.getAlpha();
}
@Override
public int getRGB() {
- return DARK ? getDarkVariant().getRGB() : super.getRGB();
+ final Color c = getColor();
+ return c == this ? super.getRGB() : c.getRGB();
}
@Override
public Color brighter() {
+ if (func != null) {
+ return new JBColor(new NotNullProducer<Color>() {
+ @NotNull
+ @Override
+ public Color produce() {
+ return func.produce().brighter();
+ }
+ });
+ }
return new JBColor(super.brighter(), getDarkVariant().brighter());
}
@Override
public Color darker() {
+ if (func != null) {
+ return new JBColor(new NotNullProducer<Color>() {
+ @NotNull
+ @Override
+ public Color produce() {
+ return func.produce().darker();
+ }
+ });
+ }
return new JBColor(super.darker(), getDarkVariant().darker());
}
@Override
public int hashCode() {
- return DARK ? getDarkVariant().hashCode() : super.hashCode();
+ final Color c = getColor();
+ return c == this ? super.hashCode() : c.hashCode();
}
@Override
public boolean equals(Object obj) {
- return DARK ? getDarkVariant().equals(obj) : super.equals(obj);
+ final Color c = getColor();
+ return c == this ? super.equals(obj) : c.equals(obj);
}
@Override
public String toString() {
- return DARK ? getDarkVariant().toString() : super.toString();
+ final Color c = getColor();
+ return c == this ? super.toString() : c.toString();
}
@Override
public float[] getRGBComponents(float[] compArray) {
- return DARK ? getDarkVariant().getRGBComponents(compArray) : super.getRGBComponents(compArray);
+ final Color c = getColor();
+ return c == this ? super.getRGBComponents(compArray) : c.getRGBComponents(compArray);
}
@Override
public float[] getRGBColorComponents(float[] compArray) {
- return DARK ? getDarkVariant().getRGBColorComponents(compArray) : super.getRGBComponents(compArray);
+ final Color c = getColor();
+ return c == this ? super.getRGBComponents(compArray) : c.getRGBColorComponents(compArray);
}
@Override
public float[] getComponents(float[] compArray) {
- return DARK ? getDarkVariant().getComponents(compArray) : super.getComponents(compArray);
+ final Color c = getColor();
+ return c == this ? super.getComponents(compArray) : c.getComponents(compArray);
}
@Override
public float[] getColorComponents(float[] compArray) {
- return DARK ? getDarkVariant().getColorComponents(compArray) : super.getColorComponents(compArray);
+ final Color c = getColor();
+ return c == this ? super.getColorComponents(compArray) : c.getColorComponents(compArray);
}
@Override
public float[] getComponents(ColorSpace cspace, float[] compArray) {
- return DARK ? getDarkVariant().getComponents(cspace, compArray) : super.getComponents(cspace, compArray);
+ final Color c = getColor();
+ return c == this ? super.getComponents(cspace, compArray) : c.getComponents(cspace, compArray);
}
@Override
public float[] getColorComponents(ColorSpace cspace, float[] compArray) {
- return DARK ? getDarkVariant().getColorComponents(cspace, compArray) : super.getColorComponents(cspace, compArray);
+ final Color c = getColor();
+ return c == this ? super.getColorComponents(cspace, compArray) : c.getColorComponents(cspace, compArray);
}
@Override
public ColorSpace getColorSpace() {
- return DARK ? getDarkVariant().getColorSpace() : super.getColorSpace();
+ final Color c = getColor();
+ return c == this ? super.getColorSpace() : c.getColorSpace();
}
@Override
public synchronized PaintContext createContext(ColorModel cm, Rectangle r, Rectangle2D r2d, AffineTransform xform, RenderingHints hints) {
- return DARK ? getDarkVariant().createContext(cm, r, r2d, xform, hints) : super.createContext(cm, r, r2d, xform, hints);
+ final Color c = getColor();
+ return c == this ? super.createContext(cm, r, r2d, xform, hints) : c.createContext(cm, r, r2d, xform, hints);
}
@Override
public int getTransparency() {
- return DARK ? getDarkVariant().getTransparency() : super.getTransparency();
+ final Color c = getColor();
+ return c == this ? super.getTransparency() : c.getTransparency();
}
public static final JBColor red = new JBColor(Color.red, DarculaColors.RED);
@@ -196,7 +249,34 @@ public class JBColor extends Color {
public static final Color cyan = new JBColor(Color.cyan, new Color(0, 137, 137));
public static final Color CYAN = cyan;
- public static Color foreground() {return UIUtil.getLabelForeground();}
+ public static Color foreground() {
+ return new JBColor(new NotNullProducer<Color>() {
+ @NotNull
+ @Override
+ public Color produce() {
+ return UIUtil.getLabelForeground();
+ }
+ });
+ }
- public static Color background() {return UIUtil.getListBackground();}
+ public static Color background() {
+ return new JBColor(new NotNullProducer<Color>() {
+ @NotNull
+ @Override
+ public Color produce() {
+ return UIUtil.getListBackground();
+ }
+ });
+ }
+
+ public static Color border() {
+ return new JBColor(new NotNullProducer<Color>() {
+ @NotNull
+ @Override
+ public Color produce() {
+ //noinspection deprecation
+ return UIUtil.getBorderColor();
+ }
+ });
+ }
}
diff --git a/platform/util/src/com/intellij/util/EventDispatcher.java b/platform/util/src/com/intellij/util/EventDispatcher.java
index 34361a8ff31b..e17c6e46e5f3 100644
--- a/platform/util/src/com/intellij/util/EventDispatcher.java
+++ b/platform/util/src/com/intellij/util/EventDispatcher.java
@@ -43,6 +43,7 @@ public class EventDispatcher<T extends EventListener> {
}
private EventDispatcher(@NotNull Class<T> listenerClass) {
+ LOG.assertTrue(listenerClass.isInterface(), "listenerClass must be an interface");
InvocationHandler handler = new InvocationHandler() {
@Override
@NonNls
@@ -71,10 +72,7 @@ public class EventDispatcher<T extends EventListener> {
};
//noinspection unchecked
- myMulticaster = (T)Proxy.newProxyInstance(listenerClass.getClassLoader(),
- new Class[]{listenerClass},
- handler
- );
+ myMulticaster = (T)Proxy.newProxyInstance(listenerClass.getClassLoader(), new Class[]{listenerClass}, handler);
}
@NotNull
@@ -82,7 +80,7 @@ public class EventDispatcher<T extends EventListener> {
return myMulticaster;
}
- private void dispatch(final Method method, final Object[] args) {
+ private void dispatch(@NotNull Method method, Object[] args) {
method.setAccessible(true);
for (T listener : myListeners) {
diff --git a/platform/util/src/com/intellij/util/PatternUtil.java b/platform/util/src/com/intellij/util/PatternUtil.java
index 7159a90d1601..0b683dddc1e6 100644
--- a/platform/util/src/com/intellij/util/PatternUtil.java
+++ b/platform/util/src/com/intellij/util/PatternUtil.java
@@ -17,8 +17,9 @@ package com.intellij.util;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.util.containers.HashMap;
-import org.jetbrains.annotations.NonNls;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
@@ -29,30 +30,22 @@ import java.util.regex.PatternSyntaxException;
public class PatternUtil {
private static final Logger LOG = Logger.getInstance("#com.intellij.util.PatternUtil");
- private static final HashMap<String, String> ourEscapeRules = new HashMap<String, String>();
+
+ public static final Pattern NOTHING = Pattern.compile("(a\\A)");
+
+ private static final Map<String, String> ourEscapeRules = ContainerUtil.newLinkedHashMap();
static {
// '.' should be escaped first
ourEscapeRules.put("*", ".*");
ourEscapeRules.put("?", ".");
- escape2('+');
- escape2('(');
- escape2(')');
- escape2('[');
- escape2(']');
- escape2('/');
- escape2('^');
- escape2('$');
- escape2('{');
- escape2('}');
- escape2('|');
- }
-
- private static void escape2(char symbol) {
- ourEscapeRules.put(String.valueOf(symbol), "\\" + symbol);
+ for (char c : "+()[]/^${}|".toCharArray()) {
+ ourEscapeRules.put(String.valueOf(c), "\\" + c);
+ }
}
- public static String convertToRegex(String mask) {
+ @NotNull
+ public static String convertToRegex(@NotNull String mask) {
List<String> strings = StringUtil.split(mask, "\\");
StringBuilder pattern = new StringBuilder();
String separator = "";
@@ -69,17 +62,26 @@ public class PatternUtil {
return pattern.toString();
}
- public static Pattern fromMask(@NonNls String mask) {
-// String pattern = mask.replaceAll("\\.", "\\.").replaceAll("\\*", ".*").replaceAll("\\?", ".");
+ @NotNull
+ public static Pattern fromMask(@NotNull String mask) {
try {
return Pattern.compile(convertToRegex(mask));
}
catch (PatternSyntaxException e) {
LOG.error(mask, e);
- return Pattern.compile("");
+ return NOTHING;
}
}
+ @Contract("_, !null->!null")
+ public static Pattern compileSafe(String pattern, Pattern def) {
+ try {
+ return Pattern.compile(pattern);
+ }
+ catch (Exception e) {
+ return def;
+ }
+ }
/**
* Finds the first match in a list os Strings.
*
diff --git a/platform/util/src/com/intellij/util/ReflectionUtil.java b/platform/util/src/com/intellij/util/ReflectionUtil.java
index a4bf4318a76e..df33a80d4cba 100644
--- a/platform/util/src/com/intellij/util/ReflectionUtil.java
+++ b/platform/util/src/com/intellij/util/ReflectionUtil.java
@@ -426,6 +426,26 @@ public class ReflectionUtil {
}
}
+ /**
+ * {@link Class#newInstance()} cannot instantiate private classes
+ */
+ @NotNull
+ public static <T> T newInstance(@NotNull Class<T> aClass, @NotNull Class... parameterTypes) {
+ try {
+ Constructor<T> constructor = aClass.getDeclaredConstructor(parameterTypes);
+ try {
+ constructor.setAccessible(true);
+ }
+ catch (SecurityException e) {
+ return aClass.newInstance();
+ }
+ return constructor.newInstance();
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
@NotNull
public static <T> T createInstance(@NotNull Constructor<T> constructor, @NotNull Object... args) {
try {
diff --git a/platform/util/src/com/intellij/util/Restarter.java b/platform/util/src/com/intellij/util/Restarter.java
index 7f1584dc73dc..01e7fc494f5b 100644
--- a/platform/util/src/com/intellij/util/Restarter.java
+++ b/platform/util/src/com/intellij/util/Restarter.java
@@ -153,12 +153,11 @@ public class Restarter {
}
public static File createTempExecutable(File executable) throws IOException {
- String ext = FileUtilRt.getExtension(executable.getName());
- File copy = FileUtilRt.createTempFile(FileUtilRt.getNameWithoutExtension(executable.getName()),
- StringUtil.isEmptyOrSpaces(ext) ? ".tmp" : ("." + ext),
- false);
- FileUtilRt.copy(executable, copy);
- if (!copy.setExecutable(executable.canExecute())) throw new IOException("Cannot make file executable: " + copy);
+ File copy = new File(System.getProperty("user.home") + "/." + System.getProperty("idea.paths.selector") + "/restart/" + executable.getName());
+ if (FileUtilRt.ensureCanCreateFile(copy)) {
+ FileUtilRt.copy(executable, copy);
+ if (!copy.setExecutable(executable.canExecute())) throw new IOException("Cannot make file executable: " + copy);
+ }
return copy;
}
diff --git a/platform/util/src/com/intellij/util/containers/ContainerUtil.java b/platform/util/src/com/intellij/util/containers/ContainerUtil.java
index 6052df2b701e..171cfababfa9 100644
--- a/platform/util/src/com/intellij/util/containers/ContainerUtil.java
+++ b/platform/util/src/com/intellij/util/containers/ContainerUtil.java
@@ -828,6 +828,7 @@ public class ContainerUtil extends ContainerUtilRt {
@NotNull
public static <T> List<T> findAll(@NotNull Collection<? extends T> collection, @NotNull Condition<? super T> condition) {
+ if (collection.isEmpty()) return emptyList();
final List<T> result = new SmartList<T>();
for (final T t : collection) {
if (condition.value(t)) {
diff --git a/platform/util/src/com/intellij/util/containers/LongStack.java b/platform/util/src/com/intellij/util/containers/LongStack.java
new file mode 100644
index 000000000000..8e1005bd0af2
--- /dev/null
+++ b/platform/util/src/com/intellij/util/containers/LongStack.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.util.containers;
+
+/**
+ * @author lambdamix
+ */
+import java.util.EmptyStackException;
+
+public class LongStack {
+ private long[] data;
+ private int size;
+ public LongStack(int initialCapacity) {
+ data = new long[initialCapacity];
+ size = 0;
+ }
+
+ public LongStack() {
+ this(5);
+ }
+
+ public void push(long t) {
+ if (size >= data.length) {
+ long[] newdata = new long[data.length * 3 / 2];
+ System.arraycopy(data, 0, newdata, 0, size);
+ data = newdata;
+ }
+ data[size++] = t;
+ }
+
+ public long peek() {
+ if (size == 0) throw new EmptyStackException();
+ return data[size - 1];
+ }
+
+ public long pop() {
+ if (size == 0) throw new EmptyStackException();
+ return data[--size];
+ }
+
+ public boolean empty() {
+ return size == 0;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof LongStack) {
+ LongStack otherStack = (LongStack)o;
+ if (size != otherStack.size) return false;
+ for (int i = 0; i < otherStack.size; i++) {
+ if (data[i] != otherStack.data[i]) return false;
+ }
+ return true;
+ }
+
+ return false;
+ }
+
+ public void clear() {
+ size = 0;
+ }
+}
diff --git a/platform/util/src/com/intellij/util/diff/DiffTree.java b/platform/util/src/com/intellij/util/diff/DiffTree.java
index 0bab60dc87da..680b15b7d1de 100644
--- a/platform/util/src/com/intellij/util/diff/DiffTree.java
+++ b/platform/util/src/com/intellij/util/diff/DiffTree.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package com.intellij.util.diff;
import com.intellij.openapi.util.Ref;
@@ -39,7 +38,6 @@ public class DiffTree<OT, NT> {
final FlyweightCapableTreeStructure<NT> newTree,
final ShallowNodeComparator<OT, NT> comparator,
final DiffTreeChangeBuilder<OT, NT> consumer) {
-
myOldTree = oldTree;
myNewTree = newTree;
myComparator = comparator;
@@ -53,7 +51,7 @@ public class DiffTree<OT, NT> {
new DiffTree<OT, NT>(oldTree, newTree, comparator, consumer).build(oldTree.getRoot(), newTree.getRoot(), 0);
}
- private static enum CompareResult {
+ private enum CompareResult {
EQUAL, // 100% equal
DRILL_DOWN_NEEDED, // element types are equal, but elements are composite
TYPE_ONLY, // only element types are equal
@@ -146,6 +144,7 @@ public class DiffTree<OT, NT> {
newIndex++;
continue;
}
+
CompareResult c12 = looksEqual(comparator, oldChild1, newChild2);
if (c12 == CompareResult.EQUAL || c12 == CompareResult.DRILL_DOWN_NEEDED || c12 == CompareResult.TYPE_ONLY) {
myConsumer.nodeInserted(oldNode, newChild1, newIndex);
@@ -170,6 +169,7 @@ public class DiffTree<OT, NT> {
oldIndex++;
continue;
}
+
myConsumer.nodeReplaced(oldChild1, newChild1);
oldIndex++;
newIndex++;
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/GeneralConfigurable.java b/platform/util/src/com/intellij/util/io/LongInlineKeyDescriptor.java
index 466279bce977..78f1fdd02f78 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/GeneralConfigurable.java
+++ b/platform/util/src/com/intellij/util/io/LongInlineKeyDescriptor.java
@@ -13,39 +13,38 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.intellij.xdebugger.impl.settings;
+package com.intellij.util.io;
-import com.intellij.openapi.options.ConfigurableBase;
-import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-class GeneralConfigurable extends ConfigurableBase<GeneralConfigurableUi, XDebuggerGeneralSettings> {
- @Override
- protected XDebuggerGeneralSettings getSettings() {
- return XDebuggerSettingsManager.getInstanceImpl().getGeneralSettings();
- }
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+/**
+ * @author lambdamix
+ */
+public class LongInlineKeyDescriptor implements KeyDescriptor<Long> {
+ public static LongInlineKeyDescriptor INSTANCE = new LongInlineKeyDescriptor();
@Override
- protected GeneralConfigurableUi createUi() {
- return new GeneralConfigurableUi();
+ public final int getHashCode(Long value) {
+ return value.hashCode();
}
- @NotNull
@Override
- public String getId() {
- return "debugger.general";
+ public final boolean isEqual(Long val1, Long val2) {
+ return val1.longValue() == val2.longValue();
}
- @Nls
@Override
- public String getDisplayName() {
- return "";
+ public final void save(@NotNull DataOutput out, Long value) throws IOException {
+ out.writeLong(value.longValue());
}
- @Nullable
@Override
- public String getHelpTopic() {
- return null;
+ public final Long read(@NotNull DataInput in) throws IOException {
+ return in.readLong();
}
-} \ No newline at end of file
+
+}
diff --git a/platform/util/src/com/intellij/util/text/StringSearcher.java b/platform/util/src/com/intellij/util/text/StringSearcher.java
index 22e9db2d9428..d5bc95f99cef 100644
--- a/platform/util/src/com/intellij/util/text/StringSearcher.java
+++ b/platform/util/src/com/intellij/util/text/StringSearcher.java
@@ -21,6 +21,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
+import java.util.Locale;
public class StringSearcher {
private static final Logger LOG = Logger.getInstance("#com.intellij.util.text.StringSearcher");
@@ -48,7 +49,7 @@ public class StringSearcher {
myPattern = pattern;
myCaseSensitive = caseSensitive;
myForwardDirection = forwardDirection;
- myPatternArray = myCaseSensitive ? myPattern.toCharArray() : myPattern.toLowerCase().toCharArray();
+ myPatternArray = myCaseSensitive ? myPattern.toCharArray() : myPattern.toLowerCase(Locale.US).toCharArray();
myPatternLength = myPatternArray.length;
Arrays.fill(mySearchTable, -1);
myJavaIdentifier = pattern.isEmpty() ||
diff --git a/platform/util/src/com/intellij/util/ui/UIUtil.java b/platform/util/src/com/intellij/util/ui/UIUtil.java
index 7ed8021bd94b..aec2a356ded0 100644
--- a/platform/util/src/com/intellij/util/ui/UIUtil.java
+++ b/platform/util/src/com/intellij/util/ui/UIUtil.java
@@ -1586,7 +1586,7 @@ public class UIUtil {
@NotNull Graphics g,
boolean useRetinaCondition,
Consumer<Graphics2D> paintRoutine) {
- if (!useRetinaCondition || !isRetina() || Registry.is("ide.mac.retina.disableDrawingFix", false)) {
+ if (!useRetinaCondition || !isRetina() || Registry.is("ide.mac.retina.disableDrawingFix")) {
paintRoutine.consume((Graphics2D)g);
}
else {
@@ -1904,6 +1904,10 @@ public class UIUtil {
return INACTIVE_HEADER_COLOR;
}
+ /**
+ * @deprecated
+ * @use JBColor.border()
+ */
public static Color getBorderColor() {
return isUnderDarcula() ? Gray._50 : BORDER_COLOR;
}
@@ -2769,7 +2773,7 @@ public class UIUtil {
@NotNull
public static Paint getGradientPaint(float x1, float y1, @NotNull Color c1, float x2, float y2, @NotNull Color c2) {
- return (Registry.is("ui.no.bangs.and.whistles", false)) ? ColorUtil.mix(c1, c2, .5) : new GradientPaint(x1, y1, c1, x2, y2, c2);
+ return (Registry.is("ui.no.bangs.and.whistles")) ? ColorUtil.mix(c1, c2, .5) : new GradientPaint(x1, y1, c1, x2, y2, c2);
}
@Nullable
diff --git a/platform/util/src/com/intellij/util/xmlb/XmlSerializerImpl.java b/platform/util/src/com/intellij/util/xmlb/XmlSerializerImpl.java
index c25ea4eda084..6cc2124c695a 100644
--- a/platform/util/src/com/intellij/util/xmlb/XmlSerializerImpl.java
+++ b/platform/util/src/com/intellij/util/xmlb/XmlSerializerImpl.java
@@ -16,13 +16,13 @@
package com.intellij.util.xmlb;
import com.intellij.openapi.util.Pair;
+import com.intellij.util.ReflectionUtil;
import org.jdom.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.lang.annotation.Annotation;
import java.lang.ref.SoftReference;
-import java.lang.reflect.Constructor;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;
@@ -184,16 +184,9 @@ class XmlSerializerImpl {
/**
* {@link Class#newInstance()} cannot instantiate private classes
*/
- static <T> T newInstance(Class<T> aClass) {
+ static <T> T newInstance(@NotNull Class<T> aClass) {
try {
- Constructor<T> constructor = aClass.getDeclaredConstructor();
- try {
- constructor.setAccessible(true);
- }
- catch (SecurityException e) {
- return aClass.newInstance();
- }
- return constructor.newInstance();
+ return ReflectionUtil.newInstance(aClass);
}
catch (Exception e) {
throw new XmlSerializationException(e);
diff --git a/platform/util/testSrc/com/intellij/util/text/StringUtilTest.java b/platform/util/testSrc/com/intellij/util/text/StringUtilTest.java
index 2f31dc4f4e61..383c07f2a87e 100644
--- a/platform/util/testSrc/com/intellij/util/text/StringUtilTest.java
+++ b/platform/util/testSrc/com/intellij/util/text/StringUtilTest.java
@@ -195,4 +195,23 @@ public class StringUtilTest extends TestCase {
assertEquals(Arrays.asList("\n", "\r\n", "\n", "\r\n", "\r", "\r", "aa\r", "bb\r\n", "cc\n", "\r", "dd\n", "\n", "\r\n", "\r"),
Arrays.asList(StringUtil.splitByLinesKeepSeparators("\n\r\n\n\r\n\r\raa\rbb\r\ncc\n\rdd\n\n\r\n\r")));
}
+
+ public void testShortened() {
+ String[] names = {"AVeryVeeryLongClassName.java", "com.test.SomeJAVAClassName.java", "strangelowercaseclassname.java", "PrefixPostfix.java", "SomeJAVAClassName.java"};
+ for (String name : names) {
+ for (int i = name.length() + 1; i > 15; i--) {
+ String shortened = StringUtil.getShortened(name, i);
+ assertTrue(shortened.length() <= i);
+ assertTrue(!shortened.contains("...."));
+ int pos = shortened.indexOf("...");
+ if (pos != -1) {
+ assertTrue(name.startsWith(shortened.substring(0, pos)));
+ assertTrue(name.endsWith(shortened.substring(pos + 3)));
+ }
+ else {
+ assertEquals(shortened, name);
+ }
+ }
+ }
+ }
}
diff --git a/platform/util/testSrc/com/intellij/util/xmlb/XmlSerializerTest.java b/platform/util/testSrc/com/intellij/util/xmlb/XmlSerializerTest.java
index 377abeba5b18..9a3fcb9d7066 100644
--- a/platform/util/testSrc/com/intellij/util/xmlb/XmlSerializerTest.java
+++ b/platform/util/testSrc/com/intellij/util/xmlb/XmlSerializerTest.java
@@ -495,6 +495,22 @@ public class XmlSerializerTest extends TestCase {
"</BeanWithFieldWithTagAnnotation>", bean);
}
+ public void testEscapeCharsInTagText() {
+ BeanWithFieldWithTagAnnotation bean = new BeanWithFieldWithTagAnnotation();
+ bean.STRING_V = "a\nb\"<";
+
+ doSerializerTest(
+ "<BeanWithFieldWithTagAnnotation>\n" +
+ " <name>a\nb&quot;&lt;</name>\n" +
+ "</BeanWithFieldWithTagAnnotation>", bean);
+ }
+
+ public void testEscapeCharsInAttributeValue() {
+ final BeanWithPropertiesBoundToAttribute bean = new BeanWithPropertiesBoundToAttribute();
+ bean.name = "a\nb\"<";
+ doSerializerTest("<BeanWithPropertiesBoundToAttribute count=\"3\" name=\"a&#10;b&quot;&lt;\" />", bean);
+ }
+
public void testShuffledDeserialize() {
BeanWithPublicFields bean = new BeanWithPublicFields();
bean.INT_V = 987;
diff --git a/platform/util/util.iml b/platform/util/util.iml
index d0155fd9b0b0..c015e73f13b3 100644
--- a/platform/util/util.iml
+++ b/platform/util/util.iml
@@ -5,6 +5,7 @@
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/testSrc" isTestSource="true" />
+ <sourceFolder url="file://$MODULE_DIR$/resources" type="java-resource" />
</content>
<orderEntry type="library" scope="PROVIDED" name="Mac" level="project" />
<orderEntry type="inheritedJdk" />
diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/ProjectLevelVcsManager.java b/platform/vcs-api/src/com/intellij/openapi/vcs/ProjectLevelVcsManager.java
index 04ce78be1601..c6b0daa0852d 100644
--- a/platform/vcs-api/src/com/intellij/openapi/vcs/ProjectLevelVcsManager.java
+++ b/platform/vcs-api/src/com/intellij/openapi/vcs/ProjectLevelVcsManager.java
@@ -272,6 +272,7 @@ public abstract class ProjectLevelVcsManager {
public abstract VcsHistoryCache getVcsHistoryCache();
public abstract ContentRevisionCache getContentRevisionCache();
public abstract boolean isFileInContent(final VirtualFile vf);
+ public abstract boolean isIgnored(VirtualFile vf);
public abstract boolean dvcsUsedInProject();
diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/changes/ChangeListManager.java b/platform/vcs-api/src/com/intellij/openapi/vcs/changes/ChangeListManager.java
index 006276b42739..9834ef5b0d9e 100644
--- a/platform/vcs-api/src/com/intellij/openapi/vcs/changes/ChangeListManager.java
+++ b/platform/vcs-api/src/com/intellij/openapi/vcs/changes/ChangeListManager.java
@@ -134,6 +134,7 @@ public abstract class ChangeListManager implements ChangeListModification {
public abstract List<CommitExecutor> getRegisteredExecutors();
public abstract void addFilesToIgnore(final IgnoredFileBean... ignoredFiles);
+ public abstract void addDirectoryToIgnoreImplicitly(@NotNull String path);
public abstract void setFilesToIgnore(final IgnoredFileBean... ignoredFiles);
public abstract IgnoredFileBean[] getFilesToIgnore();
public abstract boolean isIgnoredFile(@NotNull VirtualFile file);
diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/changes/IgnoredFileBean.java b/platform/vcs-api/src/com/intellij/openapi/vcs/changes/IgnoredFileBean.java
index c09ce973634f..1091f908b600 100644
--- a/platform/vcs-api/src/com/intellij/openapi/vcs/changes/IgnoredFileBean.java
+++ b/platform/vcs-api/src/com/intellij/openapi/vcs/changes/IgnoredFileBean.java
@@ -26,7 +26,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
-import com.intellij.openapi.vfs.VfsUtil;
+import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.newvfs.impl.NullVirtualFile;
import com.intellij.util.PatternUtil;
@@ -49,7 +49,8 @@ public class IgnoredFileBean {
myType = type;
if (IgnoreSettingsType.FILE.equals(type)) {
myFilenameIfFile = new File(path).getName();
- } else {
+ }
+ else {
myFilenameIfFile = null;
}
myProject = project;
@@ -115,9 +116,10 @@ public class IgnoredFileBean {
if (myType == IgnoreSettingsType.MASK) {
myMatcher.reset(file.getName());
return myMatcher.matches();
- } else {
+ }
+ else {
// quick check for 'file' == exact match pattern
- if (IgnoreSettingsType.FILE.equals(myType) && ! myFilenameIfFile.equals(file.getName())) return false;
+ if (IgnoreSettingsType.FILE.equals(myType) && !myFilenameIfFile.equals(file.getName())) return false;
VirtualFile selector = resolve();
if (Comparing.equal(selector, NullVirtualFile.INSTANCE)) return false;
@@ -130,7 +132,7 @@ public class IgnoredFileBean {
// special case for ignoring the project base dir (IDEADEV-16056)
return !file.isDirectory() && Comparing.equal(file.getParent(), selector);
}
- return VfsUtil.isAncestor(selector, file, false);
+ return VfsUtilCore.isAncestor(selector, file, false);
}
}
}
@@ -146,7 +148,9 @@ public class IgnoredFileBean {
@Nullable
private VirtualFile doResolve() {
- if (myProject == null || myProject.isDisposed()) { return null; }
+ if (myProject == null || myProject.isDisposed()) {
+ return null;
+ }
VirtualFile baseDir = myProject.getBaseDir();
String path = FileUtil.toSystemIndependentName(myPath);
diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/changes/VcsDirtyScopeModifier.java b/platform/vcs-api/src/com/intellij/openapi/vcs/changes/VcsDirtyScopeModifier.java
index b97305c1a0a3..c8a8eda7a436 100644
--- a/platform/vcs-api/src/com/intellij/openapi/vcs/changes/VcsDirtyScopeModifier.java
+++ b/platform/vcs-api/src/com/intellij/openapi/vcs/changes/VcsDirtyScopeModifier.java
@@ -17,7 +17,7 @@ package com.intellij.openapi.vcs.changes;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vfs.VirtualFile;
-import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.NotNull;
import java.util.Collection;
import java.util.Iterator;
@@ -28,7 +28,7 @@ import java.util.Iterator;
public interface VcsDirtyScopeModifier {
Iterator<FilePath> getDirtyFilesIterator();
Collection<VirtualFile> getAffectedVcsRoots();
- @Nullable
+ @NotNull
Iterator<FilePath> getDirtyDirectoriesIterator(VirtualFile root);
void recheckDirtyKeys();
}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerImpl.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerImpl.java
index b9f0855c175c..5e01feada2f3 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerImpl.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerImpl.java
@@ -23,15 +23,20 @@ import com.intellij.openapi.application.RuntimeInterruptedException;
import com.intellij.openapi.components.ProjectComponent;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.progress.EmptyProgressIndicator;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.project.DumbAwareRunnable;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.ModuleRootManager;
+import com.intellij.openapi.roots.impl.DirectoryIndexExcludePolicy;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.*;
import com.intellij.openapi.vcs.changes.conflicts.ChangelistConflictTracker;
@@ -43,6 +48,7 @@ import com.intellij.openapi.vcs.readOnlyHandler.ReadonlyStatusHandlerImpl;
import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsUtil;
+import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.EditorNotifications;
import com.intellij.util.*;
@@ -68,8 +74,10 @@ import java.util.concurrent.atomic.AtomicReference;
/**
* @author max
*/
-public class ChangeListManagerImpl extends ChangeListManagerEx implements ProjectComponent, ChangeListOwner, JDOMExternalizable, RoamingTypeDisabled {
+public class ChangeListManagerImpl extends ChangeListManagerEx implements ProjectComponent, ChangeListOwner, JDOMExternalizable,
+ RoamingTypeDisabled {
public static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.changes.ChangeListManagerImpl");
+ private static final String EXCLUDED_CONVERTED_TO_IGNORED_OPTION = "EXCLUDED_CONVERTED_TO_IGNORED";
private final Project myProject;
private final VcsConfiguration myConfig;
@@ -101,6 +109,7 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
private final List<CommitExecutor> myExecutors = new ArrayList<CommitExecutor>();
private final IgnoredFilesComponent myIgnoredIdeaLevel;
+ private boolean myExcludedConvertedToIgnored;
private ProgressIndicator myUpdateChangesProgressIndicator;
public static final Topic<LocalChangeListsLoadedListener> LISTS_LOADED = new Topic<LocalChangeListsLoadedListener>(
@@ -191,6 +200,7 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
/**
* Shows the proposal to delete one or more changelists that were default and became empty.
+ *
* @return true if the changelists have to be deleted, false if not.
*/
private boolean showRemoveEmptyChangeListsProposal(@NotNull final VcsConfiguration config, @NotNull Collection<LocalChangeList> lists) {
@@ -242,7 +252,7 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
public void unblockModalNotifications() {
myModalNotificationsBlocked = false;
if (myListsToBeDeleted.isEmpty()) {
- return ;
+ return;
}
if (showRemoveEmptyChangeListsProposal(myConfig, myListsToBeDeleted)) {
for (LocalChangeList list : myListsToBeDeleted) {
@@ -261,14 +271,14 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
vcsManager.addVcsListener(myVcsListener);
}
else {
- ((ProjectLevelVcsManagerImpl) vcsManager).addInitializationRequest(
+ ((ProjectLevelVcsManagerImpl)vcsManager).addInitializationRequest(
VcsInitObject.CHANGE_LIST_MANAGER, new DumbAwareRunnable() {
- public void run() {
- myUpdater.initialized();
- broadcastStateAfterLoad();
- vcsManager.addVcsListener(myVcsListener);
- }
- });
+ public void run() {
+ myUpdater.initialized();
+ broadcastStateAfterLoad();
+ vcsManager.addVcsListener(myVcsListener);
+ }
+ });
}
myConflictTracker.startTracking();
@@ -279,7 +289,9 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
synchronized (myDataLock) {
listCopy = getChangeListsCopy();
}
- myProject.getMessageBus().syncPublisher(LISTS_LOADED).processLoadedLists(listCopy);
+ if (!myProject.isDisposed()) {
+ myProject.getMessageBus().syncPublisher(LISTS_LOADED).processLoadedLists(listCopy);
+ }
}
private void initializeForNewProject() {
@@ -297,11 +309,29 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
myIgnoredIdeaLevel.add(IgnoredBeanFactory.ignoreFile(Project.DIRECTORY_STORE_FOLDER + "/workspace.xml", myProject));
}
}
+ if (!Registry.is("ide.hide.excluded.files") && !myExcludedConvertedToIgnored) {
+ convertExcludedToIgnored();
+ myExcludedConvertedToIgnored = true;
+ }
}
}
});
}
+ void convertExcludedToIgnored() {
+ for (DirectoryIndexExcludePolicy policy : DirectoryIndexExcludePolicy.EP_NAME.getExtensions(myProject)) {
+ for (VirtualFile file : policy.getExcludeRootsForProject()) {
+ addDirectoryToIgnoreImplicitly(file.getPath());
+ }
+ }
+
+ for (Module module : ModuleManager.getInstance(myProject).getModules()) {
+ for (String url : ModuleRootManager.getInstance(module).getExcludeRootUrls()) {
+ addDirectoryToIgnoreImplicitly(VfsUtilCore.urlToPath(url));
+ }
+ }
+ }
+
public void projectClosed() {
ProjectLevelVcsManager.getInstance(myProject).removeVcsListener(myVcsListener);
@@ -328,11 +358,12 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
/**
* update itself might produce actions done on AWT thread (invoked-after),
- * so waiting for its completion on AWT thread is not good
- *
- * runnable is invoked on AWT thread
+ * so waiting for its completion on AWT thread is not good runnable is invoked on AWT thread
*/
- public void invokeAfterUpdate(final Runnable afterUpdate, final InvokeAfterUpdateMode mode, @Nullable final String title, @Nullable final ModalityState state) {
+ public void invokeAfterUpdate(final Runnable afterUpdate,
+ final InvokeAfterUpdateMode mode,
+ @Nullable final String title,
+ @Nullable final ModalityState state) {
myUpdater.invokeAfterUpdate(afterUpdate, mode, title, null, state);
}
@@ -394,13 +425,13 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
synchronized (myDataLock) {
final IgnoredFilesHolder fileHolder = (IgnoredFilesHolder)myComposite.get(FileHolder.HolderType.IGNORED);
- for (Iterator<VcsDirtyScope> iterator = scopes.iterator(); iterator.hasNext();) {
- final VcsModifiableDirtyScope scope = (VcsModifiableDirtyScope) iterator.next();
+ for (Iterator<VcsDirtyScope> iterator = scopes.iterator(); iterator.hasNext(); ) {
+ final VcsModifiableDirtyScope scope = (VcsModifiableDirtyScope)iterator.next();
final VcsDirtyScopeModifier modifier = scope.getModifier();
if (modifier != null) {
fileHolder.notifyVcsStarted(scope.getVcs());
final Iterator<FilePath> filesIterator = modifier.getDirtyFilesIterator();
- for (; filesIterator.hasNext();) {
+ while (filesIterator.hasNext()) {
final FilePath dirtyFile = filesIterator.next();
if ((dirtyFile.getVirtualFile() != null) && isIgnoredFile(dirtyFile.getVirtualFile())) {
filesIterator.remove();
@@ -411,7 +442,7 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
final Collection<VirtualFile> roots = modifier.getAffectedVcsRoots();
for (VirtualFile root : roots) {
final Iterator<FilePath> dirIterator = modifier.getDirtyDirectoriesIterator(root);
- for (; dirIterator.hasNext(); ) {
+ while (dirIterator.hasNext()) {
final FilePath dir = dirIterator.next();
if ((dir.getVirtualFile() != null) && isIgnoredFile(dir.getVirtualFile())) {
dirIterator.remove();
@@ -428,10 +459,10 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
}
}
}
- catch(Exception ex) {
+ catch (Exception ex) {
LOG.error(ex);
}
- catch(AssertionError ex) {
+ catch (AssertionError ex) {
LOG.error(ex);
}
for (VirtualFile file : refreshFiles) {
@@ -443,7 +474,7 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
final DataHolder dataHolder;
final ProjectLevelVcsManager vcsManager = ProjectLevelVcsManager.getInstance(myProject);
- if (! vcsManager.hasActiveVcss()) return;
+ if (!vcsManager.hasActiveVcss()) return;
final VcsInvalidated invalidated = myDirtyScopeManager.retrieveScopes();
if (checkScopeIsEmpty(invalidated)) return;
@@ -458,14 +489,14 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
// mark for "modifier" that update started (it would create duplicates of modification commands done by user during update;
// after update of copies of objects is complete, it would apply the same modifications to copies.)
synchronized (myDataLock) {
- dataHolder = new DataHolder((FileHolderComposite) myComposite.copy(), myWorker.copy(), wasEverythingDirty);
+ dataHolder = new DataHolder((FileHolderComposite)myComposite.copy(), myWorker.copy(), wasEverythingDirty);
myModifier.enterUpdate();
if (wasEverythingDirty) {
myUpdateException = null;
myAdditionalInfo = null;
}
}
- final String scopeInString = (! LOG.isDebugEnabled()) ? "" : StringUtil.join(scopes, new Function<VcsDirtyScope, String>() {
+ final String scopeInString = (!LOG.isDebugEnabled()) ? "" : StringUtil.join(scopes, new Function<VcsDirtyScope, String>() {
@Override
public String fun(VcsDirtyScope scope) {
return scope.toString();
@@ -504,7 +535,7 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
myWorker.onAfterWorkerSwitch(oldWorker);
myModifier.setWorker(myWorker);
LOG.debug("refresh procedure finished, unversioned size: " +
- dataHolder.getComposite().getVFHolder(FileHolder.HolderType.UNVERSIONED).getSize() + "\n changes: " + myWorker);
+ dataHolder.getComposite().getVFHolder(FileHolder.HolderType.UNVERSIONED).getSize() + "\n changes: " + myWorker);
final boolean statusChanged = !myComposite.equals(dataHolder.getComposite());
myComposite = dataHolder.getComposite();
if (statusChanged) {
@@ -535,19 +566,20 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
catch (DisposedException e) {
// OK, we're finishing all the stuff now.
}
- catch(ProcessCanceledException e) {
+ catch (ProcessCanceledException e) {
// OK, we're finishing all the stuff now.
- } catch (RuntimeInterruptedException ignore) {
}
- catch(Exception ex) {
+ catch (RuntimeInterruptedException ignore) {
+ }
+ catch (Exception ex) {
LOG.error(ex);
}
- catch(AssertionError ex) {
+ catch (AssertionError ex) {
LOG.error(ex);
}
finally {
myDirtyScopeManager.changesProcessed();
-
+
synchronized (myDataLock) {
myDelayedNotificator.getProxyDispatcher().changeListUpdateDone();
myChangesViewManager.scheduleRefresh();
@@ -556,7 +588,7 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
}
private boolean checkScopeIsAllIgnored(VcsInvalidated invalidated) {
- if (! invalidated.isEverythingDirty()) {
+ if (!invalidated.isEverythingDirty()) {
filterOutIgnoredFiles(invalidated.getScopes());
if (invalidated.isEmpty()) {
return true;
@@ -586,7 +618,8 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
}
};
final UpdatingChangeListBuilder builder = new UpdatingChangeListBuilder(dataHolder.getChangeListWorker(),
- dataHolder.getComposite(), disposedGetter, myIgnoredIdeaLevel, gate);
+ dataHolder.getComposite(), disposedGetter, myIgnoredIdeaLevel,
+ gate);
for (final VcsDirtyScope scope : scopes) {
myUpdateChangesProgressIndicator.checkCanceled();
@@ -594,7 +627,7 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
final AbstractVcs vcs = scope.getVcs();
if (vcs == null) continue;
scope.setWasEverythingDirty(wasEverythingDirty);
- final VcsModifiableDirtyScope adjustedScope = vcs.adjustDirtyScope((VcsModifiableDirtyScope) scope);
+ final VcsModifiableDirtyScope adjustedScope = vcs.adjustDirtyScope((VcsModifiableDirtyScope)scope);
myChangesViewManager.setBusy(true);
dataHolder.notifyStartProcessingChanges(adjustedScope);
@@ -614,7 +647,8 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
final ContentRevisionCache cache = ProjectLevelVcsManager.getInstance(myProject).getContentRevisionCache();
if (invalidated.isEverythingDirty()) {
cache.clearAllCurrent();
- } else {
+ }
+ else {
cache.clearScope(invalidated.getScopes());
}
}
@@ -625,6 +659,7 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
public boolean isCanceled() {
return myUpdater.isStopped();
}
+
@Override
public void checkCanceled() {
checkIfDisposed();
@@ -651,7 +686,7 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
}
public void notifyStartProcessingChanges(@NotNull final VcsModifiableDirtyScope scope) {
- if (! myWasEverythingDirty) {
+ if (!myWasEverythingDirty) {
myComposite.cleanAndAdjustScope(scope);
myChangeListWorker.notifyStartProcessingChanges(scope);
}
@@ -661,7 +696,7 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
}
public void notifyDoneProcessingChanges() {
- if (! myWasEverythingDirty) {
+ if (!myWasEverythingDirty) {
myChangeListWorker.notifyDoneProcessingChanges(myDelayedNotificator.getProxyDispatcher());
}
}
@@ -695,11 +730,14 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
handleUpdateException(e);
}
}
- } catch (ProcessCanceledException ignore) {
- } catch (Throwable t) {
+ }
+ catch (ProcessCanceledException ignore) {
+ }
+ catch (Throwable t) {
LOG.debug(t);
Rethrow.reThrowRuntime(t);
- } finally {
+ }
+ finally {
if (!myUpdater.isStopped()) {
dataHolder.notifyDoneProcessingChanges();
}
@@ -748,8 +786,7 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
}
/**
- * @deprecated
- * this method made equivalent to {@link #getChangeListsCopy()} so to don't be confused by method name,
+ * @deprecated this method made equivalent to {@link #getChangeListsCopy()} so to don't be confused by method name,
* better use {@link #getChangeListsCopy()}
*/
@NotNull
@@ -816,13 +853,14 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
Map<VirtualFile, LogicalLock> getLogicallyLockedFolders() {
synchronized (myDataLock) {
- return new HashMap<VirtualFile, LogicalLock>(((LogicallyLockedHolder) myComposite.get(FileHolder.HolderType.LOGICALLY_LOCKED)).getMap());
+ return new HashMap<VirtualFile, LogicalLock>(
+ ((LogicallyLockedHolder)myComposite.get(FileHolder.HolderType.LOGICALLY_LOCKED)).getMap());
}
}
public boolean isLogicallyLocked(final VirtualFile file) {
synchronized (myDataLock) {
- return ((LogicallyLockedHolder) myComposite.get(FileHolder.HolderType.LOGICALLY_LOCKED)).containsKey(file);
+ return ((LogicallyLockedHolder)myComposite.get(FileHolder.HolderType.LOGICALLY_LOCKED)).containsKey(file);
}
}
@@ -847,7 +885,7 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
@Nullable
Map<VirtualFile, String> getSwitchedRoots() {
synchronized (myDataLock) {
- return ((SwitchedFileHolder) myComposite.get(FileHolder.HolderType.ROOT_SWITCH)).getFilesMapCopy();
+ return ((SwitchedFileHolder)myComposite.get(FileHolder.HolderType.ROOT_SWITCH)).getFilesMapCopy();
}
}
@@ -856,7 +894,7 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
return myUpdateException;
}
}
-
+
public Factory<JComponent> getAdditionalUpdateInfo() {
synchronized (myDataLock) {
return myAdditionalInfo;
@@ -937,7 +975,7 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
synchronized (myDataLock) {
for (Map.Entry<String, List<Change>> entry : map.entrySet()) {
final List<Change> changes = entry.getValue();
- for (Iterator<Change> iterator = changes.iterator(); iterator.hasNext();) {
+ for (Iterator<Change> iterator = changes.iterator(); iterator.hasNext(); ) {
final Change change = iterator.next();
if (getChangeList(change) != null) {
// was not actually rolled back
@@ -948,7 +986,7 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
}
for (String listName : map.keySet()) {
final LocalChangeList byName = myWorker.getCopyByName(listName);
- if (byName != null && byName.getChanges().isEmpty() && ! byName.isDefault() && ! byName.isReadOnly()) {
+ if (byName != null && byName.getChanges().isEmpty() && !byName.isDefault() && !byName.isReadOnly()) {
myWorker.removeChangeList(listName);
}
}
@@ -1005,15 +1043,14 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
}
/**
- * @deprecated
- * better use normal comparison, with equals
+ * @deprecated better use normal comparison, with equals
*/
@Nullable
public LocalChangeList getIdentityChangeList(Change change) {
synchronized (myDataLock) {
final List<LocalChangeList> lists = myWorker.getListsCopy();
for (LocalChangeList list : lists) {
- for(Change oldChange: list.getChanges()) {
+ for (Change oldChange : list.getChanges()) {
if (oldChange == change) {
return list;
}
@@ -1168,7 +1205,7 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
if (exceptions.size() > 0) {
StringBuilder message = new StringBuilder(VcsBundle.message("error.adding.files.prompt"));
- for(VcsException ex: exceptions) {
+ for (VcsException ex : exceptions) {
message.append("\n").append(ex.getMessage());
}
Messages.showErrorDialog(myProject, message.toString(), VcsBundle.message("error.adding.files.title"));
@@ -1189,7 +1226,7 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
synchronized (myDataLock) {
List<Change> changesToMove = new ArrayList<Change>();
final LocalChangeList defaultList = getDefaultChangeList();
- for(Change change: defaultList.getChanges()) {
+ for (Change change : defaultList.getChanges()) {
final ContentRevision afterRevision = change.getAfterRevision();
if (afterRevision != null) {
VirtualFile vFile = afterRevision.getFile().getVirtualFile();
@@ -1208,8 +1245,9 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
myChangesViewManager.scheduleRefresh();
}
- }, InvokeAfterUpdateMode.BACKGROUND_NOT_CANCELLABLE_NOT_AWT, VcsBundle.message("change.lists.manager.add.unversioned"), null);
- } else {
+ }, InvokeAfterUpdateMode.BACKGROUND_NOT_CANCELLABLE_NOT_AWT, VcsBundle.message("change.lists.manager.add.unversioned"), null);
+ }
+ else {
myChangesViewManager.scheduleRefresh();
}
}
@@ -1238,8 +1276,8 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
private boolean doCommit(final LocalChangeList changeList, final List<Change> changes, final boolean synchronously) {
FileDocumentManager.getInstance().saveAllDocuments();
return new CommitHelper(myProject, changeList, changes, changeList.getName(),
- StringUtil.isEmpty(changeList.getComment()) ? changeList.getName() : changeList.getComment(),
- new ArrayList<CheckinHandler>(), false, synchronously, NullableFunction.NULL, null).doCommit();
+ StringUtil.isEmpty(changeList.getComment()) ? changeList.getName() : changeList.getComment(),
+ new ArrayList<CheckinHandler>(), false, synchronously, NullableFunction.NULL, null).doCommit();
}
public void commitChangesSynchronously(LocalChangeList changeList, List<Change> changes) {
@@ -1252,20 +1290,21 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
@SuppressWarnings({"unchecked"})
public void readExternal(Element element) throws InvalidDataException {
- if (! myProject.isDefault()) {
+ if (!myProject.isDefault()) {
synchronized (myDataLock) {
myIgnoredIdeaLevel.clear();
new ChangeListManagerSerialization(myIgnoredIdeaLevel, myWorker).readExternal(element);
- if ((! myWorker.isEmpty()) && getDefaultChangeList() == null) {
+ if ((!myWorker.isEmpty()) && getDefaultChangeList() == null) {
setDefaultChangeList(myWorker.getListsCopy().get(0));
}
}
+ myExcludedConvertedToIgnored = Boolean.parseBoolean(JDOMExternalizerUtil.readField(element, EXCLUDED_CONVERTED_TO_IGNORED_OPTION));
myConflictTracker.loadState(element);
}
}
public void writeExternal(Element element) throws WriteExternalException {
- if (! myProject.isDefault()) {
+ if (!myProject.isDefault()) {
final IgnoredFilesComponent ignoredFilesComponent;
final ChangeListWorker worker;
synchronized (myDataLock) {
@@ -1273,6 +1312,9 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
worker = myWorker.copy();
}
new ChangeListManagerSerialization(ignoredFilesComponent, worker).writeExternal(element);
+ if (myExcludedConvertedToIgnored) {
+ JDOMExternalizerUtil.writeField(element, EXCLUDED_CONVERTED_TO_IGNORED_OPTION, String.valueOf(true));
+ }
myConflictTracker.saveState(element);
}
}
@@ -1316,10 +1358,11 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
}
if (vf.isDirectory()) {
myDirs.add(vf);
- } else {
+ }
+ else {
myFiles.add(vf);
}
- ++ myCnt;
+ ++myCnt;
}
}
@@ -1327,7 +1370,8 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
final VcsDirtyScopeManager vcsDirtyScopeManager = VcsDirtyScopeManager.getInstance(myProject);
if (myEveryThing) {
vcsDirtyScopeManager.markEverythingDirty();
- } else {
+ }
+ else {
vcsDirtyScopeManager.filesDirty(myFiles, myDirs);
}
}
@@ -1338,12 +1382,21 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
scheduleUnversionedUpdate();
}
+ @Override
+ public void addDirectoryToIgnoreImplicitly(@NotNull String path) {
+ myIgnoredIdeaLevel.addIgnoredDirectoryImplicitly(path, myProject);
+ }
+
+ public IgnoredFilesComponent getIgnoredFilesComponent() {
+ return myIgnoredIdeaLevel;
+ }
+
private void scheduleUnversionedUpdate() {
final MyDirtyFilesScheduler scheduler = new MyDirtyFilesScheduler(myProject);
synchronized (myDataLock) {
final VirtualFileHolder unversionedHolder = myComposite.getVFHolder(FileHolder.HolderType.UNVERSIONED);
- final IgnoredFilesHolder ignoredHolder = (IgnoredFilesHolder) myComposite.get(FileHolder.HolderType.IGNORED);
+ final IgnoredFilesHolder ignoredHolder = (IgnoredFilesHolder)myComposite.get(FileHolder.HolderType.IGNORED);
scheduler.accept(unversionedHolder.getFiles());
scheduler.accept(ignoredHolder.values());
@@ -1368,7 +1421,7 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
}
private void exchangeWithIgnored(FileHolderComposite composite, VirtualFileHolder vfHolder, List<VirtualFile> unversionedFiles) {
- for(VirtualFile file: unversionedFiles) {
+ for (VirtualFile file : unversionedFiles) {
if (isIgnoredFile(file)) {
vfHolder.removeFile(file);
composite.getIgnoredFileHolder().addFile(file);
@@ -1594,11 +1647,11 @@ public class ChangeListManagerImpl extends ChangeListManagerEx implements Projec
if (freezeReason != null) {
if (modalTitle != null) {
Messages.showErrorDialog(myProject, freezeReason, modalTitle);
- } else {
+ }
+ else {
VcsBalloonProblemNotifier.showOverChangesView(myProject, freezeReason, MessageType.WARNING);
}
}
return freezeReason != null;
}
-
}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerSerialization.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerSerialization.java
index a4c30e62bda5..0e20b4140b56 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerSerialization.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerSerialization.java
@@ -22,12 +22,10 @@ import com.intellij.openapi.util.WriteExternalException;
import com.intellij.openapi.util.text.StringUtil;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import java.io.File;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
+import java.util.*;
class ChangeListManagerSerialization {
@NonNls static final String ATT_ID = "id";
@@ -44,6 +42,8 @@ class ChangeListManagerSerialization {
@NonNls static final String NODE_LIST = "list";
@NonNls static final String NODE_IGNORED = "ignored";
@NonNls static final String NODE_CHANGE = "change";
+ @NonNls static final String MANUALLY_REMOVED_FROM_IGNORED = "manually-removed-from-ignored";
+ @NonNls static final String DIRECTORY_TAG = "directory";
private final IgnoredFilesComponent myIgnoredIdeaLevel;
private final ChangeListWorker myWorker;
@@ -60,9 +60,17 @@ class ChangeListManagerSerialization {
readChangeList(listNode);
}
final List<Element> ignoredNodes = element.getChildren(NODE_IGNORED);
- for (Element ignoredNode: ignoredNodes) {
+ for (Element ignoredNode : ignoredNodes) {
readFileToIgnore(ignoredNode);
}
+ Element manuallyRemovedFromIgnoredTag = element.getChild(MANUALLY_REMOVED_FROM_IGNORED);
+ Set<String> manuallyRemovedFromIgnoredPaths = new HashSet<String>();
+ if (manuallyRemovedFromIgnoredTag != null) {
+ for (Element tag : manuallyRemovedFromIgnoredTag.getChildren(DIRECTORY_TAG)) {
+ manuallyRemovedFromIgnoredPaths.add(tag.getAttributeValue(ATT_PATH));
+ }
+ }
+ myIgnoredIdeaLevel.setDirectoriesManuallyRemovedFromIgnored(manuallyRemovedFromIgnoredPaths);
}
private void readChangeList(final Element listNode) {
@@ -90,7 +98,6 @@ class ChangeListManagerSerialization {
if (ATT_VALUE_TRUE.equals(listNode.getAttributeValue(ATT_READONLY))) {
list.setReadOnly(true);
}
-
}
private void readFileToIgnore(final Element ignoredNode) {
@@ -123,7 +130,10 @@ class ChangeListManagerSerialization {
listNode.setAttribute(ATT_ID, list.getId());
listNode.setAttribute(ATT_NAME, list.getName());
- listNode.setAttribute(ATT_COMMENT, list.getComment());
+ String comment = list.getComment();
+ if (comment != null) {
+ listNode.setAttribute(ATT_COMMENT, comment);
+ }
List<Change> changes = new ArrayList<Change>(list.getChanges());
Collections.sort(changes, new ChangeComparator());
for (Change change : changes) {
@@ -131,26 +141,35 @@ class ChangeListManagerSerialization {
}
}
final IgnoredFileBean[] filesToIgnore = myIgnoredIdeaLevel.getFilesToIgnore();
- for(IgnoredFileBean bean: filesToIgnore) {
- Element fileNode = new Element(NODE_IGNORED);
- element.addContent(fileNode);
- String path = bean.getPath();
- if (path != null) {
- fileNode.setAttribute("path", path);
- }
- String mask = bean.getMask();
- if (mask != null) {
- fileNode.setAttribute("mask", mask);
- }
+ for (IgnoredFileBean bean : filesToIgnore) {
+ Element fileNode = new Element(NODE_IGNORED);
+ element.addContent(fileNode);
+ String path = bean.getPath();
+ if (path != null) {
+ fileNode.setAttribute("path", path);
+ }
+ String mask = bean.getMask();
+ if (mask != null) {
+ fileNode.setAttribute("mask", mask);
}
+ }
+ Set<String> manuallyRemovedFromIgnored = myIgnoredIdeaLevel.getDirectoriesManuallyRemovedFromIgnored();
+ if (!manuallyRemovedFromIgnored.isEmpty()) {
+ Element list = new Element(MANUALLY_REMOVED_FROM_IGNORED);
+ for (String path : manuallyRemovedFromIgnored) {
+ list.addContent(new Element(DIRECTORY_TAG).setAttribute(ATT_PATH, path));
+ }
+ element.addContent(list);
+ }
}
private static class ChangeComparator implements Comparator<Change> {
@Override
- public int compare(Change o1, Change o2) {
+ public int compare(@NotNull Change o1, @NotNull Change o2) {
return Comparing.compare(o1.toString(), o2.toString());
}
}
+
private static void writeChange(final Element listNode, final Change change) {
Element changeNode = new Element(NODE_CHANGE);
listNode.addContent(changeNode);
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/FragmentedContent.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/FragmentedContent.java
index 6d13d21a996c..f81c5069718b 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/FragmentedContent.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/FragmentedContent.java
@@ -16,7 +16,10 @@
package com.intellij.openapi.vcs.changes;
import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.vcs.FileStatus;
+import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.BeforeAfter;
import java.util.List;
@@ -30,13 +33,41 @@ public class FragmentedContent {
private final Document myBefore;
private final Document myAfter;
private final List<BeforeAfter<TextRange>> myRanges;
- private boolean myOneSide;
- private boolean myIsAddition;
- public FragmentedContent(Document before, Document after, List<BeforeAfter<TextRange>> ranges) {
+ private final boolean myOneSide;
+ private final boolean myIsAddition;
+
+ private final VirtualFile myFileBefore;
+ private final VirtualFile myFileAfter;
+ private final FileType myFileTypeBefore;
+ private final FileType myFileTypeAfter;
+
+ public FragmentedContent(Document before, Document after, List<BeforeAfter<TextRange>> ranges, Change change) {
myBefore = before;
myAfter = after;
myRanges = ranges;
+
+ final FileStatus fs = change.getFileStatus();
+ myIsAddition = FileStatus.ADDED.equals(fs);
+ myOneSide = FileStatus.ADDED.equals(fs) || FileStatus.DELETED.equals(fs);
+
+ if (change.getBeforeRevision() != null) {
+ myFileBefore = change.getBeforeRevision().getFile().getVirtualFile();
+ myFileTypeBefore = change.getBeforeRevision().getFile().getFileType();
+ }
+ else {
+ myFileBefore = null;
+ myFileTypeBefore = null;
+ }
+
+ if (change.getAfterRevision() != null) {
+ myFileAfter = change.getAfterRevision().getFile().getVirtualFile();
+ myFileTypeAfter = change.getAfterRevision().getFile().getFileType();
+ }
+ else {
+ myFileAfter = null;
+ myFileTypeAfter = null;
+ }
}
public Document getBefore() {
@@ -50,7 +81,7 @@ public class FragmentedContent {
public List<BeforeAfter<TextRange>> getRanges() {
return myRanges;
}
-
+
public int getSize() {
return myRanges.size();
}
@@ -59,15 +90,23 @@ public class FragmentedContent {
return myOneSide;
}
- public void setOneSide(boolean oneSide) {
- myOneSide = oneSide;
- }
-
public boolean isAddition() {
return myIsAddition;
}
- public void setIsAddition(boolean isAddition) {
- myIsAddition = isAddition;
+ public VirtualFile getFileBefore() {
+ return myFileBefore;
+ }
+
+ public VirtualFile getFileAfter() {
+ return myFileAfter;
+ }
+
+ public FileType getFileTypeBefore() {
+ return myFileTypeBefore;
+ }
+
+ public FileType getFileTypeAfter() {
+ return myFileTypeAfter;
}
}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/FragmentedDiffRequestFromChange.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/FragmentedDiffRequestFromChange.java
index 2f3788ae509c..77dd9b3f42b3 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/FragmentedDiffRequestFromChange.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/FragmentedDiffRequestFromChange.java
@@ -81,10 +81,7 @@ public class FragmentedDiffRequestFromChange {
}
List<BeforeAfter<TextRange>> ranges = calculator.getRanges();
if (ranges == null || ranges.isEmpty()) return null;
- FragmentedContent fragmentedContent = new FragmentedContent(calculator.getOldDocument(), calculator.getDocument(), ranges);
- final FileStatus fs = change.getFileStatus();
- fragmentedContent.setIsAddition(FileStatus.ADDED.equals(fs));
- fragmentedContent.setOneSide(FileStatus.ADDED.equals(fs) || FileStatus.DELETED.equals(fs));
+ FragmentedContent fragmentedContent = new FragmentedContent(calculator.getOldDocument(), calculator.getDocument(), ranges, change);
VirtualFile file = filePath.getVirtualFile();
if (file == null) {
filePath.hardRefresh();
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/IgnoredFilesComponent.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/IgnoredFilesComponent.java
index 5c8ac2a6b623..b2eaa1f2e6e3 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/IgnoredFilesComponent.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/IgnoredFilesComponent.java
@@ -16,6 +16,7 @@
package com.intellij.openapi.vcs.changes;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.openapi.vfs.newvfs.BulkFileListener;
@@ -27,6 +28,7 @@ import java.util.*;
public class IgnoredFilesComponent {
private final Set<IgnoredFileBean> myFilesToIgnore;
private final Map<String, IgnoredFileBean> myFilesMap;
+ private final Set<String> myDirectoriesManuallyRemovedFromIgnored;
public IgnoredFilesComponent(final Project project, final boolean registerListener) {
myFilesToIgnore = new LinkedHashSet<IgnoredFileBean>();
@@ -40,20 +42,53 @@ public class IgnoredFilesComponent {
}
});
}
+ myDirectoriesManuallyRemovedFromIgnored = new HashSet<String>();
}
public IgnoredFilesComponent(final IgnoredFilesComponent other) {
myFilesToIgnore = new LinkedHashSet<IgnoredFileBean>(other.myFilesToIgnore);
myFilesMap = new HashMap<String, IgnoredFileBean>(other.myFilesMap);
+ myDirectoriesManuallyRemovedFromIgnored = new HashSet<String>(other.myDirectoriesManuallyRemovedFromIgnored);
}
public void add(final IgnoredFileBean... filesToIgnore) {
- synchronized(myFilesToIgnore) {
+ synchronized (myFilesToIgnore) {
Collections.addAll(myFilesToIgnore, filesToIgnore);
addIgnoredFiles(filesToIgnore);
}
}
+ public Set<String> getDirectoriesManuallyRemovedFromIgnored() {
+ return Collections.unmodifiableSet(myDirectoriesManuallyRemovedFromIgnored);
+ }
+
+ public void setDirectoriesManuallyRemovedFromIgnored(Set<String> directories) {
+ myDirectoriesManuallyRemovedFromIgnored.clear();
+ myDirectoriesManuallyRemovedFromIgnored.addAll(directories);
+ }
+
+ public void addIgnoredDirectoryImplicitly(@NotNull String path, @NotNull Project project) {
+ synchronized (myFilesToIgnore) {
+ if (myDirectoriesManuallyRemovedFromIgnored.contains(path) || myDirectoriesManuallyRemovedFromIgnored.contains(path + "/")) {
+ return;
+ }
+ for (IgnoredFileBean bean : myFilesToIgnore) {
+ if (bean.getType() == IgnoreSettingsType.UNDER_DIR && FileUtil.isAncestor(bean.getPath(), path, false)) {
+ return;
+ }
+ }
+ List<IgnoredFileBean> toRemove = new ArrayList<IgnoredFileBean>();
+ for (IgnoredFileBean bean : myFilesToIgnore) {
+ if ((bean.getType() == IgnoreSettingsType.UNDER_DIR || bean.getType() == IgnoreSettingsType.FILE) &&
+ FileUtil.isAncestor(path, bean.getPath(), false)) {
+ toRemove.add(bean);
+ }
+ }
+ myFilesToIgnore.removeAll(toRemove);
+ myFilesToIgnore.add(IgnoredBeanFactory.ignoreUnderDirectory(path, project));
+ }
+ }
+
private void addIgnoredFiles(final IgnoredFileBean... filesToIgnore) {
for (IgnoredFileBean bean : filesToIgnore) {
if (IgnoreSettingsType.FILE.equals(bean.getType())) {
@@ -73,6 +108,7 @@ public class IgnoredFilesComponent {
myFilesMap.clear();
}
}
+
public boolean isEmpty() {
synchronized (myFilesToIgnore) {
return myFilesToIgnore.isEmpty();
@@ -80,7 +116,7 @@ public class IgnoredFilesComponent {
}
public void set(final IgnoredFileBean... filesToIgnore) {
- synchronized(myFilesToIgnore) {
+ synchronized (myFilesToIgnore) {
myFilesToIgnore.clear();
Collections.addAll(myFilesToIgnore, filesToIgnore);
myFilesMap.clear();
@@ -89,7 +125,7 @@ public class IgnoredFilesComponent {
}
public IgnoredFileBean[] getFilesToIgnore() {
- synchronized(myFilesToIgnore) {
+ synchronized (myFilesToIgnore) {
return myFilesToIgnore.toArray(new IgnoredFileBean[myFilesToIgnore.size()]);
}
}
@@ -103,14 +139,14 @@ public class IgnoredFilesComponent {
}
public boolean isIgnoredFile(@NotNull VirtualFile file) {
- synchronized(myFilesToIgnore) {
+ synchronized (myFilesToIgnore) {
if (myFilesToIgnore.size() == 0) return false;
final String path = FilePathsHelper.convertPath(file);
final IgnoredFileBean fileBean = myFilesMap.get(path);
if (fileBean != null && fileBean.matchesFile(file)) return true;
- for(IgnoredFileBean bean: myFilesToIgnore) {
+ for (IgnoredFileBean bean : myFilesToIgnore) {
if (bean.matchesFile(file)) return true;
}
return false;
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/LocalChangeListImpl.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/LocalChangeListImpl.java
index c413cca246c3..1d310d5a023a 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/LocalChangeListImpl.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/LocalChangeListImpl.java
@@ -1,14 +1,13 @@
package com.intellij.openapi.vcs.changes;
-import com.intellij.lifecycle.PeriodicalTasksCloser;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.roots.FileIndexFacade;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vcs.ProjectLevelVcsManager;
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.OpenTHashSet;
@@ -147,12 +146,11 @@ public class LocalChangeListImpl extends LocalChangeList {
createReadChangesCache();
final Collection<Change> result = new ArrayList<Change>();
myChangesBeforeUpdate = new OpenTHashSet<Change>(myChanges);
- final FileIndexFacade fileIndex = PeriodicalTasksCloser.getInstance().safeGetService(project, FileIndexFacade.class);
for (Change oldBoy : myChangesBeforeUpdate) {
final ContentRevision before = oldBoy.getBeforeRevision();
final ContentRevision after = oldBoy.getAfterRevision();
if (scope == null || before != null && scope.belongsTo(before.getFile()) || after != null && scope.belongsTo(after.getFile())
- || isIgnoredChange(oldBoy, fileIndex)) {
+ || isIgnoredChange(oldBoy, project)) {
result.add(oldBoy);
myChanges.remove(oldBoy);
myReadChangesCache = null;
@@ -161,18 +159,21 @@ public class LocalChangeListImpl extends LocalChangeList {
return result;
}
- private static boolean isIgnoredChange(final Change change, final FileIndexFacade fileIndex) {
- boolean beforeRevIgnored = change.getBeforeRevision() == null || isIgnoredRevision(change.getBeforeRevision(), fileIndex);
- boolean afterRevIgnored = change.getAfterRevision() == null || isIgnoredRevision(change.getAfterRevision(), fileIndex);
+ private static boolean isIgnoredChange(@NotNull Change change, @NotNull Project project) {
+ boolean beforeRevIgnored = change.getBeforeRevision() == null || isIgnoredRevision(change.getBeforeRevision(), project);
+ boolean afterRevIgnored = change.getAfterRevision() == null || isIgnoredRevision(change.getAfterRevision(), project);
return beforeRevIgnored && afterRevIgnored;
}
- private static boolean isIgnoredRevision(final ContentRevision revision, final FileIndexFacade fileIndex) {
+ private static boolean isIgnoredRevision(final @NotNull ContentRevision revision, final @NotNull Project project) {
return ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
@Override
public Boolean compute() {
+ if (project.isDisposed()) {
+ return false;
+ }
VirtualFile vFile = revision.getFile().getVirtualFile();
- return vFile != null && fileIndex.isExcludedFile(vFile);
+ return vFile != null && ProjectLevelVcsManager.getInstance(project).isIgnored(vFile);
}
});
}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/PreparedFragmentedContent.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/PreparedFragmentedContent.java
index 2c2d0634b709..6e8a1a04d135 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/PreparedFragmentedContent.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/PreparedFragmentedContent.java
@@ -18,6 +18,8 @@ package com.intellij.openapi.vcs.changes;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diff.DiffContent;
import com.intellij.openapi.diff.SimpleContent;
+import com.intellij.openapi.diff.impl.DiffHighlighterFactory;
+import com.intellij.openapi.diff.impl.DiffHighlighterFactoryImpl;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.highlighter.*;
@@ -35,6 +37,7 @@ import com.intellij.openapi.vcs.ProjectLevelVcsManager;
import com.intellij.openapi.vcs.VcsConfiguration;
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
import com.intellij.openapi.vcs.impl.ContentRevisionCache;
+import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.BeforeAfter;
import com.intellij.util.Consumer;
@@ -140,6 +143,9 @@ public class PreparedFragmentedContent {
fragmentedContent.getBefore(), fragmentedContent.getAfter());
// add "artificial" empty lines
+ final Document document = fragmentedContent.getBefore();
+ final Document document1 = fragmentedContent.getAfter();
+
// line starts
BeforeAfter<Integer> lines = new BeforeAfter<Integer>(0, 0);
for (BeforeAfter<TextRange> lineNumbers : expandedRanges) {
@@ -155,7 +161,6 @@ public class PreparedFragmentedContent {
oldConvertor.put(lines.getBefore(), lineNumbers.getBefore().getStartOffset());
newConvertor.put(lines.getAfter(), lineNumbers.getAfter().getStartOffset());
- final Document document = fragmentedContent.getBefore();
if (sbOld.length() > 0) {
sbOld.append('\n');
}
@@ -164,7 +169,6 @@ public class PreparedFragmentedContent {
myBeforeFragments.add(beforeRange);
sbOld.append(document.getText(beforeRange));
- final Document document1 = fragmentedContent.getAfter();
if (sbNew.length() > 0) {
sbNew.append('\n');
}
@@ -180,7 +184,23 @@ public class PreparedFragmentedContent {
myLineRanges.add(new BeforeAfter<Integer>(lines.getBefore() == 0 ? 0 : lines.getBefore() - 1,
lines.getAfter() == 0 ? 0 : lines.getAfter() - 1));
- setHighlighters(fragmentedContent.getBefore(), fragmentedContent.getAfter(), expandedRanges);
+ if (!expandedRanges.isEmpty()) {
+ BeforeAfter<TextRange> last = expandedRanges.get(expandedRanges.size() - 1);
+ if (sbOld.length() > 0) {
+ if (document.getLineEndOffset(last.getBefore().getEndOffset()) != document.getTextLength()) {
+ sbOld.append('\n');
+ oldConvertor.emptyLine(lines.getBefore());
+ }
+ }
+ if (sbNew.length() > 0) {
+ if (document1.getLineEndOffset(last.getAfter().getEndOffset()) != document1.getTextLength()) {
+ sbNew.append('\n');
+ newConvertor.emptyLine(lines.getAfter());
+ }
+ }
+ }
+
+ setHighlighters(fragmentedContent.getBefore(), fragmentedContent.getAfter(), expandedRanges, fragmentedContent);
setTodoHighlighting(fragmentedContent.getBefore(), fragmentedContent.getAfter());
}
});
@@ -323,29 +343,37 @@ public class PreparedFragmentedContent {
}
private void setHighlighters(final Document oldDocument, final Document document,
- List<BeforeAfter<TextRange>> ranges) {
- EditorHighlighterFactory editorHighlighterFactory = EditorHighlighterFactory.getInstance();
- final SyntaxHighlighter syntaxHighlighter = SyntaxHighlighterFactory.getSyntaxHighlighter(myFileType, myProject, null);
- final EditorHighlighter highlighter =
- editorHighlighterFactory.createEditorHighlighter(syntaxHighlighter, EditorColorsManager.getInstance().getGlobalScheme());
-
+ List<BeforeAfter<TextRange>> ranges, FragmentedContent fragmentedContent) {
+ EditorHighlighter highlighter = createHighlighter(fragmentedContent.getFileTypeBefore(),
+ fragmentedContent.getFileBefore(),
+ fragmentedContent.getFileAfter(), myProject).createHighlighter();
highlighter.setEditor(new LightHighlighterClient(oldDocument, myProject));
highlighter.setText(oldDocument.getText());
HighlighterIterator iterator = highlighter.createIterator(ranges.get(0).getBefore().getStartOffset());
- FragmentedEditorHighlighter beforeHighlighter =
- new FragmentedEditorHighlighter(iterator, getBeforeFragments(), 1, true);
+ FragmentedEditorHighlighter beforeHighlighter = new FragmentedEditorHighlighter(iterator, getBeforeFragments(), 1, true);
setBeforeHighlighter(beforeHighlighter);
- final EditorHighlighter highlighter1 =
- editorHighlighterFactory.createEditorHighlighter(syntaxHighlighter, EditorColorsManager.getInstance().getGlobalScheme());
+ EditorHighlighter highlighter1 = createHighlighter(fragmentedContent.getFileTypeAfter(),
+ fragmentedContent.getFileAfter(),
+ fragmentedContent.getFileBefore(), myProject).createHighlighter();
highlighter1.setEditor(new LightHighlighterClient(document, myProject));
highlighter1.setText(document.getText());
HighlighterIterator iterator1 = highlighter1.createIterator(ranges.get(0).getAfter().getStartOffset());
- FragmentedEditorHighlighter afterHighlighter =
- new FragmentedEditorHighlighter(iterator1, getAfterFragments(), 1, true);
+ FragmentedEditorHighlighter afterHighlighter = new FragmentedEditorHighlighter(iterator1, getAfterFragments(), 1, true);
setAfterHighlighter(afterHighlighter);
}
+ private DiffHighlighterFactory createHighlighter(FileType contentType,
+ VirtualFile file,
+ VirtualFile otherFile,
+ Project project) {
+ VirtualFile baseFile = file;
+ if (baseFile == null) baseFile = otherFile;
+ if (contentType == null) contentType = myFileType;
+
+ return new DiffHighlighterFactoryImpl(contentType, baseFile, project);
+ }
+
private void setTodoHighlighting(final Document oldDocument, final Document document) {
final ContentRevisionCache cache = ProjectLevelVcsManager.getInstance(myProject).getContentRevisionCache();
final List<Pair<TextRange,TextAttributes>> beforeTodoRanges = myBeforeNumber == null ? Collections.<Pair<TextRange,TextAttributes>>emptyList() :
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/UpdatingChangeListBuilder.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/UpdatingChangeListBuilder.java
index fdc079641b68..d06c8f888ad7 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/UpdatingChangeListBuilder.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/UpdatingChangeListBuilder.java
@@ -15,16 +15,15 @@
*/
package com.intellij.openapi.vcs.changes;
-import com.intellij.lifecycle.PeriodicalTasksCloser;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileTypes.FileTypeManager;
-import com.intellij.openapi.roots.FileIndexFacade;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Factory;
import com.intellij.openapi.util.Getter;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.FilePathImpl;
+import com.intellij.openapi.vcs.ProjectLevelVcsManager;
import com.intellij.openapi.vcs.VcsKey;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.Nullable;
@@ -40,7 +39,7 @@ class UpdatingChangeListBuilder implements ChangelistBuilder {
private VcsDirtyScope myScope;
private FoldersCutDownWorker myFoldersCutDownWorker;
private final IgnoredFilesComponent myIgnoredFilesComponent;
- private final FileIndexFacade myIndex;
+ private final ProjectLevelVcsManager myVcsManager;
private final ChangeListManagerGate myGate;
private Factory<JComponent> myAdditionalInfo;
@@ -53,7 +52,7 @@ class UpdatingChangeListBuilder implements ChangelistBuilder {
myDisposedGetter = disposedGetter;
myIgnoredFilesComponent = ignoredFilesComponent;
myGate = gate;
- myIndex = PeriodicalTasksCloser.getInstance().safeGetService(changeListWorker.getProject(), FileIndexFacade.class);
+ myVcsManager = ProjectLevelVcsManager.getInstance(changeListWorker.getProject());
}
private void checkIfDisposed() {
@@ -117,12 +116,12 @@ class UpdatingChangeListBuilder implements ChangelistBuilder {
myChangeListWorker.removeRegisteredChangeFor(path);
}
- private boolean isExcluded(final VirtualFile file) {
+ private boolean isIgnoredByVcs(final VirtualFile file) {
return ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
@Override
public Boolean compute() {
checkIfDisposed();
- return myIndex.isExcludedFile(file);
+ return myVcsManager.isIgnored(file);
}
});
}
@@ -133,7 +132,7 @@ class UpdatingChangeListBuilder implements ChangelistBuilder {
}
if (file == null) return;
checkIfDisposed();
- if (isExcluded(file)) return;
+ if (isIgnoredByVcs(file)) return;
if (myScope.belongsTo(new FilePathImpl(file))) {
if (myIgnoredFilesComponent.isIgnoredFile(file)) {
myComposite.getIgnoredFileHolder().addFile(file);
@@ -165,7 +164,7 @@ class UpdatingChangeListBuilder implements ChangelistBuilder {
public void processModifiedWithoutCheckout(final VirtualFile file) {
if (file == null) return;
checkIfDisposed();
- if (isExcluded(file)) return;
+ if (isIgnoredByVcs(file)) return;
if (myScope.belongsTo(new FilePathImpl(file))) {
if (LOG.isDebugEnabled()) {
LOG.debug("processModifiedWithoutCheckout " + file);
@@ -177,7 +176,7 @@ class UpdatingChangeListBuilder implements ChangelistBuilder {
public void processIgnoredFile(final VirtualFile file) {
if (file == null) return;
checkIfDisposed();
- if (isExcluded(file)) return;
+ if (isIgnoredByVcs(file)) return;
if (myScope.belongsTo(new FilePathImpl(file))) {
IgnoredFilesHolder ignoredFilesHolder = myComposite.getIgnoredFileHolder();
if (ignoredFilesHolder instanceof IgnoredFilesCompositeHolder) {
@@ -212,7 +211,7 @@ class UpdatingChangeListBuilder implements ChangelistBuilder {
public void processSwitchedFile(final VirtualFile file, final String branch, final boolean recursive) {
if (file == null) return;
checkIfDisposed();
- if (isExcluded(file)) return;
+ if (isIgnoredByVcs(file)) return;
if (myScope.belongsTo(new FilePathImpl(file))) {
myChangeListWorker.addSwitched(file, branch, recursive);
}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsDirtyScopeImpl.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsDirtyScopeImpl.java
index eb44d591d605..c8617dc5f347 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsDirtyScopeImpl.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsDirtyScopeImpl.java
@@ -34,6 +34,7 @@ import com.intellij.util.containers.Convertor;
import com.intellij.util.containers.MultiMap;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
@@ -75,14 +76,14 @@ public class VcsDirtyScopeImpl extends VcsModifiableDirtyScope {
return ContainerUtil.concatIterators(iteratorList);
}
- @Nullable
+ @NotNull
@Override
public Iterator<FilePath> getDirtyDirectoriesIterator(final VirtualFile root) {
final THashSet<FilePath> filePaths = myDirtyDirectoriesRecursively.get(root);
if (filePaths != null) {
return filePaths.iterator();
}
- return null;
+ return ContainerUtil.emptyIterator();
}
@Override
@@ -338,10 +339,8 @@ public class VcsDirtyScopeImpl extends VcsModifiableDirtyScope {
}
/**
- * Add dirty file to the scope. Note that file is not added
- * if its ancestor was added as dirty recursively or if its parent
- * is in already in the dirty scope. Also immendiate non-directory
- * children are removed from the set of dirty files.
+ * Add dirty file to the scope. Note that file is not added if its ancestor was added as dirty recursively or if its parent is in already
+ * in the dirty scope. Also immediate non-directory children are removed from the set of dirty files.
*
* @param newcomer a file or directory added to the dirty scope.
*/
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsGuess.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsGuess.java
index 00ca9f2ebf4f..112caa4a40b4 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsGuess.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsGuess.java
@@ -73,7 +73,7 @@ public class VcsGuess {
final boolean inContent = myVcsManager.isFileInContent(validParent);
if (inContent) return true;
if (filePath != null) {
- return isFileInBaseDir(filePath, myProject.getBaseDir()) && !myExcludedFileIndex.isExcludedFile(validParent);
+ return isFileInBaseDir(filePath, myProject.getBaseDir()) && !myVcsManager.isIgnored(validParent);
}
return false;
}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ConflictedDiffRequestPresentable.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ConflictedDiffRequestPresentable.java
index 02586bba5e78..f70c84405c2d 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ConflictedDiffRequestPresentable.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ConflictedDiffRequestPresentable.java
@@ -20,6 +20,7 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.diff.DiffRequestFactory;
import com.intellij.openapi.diff.MergeRequest;
import com.intellij.openapi.diff.SimpleDiffRequest;
+import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Getter;
import com.intellij.openapi.util.io.FileUtil;
@@ -60,6 +61,7 @@ public class ConflictedDiffRequestPresentable implements DiffRequestPresentable
public MyResult step(DiffChainContext context) {
if (myChange.getAfterRevision() == null) return createErrorResult();
final Getter<MergeTexts> mergeProvider = myChange.getMergeProvider();
+ FileType type = myChange.getVirtualFile() != null ? myChange.getVirtualFile().getFileType() : null;
if (mergeProvider != null) {
// guaranteed text
final MergeTexts texts = mergeProvider.get();
@@ -67,7 +69,7 @@ public class ConflictedDiffRequestPresentable implements DiffRequestPresentable
return createErrorResult();
}
final MergeRequest request = DiffRequestFactory.getInstance()
- .create3WayDiffRequest(texts.getLeft(), texts.getRight(), texts.getBase(), myProject, null, null);
+ .create3WayDiffRequest(texts.getLeft(), texts.getRight(), texts.getBase(), type, myProject, null, null);
request.setWindowTitle(FileUtil.toSystemDependentName(myFile.getPresentableUrl()));
// todo titles?
request.setVersionTitles(new String[] {myChange.getAfterRevision().getRevisionNumber().asString(),
@@ -95,7 +97,8 @@ public class ConflictedDiffRequestPresentable implements DiffRequestPresentable
final MergeRequest request = DiffRequestFactory.getInstance()
.create3WayDiffRequest(CharsetToolkit.bytesToString(mergeData.CURRENT, charset),
CharsetToolkit.bytesToString(mergeData.LAST, charset),
- CharsetToolkit.bytesToString(mergeData.ORIGINAL, charset), myProject, null, null);
+ CharsetToolkit.bytesToString(mergeData.ORIGINAL, charset),
+ type, myProject, null, null);
request.setWindowTitle(FileUtil.toSystemDependentName(myFile.getPresentableUrl()));
// todo titles?
VcsRevisionNumber lastRevisionNumber = mergeData.LAST_REVISION_NUMBER;
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchAction.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchAction.java
index 6b4a3fb2c390..f7fbe4c9980d 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchAction.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchAction.java
@@ -325,7 +325,7 @@ public class ApplyPatchAction extends DumbAwareAction {
MergeRequest request;
if (myReadOnly) {
request = DiffRequestFactory.getInstance()
- .create3WayDiffRequest(leftText, rightText, originalContent, project, null, null);
+ .create3WayDiffRequest(leftText, rightText, originalContent, file.getFileType(), project, null, null);
} else {
request = DiffRequestFactory.getInstance().createMergeRequest(reverse ? rightText : leftText,
reverse ? leftText : rightText, originalContent,
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/MergedDiffRequestPresentable.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/MergedDiffRequestPresentable.java
index 05b4e95b8672..a3ddc2ba450d 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/MergedDiffRequestPresentable.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/MergedDiffRequestPresentable.java
@@ -58,7 +58,10 @@ public class MergedDiffRequestPresentable implements DiffRequestPresentable {
return new MyResult(badDiffRequest, DiffPresentationReturnValue.useRequest);
}
final MergeRequest request = DiffRequestFactory.getInstance()
- .create3WayDiffRequest(revisionTexts.getLocal().toString(), revisionTexts.getPatched(), revisionTexts.getBase().toString(), myProject, null, null);
+ .create3WayDiffRequest(revisionTexts.getLocal().toString(),
+ revisionTexts.getPatched(),
+ revisionTexts.getBase().toString(),
+ filePath.getFileType(), myProject, null, null);
request.setWindowTitle(VcsBundle.message("patch.apply.conflict.title", FileUtil.toSystemDependentName(myFile.getPresentableUrl())));
request.setVersionTitles(new String[] {"Current Version", "Base Version", FileUtil.toSystemDependentName(myAfterTitle)});
return new MyResult(request, DiffPresentationReturnValue.useRequest);
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/FilePathChangesTreeList.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/FilePathChangesTreeList.java
index fe9c12036596..ee3390390f06 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/FilePathChangesTreeList.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/FilePathChangesTreeList.java
@@ -24,13 +24,11 @@ import javax.swing.tree.DefaultTreeModel;
import java.util.List;
public class FilePathChangesTreeList extends ChangesTreeList<FilePath> {
- private final Project myProject;
public FilePathChangesTreeList(@NotNull Project project, @NotNull List<FilePath> originalFiles,
boolean showCheckboxes, boolean highlightProblems,
@Nullable Runnable inclusionListener, @Nullable ChangeNodeDecorator nodeDecorator) {
super(project, originalFiles, showCheckboxes, highlightProblems, inclusionListener, nodeDecorator);
- myProject = project;
}
protected DefaultTreeModel buildTreeModel(final List<FilePath> changes, ChangeNodeDecorator changeNodeDecorator) {
@@ -43,10 +41,7 @@ public class FilePathChangesTreeList extends ChangesTreeList<FilePath> {
@Nullable
protected FilePath getLeadSelectedObject(final ChangesBrowserNode node) {
- final Object userObject = node.getUserObject();
- if (userObject instanceof FilePath) {
- return (FilePath) userObject;
- }
- return null;
+ Object userObject = node.getUserObject();
+ return userObject instanceof FilePath ? (FilePath)userObject : null;
}
}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/IgnoredSettingsPanel.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/IgnoredSettingsPanel.java
index 82b676a8834d..6edfbb96c848 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/IgnoredSettingsPanel.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/IgnoredSettingsPanel.java
@@ -27,7 +27,8 @@ import com.intellij.openapi.options.SearchableConfigurable;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.vcs.VcsBundle;
-import com.intellij.openapi.vcs.changes.ChangeListManager;
+import com.intellij.openapi.vcs.changes.ChangeListManagerImpl;
+import com.intellij.openapi.vcs.changes.IgnoreSettingsType;
import com.intellij.openapi.vcs.changes.IgnoredFileBean;
import com.intellij.ui.*;
import com.intellij.ui.components.JBList;
@@ -37,13 +38,16 @@ import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
+import java.util.HashSet;
+import java.util.Set;
public class IgnoredSettingsPanel implements SearchableConfigurable, Configurable.NoScroll {
private JBList myList;
private JPanel myPanel;
private final Project myProject;
private DefaultListModel myModel;
- private final ChangeListManager myChangeListManager;
+ private final ChangeListManagerImpl myChangeListManager;
+ private final Set<String> myDirectoriesManuallyRemovedFromIgnored = new HashSet<String>();
public IgnoredSettingsPanel(Project project) {
myList = new JBList();
@@ -51,7 +55,7 @@ public class IgnoredSettingsPanel implements SearchableConfigurable, Configurabl
myList.getEmptyText().setText(VcsBundle.message("no.ignored.files"));
myProject = project;
- myChangeListManager = ChangeListManager.getInstance(myProject);
+ myChangeListManager = ChangeListManagerImpl.getInstanceImpl(myProject);
}
private void setItems(final IgnoredFileBean[] filesToIgnore) {
@@ -97,32 +101,30 @@ public class IgnoredSettingsPanel implements SearchableConfigurable, Configurabl
}
private void deleteItems() {
- boolean contigiousSelection = true;
- int minSelectionIndex = myList.getSelectionModel().getMinSelectionIndex();
- int maxSelectionIndex = myList.getSelectionModel().getMaxSelectionIndex();
- for (int i = minSelectionIndex; i <= maxSelectionIndex; i++) {
- if (!myList.getSelectionModel().isSelectedIndex(i)) {
- contigiousSelection = false;
- break;
- }
- }
- if (contigiousSelection) {
- myModel.removeRange(minSelectionIndex, maxSelectionIndex);
- }
- else {
- final Object[] selection = myList.getSelectedValues();
- for (Object item : selection) {
- myModel.removeElement(item);
+ for (Object o : myList.getSelectedValues()) {
+ IgnoredFileBean bean = (IgnoredFileBean)o;
+ if (bean.getType() == IgnoreSettingsType.UNDER_DIR) {
+ myDirectoriesManuallyRemovedFromIgnored.add(bean.getPath());
}
}
+ ListUtil.removeSelectedItems(myList);
}
public void reset() {
setItems(myChangeListManager.getFilesToIgnore());
+ myDirectoriesManuallyRemovedFromIgnored.clear();
+ myDirectoriesManuallyRemovedFromIgnored.addAll(myChangeListManager.getIgnoredFilesComponent().getDirectoriesManuallyRemovedFromIgnored());
}
public void apply() {
- myChangeListManager.setFilesToIgnore(getItems());
+ IgnoredFileBean[] toIgnore = getItems();
+ myChangeListManager.setFilesToIgnore(toIgnore);
+ for (IgnoredFileBean bean : toIgnore) {
+ if (bean.getType() == IgnoreSettingsType.UNDER_DIR) {
+ myDirectoriesManuallyRemovedFromIgnored.remove(bean.getPath());
+ }
+ }
+ myChangeListManager.getIgnoredFilesComponent().setDirectoriesManuallyRemovedFromIgnored(myDirectoriesManuallyRemovedFromIgnored);
}
public boolean isModified() {
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTrackerDrawing.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTrackerDrawing.java
index 6f1cd15ef018..d332d1faa792 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTrackerDrawing.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTrackerDrawing.java
@@ -160,11 +160,16 @@ public class LineStatusTrackerDrawing {
localShowPrevAction.copyFrom(globalShowPrevAction);
final RollbackLineStatusRangeAction rollback = new RollbackLineStatusRangeAction(tracker, range, editor);
- EmptyAction.setupAction(rollback, IdeActions.SELECTED_CHANGES_ROLLBACK, editorComponent);
+ final ShowLineStatusRangeDiffAction showDiff = new ShowLineStatusRangeDiffAction(tracker, range, editor);
+ final CopyLineStatusRangeAction copyRange = new CopyLineStatusRangeAction(tracker, range);
+
group.add(rollback);
+ group.add(showDiff);
+ group.add(copyRange);
- group.add(new ShowLineStatusRangeDiffAction(tracker, range, editor));
- group.add(new CopyLineStatusRangeAction(tracker, range));
+ EmptyAction.setupAction(rollback, IdeActions.SELECTED_CHANGES_ROLLBACK, editorComponent);
+ EmptyAction.setupAction(showDiff, "ChangesView.Diff", editorComponent);
+ EmptyAction.setupAction(copyRange, IdeActions.ACTION_COPY, editorComponent);
final JComponent toolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.FILEHISTORY_VIEW_TOOLBAR, group, true).getComponent();
@@ -221,6 +226,8 @@ public class LineStatusTrackerDrawing {
HintListener closeListener = new HintListener() {
public void hintHidden(final EventObject event) {
actionList.remove(rollback);
+ actionList.remove(showDiff);
+ actionList.remove(copyRange);
actionList.remove(localShowPrevAction);
actionList.remove(localShowNextAction);
}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/RollbackLineStatusAction.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/RollbackLineStatusAction.java
index 59697f1222dd..6e08d90a3b5d 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/RollbackLineStatusAction.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/RollbackLineStatusAction.java
@@ -13,6 +13,7 @@
package com.intellij.openapi.vcs.ex;
import com.intellij.icons.AllIcons;
+import com.intellij.idea.ActionsBundle;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.application.ApplicationManager;
@@ -32,7 +33,9 @@ import java.util.List;
public class RollbackLineStatusAction extends DumbAwareAction {
public RollbackLineStatusAction() {
- super("Rollback", "Rollback selected changes", AllIcons.Actions.Reset);
+ super(ActionsBundle.actionText("Vcs.RollbackChangedLines"),
+ ActionsBundle.actionDescription("Vcs.RollbackChangedLines"),
+ AllIcons.Actions.Reset);
}
@Override
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/history/BaseDiffFromHistoryHandler.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/history/BaseDiffFromHistoryHandler.java
new file mode 100644
index 000000000000..8a16ba6a481f
--- /dev/null
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/history/BaseDiffFromHistoryHandler.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.vcs.history;
+
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.Task;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.DialogBuilder;
+import com.intellij.openapi.ui.MessageType;
+import com.intellij.openapi.util.Couple;
+import com.intellij.openapi.vcs.FilePath;
+import com.intellij.openapi.vcs.VcsException;
+import com.intellij.openapi.vcs.changes.Change;
+import com.intellij.openapi.vcs.changes.ui.ChangesBrowser;
+import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public abstract class BaseDiffFromHistoryHandler<T extends VcsFileRevision> implements DiffFromHistoryHandler {
+
+ private static final Logger LOG = Logger.getInstance(BaseDiffFromHistoryHandler.class);
+
+ @NotNull protected final Project myProject;
+
+ protected BaseDiffFromHistoryHandler(@NotNull Project project) {
+ myProject = project;
+ }
+
+ @Override
+ public void showDiffForOne(@NotNull AnActionEvent e,
+ @NotNull FilePath filePath,
+ @NotNull VcsFileRevision previousRevision,
+ @NotNull VcsFileRevision revision) {
+ doShowDiff(filePath, previousRevision, revision, false);
+ }
+
+ @Override
+ public void showDiffForTwo(@NotNull FilePath filePath, @NotNull VcsFileRevision revision1, @NotNull VcsFileRevision revision2) {
+ doShowDiff(filePath, revision1, revision2, true);
+ }
+
+ @SuppressWarnings("unchecked")
+ protected void doShowDiff(@NotNull FilePath filePath,
+ @NotNull VcsFileRevision revision1,
+ @NotNull VcsFileRevision revision2,
+ boolean autoSort) {
+ if (!filePath.isDirectory()) {
+ VcsHistoryUtil.showDifferencesInBackground(myProject, filePath, revision1, revision2, autoSort);
+ }
+ else if (revision1.equals(VcsFileRevision.NULL)) {
+ T right = (T)revision2;
+ showAffectedChanges(filePath, right);
+ }
+ else if (revision2 instanceof CurrentRevision) {
+ T left = (T)revision1;
+ showChangesBetweenRevisions(filePath, left, null);
+ }
+ else {
+ T left = (T)revision1;
+ T right = (T)revision2;
+ if (autoSort) {
+ Couple<VcsFileRevision> pair = VcsHistoryUtil.sortRevisions(revision1, revision2);
+ left = (T)pair.first;
+ right = (T)pair.second;
+ }
+ showChangesBetweenRevisions(filePath, left, right);
+ }
+ }
+
+ protected void showChangesBetweenRevisions(@NotNull final FilePath path, @NotNull final T rev1, @Nullable final T rev2) {
+ new CollectChangesTask("Comparing revisions...") {
+
+ @NotNull
+ @Override
+ public List<Change> getChanges() throws VcsException {
+ return getChangesBetweenRevisions(path, rev1, rev2);
+ }
+
+ @NotNull
+ @Override
+ public String getDialogTitle() {
+ return getChangesBetweenRevisionsDialogTitle(path, rev1, rev2);
+ }
+ }.queue();
+ }
+
+ protected void showAffectedChanges(@NotNull final FilePath path, @NotNull final T rev) {
+ new CollectChangesTask("Collecting affected changes...") {
+
+ @NotNull
+ @Override
+ public List<Change> getChanges() throws VcsException {
+ return getAffectedChanges(path, rev);
+ }
+
+ @NotNull
+ @Override
+ public String getDialogTitle() {
+ return getAffectedChangesDialogTitle(path, rev);
+ }
+ }.queue();
+ }
+
+ // rev2 == null -> compare rev1 with local
+ // rev2 != null -> compare rev1 with rev2
+ @NotNull
+ protected abstract List<Change> getChangesBetweenRevisions(@NotNull final FilePath path, @NotNull final T rev1, @Nullable final T rev2)
+ throws VcsException;
+
+ @NotNull
+ protected abstract List<Change> getAffectedChanges(@NotNull final FilePath path, @NotNull final T rev) throws VcsException;
+
+ @NotNull
+ protected abstract String getPresentableName(@NotNull T revision);
+
+ protected void showChangesDialog(@NotNull String title, @NotNull List<Change> changes) {
+ DialogBuilder dialogBuilder = new DialogBuilder(myProject);
+
+ dialogBuilder.setTitle(title);
+ dialogBuilder.setActionDescriptors(new DialogBuilder.ActionDescriptor[]{new DialogBuilder.CloseDialogAction()});
+ final ChangesBrowser changesBrowser =
+ new ChangesBrowser(myProject, null, changes, null, false, true, null, ChangesBrowser.MyUseCase.COMMITTED_CHANGES, null);
+ changesBrowser.setChangesToDisplay(changes);
+ dialogBuilder.setCenterPanel(changesBrowser);
+ dialogBuilder.showNotModal();
+ }
+
+ protected void showError(@NotNull VcsException e, @NotNull String logMessage) {
+ LOG.info(logMessage, e);
+ VcsBalloonProblemNotifier.showOverVersionControlView(myProject, e.getMessage(), MessageType.ERROR);
+ }
+
+ @NotNull
+ protected String getChangesBetweenRevisionsDialogTitle(@NotNull final FilePath path, @NotNull final T rev1, @Nullable final T rev2) {
+ String rev1Title = getPresentableName(rev1);
+
+ return rev2 != null
+ ? String.format("Difference between %s and %s in %s", rev1Title, getPresentableName(rev2), path.getName())
+ : String.format("Difference between %s and local version in %s", rev1Title, path.getName());
+ }
+
+ @NotNull
+ protected String getAffectedChangesDialogTitle(@NotNull final FilePath path, @NotNull final T rev) {
+ return String.format("Initial commit %s in %s", getPresentableName(rev), path.getName());
+ }
+
+ protected abstract class CollectChangesTask extends Task.Backgroundable {
+
+ private List<Change> myChanges;
+
+ public CollectChangesTask(@NotNull String title) {
+ super(BaseDiffFromHistoryHandler.this.myProject, title);
+ }
+
+ @Override
+ public void run(@NotNull ProgressIndicator indicator) {
+ try {
+ myChanges = getChanges();
+ }
+ catch (VcsException e) {
+ showError(e, "Error during task: " + getDialogTitle());
+ }
+ }
+
+ @NotNull
+ public abstract List<Change> getChanges() throws VcsException;
+
+ @NotNull
+ public abstract String getDialogTitle();
+
+ @Override
+ public void onSuccess() {
+ showChangesDialog(getDialogTitle(), ContainerUtil.notNullize(myChanges));
+ }
+ }
+}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/DefaultFileIndexFacade.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/DefaultFileIndexFacade.java
index a63bbdbf0a69..d4063478d373 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/DefaultFileIndexFacade.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/DefaultFileIndexFacade.java
@@ -66,6 +66,11 @@ public class DefaultFileIndexFacade extends FileIndexFacade {
}
@Override
+ public boolean isUnderIgnored(@NotNull VirtualFile file) {
+ return false;
+ }
+
+ @Override
public Module getModuleForFile(@NotNull VirtualFile file) {
return null;
}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ProjectLevelVcsManagerImpl.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ProjectLevelVcsManagerImpl.java
index 5cc3a8a9ca92..e699383321ae 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ProjectLevelVcsManagerImpl.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ProjectLevelVcsManagerImpl.java
@@ -132,7 +132,7 @@ public class ProjectLevelVcsManagerImpl extends ProjectLevelVcsManagerEx impleme
myBackgroundableActionHandlerMap = new EnumMap<VcsBackgroundableActions, BackgroundableActionEnabledHandler>(VcsBackgroundableActions.class);
myInitialization = new VcsInitialization(myProject);
- myMappings = new NewMappings(myProject, myMessageBus, this, manager, excludedFileIndex);
+ myMappings = new NewMappings(myProject, myMessageBus, this, manager);
myMappingsToRoots = new MappingsToRoots(myMappings, myProject);
if (!myProject.isDefault()) {
@@ -843,12 +843,24 @@ public class ProjectLevelVcsManagerImpl extends ProjectLevelVcsManagerEx impleme
@Override
public Boolean compute() {
return vf != null && (myExcludedIndex.isInContent(vf) || isFileInBaseDir(vf) || vf.equals(myProject.getBaseDir()) ||
- hasExplicitMapping(vf) || isInDirectoryBasedRoot(vf)) && !myExcludedIndex.isExcludedFile(vf);
+ hasExplicitMapping(vf) || isInDirectoryBasedRoot(vf)
+ || !Registry.is("ide.hide.excluded.files") && myExcludedIndex.isExcludedFile(vf))
+ && !isIgnored(vf);
}
});
}
@Override
+ public boolean isIgnored(VirtualFile vf) {
+ if (Registry.is("ide.hide.excluded.files")) {
+ return myExcludedIndex.isExcludedFile(vf);
+ }
+ else {
+ return myExcludedIndex.isUnderIgnored(vf);
+ }
+ }
+
+ @Override
public boolean dvcsUsedInProject() {
AbstractVcs[] allActiveVcss = getAllActiveVcss();
for (AbstractVcs activeVcs : allActiveVcss) {
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/VcsRootIterator.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/VcsRootIterator.java
index 122988896cb2..cfddcaa3e65d 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/VcsRootIterator.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/VcsRootIterator.java
@@ -36,14 +36,17 @@ public class VcsRootIterator {
// folder path to files to be excluded
private final Map<String, MyRootFilter> myOtherVcsFolders;
private final FileIndexFacade myExcludedFileIndex;
+ private final ProjectLevelVcsManager myVcsManager;
+ private final Project myProject;
public VcsRootIterator(final Project project, final AbstractVcs vcs) {
- final ProjectLevelVcsManager plVcsManager = ProjectLevelVcsManager.getInstance(project);
+ myProject = project;
+ myVcsManager = ProjectLevelVcsManager.getInstance(project);
myOtherVcsFolders = new HashMap<String, MyRootFilter>();
myExcludedFileIndex = PeriodicalTasksCloser.getInstance().safeGetService(project, FileIndexFacade.class);
- final VcsRoot[] allRoots = plVcsManager.getAllVcsRoots();
- final VirtualFile[] roots = plVcsManager.getRootsUnderVcs(vcs);
+ final VcsRoot[] allRoots = myVcsManager.getAllVcsRoots();
+ final VirtualFile[] roots = myVcsManager.getRootsUnderVcs(vcs);
for (VirtualFile root : roots) {
final MyRootFilter rootPresentFilter = new MyRootFilter(root, vcs.getName());
rootPresentFilter.init(allRoots);
@@ -57,14 +60,14 @@ public class VcsRootIterator {
if ((rootFilter != null) && (!rootFilter.accept(file))) {
return false;
}
- return !isExcluded(myExcludedFileIndex, file);
+ return !isIgnoredByVcs(myVcsManager, myProject, file);
}
- private static boolean isExcluded(final FileIndexFacade indexFacade, final VirtualFile file) {
+ private static boolean isIgnoredByVcs(final ProjectLevelVcsManager vcsManager, final Project project, final VirtualFile file) {
return ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
@Override
public Boolean compute() {
- return indexFacade.isExcludedFile(file);
+ return !project.isDisposed() && vcsManager.isIgnored(file);
}
});
}
@@ -140,7 +143,7 @@ public class VcsRootIterator {
@Nullable private final VirtualFileFilter myDirectoryFilter;
private final VirtualFile myRoot;
private final MyRootFilter myRootPresentFilter;
- private final FileIndexFacade myExcludedFileIndex;
+ private final ProjectLevelVcsManager myVcsManager;
private MyRootIterator(final Project project,
final VirtualFile root,
@@ -153,13 +156,12 @@ public class VcsRootIterator {
myDirectoryFilter = directoryFilter;
myRoot = root;
- final ProjectLevelVcsManager plVcsManager = ProjectLevelVcsManager.getInstance(project);
- final AbstractVcs vcs = plVcsManager.getVcsFor(root);
- myRootPresentFilter = (vcs == null) ? null : new MyRootFilter(root, vcs.getName());
+ myVcsManager = ProjectLevelVcsManager.getInstance(project);
+ final AbstractVcs vcs = myVcsManager.getVcsFor(root);
+ myRootPresentFilter = vcs == null ? null : new MyRootFilter(root, vcs.getName());
if (myRootPresentFilter != null) {
- myRootPresentFilter.init(ProjectLevelVcsManager.getInstance(myProject).getAllVcsRoots());
+ myRootPresentFilter.init(myVcsManager.getAllVcsRoots());
}
- myExcludedFileIndex = PeriodicalTasksCloser.getInstance().safeGetService(project, FileIndexFacade.class);
}
public void iterate() {
@@ -174,7 +176,7 @@ public class VcsRootIterator {
@NotNull
@Override
public Result visitFileEx(@NotNull VirtualFile file) {
- if (isExcluded(myExcludedFileIndex, file)) return SKIP_CHILDREN;
+ if (isIgnoredByVcs(myVcsManager, myProject, file)) return SKIP_CHILDREN;
if (myRootPresentFilter != null && !myRootPresentFilter.accept(file)) return SKIP_CHILDREN;
if (myProject.isDisposed() || !process(file)) return skipTo(myRoot);
if (myDirectoryFilter != null && file.isDirectory() && !myDirectoryFilter.shouldGoIntoDirectory(file)) return SKIP_CHILDREN;
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/projectlevelman/NewMappings.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/projectlevelman/NewMappings.java
index 32fe920fc4db..5ff541ebc67d 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/projectlevelman/NewMappings.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/projectlevelman/NewMappings.java
@@ -19,7 +19,6 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.DumbAwareRunnable;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.roots.FileIndexFacade;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.util.EmptyRunnable;
import com.intellij.openapi.util.Pair;
@@ -52,18 +51,18 @@ public class NewMappings {
private final DefaultVcsRootPolicy myDefaultVcsRootPolicy;
private final MessageBus myMessageBus;
+ private final ProjectLevelVcsManager myVcsManager;
private final FileStatusManager myFileStatusManager;
- private final FileIndexFacade myFileIndexFacade;
private final Project myProject;
private boolean myActivated;
- public NewMappings(final Project project, final MessageBus messageBus,
- final ProjectLevelVcsManagerImpl vcsManager, FileStatusManager fileStatusManager, FileIndexFacade fileIndexFacade) {
+ public NewMappings(final Project project, final MessageBus messageBus, final ProjectLevelVcsManagerImpl vcsManager,
+ FileStatusManager fileStatusManager) {
myProject = project;
myMessageBus = messageBus;
+ myVcsManager = vcsManager;
myFileStatusManager = fileStatusManager;
- myFileIndexFacade = fileIndexFacade;
myLock = new Object();
myVcsToPaths = new HashMap<String, List<VcsDirectoryMapping>>();
myFileWatchRequestsManager = new FileWatchRequestsManager(myProject, this, LocalFileSystem.getInstance());
@@ -235,7 +234,7 @@ public class NewMappings {
@Nullable
public VcsDirectoryMapping getMappingFor(final VirtualFile file, final Object parentModule) {
// if parentModule is not null it means that file belongs to the module so it isn't excluded
- if (parentModule == null && myFileIndexFacade.isExcludedFile(file)) {
+ if (parentModule == null && myVcsManager.isIgnored(file)) {
return null;
}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/roots/VcsRootErrorsFinder.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/roots/VcsRootErrorsFinder.java
index 2769b3ca84cb..bb88f3dc3260 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/roots/VcsRootErrorsFinder.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/roots/VcsRootErrorsFinder.java
@@ -16,23 +16,21 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
-/**
- * @author Nadya Zabrodina
- */
public class VcsRootErrorsFinder {
- private final @NotNull Project myProject;
- private final @NotNull ProjectLevelVcsManager myVcsManager;
+ @NotNull private final Project myProject;
+ @NotNull private final ProjectLevelVcsManager myVcsManager;
+ @NotNull private final VcsRootDetector myRootDetector;
public VcsRootErrorsFinder(@NotNull Project project) {
myProject = project;
myVcsManager = ProjectLevelVcsManager.getInstance(project);
+ myRootDetector = ServiceManager.getService(myProject, VcsRootDetector.class);
}
@NotNull
public Collection<VcsRootError> find() {
List<VcsDirectoryMapping> mappings = myVcsManager.getDirectoryMappings();
- Collection<VcsRoot> vcsRoots = ServiceManager.getService(myProject, VcsRootDetector.class).detect();
-
+ Collection<VcsRoot> vcsRoots = myRootDetector.detect();
Collection<VcsRootError> errors = new ArrayList<VcsRootError>();
errors.addAll(findExtraMappings(mappings));
errors.addAll(findUnregisteredRoots(mappings, vcsRoots));
diff --git a/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/Executor.java b/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/Executor.java
index 1eebb80e8004..388b9e05fe56 100644
--- a/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/Executor.java
+++ b/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/Executor.java
@@ -156,9 +156,10 @@ public class Executor {
}
}
- protected static String run(@NotNull List<String> params, boolean ignoreNonZeroExitCode) throws ExecutionException {
+ protected static String run(@NotNull File workingDir, @NotNull List<String> params,
+ boolean ignoreNonZeroExitCode) throws ExecutionException {
final ProcessBuilder builder = new ProcessBuilder().command(params);
- builder.directory(ourCurrentDir());
+ builder.directory(workingDir);
builder.redirectErrorStream(true);
Process clientProcess;
try {
@@ -279,7 +280,8 @@ public class Executor {
return new File(ourCurrentDir, fileName);
}
- private static File ourCurrentDir() {
+ @NotNull
+ protected static File ourCurrentDir() {
assert ourCurrentDir != null : "Current dir hasn't been initialized yet. Call cd at least once before any other command.";
return new File(ourCurrentDir);
}
diff --git a/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/changes/ConvertExcludedToIgnoredTest.java b/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/changes/ConvertExcludedToIgnoredTest.java
new file mode 100644
index 000000000000..4ec5ea4bcdad
--- /dev/null
+++ b/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/changes/ConvertExcludedToIgnoredTest.java
@@ -0,0 +1,94 @@
+package com.intellij.openapi.vcs.changes;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.CompilerProjectExtension;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.testFramework.PlatformTestCase;
+import com.intellij.testFramework.PsiTestUtil;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public class ConvertExcludedToIgnoredTest extends PlatformTestCase {
+ private VirtualFile myContentRoot;
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ myContentRoot = getVirtualFile(createTempDirectory());
+ PsiTestUtil.addContentRoot(myModule, myContentRoot);
+ }
+
+ public void testExcludedFolder() throws IOException {
+ VirtualFile excluded = createChildDirectory(myContentRoot, "exc");
+ PsiTestUtil.addExcludedRoot(myModule, excluded);
+ getChangeListManager().convertExcludedToIgnored();
+ assertFalse(getChangeListManager().isIgnoredFile(myContentRoot));
+ assertTrue(getChangeListManager().isIgnoredFile(excluded));
+ assertIgnored(excluded);
+ }
+
+ public void testModuleOutput() throws IOException {
+ VirtualFile output = createChildDirectory(myContentRoot, "out");
+ PsiTestUtil.setCompilerOutputPath(myModule, output.getUrl(), false);
+ getChangeListManager().convertExcludedToIgnored();
+ assertFalse(getChangeListManager().isIgnoredFile(myContentRoot));
+ assertTrue(getChangeListManager().isIgnoredFile(output));
+ assertIgnored(output);
+ }
+
+ public void testProjectOutput() throws IOException {
+ VirtualFile output = getVirtualFile(createTempDir("projectOutput"));
+ CompilerProjectExtension.getInstance(getProject()).setCompilerOutputUrl(output.getUrl());
+ getChangeListManager().convertExcludedToIgnored();
+ assertTrue(getChangeListManager().isIgnoredFile(output));
+ assertIgnored(output);
+ }
+
+ public void testModuleOutputUnderProjectOutput() throws IOException {
+ VirtualFile output = getVirtualFile(createTempDir("projectOutput"));
+ CompilerProjectExtension.getInstance(getProject()).setCompilerOutputUrl(output.getUrl());
+ VirtualFile moduleOutput = createChildDirectory(output, "module");
+ PsiTestUtil.setCompilerOutputPath(myModule, moduleOutput.getUrl(), false);
+ getChangeListManager().convertExcludedToIgnored();
+ assertTrue(getChangeListManager().isIgnoredFile(output));
+ assertTrue(getChangeListManager().isIgnoredFile(moduleOutput));
+ assertIgnored(output);
+ }
+
+ public void testModuleOutputUnderExcluded() throws IOException {
+ VirtualFile excluded = createChildDirectory(myContentRoot, "target");
+ PsiTestUtil.addExcludedRoot(myModule, excluded);
+ VirtualFile moduleOutput = createChildDirectory(excluded, "classes");
+ PsiTestUtil.setCompilerOutputPath(myModule, moduleOutput.getUrl(), false);
+ getChangeListManager().convertExcludedToIgnored();
+ assertTrue(getChangeListManager().isIgnoredFile(excluded));
+ assertTrue(getChangeListManager().isIgnoredFile(moduleOutput));
+ assertIgnored(excluded);
+ }
+
+ private void assertIgnored(VirtualFile... ignoredDirs) {
+ assertIgnoredDirectories(getProject(), ignoredDirs);
+ }
+
+ public static void assertIgnoredDirectories(final Project project, VirtualFile... ignoredDirs) {
+ List<String> expectedIgnoredPaths = new ArrayList<String>();
+ for (VirtualFile dir : ignoredDirs) {
+ expectedIgnoredPaths.add(dir.getPath() + "/");
+ }
+ List<String> actualIgnoredPaths = new ArrayList<String>();
+ for (IgnoredFileBean fileBean : ChangeListManagerImpl.getInstanceImpl(project).getFilesToIgnore()) {
+ assertEquals("Unexpected ignore: " + fileBean, IgnoreSettingsType.UNDER_DIR, fileBean.getType());
+ actualIgnoredPaths.add(fileBean.getPath());
+ }
+ assertSameElements(expectedIgnoredPaths, actualIgnoredPaths);
+ }
+
+ private ChangeListManagerImpl getChangeListManager() {
+ return ChangeListManagerImpl.getInstanceImpl(getProject());
+ }
+}
diff --git a/platform/vcs-impl/vcs-impl.iml b/platform/vcs-impl/vcs-impl.iml
index d5e517397bb9..9492e1b4205c 100644
--- a/platform/vcs-impl/vcs-impl.iml
+++ b/platform/vcs-impl/vcs-impl.iml
@@ -18,6 +18,7 @@
<orderEntry type="module" module-name="lang-impl" />
<orderEntry type="module" module-name="spellchecker" />
<orderEntry type="library" name="JUnit4" level="project" />
+ <orderEntry type="module" module-name="testFramework" scope="TEST" />
</component>
</module>
diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/TimedVcsCommit.java b/platform/vcs-log/api/src/com/intellij/vcs/log/TimedVcsCommit.java
index c7b7ef9a7300..54f7ba19b187 100644
--- a/platform/vcs-log/api/src/com/intellij/vcs/log/TimedVcsCommit.java
+++ b/platform/vcs-log/api/src/com/intellij/vcs/log/TimedVcsCommit.java
@@ -20,7 +20,7 @@ import com.intellij.vcs.log.graph.GraphCommit;
import java.util.List;
/**
- * A {@link GraphCommit} with information about date & time when this commit was made.
+ * A typified {@link GraphCommit}.
* <p/>
* An instance of this object can be obtained via
* {@link VcsLogObjectsFactory#createTimedCommit(Hash, List, long) VcsLogObjectsFactory#createTimedCommit}.
@@ -31,12 +31,4 @@ import java.util.List;
*/
public interface TimedVcsCommit extends GraphCommit<Hash> {
- /**
- * <p>Returns the timestamp indicating the date & time when this commit was made.</p>
- * <p>This time is displayed in the table by default;
- * is used for joining commits from different repositories;
- * is used for ordering commits in a single repository (keeping the preference of the topological ordering of course).</p>
- */
- long getTimestamp();
-
}
diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogProvider.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogProvider.java
index 5d4f1fb83cad..89805947869c 100644
--- a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogProvider.java
+++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogProvider.java
@@ -29,8 +29,8 @@ public interface VcsLogProvider {
* <p>Reads the whole history, but only hashes & parents.</p>
* <p>Also reports authors/committers of this repository to the given user registry.</p>
*/
- @NotNull
- List<TimedVcsCommit> readAllHashes(@NotNull VirtualFile root, @NotNull Consumer<VcsUser> userRegistry) throws VcsException;
+ void readAllHashes(@NotNull VirtualFile root, @NotNull Consumer<VcsUser> userRegistry,
+ @NotNull Consumer<TimedVcsCommit> commitConsumer) throws VcsException;
/**
* Reads those details of the given commits, which are necessary to be shown in the log table.
diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsShortCommitDetails.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsShortCommitDetails.java
index 3069f3f6d967..9f6cecee49fb 100644
--- a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsShortCommitDetails.java
+++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsShortCommitDetails.java
@@ -21,20 +21,9 @@ import java.util.List;
*/
public interface VcsShortCommitDetails extends TimedVcsCommit {
- @Override
- @NotNull
- Hash getId();
-
@NotNull
VirtualFile getRoot();
- @Override
- @NotNull
- List<Hash> getParents();
-
- @Override
- long getTimestamp();
-
@NotNull
String getSubject();
diff --git a/platform/vcs-log/graph-api/src/com/intellij/vcs/log/graph/GraphCommit.java b/platform/vcs-log/graph-api/src/com/intellij/vcs/log/graph/GraphCommit.java
index 6a414853da45..02b337804f5c 100644
--- a/platform/vcs-log/graph-api/src/com/intellij/vcs/log/graph/GraphCommit.java
+++ b/platform/vcs-log/graph-api/src/com/intellij/vcs/log/graph/GraphCommit.java
@@ -29,6 +29,12 @@ public interface GraphCommit<CommitId> {
@NotNull
List<CommitId> getParents();
+ /**
+ * <p>Returns the timestamp indicating the date & time when this commit was made.</p>
+ * <p>This time is displayed in the table by default;
+ * it is used for joining commits from different repositories;
+ * it is used for ordering commits in a single repository (keeping the preference of the topological ordering of course).</p>
+ */
long getTimestamp();
}
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogJoiner.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogJoiner.java
index 6ed592f10939..fc51742b5318 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogJoiner.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogJoiner.java
@@ -30,9 +30,7 @@ import java.util.*;
* @author Kirill Likhodedov
*/
public class VcsLogJoiner<CommitId, Commit extends GraphCommit<CommitId>> {
- private final static int BOUND_SAVED_LOG = 10000;
- public final static String NOT_ENOUGH_FIRST_BLOCK = "Not enough first block";
public final static String ILLEGAL_DATA_RELOAD_ALL = "All data is illegal - request reload all";
/**
@@ -100,12 +98,10 @@ public class VcsLogJoiner<CommitId, Commit extends GraphCommit<CommitId>> {
Commit commit = commits.get(lastIndex);
if (searchHashes.size() == 0)
return lastIndex;
- if (lastIndex > BOUND_SAVED_LOG)
- throw new IllegalStateException(ILLEGAL_DATA_RELOAD_ALL);
searchHashes.remove(commit.getId());
}
if (searchHashes.size() != 0)
- throw new IllegalStateException(ILLEGAL_DATA_RELOAD_ALL);
+ throw new VcsLogRefreshNotEnoughDataException();
return lastIndex;
}
@@ -157,16 +153,13 @@ public class VcsLogJoiner<CommitId, Commit extends GraphCommit<CommitId>> {
private void markRealRedNode(@NotNull CommitId node) {
if (!currentRed.remove(node))
- throw new IllegalStateException(NOT_ENOUGH_FIRST_BLOCK);
+ throw new IllegalStateException(ILLEGAL_DATA_RELOAD_ALL); // never happened
allRedCommit.add(node);
}
private int getFirstSaveIndex() {
for (int lastIndex = 0; lastIndex < savedLog.size(); lastIndex++) {
Commit commit = savedLog.get(lastIndex);
- if (lastIndex > BOUND_SAVED_LOG)
- throw new IllegalStateException(ILLEGAL_DATA_RELOAD_ALL);
-
boolean isGreen = currentGreen.contains(commit.getId());
if (isGreen) {
currentRed.remove(commit.getId());
@@ -180,7 +173,7 @@ public class VcsLogJoiner<CommitId, Commit extends GraphCommit<CommitId>> {
if (currentRed.isEmpty())
return lastIndex + 1;
}
- throw new IllegalStateException(ILLEGAL_DATA_RELOAD_ALL);
+ throw new IllegalStateException(ILLEGAL_DATA_RELOAD_ALL); // see VcsLogJoinerTest#illegalStateExceptionTest
}
public Set<CommitId> getAllRedCommit() {
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogMultiRepoJoiner.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogMultiRepoJoiner.java
index 7006408943a8..072e0e26ace1 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogMultiRepoJoiner.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogMultiRepoJoiner.java
@@ -1,36 +1,36 @@
package com.intellij.vcs.log.data;
import com.intellij.util.containers.ContainerUtil;
-import com.intellij.vcs.log.TimedVcsCommit;
+import com.intellij.vcs.log.graph.GraphCommit;
import org.jetbrains.annotations.NotNull;
import java.util.*;
-public class VcsLogMultiRepoJoiner {
+public class VcsLogMultiRepoJoiner<CommitId> {
@NotNull
- public List<? extends TimedVcsCommit> join(@NotNull Collection<List<? extends TimedVcsCommit>> logsFromRepos) {
+ public List<? extends GraphCommit<CommitId>> join(@NotNull Collection<List<? extends GraphCommit<CommitId>>> logsFromRepos) {
if (logsFromRepos.size() == 1) {
return logsFromRepos.iterator().next();
}
int size = 0;
- for (List<? extends TimedVcsCommit> repo : logsFromRepos) {
+ for (List<? extends GraphCommit<CommitId>> repo : logsFromRepos) {
size += repo.size();
}
- List<TimedVcsCommit> result = new ArrayList<TimedVcsCommit>(size);
+ List<GraphCommit<CommitId>> result = new ArrayList<GraphCommit<CommitId>>(size);
- Map<TimedVcsCommit, Iterator<? extends TimedVcsCommit>> nextCommits = ContainerUtil.newHashMap();
- for (List<? extends TimedVcsCommit> log : logsFromRepos) {
- Iterator<? extends TimedVcsCommit> iterator = log.iterator();
+ Map<GraphCommit<CommitId>, Iterator<? extends GraphCommit<CommitId>>> nextCommits = ContainerUtil.newHashMap();
+ for (List<? extends GraphCommit<CommitId>> log : logsFromRepos) {
+ Iterator<? extends GraphCommit<CommitId>> iterator = log.iterator();
if (iterator.hasNext()) {
nextCommits.put(iterator.next(), iterator);
}
}
while (!nextCommits.isEmpty()) {
- TimedVcsCommit lastCommit = findLatestCommit(nextCommits.keySet());
- Iterator<? extends TimedVcsCommit> iterator = nextCommits.get(lastCommit);
+ GraphCommit<CommitId> lastCommit = findLatestCommit(nextCommits.keySet());
+ Iterator<? extends GraphCommit<CommitId>> iterator = nextCommits.get(lastCommit);
result.add(lastCommit);
nextCommits.remove(lastCommit);
@@ -43,10 +43,10 @@ public class VcsLogMultiRepoJoiner {
}
@NotNull
- private static TimedVcsCommit findLatestCommit(@NotNull Set<TimedVcsCommit> commits) {
+ private GraphCommit<CommitId> findLatestCommit(@NotNull Set<GraphCommit<CommitId>> commits) {
long maxTimeStamp = Long.MIN_VALUE;
- TimedVcsCommit lastCommit = null;
- for (TimedVcsCommit commit : commits) {
+ GraphCommit<CommitId> lastCommit = null;
+ for (GraphCommit<CommitId> commit : commits) {
if (commit.getTimestamp() >= maxTimeStamp) {
maxTimeStamp = commit.getTimestamp();
lastCommit = commit;
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogRefreshNotEnoughDataException.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogRefreshNotEnoughDataException.java
new file mode 100644
index 000000000000..9863be8d0304
--- /dev/null
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogRefreshNotEnoughDataException.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.vcs.log.data;
+
+public class VcsLogRefreshNotEnoughDataException extends RuntimeException {
+
+ private final static String NOT_ENOUGH_FIRST_BLOCK = "Not enough first block";
+
+ public VcsLogRefreshNotEnoughDataException() {
+ super(NOT_ENOUGH_FIRST_BLOCK);
+ }
+}
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogRefresherImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogRefresherImpl.java
index 0c25d7f5709d..12996f91c116 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogRefresherImpl.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogRefresherImpl.java
@@ -96,11 +96,11 @@ public class VcsLogRefresherImpl implements VcsLogRefresher {
Map<VirtualFile, Collection<VcsRef>> refs = loadRefsFromVcs(myProviders);
Set<VirtualFile> roots = myProviders.keySet();
Map<VirtualFile, VcsLogProvider.Requirements> requirements = prepareSimpleRequirements(roots, myRecentCommitCount);
- Map<VirtualFile, List<? extends TimedVcsCommit>> commits = loadRecentCommitsFromVcs(myProviders, requirements,
- myUserRegistry, myTopCommitsDetailsCache);
- List<? extends TimedVcsCommit> compoundLog = compound(commits.values());
- List<GraphCommit<Integer>> compactedLog = compactCommits(compoundLog, myHashMap);
- DataPack dataPack = DataPack.build(compactedLog, new RefsModel(refs, myHashMap.asIndexGetter()),
+ Map<VirtualFile, List<? extends GraphCommit<Integer>>> commits = loadRecentCommitsFromVcs(myProviders, requirements,
+ myUserRegistry, myTopCommitsDetailsCache,
+ myHashMap);
+ List<? extends GraphCommit<Integer>> compoundLog = compound(commits.values());
+ DataPack dataPack = DataPack.build(compoundLog, new RefsModel(refs, myHashMap.asIndexGetter()),
myHashMap.asIndexGetter(), myHashMap.asHashGetter(), myProviders, false);
mySingleTaskController.request(RefreshRequest.RELOAD_ALL); // build/rebuild the full log in bg
return dataPack;
@@ -152,19 +152,21 @@ public class VcsLogRefresherImpl implements VcsLogRefresher {
}
@NotNull
- private static Map<VirtualFile, List<? extends TimedVcsCommit>> loadRecentCommitsFromVcs(@NotNull Map<VirtualFile, VcsLogProvider> providers,
- @NotNull final Map<VirtualFile, VcsLogProvider.Requirements> requirements,
- @NotNull final VcsUserRegistryImpl userRegistry,
- @NotNull final Map<Hash, VcsCommitMetadata> topCommitsDetailsCache)
- throws VcsException {
+ private static Map<VirtualFile, List<? extends GraphCommit<Integer>>> loadRecentCommitsFromVcs(
+ @NotNull Map<VirtualFile, VcsLogProvider> providers,
+ @NotNull final Map<VirtualFile, VcsLogProvider.Requirements> requirements,
+ @NotNull final VcsUserRegistryImpl userRegistry,
+ @NotNull final Map<Hash, VcsCommitMetadata> topCommitsDetailsCache,
+ @NotNull final VcsLogHashMap hashMap) throws VcsException
+ {
final StopWatch sw = StopWatch.start("loading commits");
- final Map<VirtualFile, List<? extends TimedVcsCommit>> commits = ContainerUtil.newHashMap();
+ final Map<VirtualFile, List<? extends GraphCommit<Integer>>> commits = ContainerUtil.newHashMap();
new ProviderIterator() {
@Override
public void each(@NotNull VirtualFile root, @NotNull VcsLogProvider provider) throws VcsException {
List<? extends VcsCommitMetadata> metadatas = provider.readFirstBlock(root, requirements.get(root));
storeUsersAndDetails(metadatas, userRegistry, topCommitsDetailsCache);
- commits.put(root, metadatas);
+ commits.put(root, compactCommits(metadatas, hashMap));
sw.rootCompleted(root);
}
}.iterate(providers);
@@ -177,9 +179,9 @@ public class VcsLogRefresherImpl implements VcsLogRefresher {
* Compounds logs from different repositories into a single multi-repository log.
*/
@NotNull
- private static List<? extends TimedVcsCommit> compound(@NotNull Collection<List<? extends TimedVcsCommit>> commits) {
+ private static List<? extends GraphCommit<Integer>> compound(@NotNull Collection<List<? extends GraphCommit<Integer>>> commits) {
StopWatch sw = StopWatch.start("multi-repo join");
- List<? extends TimedVcsCommit> joined = new VcsLogMultiRepoJoiner().join(commits);
+ List<? extends GraphCommit<Integer>> joined = new VcsLogMultiRepoJoiner<Integer>().join(commits);
sw.report();
return joined;
}
@@ -192,8 +194,7 @@ public class VcsLogRefresherImpl implements VcsLogRefresher {
@NotNull
@Override
public GraphCommit<Integer> fun(@NotNull TimedVcsCommit commit) {
- return new GraphCommitImpl<Integer>(hashMap.getCommitIndex(commit.getId()),
- ContainerUtil.map(commit.getParents(), hashMap.asIndexGetter()), commit.getTimestamp());
+ return compactCommit(commit, hashMap);
}
});
hashMap.flush();
@@ -201,6 +202,12 @@ public class VcsLogRefresherImpl implements VcsLogRefresher {
return map;
}
+ @NotNull
+ private static GraphCommitImpl<Integer> compactCommit(@NotNull TimedVcsCommit commit, @NotNull VcsLogHashMap hashMap) {
+ return new GraphCommitImpl<Integer>(hashMap.getCommitIndex(commit.getId()),
+ ContainerUtil.map(commit.getParents(), hashMap.asIndexGetter()), commit.getTimestamp());
+ }
+
private static void storeUsersAndDetails(@NotNull List<? extends VcsCommitMetadata> metadatas, @NotNull VcsUserRegistryImpl userRegistry,
@NotNull Map<Hash, VcsCommitMetadata> topCommitsDetailsCache) {
for (VcsCommitMetadata detail : metadatas) {
@@ -218,9 +225,9 @@ public class VcsLogRefresherImpl implements VcsLogRefresher {
private final Map<VirtualFile, LogAndRefs> myLoadedInfos = ContainerUtil.newHashMap();
private class LogAndRefs {
- List<? extends TimedVcsCommit> log;
+ List<? extends GraphCommit<Integer>> log;
Collection<VcsRef> refs;
- LogAndRefs(Collection<VcsRef> refs, List<? extends TimedVcsCommit> commits) {
+ LogAndRefs(Collection<VcsRef> refs, List<? extends GraphCommit<Integer>> commits) {
this.refs = refs;
this.log = commits;
}
@@ -266,16 +273,16 @@ public class VcsLogRefresherImpl implements VcsLogRefresher {
try {
if (permanentGraph != null) {
loadLogAndRefs(roots, currentRefs, myRecentCommitCount);
- List<? extends TimedVcsCommit> compoundLog = compound(ContainerUtil.map(myLoadedInfos.values(),
- new Function<LogAndRefs, List<? extends TimedVcsCommit>>() {
+ List<? extends GraphCommit<Integer>> compoundLog = compound(ContainerUtil.map(myLoadedInfos.values(),
+ new Function<LogAndRefs, List<? extends GraphCommit<Integer>>>() {
@Override
- public List<? extends TimedVcsCommit> fun(LogAndRefs refs) {
+ public List<? extends GraphCommit<Integer>> fun(
+ LogAndRefs refs) {
return refs.log;
}
}));
- List<GraphCommit<Integer>> preparedLog = compactCommits(compoundLog, myHashMap);
Map<VirtualFile, Collection<VcsRef>> allNewRefs = getAllNewRefs(myLoadedInfos, currentRefs);
- List<GraphCommit<Integer>> joinedFullLog = join(preparedLog, permanentGraph.getAllCommits(), currentRefs, allNewRefs);
+ List<GraphCommit<Integer>> joinedFullLog = join(compoundLog, permanentGraph.getAllCommits(), currentRefs, allNewRefs);
if (joinedFullLog != null) {
return DataPack.build(joinedFullLog, new RefsModel(allNewRefs, myHashMap.asIndexGetter()),
myHashMap.asIndexGetter(), myHashMap.asHashGetter(), myProviders, true);
@@ -310,8 +317,9 @@ public class VcsLogRefresherImpl implements VcsLogRefresher {
Map<VirtualFile, VcsLogProvider> providers = getProviders(roots);
Map<VirtualFile, Collection<VcsRef>> refs = loadRefsFromVcs(providers);
Map<VirtualFile, VcsLogProvider.Requirements> requirements = prepareRequirements(roots, commitCount, prevRefs, refs);
- Map<VirtualFile, List<? extends TimedVcsCommit>> commits = loadRecentCommitsFromVcs(providers, requirements,
- myUserRegistry, myTopCommitsDetailsCache);
+ Map<VirtualFile, List<? extends GraphCommit<Integer>>> commits = loadRecentCommitsFromVcs(providers, requirements,
+ myUserRegistry, myTopCommitsDetailsCache,
+ myHashMap);
for (VirtualFile root : roots) {
myLoadedInfos.put(root, new LogAndRefs(refs.get(root), commits.get(root)));
}
@@ -345,7 +353,7 @@ public class VcsLogRefresherImpl implements VcsLogRefresher {
}
@Nullable
- private List<GraphCommit<Integer>> join(@NotNull List<GraphCommit<Integer>> recentCommits, @NotNull List<GraphCommit<Integer>> fullLog,
+ private List<GraphCommit<Integer>> join(@NotNull List<? extends GraphCommit<Integer>> recentCommits, @NotNull List<GraphCommit<Integer>> fullLog,
@NotNull Map<VirtualFile, Collection<VcsRef>> previousRefs,
@NotNull Map<VirtualFile, Collection<VcsRef>> newRefs) {
StopWatch sw = StopWatch.start("joining new commits");
@@ -365,18 +373,20 @@ public class VcsLogRefresherImpl implements VcsLogRefresher {
sw.report();
return commits;
}
+ catch (VcsLogRefreshNotEnoughDataException e) {
+ LOG.error(e); // collecting information : how often this situation happens, do we need to try to load more or can safely reload all
+ }
catch (IllegalStateException e) {
- LOG.info(e);
- return null;
+ LOG.error(e);
}
+ return null;
}
@NotNull
private Pair<PermanentGraph<Integer>, Map<VirtualFile, Collection<VcsRef>>> loadFullLog() throws VcsException {
StopWatch sw = StopWatch.start("full log reload");
- Collection<List<? extends TimedVcsCommit>> commits = readFullLogFromVcs();
- List<? extends TimedVcsCommit> compoundLog = compound(commits);
- List<GraphCommit<Integer>> graphCommits = compactCommits(compoundLog, myHashMap);
+ Collection<List<? extends GraphCommit<Integer>>> commits = readFullLogFromVcs();
+ List<? extends GraphCommit<Integer>> graphCommits = compound(commits);
Map<VirtualFile, Collection<VcsRef>> refMap = loadRefsFromVcs(myProviders);
PermanentGraph<Integer> permanentGraph = DataPack.buildPermanentGraph(graphCommits, new RefsModel(refMap, myHashMap.asIndexGetter()),
myHashMap.asIndexGetter(),
@@ -386,24 +396,31 @@ public class VcsLogRefresherImpl implements VcsLogRefresher {
}
@NotNull
- private Collection<List<? extends TimedVcsCommit>> readFullLogFromVcs() throws VcsException {
+ private Collection<List<? extends GraphCommit<Integer>>> readFullLogFromVcs() throws VcsException {
final StopWatch sw = StopWatch.start("read full log from VCS");
- final Collection<List<? extends TimedVcsCommit>> commits = ContainerUtil.newArrayList();
+ final Collection<List<? extends GraphCommit<Integer>>> logs = ContainerUtil.newArrayList();
new ProviderIterator() {
@Override
void each(@NotNull VirtualFile root, @NotNull VcsLogProvider provider) throws VcsException {
- commits.add(provider.readAllHashes(root, new Consumer<VcsUser>() {
+ final List<GraphCommit<Integer>> graphCommits = ContainerUtil.newArrayList();
+ provider.readAllHashes(root, new Consumer<VcsUser>() {
@Override
public void consume(@NotNull VcsUser user) {
myUserRegistry.addUser(user);
}
- }));
+ }, new Consumer<TimedVcsCommit>() {
+ @Override
+ public void consume(TimedVcsCommit commit) {
+ graphCommits.add(compactCommit(commit, myHashMap));
+ }
+ });
+ logs.add(graphCommits);
sw.rootCompleted(root);
}
}.iterate(myProviders);
myUserRegistry.flush();
sw.report();
- return commits;
+ return logs;
}
}
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/graph/GraphColorManagerImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/graph/GraphColorManagerImpl.java
index ec74038a66e4..4f0e44cbd3d2 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/graph/GraphColorManagerImpl.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/graph/GraphColorManagerImpl.java
@@ -58,7 +58,7 @@ public class GraphColorManagerImpl implements GraphColorManager<Integer> {
if (isEmptyRefs(refs, headCommit)) {
return DEFAULT_COLOR;
}
- VcsRef firstRef = ContainerUtil.sorted(refs, getRefManager(refs).getComparator()).get(0);
+ VcsRef firstRef = Collections.min(refs, getRefManager(refs).getComparator());
// TODO dark variant
return firstRef.getName().hashCode();
}
@@ -67,7 +67,7 @@ public class GraphColorManagerImpl implements GraphColorManager<Integer> {
if (refs.isEmpty()) {
if (!myErrorWasReported.containsKey(head)) {
myErrorWasReported.put(head, head);
- LOG.error("No references found at head " + head + " which corresponds to hash " + myHashGetter.fun(head));
+ LOG.warn("No references found at head " + head + " which corresponds to hash " + myHashGetter.fun(head));
}
return true;
}
diff --git a/platform/vcs-log/impl/test/com/intellij/vcs/log/data/VcsLogJoinerTest.java b/platform/vcs-log/impl/test/com/intellij/vcs/log/data/VcsLogJoinerTest.java
deleted file mode 100644
index 63e54b910bfc..000000000000
--- a/platform/vcs-log/impl/test/com/intellij/vcs/log/data/VcsLogJoinerTest.java
+++ /dev/null
@@ -1,141 +0,0 @@
-package com.intellij.vcs.log.data;
-
-import com.intellij.util.ArrayUtil;
-import com.intellij.util.Function;
-import com.intellij.util.containers.ContainerUtil;
-import com.intellij.vcs.log.Hash;
-import com.intellij.vcs.log.TimedCommitParser;
-import com.intellij.vcs.log.TimedVcsCommit;
-import com.intellij.vcs.log.impl.HashImpl;
-import org.junit.Test;
-
-import java.util.Collection;
-import java.util.List;
-
-import static java.util.Arrays.asList;
-import static org.junit.Assert.assertEquals;
-
-/**
- * @author Kirill Likhodedov
- */
-public class VcsLogJoinerTest {
-
- public void runTest(List<String> initial, List<String> updateBlock, List<String> oldRefs, List<String> newRefs, String expected) {
- List<TimedVcsCommit> savedLog = TimedCommitParser.log(ArrayUtil.toStringArray(initial));
- List<? extends TimedVcsCommit> firstBlock = TimedCommitParser.log(ArrayUtil.toStringArray(updateBlock));
- Collection<Hash> vcsOldRefs = ContainerUtil.map(oldRefs, new Function<String, Hash>() {
- @Override
- public Hash fun(String s) {
- return HashImpl.build(s);
- }
- });
- Collection<Hash> vcsNewRefs = ContainerUtil.map(newRefs, new Function<String, Hash>() {
- @Override
- public Hash fun(String s) {
- return HashImpl.build(s);
- }
- });
-
- List<? extends TimedVcsCommit> result = new VcsLogJoiner<Hash, TimedVcsCommit>().addCommits(savedLog, vcsOldRefs, firstBlock, vcsNewRefs).getFirst();
- assertEquals(expected, toStr(result));
- }
-
- @Test
- public void simpleTest() {
- runTest(
- asList("4|-a2|-a1", "3|-b1|-a", "2|-a1|-a", "1|-a|-"),
- asList("5|-f|-b1", "6|-e|-a2"),
- asList("a2", "b1"),
- asList("f", "e"),
- "e, f, a2, b1, a1, a"
- );
- }
-
- @Test
- public void oneNodeTest() {
- runTest(
- asList("3|-a1|-"),
- asList("3|-a1|-"),
- asList("a1"),
- asList("a1"),
- "a1"
- );
- }
-
- @Test
- public void oneNodeResetTest() {
- runTest(
- asList("3|-a1|-a2", "2|-a2|-"),
- asList("2|-a2|-"),
- asList("a2", "a1"),
- asList("a2"),
- "a2"
- );
- }
-
- @Test
- public void oneNodeReset2Test() {
- runTest(
- asList("3|-a1|-a2", "2|-a2|-"),
- asList("2|-a2|-"),
- asList("a1"),
- asList("a2"),
- "a2"
- );
- }
-
- @Test
- public void simpleRemoveCommitsTest() {
- runTest(
- asList("4|-a2|-a1", "3|-b1|-a", "2|-a1|-a", "1|-a|-"),
- asList("5|-f|-b1", "6|-e|-a1"),
- asList("a2"),
- asList("f", "e"),
- "e, f, b1, a1, a"
- );
- }
-
- @Test
- public void removeCommitsTest() {
- runTest(
- asList("5|-a5|-a4", "4|-a4|-a2 a3", "3|-a3|-a1", "2|-a2|-a1", "1|-a1|-"),
- asList("6|-a6|-a3"),
- asList("a5"),
- asList("a6"),
- "a6, a3, a1"
- );
- }
-
- @Test
- public void removeCommitsTest2() {
- runTest(
- asList("2|-a2|-a1", "1|-a1|-"),
- asList("5|-a5|-a4", "3|-a3|-a2", "4|-a4|-a3"),
- asList("a2"),
- asList("a5"),
- "a5, a4, a3, a2, a1"
- );
- }
-
- @Test
- public void removeCommitsTest3() {
- runTest(
- asList("3|-a3|-a2", "2|-a2|-a1", "1|-a1|-"),
- asList("2|-a2|-a1"),
- asList("a3"),
- asList("a2"),
- "a2, a1"
- );
- }
-
- private static String toStr(List<? extends TimedVcsCommit> commits) {
- StringBuilder s = new StringBuilder();
- for (TimedVcsCommit commit : commits) {
- if (s.length() != 0) {
- s.append(", ");
- }
- s.append(commit.getId().asString());
- }
- return s.toString();
- }
-}
diff --git a/platform/vcs-log/impl/test/com/intellij/vcs/log/data/VcsLogJoinerTest.kt b/platform/vcs-log/impl/test/com/intellij/vcs/log/data/VcsLogJoinerTest.kt
new file mode 100644
index 000000000000..ed4218473984
--- /dev/null
+++ b/platform/vcs-log/impl/test/com/intellij/vcs/log/data/VcsLogJoinerTest.kt
@@ -0,0 +1,468 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.vcs.log.data
+
+import org.junit.Test
+import java.util.ArrayList
+import com.intellij.vcs.log.TimedCommitParser
+import com.intellij.util.ArrayUtil
+import com.intellij.vcs.log.impl.HashImpl
+import com.intellij.vcs.log.TimedVcsCommit
+import com.intellij.vcs.log.Hash
+import org.junit.Assert.*
+
+
+class VcsLogJoinerTest {
+
+ class StringArrayBuilder() {
+ val result = ArrayList<String>()
+
+ fun String.plus() = result.add(this)
+
+ fun Collection<String>.plus() = result.addAll(this)
+ }
+
+ class TestRunner() {
+ private var fullLog: List<String>? = null
+ private var recentCommits: List<String>? = null
+ private var oldRefs: List<String>? = null
+ private var newRefs: List<String>? = null
+ private var expected: String? = null
+
+ private fun build(f: StringArrayBuilder.() -> Unit): List<String> {
+ val stringArrayBuilder = StringArrayBuilder()
+ stringArrayBuilder.f()
+ return stringArrayBuilder.result
+ }
+
+ fun fullLog(f: StringArrayBuilder.() -> Unit) {fullLog = build(f)}
+
+ fun recentCommits(f: StringArrayBuilder.() -> Unit) {recentCommits = build(f)}
+
+ fun oldRefs(f: StringArrayBuilder.() -> Unit) {oldRefs = build(f)}
+
+ fun newRefs(f: StringArrayBuilder.() -> Unit) {newRefs = build(f)}
+
+ fun expected(f: StringArrayBuilder.() -> Unit) {expected = build(f).join(separator = "\n")}
+
+ fun run() {
+ val vcsFullLog = TimedCommitParser.log(fullLog!!)
+ val vcsRecentCommits = TimedCommitParser.log(recentCommits!!)
+ val vcsOldRefs = oldRefs!!.map { HashImpl.build(it) }
+ val vcsNewRefs = newRefs!!.map { HashImpl.build(it) }
+
+ val result = VcsLogJoiner<Hash, TimedVcsCommit>().addCommits(vcsFullLog, vcsOldRefs, vcsRecentCommits, vcsNewRefs).getFirst()!!
+ val actual = result.map { it.getId().asString() }.join(separator = "\n")
+ assertEquals(expected, actual)
+ }
+ }
+
+ fun runTest(f: TestRunner.() -> Unit) {
+ val testRunner = TestRunner()
+ testRunner.f()
+ testRunner.run()
+ }
+
+ val BIG_TIME = 100000000
+
+ Test fun simple() {
+ runTest {
+ fullLog {
+ +"4|-a2|-a1"
+ +"3|-b1|-a"
+ +"2|-a1|-a"
+ +"1|-a|-"
+ }
+ recentCommits {
+ +"5|-f|-b1"
+ +"6|-e|-a2"
+ }
+ oldRefs {
+ +"a2"
+ +"b1"
+ }
+ newRefs {
+ +"f"
+ +"e"
+ }
+ expected {
+ +"e"
+ +"f"
+ +"a2"
+ +"b1"
+ +"a1"
+ +"a"
+ }
+ }
+ }
+
+ Test fun oneNode() {
+ runTest {
+ fullLog {
+ +"3|-a1|-"
+ }
+ recentCommits {
+ +"3|-a1|-"
+ }
+ oldRefs {
+ +"a1"
+ }
+ newRefs {
+ +"a1"
+ }
+ expected {
+ +"a1"
+ }
+ }
+ }
+
+ Test fun oneNodeReset() {
+ runTest {
+ fullLog {
+ +"3|-a1|-a2"
+ +"2|-a2|-"
+ }
+ recentCommits {
+ +"2|-a2|-"
+ }
+ oldRefs {
+ +"a2"
+ +"a1"
+ }
+ newRefs {
+ +"a2"
+ }
+ expected {
+ +"a2"
+ }
+ }
+ }
+
+ Test fun oneNodeReset2() {
+ runTest {
+ fullLog {
+ +"3|-a1|-a2"
+ +"2|-a2|-"
+ }
+ recentCommits {
+ +"2|-a2|-"
+ }
+ oldRefs {
+ +"a1"
+ }
+ newRefs {
+ +"a2"
+ }
+ expected {
+ +"a2"
+ }
+ }
+ }
+
+ Test fun simpleRemoveCommits() {
+ runTest {
+ fullLog {
+ +"4|-a2|-a1"
+ +"3|-b1|-a"
+ +"2|-a1|-a"
+ +"1|-a|-"
+ }
+ recentCommits {
+ +"5|-f|-b1"
+ +"6|-e|-a1"
+ }
+ oldRefs {
+ +"a2"
+ }
+ newRefs {
+ +"f"
+ +"e"
+ }
+ expected {
+ +"e"
+ +"f"
+ +"b1"
+ +"a1"
+ +"a"
+ }
+ }
+ }
+
+ Test fun removeCommits() {
+ runTest {
+ fullLog {
+ +"5|-a5|-a4"
+ +"4|-a4|-a2 a3"
+ +"3|-a3|-a1"
+ +"2|-a2|-a1"
+ +"1|-a1|-"
+ }
+ recentCommits {
+ +"6|-a6|-a3"
+ }
+ oldRefs {
+ +"a5"
+ }
+ newRefs {
+ +"a6"
+ }
+ expected {
+ +"a6"
+ +"a3"
+ +"a1"
+ }
+ }
+ }
+
+ Test fun removeCommits2() {
+ runTest {
+ fullLog {
+ +"2|-a2|-a1"
+ +"1|-a1|-"
+ }
+ recentCommits {
+ +"5|-a5|-a4"
+ +"3|-a3|-a2"
+ +"4|-a4|-a3"
+ }
+ oldRefs {
+ +"a2"
+ }
+ newRefs {
+ +"a5"
+ }
+ expected {
+ +"a5"
+ +"a4"
+ +"a3"
+ +"a2"
+ +"a1"
+ }
+ }
+ }
+
+ Test fun removeCommits3() {
+ runTest {
+ fullLog {
+ +"3|-a3|-a2"
+ +"2|-a2|-a1"
+ +"1|-a1|-"
+ }
+ recentCommits {
+ +"2|-a2|-a1"
+ }
+ oldRefs {
+ +"a3"
+ }
+ newRefs {
+ +"a2"
+ }
+ expected {
+ +"a2"
+ +"a1"
+ }
+ }
+ }
+
+ Test fun removeOldBranch() {
+ runTest {
+ fullLog {
+ +"100|-e1|-e10"
+ +(10..100000).map { "${BIG_TIME - it}|-e${it}|-e${it + 1}" }
+ +"5|-e100001|-a1"
+ +"4|-b2|-b1"
+ +"3|-b1|-a1"
+ +"1|-a1|-"
+ }
+ recentCommits {
+ +"100|-e1|-e10"
+ }
+ oldRefs {
+ +"e1"
+ +"b2"
+ }
+ newRefs {
+ "e1"
+ }
+ expected {
+ +"e1"
+ +(10..100000).map { "e$it" }
+ +"e100001"
+ +"a1"
+ }
+ }
+ }
+
+ Test fun addToOldBranch() {
+ runTest {
+ fullLog {
+ +"100|-e1|-e10"
+ +(10..100000).map { "${BIG_TIME - it}|-e${it}|-e${it + 1}" }
+ +"5|-e100001|-a1"
+ +"4|-b2|-b1"
+ +"3|-b1|-a1"
+ +"1|-a1|-"
+ }
+ recentCommits {
+ +"50|-b4|-b3"
+ +"49|-b3|-b2"
+ }
+ oldRefs {
+ +"e1"
+ +"b2"
+ }
+ newRefs {
+ +"e1"
+ +"b4"
+ }
+ expected {
+ +"e1"
+ +(10..100000).map { "e$it" }
+ +"b4"
+ +"b3"
+ +"e100001"
+ +"b2"
+ +"b1"
+ +"a1"
+ }
+ }
+ }
+
+ Test fun removeLongBranch() {
+ runTest {
+ fullLog {
+ +"100|-e1|-e10"
+ +(10..100000).map { "${BIG_TIME - it}|-e${it}|-e${it + 1}" }
+ +"5|-e100001|-a1"
+ +"4|-b2|-b1"
+ +"3|-b1|-a1"
+ +"1|-a1|-"
+ }
+ recentCommits {
+ +"50|-b4|-b3"
+ +"49|-b3|-b2"
+ }
+ oldRefs {
+ +"e1"
+ +"b2"
+ }
+ newRefs {
+ +"b4"
+ }
+ expected {
+ +"b4"
+ +"b3"
+ +"b2"
+ +"b1"
+ +"a1"
+ }
+ }
+ }
+
+ Test fun notEnoughDataExceptionTest() {
+ try {
+ runTest {
+ fullLog {
+ +"1|-a1|-"
+ }
+ recentCommits {
+ +"3|-a3|-a2"
+ }
+ oldRefs {
+ +"a1"
+ }
+ newRefs {
+ +"a3"
+ }
+ }
+ } catch (e: VcsLogRefreshNotEnoughDataException) {
+ return
+ }
+ fail()
+ }
+
+ Test fun illegalStateExceptionTest() {
+ try {
+ runTest {
+ fullLog {
+ +"1|-a1|-"
+ }
+ recentCommits {
+ +"1|-a1|-"
+ }
+ oldRefs {
+ +"a1"
+ +"a2"
+ }
+ newRefs {
+ +"a1"
+ }
+ }
+ } catch (e: IllegalStateException) {
+ return
+ }
+ fail()
+ }
+
+ Test fun removeParallelBranch() {
+ runTest {
+ fullLog {
+ +"4|-a4|-a1"
+ +"3|-a3|-a2"
+ +"2|-a2|-"
+ +"1|-a1|-"
+ }
+ recentCommits {
+
+ }
+ oldRefs {
+ +"a4"
+ +"a3"
+ }
+ newRefs {
+ +"a3"
+ }
+ expected {
+ +"a3"
+ +"a2"
+ }
+ }
+ }
+
+ Test fun removeAll() {
+ runTest {
+ fullLog {
+ +"4|-a4|-a1"
+ +"3|-a3|-a2"
+ +"2|-a2|-"
+ +"1|-a1|-"
+ }
+ recentCommits {
+
+ }
+ oldRefs {
+ +"a4"
+ +"a3"
+ }
+ newRefs {
+
+ }
+ expected {
+
+ }
+ }
+ }
+}
diff --git a/platform/vcs-log/impl/test/com/intellij/vcs/log/impl/TestVcsLogProvider.java b/platform/vcs-log/impl/test/com/intellij/vcs/log/impl/TestVcsLogProvider.java
index d3709b2d8f55..850478b048dc 100644
--- a/platform/vcs-log/impl/test/com/intellij/vcs/log/impl/TestVcsLogProvider.java
+++ b/platform/vcs-log/impl/test/com/intellij/vcs/log/impl/TestVcsLogProvider.java
@@ -93,9 +93,9 @@ public class TestVcsLogProvider implements VcsLogProvider {
return ContainerUtil.map(myCommits.subList(0, requirements.getCommitCount()), myCommitToMetadataConvertor);
}
- @NotNull
@Override
- public List<TimedVcsCommit> readAllHashes(@NotNull VirtualFile root, @NotNull Consumer<VcsUser> userRegistry) throws VcsException {
+ public void readAllHashes(@NotNull VirtualFile root, @NotNull Consumer<VcsUser> userRegistry,
+ @NotNull Consumer<TimedVcsCommit> commitConsumer) throws VcsException {
try {
myFullLogSemaphore.acquire();
}
@@ -103,7 +103,9 @@ public class TestVcsLogProvider implements VcsLogProvider {
throw new RuntimeException(e);
}
assertRoot(root);
- return myCommits;
+ for (TimedVcsCommit commit : myCommits) {
+ commitConsumer.consume(commit);
+ }
}
private void assertRoot(@NotNull VirtualFile root) {
diff --git a/platform/vcs-log/impl/vcs-log-impl.iml b/platform/vcs-log/impl/vcs-log-impl.iml
index 5668888806ac..304affc03123 100644
--- a/platform/vcs-log/impl/vcs-log-impl.iml
+++ b/platform/vcs-log/impl/vcs-log-impl.iml
@@ -21,6 +21,7 @@
<orderEntry type="module" module-name="spellchecker" />
<orderEntry type="module" module-name="vcs-log-graph-api" />
<orderEntry type="module" module-name="testFramework" scope="TEST" />
+ <orderEntry type="library" scope="TEST" name="KotlinJavaRuntime" level="project" />
</component>
</module>
diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/evaluation/XDebuggerEvaluator.java b/platform/xdebugger-api/src/com/intellij/xdebugger/evaluation/XDebuggerEvaluator.java
index 098501af7489..6109e9a41598 100644
--- a/platform/xdebugger-api/src/com/intellij/xdebugger/evaluation/XDebuggerEvaluator.java
+++ b/platform/xdebugger-api/src/com/intellij/xdebugger/evaluation/XDebuggerEvaluator.java
@@ -164,8 +164,10 @@ public abstract class XDebuggerEvaluator {
return text;
}
+ @Deprecated
/**
* @return delay before showing value tooltip (in ms)
+ * @deprecated Since IDEA 14 it is a platform setting
*/
public int getValuePopupDelay() {
return XDebuggerSettingsManager.getInstance().getDataViewSettings().getValueLookupDelay();
diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/settings/DebuggerConfigurableProvider.java b/platform/xdebugger-api/src/com/intellij/xdebugger/settings/DebuggerConfigurableProvider.java
new file mode 100644
index 000000000000..6cc25bd87f5f
--- /dev/null
+++ b/platform/xdebugger-api/src/com/intellij/xdebugger/settings/DebuggerConfigurableProvider.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.xdebugger.settings;
+
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.openapi.options.Configurable;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collection;
+import java.util.Collections;
+
+public abstract class DebuggerConfigurableProvider {
+ public static final ExtensionPointName<DebuggerConfigurableProvider> EXTENSION_POINT = ExtensionPointName.create("com.intellij.xdebugger.configurableProvider");
+
+ @NotNull
+ public Collection<? extends Configurable> getConfigurables(@NotNull DebuggerSettingsCategory category) {
+ return Collections.emptyList();
+ }
+
+ /**
+ * General settings of category were applied
+ */
+ public void generalApplied(@NotNull DebuggerSettingsCategory category) {
+ }
+
+ public boolean isTargetedToProduct(@NotNull Configurable configurable) {
+ return false;
+ }
+} \ No newline at end of file
diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/settings/DebuggerSettingsCategory.java b/platform/xdebugger-api/src/com/intellij/xdebugger/settings/DebuggerSettingsCategory.java
new file mode 100644
index 000000000000..fab630fe751c
--- /dev/null
+++ b/platform/xdebugger-api/src/com/intellij/xdebugger/settings/DebuggerSettingsCategory.java
@@ -0,0 +1,6 @@
+package com.intellij.xdebugger.settings;
+
+public enum DebuggerSettingsCategory {
+ ROOT /* will be placed under root "Debugger" node, use it with care */,
+ GENERAL, DATA_VIEWS, STEPPING, HOTSWAP
+} \ No newline at end of file
diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/settings/XDebuggerSettings.java b/platform/xdebugger-api/src/com/intellij/xdebugger/settings/XDebuggerSettings.java
index 52049f76ae72..367601db12aa 100644
--- a/platform/xdebugger-api/src/com/intellij/xdebugger/settings/XDebuggerSettings.java
+++ b/platform/xdebugger-api/src/com/intellij/xdebugger/settings/XDebuggerSettings.java
@@ -23,6 +23,9 @@ import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.util.Collection;
+import java.util.Collections;
+
/**
* Implement this class to provide settings page for debugger. Settings page will be placed under 'Debugger' node in the 'Settings' dialog.
* An implementation should be registered in plugin.xml:
@@ -34,10 +37,6 @@ import org.jetbrains.annotations.Nullable;
* @author nik
*/
public abstract class XDebuggerSettings<T> implements PersistentStateComponent<T> {
- public enum Category {
- ROOT, DATA_VIEWS, STEPPING
- }
-
public static final ExtensionPointName<XDebuggerSettings> EXTENSION_POINT = ExtensionPointName.create("com.intellij.xdebugger.settings");
private final String myId;
@@ -55,15 +54,23 @@ public abstract class XDebuggerSettings<T> implements PersistentStateComponent<T
}
@Nullable
+ @Deprecated
+ /**
+ * @deprecated Please use {@link #createConfigurables(DebuggerSettingsCategory)}
+ */
public Configurable createConfigurable() {
return null;
}
- @Nullable
- public Configurable createConfigurable(@NotNull Category category) {
- return null;
+ @NotNull
+ public Collection<? extends Configurable> createConfigurables(@NotNull DebuggerSettingsCategory category) {
+ return Collections.emptyList();
+ }
+
+ public void generalApplied(@NotNull DebuggerSettingsCategory category) {
}
- public void generalApplied(@NotNull Category category) {
+ public boolean isTargetedToProduct(@NotNull Configurable configurable) {
+ return false;
}
}
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/DebuggerSupport.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/DebuggerSupport.java
index 840163bb9e43..b09c7388748f 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/DebuggerSupport.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/DebuggerSupport.java
@@ -36,6 +36,7 @@ import org.jetbrains.annotations.Nullable;
public abstract class DebuggerSupport {
private static final ExtensionPointName<DebuggerSupport> EXTENSION_POINT = ExtensionPointName.create("com.intellij.xdebugger.debuggerSupport");
+ @SuppressWarnings("deprecation")
private static final DebuggerSettingsPanelProvider EMPTY_SETTINGS_PANEL_PROVIDER = new DebuggerSettingsPanelProvider() {
};
@@ -60,6 +61,11 @@ public abstract class DebuggerSupport {
@NotNull
public abstract BreakpointPanelProvider<?> getBreakpointPanelProvider();
+ /**
+ * @deprecated Use {@link com.intellij.xdebugger.settings.DebuggerConfigurableProvider}
+ */
+ @Deprecated
+ @SuppressWarnings("deprecation")
@NotNull
public DebuggerSettingsPanelProvider getSettingsPanelProvider() {
return EMPTY_SETTINGS_PANEL_PROVIDER;
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java
index 9ab13ba0ae74..762855510a1e 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java
@@ -46,7 +46,6 @@ import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.util.Comparing;
-import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.wm.ToolWindowId;
import com.intellij.ui.AppUIUtil;
@@ -91,7 +90,7 @@ public class XDebugSessionImpl implements XDebugSession {
private XDebugProcess myDebugProcess;
private final Map<XBreakpoint<?>, CustomizedBreakpointPresentation> myRegisteredBreakpoints =
new THashMap<XBreakpoint<?>, CustomizedBreakpointPresentation>();
- private final Set<XBreakpoint<?>> myInactiveSlaveBreakpoints = new SmartHashSet<XBreakpoint<?>>();
+ private final Set<XBreakpoint<?>> myInactiveSlaveBreakpoints = Collections.synchronizedSet(new SmartHashSet<XBreakpoint<?>>());
private boolean myBreakpointsDisabled;
private final XDebuggerManagerImpl myDebuggerManager;
private MyBreakpointListener myBreakpointListener;
@@ -103,7 +102,7 @@ public class XDebugSessionImpl implements XDebugSession {
private MyDependentBreakpointListener myDependentBreakpointListener;
private XValueMarkers<?, ?> myValueMarkers;
private final String mySessionName;
- private XDebugSessionTab mySessionTab;
+ private @Nullable XDebugSessionTab mySessionTab;
private XDebugSessionData mySessionData;
private XBreakpoint<?> myActiveNonLineBreakpoint;
private final EventDispatcher<XDebugSessionListener> myDispatcher = EventDispatcher.create(XDebugSessionListener.class);
@@ -289,6 +288,7 @@ public class XDebugSessionImpl implements XDebugSession {
@Override
public void initBreakpoints() {
+ ApplicationManager.getApplication().assertReadAccessAllowed();
LOG.assertTrue(!breakpointsInitialized);
breakpointsInitialized = true;
@@ -308,12 +308,14 @@ public class XDebugSessionImpl implements XDebugSession {
return myConsoleView;
}
+ @Nullable
public XDebugSessionTab getSessionTab() {
return mySessionTab;
}
@Override
public RunnerLayoutUi getUI() {
+ assertSessionTabInitialized();
return mySessionTab.getUi();
}
@@ -368,12 +370,7 @@ public class XDebugSessionImpl implements XDebugSession {
private <B extends XBreakpoint<?>> void processBreakpoints(final XBreakpointHandler<B> handler,
boolean register,
final boolean temporary) {
- Collection<? extends B> breakpoints = ApplicationManager.getApplication().runReadAction(new Computable<Collection<? extends B>>() {
- @Override
- public Collection<? extends B> compute() {
- return myDebuggerManager.getBreakpointManager().getBreakpoints(handler.getBreakpointTypeClass());
- }
- });
+ Collection<? extends B> breakpoints = myDebuggerManager.getBreakpointManager().getBreakpoints(handler.getBreakpointTypeClass());
for (B b : breakpoints) {
handleBreakpoint(handler, b, register, temporary);
}
@@ -422,8 +419,9 @@ public class XDebugSessionImpl implements XDebugSession {
}
}
- private boolean isBreakpointActive(final XBreakpoint<?> b) {
- return !areBreakpointsMuted() && b.isEnabled() && !myInactiveSlaveBreakpoints.contains(b);
+ public boolean isBreakpointActive(final XBreakpoint<?> b) {
+ ApplicationManager.getApplication().assertReadAccessAllowed();
+ return !areBreakpointsMuted() && b.isEnabled() && !isInactiveSlaveBreakpoint(b);
}
@Override
@@ -448,6 +446,7 @@ public class XDebugSessionImpl implements XDebugSession {
@Override
public void setBreakpointMuted(boolean muted) {
+ ApplicationManager.getApplication().assertReadAccessAllowed();
if (areBreakpointsMuted() == muted) return;
mySessionData.setBreakpointsMuted(muted);
processAllBreakpoints(!muted, muted);
@@ -714,8 +713,10 @@ public class XDebugSessionImpl implements XDebugSession {
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
public void run() {
- mySessionTab.toFront();
- mySessionTab.getUi().attractBy(XDebuggerUIConstants.LAYOUT_VIEW_BREAKPOINT_CONDITION);
+ if (mySessionTab != null) {
+ mySessionTab.toFront(true);
+ mySessionTab.getUi().attractBy(XDebuggerUIConstants.LAYOUT_VIEW_BREAKPOINT_CONDITION);
+ }
}
});
@@ -847,7 +848,9 @@ public class XDebugSessionImpl implements XDebugSession {
if (myStopped) return;
myDebugProcess.stop();
- myProject.getMessageBus().syncPublisher(XDebuggerManager.TOPIC).processStopped(myDebugProcess);
+ if (!myProject.isDisposed()) {
+ myProject.getMessageBus().syncPublisher(XDebuggerManager.TOPIC).processStopped(myDebugProcess);
+ }
myCurrentPosition = null;
myCurrentExecutionStack = null;
myCurrentStackFrame = null;
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerSupport.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerSupport.java
index fbfe184a5f3f..7f8eda2a347f 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerSupport.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerSupport.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,8 +26,6 @@ import com.intellij.xdebugger.impl.breakpoints.XBreakpointPanelProvider;
import com.intellij.xdebugger.impl.breakpoints.ui.BreakpointPanelProvider;
import com.intellij.xdebugger.impl.evaluate.quick.XQuickEvaluateHandler;
import com.intellij.xdebugger.impl.evaluate.quick.common.QuickEvaluateHandler;
-import com.intellij.xdebugger.impl.settings.DebuggerSettingsPanelProvider;
-import com.intellij.xdebugger.impl.settings.XDebuggerSettingsPanelProviderImpl;
import org.jetbrains.annotations.NotNull;
/**
@@ -49,7 +47,6 @@ public class XDebuggerSupport extends DebuggerSupport {
private final XDebuggerSuspendedActionHandler myShowExecutionPointHandler;
private final XDebuggerEvaluateActionHandler myEvaluateHandler;
private final XQuickEvaluateHandler myQuickEvaluateHandler;
- private final XDebuggerSettingsPanelProviderImpl mySettingsPanelProvider;
private final XAddToWatchesFromEditorActionHandler myAddToWatchesActionHandler;
private final DebuggerActionHandler myEvaluateInConsoleActionHandler = new XEvaluateInConsoleFromEditorActionHandler();
@@ -118,7 +115,6 @@ public class XDebuggerSupport extends DebuggerSupport {
myMuteBreakpointsHandler = new XDebuggerMuteBreakpointsHandler();
myEvaluateHandler = new XDebuggerEvaluateActionHandler();
myQuickEvaluateHandler = new XQuickEvaluateHandler();
- mySettingsPanelProvider = new XDebuggerSettingsPanelProviderImpl();
myMarkObjectActionHandler = new XMarkObjectActionHandler();
myEditBreakpointActionHandler = new XDebuggerEditBreakpointActionHandler();
}
@@ -253,10 +249,4 @@ public class XDebuggerSupport extends DebuggerSupport {
public EditBreakpointActionHandler getEditBreakpointAction() {
return myEditBreakpointActionHandler;
}
-
- @Override
- @NotNull
- public DebuggerSettingsPanelProvider getSettingsPanelProvider() {
- return mySettingsPanelProvider;
- }
}
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/ForceStepIntoAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/ForceStepIntoAction.java
index e7c9cae4db92..e5620e20011b 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/ForceStepIntoAction.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/ForceStepIntoAction.java
@@ -15,13 +15,14 @@
*/
package com.intellij.xdebugger.impl.actions;
-import org.jetbrains.annotations.NotNull;
import com.intellij.xdebugger.impl.DebuggerSupport;
+import org.jetbrains.annotations.NotNull;
/**
* @author nik
*/
public class ForceStepIntoAction extends XDebuggerActionBase {
+ @Override
@NotNull
protected DebuggerActionHandler getHandler(@NotNull final DebuggerSupport debuggerSupport) {
return debuggerSupport.getForceStepIntoHandler();
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/BreakpointState.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/BreakpointState.java
index 364353c2ac63..8631b8fc901b 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/BreakpointState.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/BreakpointState.java
@@ -156,11 +156,11 @@ public class BreakpointState<B extends XBreakpoint<P>, P extends XBreakpointProp
}
public boolean isLogExpressionEnabled() {
- return myLogExpression != null && !myLogExpression.myDisabled;
+ return myLogExpression == null || !myLogExpression.myDisabled;
}
public boolean isConditionEnabled() {
- return myCondition != null && !myCondition.myDisabled;
+ return myCondition == null || !myCondition.myDisabled;
}
@Property(surroundWithTag = false)
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointBase.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointBase.java
index ddf673fe2504..4ee505afec81 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointBase.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointBase.java
@@ -62,9 +62,9 @@ public class XBreakpointBase<Self extends XBreakpoint<P>, P extends XBreakpointP
private final XBreakpointManagerImpl myBreakpointManager;
private Icon myIcon;
private CustomizedBreakpointPresentation myCustomizedPresentation;
- private boolean myConditionEnabled;
+ private boolean myConditionEnabled = true;
private XExpression myCondition;
- private boolean myLogExpressionEnabled;
+ private boolean myLogExpressionEnabled = true;
private XExpression myLogExpression;
public XBreakpointBase(final XBreakpointType<Self, P> type, XBreakpointManagerImpl breakpointManager, final @Nullable P properties, final S state) {
@@ -192,7 +192,6 @@ public class XBreakpointBase<Self extends XBreakpoint<P>, P extends XBreakpointP
@Override
public void setLogExpression(@Nullable final String expression) {
- setLogExpressionEnabled(true);
if (!Comparing.equal(getLogExpression(), expression)) {
myLogExpression = XExpressionImpl.fromText(expression);
fireBreakpointChanged();
@@ -211,7 +210,6 @@ public class XBreakpointBase<Self extends XBreakpoint<P>, P extends XBreakpointP
@Override
public void setLogExpressionObject(@Nullable XExpression expression) {
- setLogExpressionEnabled(true);
if (!Comparing.equal(myLogExpression, expression)) {
myLogExpression = expression;
fireBreakpointChanged();
@@ -226,7 +224,6 @@ public class XBreakpointBase<Self extends XBreakpoint<P>, P extends XBreakpointP
@Override
public void setCondition(@Nullable final String condition) {
- setConditionEnabled(true);
if (!Comparing.equal(condition, getCondition())) {
myCondition = XExpressionImpl.fromText(condition);
fireBreakpointChanged();
@@ -245,7 +242,6 @@ public class XBreakpointBase<Self extends XBreakpoint<P>, P extends XBreakpointP
@Override
public void setConditionExpression(@Nullable XExpression condition) {
- setConditionEnabled(true);
if (!Comparing.equal(condition, myCondition)) {
myCondition = condition;
fireBreakpointChanged();
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointActionsPanel.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointActionsPanel.java
index 6ee8eadbe0ad..36584d1105d4 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointActionsPanel.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointActionsPanel.java
@@ -116,7 +116,7 @@ public class XBreakpointActionsPanel<B extends XBreakpointBase<?,?,?>> extends X
if (myLogExpressionComboBox != null) {
XExpression expression = myLogExpressionComboBox.getExpression();
XExpression logExpression = !XDebuggerUtilImpl.isEmptyExpression(expression) ? expression : null;
- myBreakpoint.setLogExpressionEnabled(myLogExpressionCheckBox.isSelected() && logExpression != null);
+ myBreakpoint.setLogExpressionEnabled(logExpression == null || myLogExpressionCheckBox.isSelected());
myBreakpoint.setLogExpressionObject(logExpression);
myLogExpressionComboBox.saveTextInHistory();
}
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.form b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.form
index 64239d330fd1..4ce06a6b52da 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.form
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.form
@@ -83,7 +83,7 @@
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
- <font size="11" style="1"/>
+ <font style="1"/>
<text value="Enabled"/>
</properties>
</component>
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.java
index 0e847d7db05d..75cbb569ddfd 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.java
@@ -208,7 +208,7 @@ public class XLightBreakpointPropertiesPanel<B extends XBreakpointBase<?,?,?>> i
if (myConditionComboBox != null) {
XExpression expression = myConditionComboBox.getExpression();
XExpression condition = !XDebuggerUtilImpl.isEmptyExpression(expression) ? expression : null;
- myBreakpoint.setConditionEnabled(myConditionEnabledCheckbox.isSelected() && condition != null);
+ myBreakpoint.setConditionEnabled(condition == null || myConditionEnabledCheckbox.isSelected());
myBreakpoint.setConditionExpression(condition);
myConditionComboBox.saveTextInHistory();
}
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/grouping/XBreakpointFileGroupingRule.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/grouping/XBreakpointFileGroupingRule.java
index b0b5998ef71f..994e51f2bbc4 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/grouping/XBreakpointFileGroupingRule.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/grouping/XBreakpointFileGroupingRule.java
@@ -62,6 +62,6 @@ public class XBreakpointFileGroupingRule<B> extends XBreakpointGroupingRule<B, X
@Nullable
@Override
public Icon getIcon() {
- return AllIcons.FileTypes.Text;
+ return AllIcons.Actions.GroupByFile;
}
}
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEvaluationDialog.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEvaluationDialog.java
index 2273ab698768..bee9b3d91fd7 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEvaluationDialog.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEvaluationDialog.java
@@ -33,6 +33,7 @@ import com.intellij.xdebugger.impl.XDebuggerUtilImpl;
import com.intellij.xdebugger.impl.actions.XDebuggerActions;
import com.intellij.xdebugger.impl.breakpoints.XExpressionImpl;
import com.intellij.xdebugger.impl.settings.XDebuggerSettingsManager;
+import com.intellij.xdebugger.impl.ui.XDebugSessionTab;
import com.intellij.xdebugger.impl.ui.XDebuggerEditorBase;
import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree;
import com.intellij.xdebugger.impl.ui.tree.XDebuggerTreePanel;
@@ -138,7 +139,11 @@ public class XDebuggerEvaluationDialog extends DialogWrapper {
// add to watches
XExpression expression = myInputComponent.getInputEditor().getExpression();
if (!XDebuggerUtilImpl.isEmptyExpression(expression)) {
- ((XDebugSessionImpl)mySession).getSessionTab().getWatchesView().addWatchExpression(expression, -1, false);
+ XDebugSessionTab tab = ((XDebugSessionImpl)mySession).getSessionTab();
+ if (tab != null) {
+ tab.getWatchesView().addWatchExpression(expression, -1, true);
+ requestFocusInEditor();
+ }
}
}
}
@@ -195,7 +200,11 @@ public class XDebuggerEvaluationDialog extends DialogWrapper {
setTitle(myInputComponent.getTitle());
mySwitchModeAction.putValue(Action.NAME, getSwitchButtonText(mode));
- final JComponent preferredFocusedComponent = myInputComponent.getInputEditor().getPreferredFocusedComponent();
+ requestFocusInEditor();
+ }
+
+ private void requestFocusInEditor() {
+ JComponent preferredFocusedComponent = myInputComponent.getInputEditor().getPreferredFocusedComponent();
if (preferredFocusedComponent != null) {
IdeFocusManager.getInstance(mySession.getProject()).requestFocus(preferredFocusedComponent, true);
}
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XQuickEvaluateHandler.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XQuickEvaluateHandler.java
index bf3e0010e6cf..0ccd488e9f9b 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XQuickEvaluateHandler.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XQuickEvaluateHandler.java
@@ -100,14 +100,7 @@ public class XQuickEvaluateHandler extends QuickEvaluateHandler {
}
@Override
- public int getValueLookupDelay(final Project project) {
- XDebugSession session = XDebuggerManager.getInstance(project).getCurrentSession();
- if (session != null) {
- XDebuggerEvaluator evaluator = session.getDebugProcess().getEvaluator();
- if (evaluator != null) {
- return evaluator.getValuePopupDelay();
- }
- }
+ public int getValueLookupDelay(Project project) {
return XDebuggerSettingsManager.getInstance().getDataViewSettings().getValueLookupDelay();
}
}
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XValueHint.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XValueHint.java
index cdfcad27354c..ca78932701d2 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XValueHint.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XValueHint.java
@@ -104,6 +104,7 @@ public class XValueHint extends AbstractValueHint {
public void evaluated(@NotNull final XValue result) {
result.computePresentation(new XValueNodePresentationConfigurator.ConfigurableXValueNodeImpl() {
private XFullValueEvaluator myFullValueEvaluator;
+ private boolean myShown = false;
@Override
public void applyPresentation(@Nullable Icon icon,
@@ -131,7 +132,7 @@ public class XValueHint extends AbstractValueHint {
}
showHint(component);
}
- else if (getType() == ValueHintType.MOUSE_CLICK_HINT) {
+ else if (getType() == ValueHintType.MOUSE_CLICK_HINT && !myShown) {
showTree(result);
}
else {
@@ -143,6 +144,7 @@ public class XValueHint extends AbstractValueHint {
});
showHint(component);
}
+ myShown = true;
}
@Override
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XWatchesViewImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XWatchesViewImpl.java
index 5183877b2a9a..6216c1312349 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XWatchesViewImpl.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XWatchesViewImpl.java
@@ -15,6 +15,8 @@
*/
package com.intellij.xdebugger.impl.frame;
+import com.intellij.debugger.ui.DebuggerContentInfo;
+import com.intellij.execution.ui.layout.impl.RunnerContentUi;
import com.intellij.ide.DataManager;
import com.intellij.ide.dnd.DnDEvent;
import com.intellij.ide.dnd.DnDManager;
@@ -22,6 +24,7 @@ import com.intellij.ide.dnd.DnDNativeTarget;
import com.intellij.openapi.CompositeDisposable;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.*;
+import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.EmptyRunnable;
import com.intellij.openapi.util.SystemInfo;
@@ -36,6 +39,7 @@ import com.intellij.xdebugger.frame.XStackFrame;
import com.intellij.xdebugger.impl.XDebugSessionImpl;
import com.intellij.xdebugger.impl.actions.XDebuggerActions;
import com.intellij.xdebugger.impl.breakpoints.XExpressionImpl;
+import com.intellij.xdebugger.impl.ui.XDebugSessionTab;
import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree;
import com.intellij.xdebugger.impl.ui.tree.XDebuggerTreePanel;
import com.intellij.xdebugger.impl.ui.tree.XDebuggerTreeRestorer;
@@ -68,6 +72,7 @@ public class XWatchesViewImpl implements DnDNativeTarget, XWatchesView, XDebugVi
@NotNull private final XDebugSessionImpl mySession;
private final JPanel myDecoratedPanel;
private final CompositeDisposable myDisposables = new CompositeDisposable();
+ private boolean myRebuildNeeded;
public XWatchesViewImpl(@NotNull final XDebugSessionImpl session) {
mySession = session;
@@ -216,10 +221,40 @@ public class XWatchesViewImpl implements DnDNativeTarget, XWatchesView, XDebugVi
public void addWatchExpression(@NotNull XExpression expression, int index, final boolean navigateToWatchNode) {
myRootNode.addWatchExpression(mySession.getDebugProcess().getEvaluator(), expression, index, navigateToWatchNode);
updateSessionData();
+ if (navigateToWatchNode) {
+ showWatchesTab();
+ }
+ }
+
+ private void showWatchesTab() {
+ XDebugSessionTab tab = mySession.getSessionTab();
+ if (tab != null) {
+ tab.toFront(false);
+ // restore watches tab if minimized
+ JComponent component = tab.getUi().getComponent();
+ if (component instanceof DataProvider) {
+ RunnerContentUi ui = RunnerContentUi.KEY.getData(((DataProvider)component));
+ if (ui != null) {
+ ui.restoreContent(DebuggerContentInfo.WATCHES_CONTENT);
+ }
+ }
+ }
+ }
+
+ public boolean rebuildNeeded() {
+ return myRebuildNeeded;
}
@Override
public void processSessionEvent(@NotNull final SessionEvent event) {
+ if (getMainPanel().isShowing() || ApplicationManager.getApplication().isUnitTestMode()) {
+ myRebuildNeeded = false;
+ }
+ else {
+ myRebuildNeeded = true;
+ return;
+ }
+
XStackFrame stackFrame = mySession.getCurrentStackFrame();
XDebuggerTree tree = myTreePanel.getTree();
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/DataViewsConfigurable.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/DataViewsConfigurable.java
index d140a74f35c8..6ee307cfa573 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/DataViewsConfigurable.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/DataViewsConfigurable.java
@@ -17,7 +17,7 @@ package com.intellij.xdebugger.impl.settings;
import com.intellij.openapi.options.Configurable;
import com.intellij.xdebugger.XDebuggerBundle;
-import com.intellij.xdebugger.settings.XDebuggerSettings;
+import com.intellij.xdebugger.settings.DebuggerSettingsCategory;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
@@ -41,8 +41,8 @@ class DataViewsConfigurable extends SubCompositeConfigurable implements Configur
@NotNull
@Override
- protected XDebuggerSettings.Category getCategory() {
- return XDebuggerSettings.Category.DATA_VIEWS;
+ protected DebuggerSettingsCategory getCategory() {
+ return DebuggerSettingsCategory.DATA_VIEWS;
}
@NotNull
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/DebuggerConfigurable.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/DebuggerConfigurable.java
index a3f4e847288c..58896a87f596 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/DebuggerConfigurable.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/DebuggerConfigurable.java
@@ -20,26 +20,23 @@ import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.options.SearchableConfigurable;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.SmartList;
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.xdebugger.XDebuggerBundle;
import com.intellij.xdebugger.impl.DebuggerSupport;
-import com.intellij.xdebugger.settings.XDebuggerSettings;
-import org.jetbrains.annotations.Nls;
+import com.intellij.xdebugger.settings.DebuggerConfigurableProvider;
+import com.intellij.xdebugger.settings.DebuggerSettingsCategory;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
-import java.util.Arrays;
-import java.util.Comparator;
-import java.util.List;
+import java.util.*;
-/**
- * @author Eugene Belyaev & Eugene Zhuravlev
- */
public class DebuggerConfigurable implements SearchableConfigurable.Parent {
public static final String DISPLAY_NAME = XDebuggerBundle.message("debugger.configurable.display.name");
static final Configurable[] EMPTY_CONFIGURABLES = new Configurable[0];
+ private static final DebuggerSettingsCategory[] MERGED_CATEGORIES = {DebuggerSettingsCategory.STEPPING, DebuggerSettingsCategory.HOTSWAP};
private Configurable myRootConfigurable;
private Configurable[] myChildren;
@@ -71,89 +68,84 @@ public class DebuggerConfigurable implements SearchableConfigurable.Parent {
return;
}
- List<DebuggerSettingsPanelProvider> providers = DebuggerConfigurableProvider.getSortedProviders();
-
List<Configurable> configurables = new SmartList<Configurable>();
configurables.add(new DataViewsConfigurable());
- List<Configurable> steppingConfigurables = DebuggerConfigurableProvider.getConfigurables(XDebuggerSettings.Category.STEPPING, providers);
- if (!steppingConfigurables.isEmpty()) {
- configurables.add(new SteppingConfigurable(steppingConfigurables));
+ DebuggerConfigurableProvider[] providers = DebuggerConfigurableProvider.EXTENSION_POINT.getExtensions();
+ computeMergedConfigurables(providers, configurables);
+
+ //noinspection deprecation
+ for (DebuggerSettingsPanelProvider provider : getSortedProviders()) {
+ configurables.addAll(provider.getConfigurables());
+ @SuppressWarnings("deprecation")
+ Configurable providerRootConfigurable = provider.getRootConfigurable();
+ if (providerRootConfigurable != null) {
+ configurables.add(providerRootConfigurable);
+ }
}
- Configurable rootConfigurable = computeRootConfigurable(providers, configurables);
+ for (DebuggerConfigurableProvider provider : providers) {
+ configurables.addAll(provider.getConfigurables(DebuggerSettingsCategory.ROOT));
+ }
- if (configurables.isEmpty() && rootConfigurable == null) {
+ MergedCompositeConfigurable mergedGeneralConfigurable = computeGeneralConfigurables(providers);
+ if (configurables.isEmpty() && mergedGeneralConfigurable == null) {
+ myRootConfigurable = null;
myChildren = EMPTY_CONFIGURABLES;
}
- else if (rootConfigurable == null && configurables.size() == 1) {
- myRootConfigurable = configurables.get(0);
- myChildren = EMPTY_CONFIGURABLES;
+ else if (configurables.size() == 1) {
+ Configurable firstConfigurable = configurables.get(0);
+ if (mergedGeneralConfigurable == null) {
+ myRootConfigurable = firstConfigurable;
+ myChildren = EMPTY_CONFIGURABLES;
+ }
+ else {
+ Configurable[] generalConfigurables = mergedGeneralConfigurable.children;
+ Configurable[] mergedArray = new Configurable[generalConfigurables.length + 1];
+ System.arraycopy(generalConfigurables, 0, mergedArray, 0, generalConfigurables.length);
+ mergedArray[generalConfigurables.length] = firstConfigurable;
+ myRootConfigurable = new MergedCompositeConfigurable("", "", mergedArray);
+ myChildren = firstConfigurable instanceof SearchableConfigurable.Parent ? ((Parent)firstConfigurable).getConfigurables() : EMPTY_CONFIGURABLES;
+ }
}
else {
myChildren = configurables.toArray(new Configurable[configurables.size()]);
- myRootConfigurable = rootConfigurable;
+ myRootConfigurable = mergedGeneralConfigurable;
}
}
- @Nullable
- private static Configurable computeRootConfigurable(@NotNull List<DebuggerSettingsPanelProvider> providers, @NotNull List<Configurable> configurables) {
- Configurable deprecatedRootConfigurable = null;
- for (DebuggerSettingsPanelProvider provider : providers) {
- configurables.addAll(provider.getConfigurables());
- @SuppressWarnings("deprecation")
- Configurable providerRootConfigurable = provider.getRootConfigurable();
- if (providerRootConfigurable != null) {
- if (deprecatedRootConfigurable == null) {
- deprecatedRootConfigurable = providerRootConfigurable;
- }
- else {
- configurables.add(providerRootConfigurable);
- }
+ private static void computeMergedConfigurables(@NotNull DebuggerConfigurableProvider[] providers, @NotNull List<Configurable> result) {
+ for (DebuggerSettingsCategory category : MERGED_CATEGORIES) {
+ List<Configurable> configurables = getConfigurables(category, providers);
+ if (!configurables.isEmpty()) {
+ String id = category.name().toLowerCase(Locale.ENGLISH);
+ result.add(new MergedCompositeConfigurable("debugger." + id, XDebuggerBundle.message("debugger." + id + ".display.name"),
+ configurables.toArray(new Configurable[configurables.size()])));
}
}
+ }
- List<Configurable> rootConfigurables = DebuggerConfigurableProvider.getConfigurables(XDebuggerSettings.Category.ROOT, providers);
+ @Nullable
+ private static MergedCompositeConfigurable computeGeneralConfigurables(@NotNull DebuggerConfigurableProvider[] providers) {
+ List<Configurable> rootConfigurables = getConfigurables(DebuggerSettingsCategory.GENERAL, providers);
if (rootConfigurables.isEmpty()) {
- return deprecatedRootConfigurable;
+ return null;
}
- else {
- Configurable[] mergedRootConfigurables = new Configurable[rootConfigurables.size() + (deprecatedRootConfigurable == null ? 0 : 1)];
- rootConfigurables.toArray(mergedRootConfigurables);
- if (deprecatedRootConfigurable != null) {
- mergedRootConfigurables[rootConfigurables.size()] = deprecatedRootConfigurable;
- }
-
- // move unnamed to top
- Arrays.sort(mergedRootConfigurables, new Comparator<Configurable>() {
- @Override
- public int compare(Configurable o1, Configurable o2) {
- boolean c1e = StringUtil.isEmpty(o1.getDisplayName());
- return c1e == StringUtil.isEmpty(o2.getDisplayName()) ? 0 : (c1e ? -1 : 1);
- }
- });
-
- return new MergedCompositeConfigurable(mergedRootConfigurables) {
- @NotNull
- @Override
- public String getId() {
- throw new UnsupportedOperationException();
- }
- @Nls
- @Override
- public String getDisplayName() {
- throw new UnsupportedOperationException();
- }
- };
- }
+ Configurable[] mergedRootConfigurables = rootConfigurables.toArray(new Configurable[rootConfigurables.size()]);
+ // move unnamed to top
+ Arrays.sort(mergedRootConfigurables, new Comparator<Configurable>() {
+ @Override
+ public int compare(@NotNull Configurable o1, @NotNull Configurable o2) {
+ boolean c1e = StringUtil.isEmpty(o1.getDisplayName());
+ return c1e == StringUtil.isEmpty(o2.getDisplayName()) ? 0 : (c1e ? -1 : 1);
+ }
+ });
+ return new MergedCompositeConfigurable("", "", mergedRootConfigurables);
}
@Override
public void apply() throws ConfigurationException {
- for (DebuggerSupport support : DebuggerSupport.getDebuggerSupports()) {
- support.getSettingsPanelProvider().apply();
- }
if (myRootConfigurable != null) {
myRootConfigurable.apply();
}
@@ -206,4 +198,51 @@ public class DebuggerConfigurable implements SearchableConfigurable.Parent {
public String getId() {
return "project.propDebugger";
}
+
+ @SuppressWarnings("deprecation")
+ @NotNull
+ private static List<DebuggerSettingsPanelProvider> getSortedProviders() {
+ List<DebuggerSettingsPanelProvider> providers = null;
+ for (DebuggerSupport support : DebuggerSupport.getDebuggerSupports()) {
+ DebuggerSettingsPanelProvider provider = support.getSettingsPanelProvider();
+ if (providers == null) {
+ providers = new SmartList<DebuggerSettingsPanelProvider>();
+ }
+ providers.add(provider);
+ }
+
+ if (ContainerUtil.isEmpty(providers)) {
+ return Collections.emptyList();
+ }
+
+ if (providers.size() > 1) {
+ Collections.sort(providers, new Comparator<DebuggerSettingsPanelProvider>() {
+ @Override
+ public int compare(@NotNull DebuggerSettingsPanelProvider o1, @NotNull DebuggerSettingsPanelProvider o2) {
+ return o2.getPriority() - o1.getPriority();
+ }
+ });
+ }
+ return providers;
+ }
+
+ @NotNull
+ static List<Configurable> getConfigurables(@NotNull DebuggerSettingsCategory category) {
+ return getConfigurables(category, DebuggerConfigurableProvider.EXTENSION_POINT.getExtensions());
+ }
+
+ @NotNull
+ private static List<Configurable> getConfigurables(@NotNull DebuggerSettingsCategory category, @NotNull DebuggerConfigurableProvider[] providers) {
+ List<Configurable> configurables = null;
+ for (DebuggerConfigurableProvider provider : providers) {
+ Collection<? extends Configurable> providerConfigurables = provider.getConfigurables(category);
+ if (!providerConfigurables.isEmpty()) {
+ if (configurables == null) {
+ configurables = new SmartList<Configurable>();
+ }
+ configurables.addAll(providerConfigurables);
+ }
+ }
+ return ContainerUtil.notNullize(configurables);
+ }
}
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/DebuggerConfigurableProvider.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/DebuggerConfigurableProvider.java
deleted file mode 100644
index 80651cadc830..000000000000
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/DebuggerConfigurableProvider.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright 2000-2010 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.xdebugger.impl.settings;
-
-import com.intellij.openapi.options.Configurable;
-import com.intellij.openapi.options.ConfigurableProvider;
-import com.intellij.util.SmartList;
-import com.intellij.util.containers.ContainerUtil;
-import com.intellij.xdebugger.impl.DebuggerSupport;
-import com.intellij.xdebugger.settings.XDebuggerSettings;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-
-/**
- * @author nik
- */
-public class DebuggerConfigurableProvider extends ConfigurableProvider {
- @NotNull
- static List<DebuggerSettingsPanelProvider> getSortedProviders() {
- List<DebuggerSettingsPanelProvider> providers = null;
- for (DebuggerSupport support : DebuggerSupport.getDebuggerSupports()) {
- DebuggerSettingsPanelProvider provider = support.getSettingsPanelProvider();
- if (providers == null) {
- providers = new SmartList<DebuggerSettingsPanelProvider>();
- }
- providers.add(provider);
- }
-
- if (ContainerUtil.isEmpty(providers)) {
- return Collections.emptyList();
- }
-
- if (providers.size() > 1) {
- Collections.sort(providers, new Comparator<DebuggerSettingsPanelProvider>() {
- @Override
- public int compare(DebuggerSettingsPanelProvider o1, DebuggerSettingsPanelProvider o2) {
- return o2.getPriority() - o1.getPriority();
- }
- });
- }
- return providers;
- }
-
- @Override
- public Configurable createConfigurable() {
- return new DebuggerConfigurable();
- }
-
- @NotNull
- static List<Configurable> getConfigurables(@NotNull XDebuggerSettings.Category category) {
- List<DebuggerSettingsPanelProvider> providers = getSortedProviders();
- return providers.isEmpty() ? Collections.<Configurable>emptyList() : getConfigurables(category, providers);
- }
-
- @NotNull
- static List<Configurable> getConfigurables(@NotNull XDebuggerSettings.Category category, @NotNull List<DebuggerSettingsPanelProvider> providers) {
- List<Configurable> configurables = null;
- for (DebuggerSettingsPanelProvider provider : providers) {
- Collection<? extends Configurable> providerConfigurables = provider.getConfigurable(category);
- if (!providerConfigurables.isEmpty()) {
- if (configurables == null) {
- configurables = new SmartList<Configurable>();
- }
- configurables.addAll(providerConfigurables);
- }
- }
- return ContainerUtil.notNullize(configurables);
- }
-}
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/DebuggerSettingsPanelProvider.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/DebuggerSettingsPanelProvider.java
index 68e6de064b9a..5b0dde609e0c 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/DebuggerSettingsPanelProvider.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/DebuggerSettingsPanelProvider.java
@@ -16,15 +16,15 @@
package com.intellij.xdebugger.impl.settings;
import com.intellij.openapi.options.Configurable;
-import com.intellij.xdebugger.settings.XDebuggerSettings;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.Collections;
+@Deprecated
/**
- * @author nik
+ * @deprecated Use {@link com.intellij.xdebugger.settings.DebuggerConfigurableProvider}
*/
public abstract class DebuggerSettingsPanelProvider {
public int getPriority() {
@@ -36,23 +36,20 @@ public abstract class DebuggerSettingsPanelProvider {
return Collections.emptyList();
}
+ @Deprecated
+ /**
+ * @deprecated Please use {@link com.intellij.xdebugger.settings.DebuggerConfigurableProvider#generalApplied(com.intellij.xdebugger.settings.DebuggerSettingsCategory)}
+ */
public void apply() {
}
@Nullable
@Deprecated
- public Configurable getRootConfigurable() {
- return null;
- }
-
- @NotNull
- public Collection<? extends Configurable> getConfigurable(@NotNull XDebuggerSettings.Category category) {
- return Collections.emptyList();
- }
-
/**
- * General settings of category were applied
+ * @deprecated Please use {@link com.intellij.xdebugger.settings.DebuggerConfigurableProvider#getConfigurables(com.intellij.xdebugger.settings.DebuggerSettingsCategory)} and
+ * check {@link com.intellij.xdebugger.settings.DebuggerSettingsCategory#GENERAL}
*/
- public void generalApplied(@NotNull XDebuggerSettings.Category category) {
+ public Configurable getRootConfigurable() {
+ return null;
}
}
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/MergedCompositeConfigurable.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/MergedCompositeConfigurable.java
index be0bdbf0ab2f..ccfc2708cb9e 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/MergedCompositeConfigurable.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/MergedCompositeConfigurable.java
@@ -7,6 +7,8 @@ import com.intellij.openapi.ui.VerticalFlowLayout;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.TitledSeparator;
+import com.intellij.xdebugger.settings.DebuggerConfigurableProvider;
+import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -14,18 +16,34 @@ import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
-abstract class MergedCompositeConfigurable implements SearchableConfigurable {
+class MergedCompositeConfigurable implements SearchableConfigurable {
static final EmptyBorder BOTTOM_INSETS = new EmptyBorder(0, 0, IdeBorderFactory.TITLED_BORDER_BOTTOM_INSET, 0);
+ private static final Insets FIRST_COMPONENT_INSETS = new Insets(0, 0, IdeBorderFactory.TITLED_BORDER_BOTTOM_INSET, 0);
+ private static final Insets N_COMPONENT_INSETS = new Insets(IdeBorderFactory.TITLED_BORDER_TOP_INSET, 0, IdeBorderFactory.TITLED_BORDER_BOTTOM_INSET, 0);
+
protected final Configurable[] children;
protected JComponent rootComponent;
- protected MergedCompositeConfigurable(@NotNull Configurable[] children) {
+ private final String id;
+ private final String displayName;
+
+ public MergedCompositeConfigurable(@NotNull String id, @NotNull String displayName, @NotNull Configurable[] children) {
this.children = children;
+ this.id = id;
+ this.displayName = displayName;
}
- protected boolean isUseTitledBorder() {
- return true;
+ @NotNull
+ @Override
+ public String getId() {
+ return id;
+ }
+
+ @Nls
+ @Override
+ public String getDisplayName() {
+ return displayName;
}
@Nullable
@@ -40,26 +58,47 @@ abstract class MergedCompositeConfigurable implements SearchableConfigurable {
return children.length == 1 ? children[0].getHelpTopic() : null;
}
+ /**
+ * false by default.
+ *
+ * If Ruby general settings will be without titled border in RubyMine, user could think that all other debugger categories also about Ruby.
+ */
+ protected boolean isUseTargetedProductPolicyIfSeveralChildren() {
+ return false;
+ }
+
@Nullable
@Override
public JComponent createComponent() {
if (rootComponent == null) {
+ Configurable firstConfigurable = children[0];
if (children.length == 1) {
- rootComponent = children[0].createComponent();
+ rootComponent = firstConfigurable.createComponent();
+ String rootComponentDisplayName = firstConfigurable.getDisplayName();
+ if (!StringUtil.isEmpty(rootComponentDisplayName) && !isTargetedToProduct(firstConfigurable)) {
+ rootComponent.setBorder(IdeBorderFactory.createTitledBorder(rootComponentDisplayName, false, FIRST_COMPONENT_INSETS));
+ }
}
else {
- JPanel panel = createPanel(isUseTitledBorder());
- for (Configurable child : children) {
- JComponent component = child.createComponent();
+ boolean isFirstNamed = true;
+ JPanel panel = createPanel(true);
+ for (Configurable configurable : children) {
+ JComponent component = configurable.createComponent();
assert component != null;
- if (isUseTitledBorder()) {
- String displayName = child.getDisplayName();
- if (StringUtil.isEmpty(displayName)) {
- component.setBorder(BOTTOM_INSETS);
+ String displayName = configurable.getDisplayName();
+ if (StringUtil.isEmpty(displayName)) {
+ component.setBorder(BOTTOM_INSETS);
+ }
+ else {
+ boolean addBorder = true;
+ if (isUseTargetedProductPolicyIfSeveralChildren() && isFirstNamed) {
+ isFirstNamed = false;
+ if (isTargetedToProduct(configurable)) {
+ addBorder = false;
+ }
}
- else {
- Insets insets = new Insets(children[0] == child ? 0 : IdeBorderFactory.TITLED_BORDER_TOP_INSET, 0, IdeBorderFactory.TITLED_BORDER_BOTTOM_INSET, 0);
- component.setBorder(IdeBorderFactory.createTitledBorder(displayName, false, insets));
+ if (addBorder) {
+ component.setBorder(IdeBorderFactory.createTitledBorder(displayName, false, firstConfigurable == configurable ? FIRST_COMPONENT_INSETS : N_COMPONENT_INSETS));
}
}
panel.add(component);
@@ -70,6 +109,15 @@ abstract class MergedCompositeConfigurable implements SearchableConfigurable {
return rootComponent;
}
+ static boolean isTargetedToProduct(@NotNull Configurable configurable) {
+ for (DebuggerConfigurableProvider provider : DebuggerConfigurableProvider.EXTENSION_POINT.getExtensions()) {
+ if (provider.isTargetedToProduct(configurable)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
@NotNull
static JPanel createPanel(boolean isUseTitledBorder) {
int verticalGap = TitledSeparator.TOP_INSET;
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/SubCompositeConfigurable.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/SubCompositeConfigurable.java
index 489e4bd80307..f06b6bcc1107 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/SubCompositeConfigurable.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/SubCompositeConfigurable.java
@@ -20,8 +20,8 @@ import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.options.SearchableConfigurable;
import com.intellij.openapi.ui.VerticalFlowLayout;
import com.intellij.ui.IdeBorderFactory;
-import com.intellij.xdebugger.impl.DebuggerSupport;
-import com.intellij.xdebugger.settings.XDebuggerSettings;
+import com.intellij.xdebugger.settings.DebuggerConfigurableProvider;
+import com.intellij.xdebugger.settings.DebuggerSettingsCategory;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -77,7 +77,7 @@ abstract class SubCompositeConfigurable implements SearchableConfigurable.Parent
protected abstract DataViewsConfigurableUi createRootUi();
@NotNull
- protected abstract XDebuggerSettings.Category getCategory();
+ protected abstract DebuggerSettingsCategory getCategory();
private boolean isChildrenMerged() {
return children != null && children.length == 1;
@@ -86,7 +86,7 @@ abstract class SubCompositeConfigurable implements SearchableConfigurable.Parent
@Override
public final Configurable[] getConfigurables() {
if (children == null) {
- List<Configurable> configurables = DebuggerConfigurableProvider.getConfigurables(getCategory());
+ List<Configurable> configurables = DebuggerConfigurable.getConfigurables(getCategory());
children = configurables.toArray(new Configurable[configurables.size()]);
}
return isChildrenMerged() ? DebuggerConfigurable.EMPTY_CONFIGURABLES : children;
@@ -115,10 +115,12 @@ abstract class SubCompositeConfigurable implements SearchableConfigurable.Parent
c.setBorder(MergedCompositeConfigurable.BOTTOM_INSETS);
panel.add(c);
}
- for (Configurable child : children) {
- JComponent component = child.createComponent();
+ for (Configurable configurable : children) {
+ JComponent component = configurable.createComponent();
if (component != null) {
- component.setBorder(IdeBorderFactory.createTitledBorder(child.getDisplayName(), false));
+ if (children[0] != configurable || !MergedCompositeConfigurable.isTargetedToProduct(configurable)) {
+ component.setBorder(IdeBorderFactory.createTitledBorder(configurable.getDisplayName(), false));
+ }
panel.add(component);
}
}
@@ -164,8 +166,8 @@ abstract class SubCompositeConfigurable implements SearchableConfigurable.Parent
public final void apply() throws ConfigurationException {
if (root != null) {
root.apply(getSettings());
- for (DebuggerSupport support : DebuggerSupport.getDebuggerSupports()) {
- support.getSettingsPanelProvider().generalApplied(getCategory());
+ for (DebuggerConfigurableProvider provider : DebuggerConfigurableProvider.EXTENSION_POINT.getExtensions()) {
+ provider.generalApplied(getCategory());
}
}
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/XDebuggerConfigurableProvider.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/XDebuggerConfigurableProvider.java
new file mode 100644
index 000000000000..2a7f636784c4
--- /dev/null
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/XDebuggerConfigurableProvider.java
@@ -0,0 +1,74 @@
+package com.intellij.xdebugger.impl.settings;
+
+import com.intellij.openapi.options.Configurable;
+import com.intellij.openapi.options.SimpleConfigurable;
+import com.intellij.openapi.util.Getter;
+import com.intellij.util.SmartList;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.xdebugger.settings.DebuggerConfigurableProvider;
+import com.intellij.xdebugger.settings.DebuggerSettingsCategory;
+import com.intellij.xdebugger.settings.XDebuggerSettings;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collection;
+import java.util.List;
+
+class XDebuggerConfigurableProvider extends DebuggerConfigurableProvider {
+ @NotNull
+ @Override
+ public Collection<? extends Configurable> getConfigurables(@NotNull DebuggerSettingsCategory category) {
+ List<Configurable> list;
+ if (category == DebuggerSettingsCategory.GENERAL) {
+ list = new SmartList<Configurable>(SimpleConfigurable.create("debugger.general", "", GeneralConfigurableUi.class, new Getter<XDebuggerGeneralSettings>() {
+ @Override
+ public XDebuggerGeneralSettings get() {
+ return XDebuggerSettingsManager.getInstanceImpl().getGeneralSettings();
+ }
+ }));
+ }
+ else {
+ list = null;
+ }
+
+ for (XDebuggerSettings<?> settings : XDebuggerSettingsManager.getInstanceImpl().getSettingsList()) {
+ Collection<? extends Configurable> configurables = settings.createConfigurables(category);
+ if (!configurables.isEmpty()) {
+ if (list == null) {
+ list = new SmartList<Configurable>();
+ }
+ list.addAll(configurables);
+ }
+ }
+
+ if (category == DebuggerSettingsCategory.ROOT) {
+ for (XDebuggerSettings settings : XDebuggerSettingsManager.getInstanceImpl().getSettingsList()) {
+ @SuppressWarnings("deprecation")
+ Configurable configurable = settings.createConfigurable();
+ if (configurable != null) {
+ if (list == null) {
+ list = new SmartList<Configurable>();
+ }
+ list.add(configurable);
+ }
+ }
+ }
+ return ContainerUtil.notNullize(list);
+ }
+
+ @Override
+ public void generalApplied(@NotNull DebuggerSettingsCategory category) {
+ for (XDebuggerSettings<?> settings : XDebuggerSettingsManager.getInstanceImpl().getSettingsList()) {
+ settings.generalApplied(category);
+ }
+ }
+
+ @Override
+ public boolean isTargetedToProduct(@NotNull Configurable configurable) {
+ for (XDebuggerSettings<?> settings : XDebuggerSettingsManager.getInstanceImpl().getSettingsList()) {
+ if (settings.isTargetedToProduct(configurable)) {
+ return true;
+ }
+ }
+ return super.isTargetedToProduct(configurable);
+ }
+} \ No newline at end of file
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/XDebuggerSettingsPanelProviderImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/XDebuggerSettingsPanelProviderImpl.java
deleted file mode 100644
index 2e20230198c6..000000000000
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/XDebuggerSettingsPanelProviderImpl.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright 2000-2014 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.xdebugger.impl.settings;
-
-import com.intellij.openapi.options.Configurable;
-import com.intellij.util.SmartList;
-import com.intellij.util.containers.ContainerUtil;
-import com.intellij.xdebugger.settings.XDebuggerSettings;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.Collection;
-import java.util.List;
-
-/**
- * @author nik
- */
-public class XDebuggerSettingsPanelProviderImpl extends DebuggerSettingsPanelProvider {
- @NotNull
- @Override
- public Collection<? extends Configurable> getConfigurables() {
- List<Configurable> list = new SmartList<Configurable>();
- for (XDebuggerSettings settings : XDebuggerSettingsManager.getInstanceImpl().getSettingsList()) {
- ContainerUtil.addIfNotNull(list, settings.createConfigurable());
- }
- return list;
- }
-
- @NotNull
- @Override
- public Collection<? extends Configurable> getConfigurable(@NotNull XDebuggerSettings.Category category) {
- List<Configurable> list;
- if (category == XDebuggerSettings.Category.ROOT) {
- list = new SmartList<Configurable>(new GeneralConfigurable());
- }
- else {
- list = null;
- }
-
- for (XDebuggerSettings settings : XDebuggerSettingsManager.getInstanceImpl().getSettingsList()) {
- Configurable configurable = settings.createConfigurable(category);
- if (configurable != null) {
- if (list == null) {
- list = new SmartList<Configurable>();
- }
- list.add(configurable);
- }
- }
- return ContainerUtil.notNullize(list);
- }
-
- @Override
- public void generalApplied(@NotNull XDebuggerSettings.Category category) {
- for (XDebuggerSettings settings : XDebuggerSettingsManager.getInstanceImpl().getSettingsList()) {
- settings.generalApplied(category);
- }
- }
-}
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/DebuggerSessionTabBase.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/DebuggerSessionTabBase.java
index 57b2e9d505e1..2134c0c8d4e1 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/DebuggerSessionTabBase.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/DebuggerSessionTabBase.java
@@ -151,19 +151,21 @@ public abstract class DebuggerSessionTabBase extends LogConsoleManagerBase imple
return environment != null ? environment.getRunProfile() : null;
}
- public void toFront() {
+ public void toFront(boolean focus) {
if (!ApplicationManager.getApplication().isUnitTestMode()) {
ExecutionManager.getInstance(getProject()).getContentManager().toFrontRunContent(DefaultDebugExecutor.getDebugExecutorInstance(), myRunContentDescriptor);
- ApplicationManager.getApplication().invokeLater(new Runnable() {
- @Override
- public void run() {
- boolean focusWnd = Registry.is("debugger.mayBringFrameToFrontOnBreakpoint");
- ProjectUtil.focusProjectWindow(getProject(), focusWnd);
- if (!focusWnd) {
- AppIcon.getInstance().requestAttention(getProject(), true);
+ if (focus) {
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ boolean focusWnd = Registry.is("debugger.mayBringFrameToFrontOnBreakpoint");
+ ProjectUtil.focusProjectWindow(getProject(), focusWnd);
+ if (!focusWnd) {
+ AppIcon.getInstance().requestAttention(getProject(), true);
+ }
}
- }
- });
+ });
+ }
}
}
}
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebugSessionTab.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebugSessionTab.java
index 2e5f8a337385..4b6bea217c54 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebugSessionTab.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebugSessionTab.java
@@ -27,6 +27,7 @@ import com.intellij.execution.ui.ExecutionConsole;
import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.execution.ui.actions.CloseAction;
import com.intellij.execution.ui.layout.PlaceInGrid;
+import com.intellij.execution.ui.layout.impl.ViewImpl;
import com.intellij.icons.AllIcons;
import com.intellij.ide.actions.ContextHelpAction;
import com.intellij.idea.ActionsBundle;
@@ -37,6 +38,8 @@ import com.intellij.openapi.util.Disposer;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.ui.AppUIUtil;
import com.intellij.ui.content.Content;
+import com.intellij.ui.content.ContentManagerAdapter;
+import com.intellij.ui.content.ContentManagerEvent;
import com.intellij.ui.content.tabs.PinToolwindowTabAction;
import com.intellij.xdebugger.XDebugProcess;
import com.intellij.xdebugger.XDebugSession;
@@ -242,6 +245,18 @@ public class XDebugSessionTab extends DebuggerSessionTabBase {
focus.add(ActionManager.getInstance().getAction(XDebuggerActions.FOCUS_ON_BREAKPOINT));
myUi.getOptions().setAdditionalFocusActions(focus);
+ myUi.addListener(new ContentManagerAdapter() {
+ @Override
+ public void selectionChanged(ContentManagerEvent event) {
+ Content content = event.getContent();
+ if (content.isSelected() && DebuggerContentInfo.WATCHES_CONTENT.equals(content.getUserData(ViewImpl.ID))) {
+ if (myWatchesView.rebuildNeeded()) {
+ myWatchesView.processSessionEvent(XDebugView.SessionEvent.SETTINGS_CHANGED);
+ }
+ }
+ }
+ }, this);
+
rebuildViews();
}
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XDebuggerTree.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XDebuggerTree.java
index d097b09ac3ac..fe32920a7ac6 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XDebuggerTree.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XDebuggerTree.java
@@ -35,10 +35,7 @@ import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider;
import com.intellij.xdebugger.frame.XDebuggerTreeNodeHyperlink;
import com.intellij.xdebugger.impl.actions.XDebuggerActions;
import com.intellij.xdebugger.impl.frame.XValueMarkers;
-import com.intellij.xdebugger.impl.ui.tree.nodes.MessageTreeNode;
-import com.intellij.xdebugger.impl.ui.tree.nodes.RestorableStateNode;
-import com.intellij.xdebugger.impl.ui.tree.nodes.XDebuggerTreeNode;
-import com.intellij.xdebugger.impl.ui.tree.nodes.XValueContainerNode;
+import com.intellij.xdebugger.impl.ui.tree.nodes.*;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -254,6 +251,12 @@ public class XDebuggerTree extends DnDAwareTree implements DataProvider, Disposa
if (XDEBUGGER_TREE_KEY.is(dataId)) {
return this;
}
+ if (PlatformDataKeys.PREDEFINED_TEXT.is(dataId)) {
+ XValueNodeImpl[] selectedNodes = getSelectedNodes(XValueNodeImpl.class, null);
+ if (selectedNodes.length == 1 && selectedNodes[0].getFullValueEvaluator() == null) {
+ return selectedNodes[0].getRawValue();
+ }
+ }
return null;
}
diff --git a/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XDebuggerSettingsTest.java b/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XDebuggerSettingsTest.java
index a4b7431d276f..942e73495f69 100644
--- a/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XDebuggerSettingsTest.java
+++ b/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XDebuggerSettingsTest.java
@@ -15,7 +15,6 @@
*/
package com.intellij.xdebugger;
-import com.intellij.openapi.options.Configurable;
import com.intellij.testFramework.PlatformLiteFixture;
import com.intellij.util.xmlb.XmlSerializer;
import com.intellij.util.xmlb.annotations.Attribute;
@@ -23,7 +22,6 @@ import com.intellij.xdebugger.impl.XDebuggerUtilImpl;
import com.intellij.xdebugger.impl.settings.XDebuggerSettingsManager;
import com.intellij.xdebugger.settings.XDebuggerSettings;
import org.jdom.Element;
-import org.jetbrains.annotations.NotNull;
/**
* @author nik
@@ -79,11 +77,5 @@ public class XDebuggerSettingsTest extends PlatformLiteFixture {
public void loadState(final MyDebuggerSettings state) {
myOption = state.myOption;
}
-
- @Override
- @NotNull
- public Configurable createConfigurable() {
- throw new UnsupportedOperationException("'createConfigurable' not implemented in " + getClass().getName());
- }
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml
index 164c690d4da3..5581810b3f2c 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml
@@ -1209,6 +1209,10 @@
key="field.has.setter.but.no.getter.display.name" groupBundle="messages.InspectionsBundle"
groupKey="group.names.javabeans.issues" enabledByDefault="false" level="WARNING"
implementationClass="com.siyeh.ig.javabeans.FieldHasSetterButNoGetterInspection"/>
+ <localInspection language="JAVA" shortName="PropertyValueSetToItself" bundle="com.siyeh.InspectionGadgetsBundle"
+ key="property.value.set.to.itself.display.name" groupBundle="messages.InspectionsBundle"
+ groupKey="group.names.javabeans.issues" enabledByDefault="false" level="WARNING"
+ implementationClass="com.siyeh.ig.javabeans.PropertyValueSetToItselfInspection"/>
<!--group.names.javadoc.issues-->
<localInspection language="JAVA" shortName="HtmlTagCanBeJavadocTag" bundle="com.siyeh.InspectionGadgetsBundle"
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties
index f92925b33bc0..715bf898c50a 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties
@@ -1841,8 +1841,9 @@ double.literal.may.be.float.literal.problem.descriptor=<code>#ref</code> could b
double.literal.may.be.float.literal.quickfix=Replace with ''{0}''
multiple.declaration.option=Ignore 'for' loop declarations
simplifiable.annotation.display.name=Simplifiable annotation
-simplifiable.annotation.problem.descriptor=Annotation <code>#ref</code> can be simplified #loc
-simplifiable.annotation.quickfix=Replace with ''{0}''
+simplifiable.annotation.problem.descriptor=Unnecessary <code>#ref</code> in annotation #loc
+simplifiable.annotation.whitespace.problem.descriptor=Unnecessary whitespace in annotation #loc
+simplifiable.annotation.quickfix=Simplify annotation
overloaded.methods.with.same.number.parameters.option=<html>Ignore overloaded methods whose parameter types are definitely incompatible</html>
string.concatenation.in.format.call.display.name=String concatenation as argument to 'format()' call
string.concatenation.in.format.call.problem.descriptor=<code>#ref()</code> call has a String concatenation argument #loc
@@ -2098,3 +2099,4 @@ assignment.to.lambda.parameter.display.name=Assignment to lambda parameter
assignment.to.lambda.parameter.problem.descriptor=Assignment to lambda parameter <code>#ref</code> #loc
class.with.only.private.constructors.display.name=Class with only 'private' constructors should be declared 'final'
class.with.only.private.constructors.problem.descriptor=Class <code>#ref</code> with only 'private' constructors should be declared 'final'
+property.value.set.to.itself.display.name=Property value set to itself
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/BaseInspectionVisitor.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/BaseInspectionVisitor.java
index 1ba34a6235d8..d792a1ae1101 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/BaseInspectionVisitor.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/BaseInspectionVisitor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2013 Dave Griffith, Bas Leijdekkers
+ * Copyright 2003-2014 Dave Griffith, Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -191,8 +191,13 @@ public abstract class BaseInspectionVisitor extends JavaElementVisitor {
holder.registerProblem(location, description, highlightType, fixes);
}
- protected final void registerErrorAtOffset(@NotNull PsiElement location,
- int offset, int length, Object... infos) {
+ protected final void registerErrorAtOffset(@NotNull PsiElement location, int offset, int length, Object... infos) {
+ registerErrorAtOffset(location, offset, length, ProblemHighlightType.GENERIC_ERROR_OR_WARNING, infos);
+ }
+
+ protected final void registerErrorAtOffset(@NotNull PsiElement location, int offset, int length,
+ ProblemHighlightType highlightType,
+ Object... infos) {
if (location.getTextLength() == 0 || length == 0) {
return;
}
@@ -202,7 +207,7 @@ public abstract class BaseInspectionVisitor extends JavaElementVisitor {
}
final String description = inspection.buildErrorString(infos);
final TextRange range = new TextRange(offset, offset + length);
- holder.registerProblem(location, range, description, fixes);
+ holder.registerProblem(location, description, highlightType, range, fixes);
}
@NotNull
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/DeclareCollectionAsInterfaceInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/DeclareCollectionAsInterfaceInspection.java
index 8db2598dc39f..7f5012f2be76 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/DeclareCollectionAsInterfaceInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/DeclareCollectionAsInterfaceInspection.java
@@ -284,8 +284,10 @@ public class DeclareCollectionAsInterfaceInspection extends BaseInspection {
weaklingList.remove(objectClass);
if (weaklingList.isEmpty()) {
final String typeText = type.getCanonicalText();
- final String interfaceText =
- CollectionUtils.getInterfaceForClass(typeText);
+ final String interfaceText = CollectionUtils.getInterfaceForClass(typeText);
+ if (interfaceText == null) {
+ return;
+ }
registerError(nameElement, interfaceText);
}
else {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/MismatchedArrayReadWriteInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/MismatchedArrayReadWriteInspection.java
index 41b391183395..17f7a83316ef 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/MismatchedArrayReadWriteInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/MismatchedArrayReadWriteInspection.java
@@ -72,8 +72,7 @@ public class MismatchedArrayReadWriteInspection extends BaseInspection {
return new MismatchedArrayReadWriteVisitor();
}
- private static class MismatchedArrayReadWriteVisitor
- extends BaseInspectionVisitor {
+ private static class MismatchedArrayReadWriteVisitor extends BaseInspectionVisitor {
@Override
public void visitField(@NotNull PsiField field) {
@@ -88,8 +87,7 @@ public class MismatchedArrayReadWriteInspection extends BaseInspection {
if (!checkVariable(field, containingClass)) {
return;
}
- final boolean written =
- arrayContentsAreWritten(field, containingClass);
+ final boolean written = arrayContentsAreWritten(field, containingClass);
final boolean read = arrayContentsAreRead(field, containingClass);
if (written == read) {
return;
@@ -98,16 +96,13 @@ public class MismatchedArrayReadWriteInspection extends BaseInspection {
}
@Override
- public void visitLocalVariable(
- @NotNull PsiLocalVariable variable) {
+ public void visitLocalVariable(@NotNull PsiLocalVariable variable) {
super.visitLocalVariable(variable);
- final PsiCodeBlock codeBlock =
- PsiTreeUtil.getParentOfType(variable, PsiCodeBlock.class);
+ final PsiCodeBlock codeBlock = PsiTreeUtil.getParentOfType(variable, PsiCodeBlock.class);
if (!checkVariable(variable, codeBlock)) {
return;
}
- final boolean written =
- arrayContentsAreWritten(variable, codeBlock);
+ final boolean written = arrayContentsAreWritten(variable, codeBlock);
final boolean read = arrayContentsAreRead(variable, codeBlock);
if (written == read) {
return;
@@ -133,8 +128,7 @@ public class MismatchedArrayReadWriteInspection extends BaseInspection {
if (VariableAccessUtils.variableIsReturned(variable, context)) {
return false;
}
- return !VariableAccessUtils.variableIsUsedInArrayInitializer(
- variable, context);
+ return !VariableAccessUtils.variableIsUsedInArrayInitializer(variable, context);
}
private static boolean arrayContentsAreWritten(PsiVariable variable,
@@ -187,26 +181,20 @@ public class MismatchedArrayReadWriteInspection extends BaseInspection {
return true;
}
if (initializer instanceof PsiNewExpression) {
- final PsiNewExpression newExpression =
- (PsiNewExpression)initializer;
- final PsiArrayInitializerExpression arrayInitializer =
- newExpression.getArrayInitializer();
- return arrayInitializer == null ||
- isDefaultArrayInitializer(arrayInitializer);
+ final PsiNewExpression newExpression = (PsiNewExpression)initializer;
+ final PsiArrayInitializerExpression arrayInitializer = newExpression.getArrayInitializer();
+ return arrayInitializer == null || isDefaultArrayInitializer(arrayInitializer);
}
else if (initializer instanceof PsiArrayInitializerExpression) {
- final PsiArrayInitializerExpression arrayInitializerExpression =
- (PsiArrayInitializerExpression)initializer;
- final PsiExpression[] initializers =
- arrayInitializerExpression.getInitializers();
+ final PsiArrayInitializerExpression arrayInitializerExpression = (PsiArrayInitializerExpression)initializer;
+ final PsiExpression[] initializers = arrayInitializerExpression.getInitializers();
return initializers.length == 0;
}
return false;
}
public static boolean variableIsWritten(@NotNull PsiVariable variable, @NotNull PsiElement context) {
- final VariableReadWriteVisitor visitor =
- new VariableReadWriteVisitor(variable, true);
+ final VariableReadWriteVisitor visitor = new VariableReadWriteVisitor(variable, true);
context.accept(visitor);
return visitor.isPassed();
}
@@ -272,8 +260,7 @@ public class MismatchedArrayReadWriteInspection extends BaseInspection {
final PsiExpression[] arguments = argumentList.getExpressions();
for (int i = 0; i < arguments.length; i++) {
final PsiExpression argument = arguments[i];
- if (VariableAccessUtils.mayEvaluateToVariable(argument,
- variable)) {
+ if (VariableAccessUtils.mayEvaluateToVariable(argument, variable)) {
if (write && i == 0 && isCallToSystemArraycopy(call)) {
return;
}
@@ -285,49 +272,50 @@ public class MismatchedArrayReadWriteInspection extends BaseInspection {
}
}
- private static boolean isCallToSystemArraycopy(
- PsiMethodCallExpression call) {
- final PsiReferenceExpression methodExpression =
- call.getMethodExpression();
- @NonNls final String name =
- methodExpression.getReferenceName();
+ private static boolean isCallToSystemArraycopy(PsiMethodCallExpression call) {
+ final PsiReferenceExpression methodExpression = call.getMethodExpression();
+ @NonNls final String name = methodExpression.getReferenceName();
if (!"arraycopy".equals(name)) {
return false;
}
- final PsiExpression qualifier =
- methodExpression.getQualifierExpression();
+ final PsiExpression qualifier = methodExpression.getQualifierExpression();
if (!(qualifier instanceof PsiReferenceExpression)) {
return false;
}
- final PsiReferenceExpression referenceExpression =
- (PsiReferenceExpression)qualifier;
- final PsiElement element =
- referenceExpression.resolve();
+ final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)qualifier;
+ final PsiElement element = referenceExpression.resolve();
if (!(element instanceof PsiClass)) {
return false;
}
- final PsiClass aClass = (PsiClass)element;
- final String qualifiedName =
- aClass.getQualifiedName();
- return "java.lang.System".equals(qualifiedName);
+ return "java.lang.System".equals(((PsiClass)element).getQualifiedName());
}
@Override
- public void visitNewExpression(
- @NotNull PsiNewExpression newExpression) {
+ public void visitNewExpression(@NotNull PsiNewExpression newExpression) {
if (passed) {
return;
}
super.visitNewExpression(newExpression);
- final PsiExpressionList argumentList =
- newExpression.getArgumentList();
+ visitPsiCall(newExpression);
+ }
+
+ @Override
+ public void visitEnumConstant(PsiEnumConstant enumConstant) {
+ if (passed) {
+ return;
+ }
+ super.visitEnumConstant(enumConstant);
+ visitPsiCall(enumConstant);
+ }
+
+ private void visitPsiCall(PsiCall newExpression) {
+ final PsiExpressionList argumentList = newExpression.getArgumentList();
if (argumentList == null) {
return;
}
final PsiExpression[] arguments = argumentList.getExpressions();
for (final PsiExpression argument : arguments) {
- if (VariableAccessUtils.mayEvaluateToVariable(argument,
- variable)) {
+ if (VariableAccessUtils.mayEvaluateToVariable(argument, variable)) {
passed = true;
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javabeans/PropertyValueSetToItselfInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javabeans/PropertyValueSetToItselfInspection.java
new file mode 100644
index 000000000000..e4ee7c5956bc
--- /dev/null
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/javabeans/PropertyValueSetToItselfInspection.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.siyeh.ig.javabeans;
+
+import com.intellij.psi.*;
+import com.intellij.psi.util.PropertyUtil;
+import com.siyeh.InspectionGadgetsBundle;
+import com.siyeh.ig.BaseInspection;
+import com.siyeh.ig.BaseInspectionVisitor;
+import com.siyeh.ig.psiutils.EquivalenceChecker;
+import com.siyeh.ig.psiutils.ParenthesesUtils;
+import org.jetbrains.annotations.Nls;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class PropertyValueSetToItselfInspection extends BaseInspection {
+
+ @Nls
+ @NotNull
+ @Override
+ public String getDisplayName() {
+ return InspectionGadgetsBundle.message("property.value.set.to.itself.display.name");
+ }
+
+ @NotNull
+ @Override
+ protected String buildErrorString(Object... infos) {
+ return InspectionGadgetsBundle.message("property.value.set.to.itself.display.name");
+ }
+
+ @Override
+ public BaseInspectionVisitor buildVisitor() {
+ return new PropertyValueSetToItselfVisitor();
+ }
+
+ private static class PropertyValueSetToItselfVisitor extends BaseInspectionVisitor {
+
+ @Override
+ public void visitMethodCallExpression(PsiMethodCallExpression expression) {
+ super.visitMethodCallExpression(expression);
+ final PsiExpressionList argumentList1 = expression.getArgumentList();
+ final PsiExpression[] arguments1 = argumentList1.getExpressions();
+ if (arguments1.length != 1) {
+ return;
+ }
+ final PsiExpression argument = arguments1[0];
+ if (!(argument instanceof PsiMethodCallExpression)) {
+ return;
+ }
+ final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)argument;
+ final PsiExpressionList argumentList2 = methodCallExpression.getArgumentList();
+ final PsiExpression[] arguments2 = argumentList2.getExpressions();
+ if (arguments2.length != 0) {
+ return;
+ }
+ final PsiReferenceExpression methodExpression1 = expression.getMethodExpression();
+ final PsiExpression qualifierExpression1 = ParenthesesUtils.stripParentheses(methodExpression1.getQualifierExpression());
+ final PsiReferenceExpression methodExpression2 = methodCallExpression.getMethodExpression();
+ final PsiExpression qualifierExpression2 = ParenthesesUtils.stripParentheses(methodExpression2.getQualifierExpression());
+ if (qualifierExpression1 instanceof PsiReferenceExpression && qualifierExpression2 instanceof PsiReferenceExpression) {
+ if (!EquivalenceChecker.expressionsAreEquivalent(qualifierExpression1, qualifierExpression2)) {
+ return;
+ }
+ }
+ else if((qualifierExpression1 != null &&
+ !(qualifierExpression1 instanceof PsiThisExpression) &&
+ !(qualifierExpression1 instanceof PsiSuperExpression))
+ ||
+ qualifierExpression2 != null &&
+ !(qualifierExpression2 instanceof PsiThisExpression) &&
+ !(qualifierExpression2 instanceof PsiSuperExpression)) {
+ return;
+ }
+ final PsiMethod method1 = expression.resolveMethod();
+ final PsiField fieldOfSetter = PropertyUtil.getFieldOfSetter(method1);
+ if (fieldOfSetter == null) {
+ return;
+ }
+ final PsiMethod method2 = methodCallExpression.resolveMethod();
+ final PsiField fieldOfGetter = PropertyUtil.getFieldOfGetter(method2);
+ if (!fieldOfSetter.equals(fieldOfGetter)) {
+ return;
+ }
+ registerMethodCallError(expression);
+ }
+ }
+}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/IfCanBeSwitchInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/IfCanBeSwitchInspection.java
index 5b4c0c9c8305..adfff487443e 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/IfCanBeSwitchInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/IfCanBeSwitchInspection.java
@@ -515,7 +515,10 @@ public class IfCanBeSwitchInspection extends BaseInspection {
super.readSettings(node);
for (Element child : node.getChildren("option")) {
if (Comparing.strEqual(child.getAttributeValue("name"), ONLY_SAFE)) {
- onlySuggestNullSafe = Boolean.parseBoolean(child.getAttributeValue("value"));
+ final String value = child.getAttributeValue("value");
+ if (value != null) {
+ onlySuggestNullSafe = Boolean.parseBoolean(value);
+ }
break;
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ImportUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ImportUtils.java
index 375e0f6a8017..9b4a3a832913 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ImportUtils.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ImportUtils.java
@@ -416,7 +416,7 @@ public class ImportUtils {
final List<PsiImportStaticStatement> imports = getMatchingImports(importList, qualifiedName);
final int onDemandCount = JavaCodeStyleSettingsFacade.getInstance(project).getNamesCountToUseImportOnDemand();
final PsiElementFactory elementFactory = psiFacade.getElementFactory();
- if (imports.size() < onDemandCount) {
+ if (imports.size() + 1 < onDemandCount) {
importList.add(elementFactory.createImportStaticStatement(aClass, memberName));
}
else {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/InstanceOfUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/InstanceOfUtils.java
index 702d84d522ac..fdbc531406de 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/InstanceOfUtils.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/InstanceOfUtils.java
@@ -117,6 +117,9 @@ public class InstanceOfUtils {
inElse = true;
}
checkExpression(operand);
+ if (agreeingInstanceof) {
+ return;
+ }
}
if (inElse && conflictingInstanceof != null) {
agreeingInstanceof = false;
@@ -215,6 +218,7 @@ public class InstanceOfUtils {
(PsiInstanceOfExpression)expression;
if (isAgreeing(instanceOfExpression)) {
agreeingInstanceof = true;
+ conflictingInstanceof = null;
}
else if (isConflicting(instanceOfExpression)) {
conflictingInstanceof = instanceOfExpression;
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/WeakestTypeFinder.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/WeakestTypeFinder.java
index 1440c58e5113..aade5a56361f 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/WeakestTypeFinder.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/WeakestTypeFinder.java
@@ -132,7 +132,7 @@ public class WeakestTypeFinder {
else if (referenceParent instanceof PsiVariable) {
final PsiVariable variable = (PsiVariable)referenceParent;
final PsiType type = variable.getType();
- if (!checkType(type, weakestTypeClasses)) {
+ if (!type.isAssignableFrom(variableOrMethodType) || !checkType(type, weakestTypeClasses)) {
return Collections.emptyList();
}
}
@@ -251,7 +251,7 @@ public class WeakestTypeFinder {
if (!hasUsages) {
return Collections.emptyList();
}
- weakestTypeClasses = filterAccessibleClasses(weakestTypeClasses, variableOrMethod);
+ weakestTypeClasses = filterAccessibleClasses(weakestTypeClasses, variableOrMethodClass, variableOrMethod);
return weakestTypeClasses;
}
@@ -442,22 +442,23 @@ public class WeakestTypeFinder {
}
final PsiExpression lhs = assignmentExpression.getLExpression();
final PsiExpression rhs = assignmentExpression.getRExpression();
+ if (rhs == null) {
+ return false;
+ }
final PsiType lhsType = lhs.getType();
+ final PsiType rhsType = rhs.getType();
+ if (lhsType == null || rhsType == null || !lhsType.isAssignableFrom(rhsType)) {
+ return false;
+ }
if (referenceElement.equals(rhs)) {
if (!checkType(lhsType, weakestTypeClasses)) {
return false;
}
}
- else if (useRighthandTypeAsWeakestTypeInAssignments) {
- if (rhs == null) {
- return false;
- }
- if (!(rhs instanceof PsiNewExpression) || !(rhs instanceof PsiTypeCastExpression)) {
- final PsiType rhsType = rhs.getType();
- if (lhsType == null || lhsType.equals(rhsType)) {
- return false;
- }
- }
+ else if (useRighthandTypeAsWeakestTypeInAssignments &&
+ (!(rhs instanceof PsiNewExpression) || !(rhs instanceof PsiTypeCastExpression)) &&
+ lhsType.equals(rhsType)) {
+ return false;
}
return true;
}
@@ -546,14 +547,14 @@ public class WeakestTypeFinder {
return true;
}
- public static Set<PsiClass> filterAccessibleClasses(Set<PsiClass> weakestTypeClasses, PsiElement context) {
+ public static Set<PsiClass> filterAccessibleClasses(Set<PsiClass> weakestTypeClasses, PsiClass upperBound, PsiElement context) {
final Set<PsiClass> result = new HashSet<PsiClass>();
for (PsiClass weakestTypeClass : weakestTypeClasses) {
- if (PsiUtil.isAccessible(weakestTypeClass, context, null)) {
+ if (PsiUtil.isAccessible(weakestTypeClass, context, null) && !weakestTypeClass.isDeprecated()) {
result.add(weakestTypeClass);
continue;
}
- final PsiClass visibleInheritor = getVisibleInheritor(weakestTypeClass, context);
+ final PsiClass visibleInheritor = getVisibleInheritor(weakestTypeClass, upperBound, context);
if (visibleInheritor != null) {
result.add(visibleInheritor);
}
@@ -562,16 +563,16 @@ public class WeakestTypeFinder {
}
@Nullable
- private static PsiClass getVisibleInheritor(@NotNull PsiClass superClass, PsiElement context) {
+ private static PsiClass getVisibleInheritor(@NotNull PsiClass superClass, PsiClass upperBound, PsiElement context) {
final Query<PsiClass> search = DirectClassInheritorsSearch.search(superClass, context.getResolveScope());
final Project project = superClass.getProject();
for (PsiClass aClass : search) {
- if (superClass.isInheritor(aClass, true)) {
+ if (aClass.isInheritor(superClass, true) && upperBound.isInheritor(aClass, true)) {
if (PsiUtil.isAccessible(project, aClass, context, null)) {
return aClass;
}
else {
- return getVisibleInheritor(aClass, context);
+ return getVisibleInheritor(aClass, upperBound, context);
}
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/SimplifiableAnnotationInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/SimplifiableAnnotationInspection.java
index 794716ba0412..e45f06cac284 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/SimplifiableAnnotationInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/SimplifiableAnnotationInspection.java
@@ -16,9 +16,10 @@
package com.siyeh.ig.style;
import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
+import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.IncorrectOperationException;
@@ -46,30 +47,30 @@ public class SimplifiableAnnotationInspection extends BaseInspection {
@NotNull
@Override
protected String buildErrorString(Object... infos) {
- return InspectionGadgetsBundle.message("simplifiable.annotation.problem.descriptor");
+ if (((Boolean)infos[0]).booleanValue()) {
+ return InspectionGadgetsBundle.message("simplifiable.annotation.whitespace.problem.descriptor");
+ }
+ else {
+ return InspectionGadgetsBundle.message("simplifiable.annotation.problem.descriptor");
+ }
}
@Override
protected InspectionGadgetsFix buildFix(Object... infos) {
- final PsiAnnotation annotation = (PsiAnnotation)infos[0];
- return new SimplifiableAnnotationFix(annotation);
+ return new SimplifiableAnnotationFix();
}
private static class SimplifiableAnnotationFix extends InspectionGadgetsFix {
- private final String replacement;
-
- public SimplifiableAnnotationFix(PsiAnnotation annotation) {
- this.replacement = buildAnnotationText(annotation, new StringBuilder()).toString();
- }
+ public SimplifiableAnnotationFix() {}
@Override
@NotNull
public String getName() {
- return InspectionGadgetsBundle.message("simplifiable.annotation.quickfix",
- StringUtil.shortenTextWithEllipsis(replacement, 50, 0, true));
+ return InspectionGadgetsBundle.message("simplifiable.annotation.quickfix");
}
- @Override
+
+ @Override
@NotNull
public String getFamilyName() {
return getName();
@@ -78,23 +79,25 @@ public class SimplifiableAnnotationInspection extends BaseInspection {
@Override
protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
final PsiElement element = descriptor.getPsiElement();
- if (!(element instanceof PsiAnnotation)) {
+ final PsiAnnotation annotation = PsiTreeUtil.getParentOfType(element, PsiAnnotation.class);
+ if (annotation == null) {
return;
}
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
- final PsiAnnotation annotation = factory.createAnnotationFromText(replacement, element);
- element.replace(annotation);
+ final String annotationText = buildAnnotationText(annotation);
+ final PsiAnnotation newAnnotation = factory.createAnnotationFromText(annotationText, element);
+ annotation.replace(newAnnotation);
}
- private static StringBuilder buildAnnotationText(PsiAnnotation annotation, StringBuilder out) {
- out.append('@');
+ private static String buildAnnotationText(PsiAnnotation annotation) {
+ final StringBuilder out = new StringBuilder("@");
final PsiJavaCodeReferenceElement nameReferenceElement = annotation.getNameReferenceElement();
assert nameReferenceElement != null;
out.append(nameReferenceElement.getText());
final PsiAnnotationParameterList parameterList = annotation.getParameterList();
final PsiNameValuePair[] attributes = parameterList.getAttributes();
if (attributes.length == 0) {
- return out;
+ return out.toString();
}
out.append('(');
if (attributes.length == 1) {
@@ -116,7 +119,7 @@ public class SimplifiableAnnotationInspection extends BaseInspection {
}
}
out.append(')');
- return out;
+ return out.toString();
}
private static StringBuilder buildAttributeValueText(PsiAnnotationMemberValue value, StringBuilder out) {
@@ -128,7 +131,7 @@ public class SimplifiableAnnotationInspection extends BaseInspection {
}
}
else if (value instanceof PsiAnnotation) {
- return buildAnnotationText((PsiAnnotation)value, out);
+ return out.append(buildAnnotationText((PsiAnnotation)value));
}
return out.append(value.getText());
}
@@ -151,36 +154,36 @@ public class SimplifiableAnnotationInspection extends BaseInspection {
}
final PsiNameValuePair[] attributes = parameterList.getAttributes();
final PsiElement[] annotationChildren = annotation.getChildren();
- if (annotationChildren.length >= 2 && annotationChildren[1] instanceof PsiWhiteSpace) {
- if (!containsError(annotation)) {
- registerError(annotation, annotation);
- }
+ if (annotationChildren.length >= 2 && annotationChildren[1] instanceof PsiWhiteSpace && !containsError(annotation)) {
+ registerError(annotationChildren[1], Boolean.TRUE);
}
- else if (attributes.length == 0) {
- final PsiElement[] children = parameterList.getChildren();
- if (children.length <= 0) {
- return;
- }
- if (!containsError(annotation)) {
- registerError(annotation, annotation);
+ if (attributes.length == 0) {
+ if (parameterList.getChildren().length > 0 && !containsError(annotation)) {
+ registerError(parameterList, ProblemHighlightType.LIKE_UNUSED_SYMBOL, Boolean.FALSE);
}
}
else if (attributes.length == 1) {
final PsiNameValuePair attribute = attributes[0];
- @NonNls final String name = attribute.getName();
+ final PsiIdentifier identifier = attribute.getNameIdentifier();
final PsiAnnotationMemberValue attributeValue = attribute.getValue();
- if (!PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME.equals(name)) {
- if (!(attributeValue instanceof PsiArrayInitializerMemberValue)) {
- return;
- }
- final PsiArrayInitializerMemberValue arrayValue = (PsiArrayInitializerMemberValue)attributeValue;
- final PsiAnnotationMemberValue[] initializers = arrayValue.getInitializers();
- if (initializers.length != 1) {
- return;
+ if (identifier != null && attributeValue != null) {
+ @NonNls final String name = attribute.getName();
+ if (PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME.equals(name) && !containsError(annotation)) {
+ registerErrorAtOffset(attribute, 0, attributeValue.getStartOffsetInParent(), ProblemHighlightType.LIKE_UNUSED_SYMBOL,
+ Boolean.FALSE);
}
}
+ if (!(attributeValue instanceof PsiArrayInitializerMemberValue)) {
+ return;
+ }
+ final PsiArrayInitializerMemberValue arrayValue = (PsiArrayInitializerMemberValue)attributeValue;
+ final PsiAnnotationMemberValue[] initializers = arrayValue.getInitializers();
+ if (initializers.length != 1) {
+ return;
+ }
if (!containsError(annotation)) {
- registerError(annotation, annotation);
+ registerError(arrayValue.getFirstChild(), ProblemHighlightType.LIKE_UNUSED_SYMBOL, Boolean.FALSE);
+ registerError(arrayValue.getLastChild(), ProblemHighlightType.LIKE_UNUSED_SYMBOL, Boolean.FALSE);
}
}
else if (attributes.length > 1) {
@@ -189,15 +192,15 @@ public class SimplifiableAnnotationInspection extends BaseInspection {
if (!(value instanceof PsiArrayInitializerMemberValue)) {
continue;
}
- final PsiArrayInitializerMemberValue arrayInitializerMemberValue = (PsiArrayInitializerMemberValue)value;
- final PsiAnnotationMemberValue[] initializers = arrayInitializerMemberValue.getInitializers();
+ final PsiArrayInitializerMemberValue arrayValue = (PsiArrayInitializerMemberValue)value;
+ final PsiAnnotationMemberValue[] initializers = arrayValue.getInitializers();
if (initializers.length != 1) {
continue;
}
if (!containsError(annotation)) {
- registerError(annotation, annotation);
+ registerError(arrayValue.getFirstChild(), ProblemHighlightType.LIKE_UNUSED_SYMBOL, Boolean.FALSE);
+ registerError(arrayValue.getLastChild(), ProblemHighlightType.LIKE_UNUSED_SYMBOL, Boolean.FALSE);
}
- return;
}
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/StringBufferReplaceableByStringInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/StringBufferReplaceableByStringInspection.java
index 4747e7426fd7..70b620f9434c 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/StringBufferReplaceableByStringInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/StringBufferReplaceableByStringInspection.java
@@ -20,7 +20,6 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
-import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.ContainerUtil;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
@@ -86,7 +85,7 @@ public class StringBufferReplaceableByStringInspection extends BaseInspection {
}
@Override
- protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
+ protected void doFix(Project project, ProblemDescriptor descriptor) {
final PsiElement element = descriptor.getPsiElement();
final PsiElement parent = element.getParent();
if (!(parent instanceof PsiVariable)) {
@@ -290,6 +289,9 @@ public class StringBufferReplaceableByStringInspection extends BaseInspection {
methodCallExpression = (PsiMethodCallExpression)grandParent;
parent = methodCallExpression.getParent();
grandParent = parent.getParent();
+ if ("toString".equals(methodCallExpression.getMethodExpression().getReferenceName())) {
+ break;
+ }
}
if (buildStringExpression(methodCallExpression, myBuilder) == null) {
myProblem = true;
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryEnumModifierInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryEnumModifierInspection.java
index 2aa72fae7bbe..7d8d9558ef53 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryEnumModifierInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryEnumModifierInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2012 Dave Griffith, Bas Leijdekkers
+ * Copyright 2003-2014 Dave Griffith, Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@ package com.siyeh.ig.style;
import com.intellij.codeInspection.CleanupLocalInspectionTool;
import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.util.IncorrectOperationException;
@@ -112,7 +113,7 @@ public class UnnecessaryEnumModifierInspection extends BaseInspection implements
for (final PsiElement child : children) {
final String text = child.getText();
if (PsiModifier.STATIC.equals(text)) {
- registerError(child, child, aClass);
+ registerError(child, ProblemHighlightType.LIKE_UNUSED_SYMBOL, child, aClass);
}
}
}
@@ -131,7 +132,7 @@ public class UnnecessaryEnumModifierInspection extends BaseInspection implements
for (final PsiElement child : children) {
final String text = child.getText();
if (PsiModifier.PRIVATE.equals(text)) {
- registerError(child, child, method);
+ registerError(child, ProblemHighlightType.LIKE_UNUSED_SYMBOL, child, method);
}
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryInterfaceModifierInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryInterfaceModifierInspection.java
index 310cc20c30b6..a0718c07fa8f 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryInterfaceModifierInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryInterfaceModifierInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2012 Dave Griffith, Bas Leijdekkers
+ * Copyright 2003-2014 Dave Griffith, Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@ package com.siyeh.ig.style;
import com.intellij.codeInspection.CleanupLocalInspectionTool;
import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiUtil;
@@ -214,7 +215,7 @@ public class UnnecessaryInterfaceModifierInspection extends BaseInspection imple
}
for (PsiElement child : children) {
if (modifiers.contains(child.getText())) {
- registerError(child, redundantModifiers.toString(), list);
+ registerError(child, ProblemHighlightType.LIKE_UNUSED_SYMBOL, redundantModifiers.toString(), list);
}
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarySemicolonInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarySemicolonInspection.java
index c1a75887c6aa..36f5af9408df 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarySemicolonInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarySemicolonInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2009 Dave Griffith, Bas Leijdekkers
+ * Copyright 2003-2014 Dave Griffith, Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@ package com.siyeh.ig.style;
import com.intellij.codeInspection.CleanupLocalInspectionTool;
import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
@@ -111,7 +112,7 @@ public class UnnecessarySemicolonInspection extends BaseInspection implements Cl
private void findTopLevelSemicolons(PsiElement element) {
for (PsiElement sibling = element.getFirstChild(); sibling != null; sibling = skipForwardWhiteSpacesAndComments(sibling)) {
if (PsiUtil.isJavaToken(sibling, JavaTokenType.SEMICOLON)) {
- registerError(sibling);
+ registerError(sibling, ProblemHighlightType.LIKE_UNUSED_SYMBOL);
}
}
}
@@ -149,7 +150,7 @@ public class UnnecessarySemicolonInspection extends BaseInspection implements Cl
if (next == null || !next.equals(aClass.getRBrace())) {
return;
}
- registerError(element);
+ registerError(element, ProblemHighlightType.LIKE_UNUSED_SYMBOL);
}
private void findUnnecessarySemicolonsAfterEnumConstants(
@@ -171,11 +172,11 @@ public class UnnecessarySemicolonInspection extends BaseInspection implements Cl
if (!JavaTokenType.COMMA.equals(prevTokenType)
&& !JavaTokenType.LBRACE.equals(
prevTokenType)) {
- registerError(child);
+ registerError(child, ProblemHighlightType.LIKE_UNUSED_SYMBOL);
}
}
else {
- registerError(child);
+ registerError(child, ProblemHighlightType.LIKE_UNUSED_SYMBOL);
}
}
}
@@ -207,7 +208,7 @@ public class UnnecessarySemicolonInspection extends BaseInspection implements Cl
if (semicolon == null) {
return;
}
- registerError(semicolon);
+ registerError(semicolon, ProblemHighlightType.LIKE_UNUSED_SYMBOL);
}
}
@@ -218,7 +219,7 @@ public class UnnecessarySemicolonInspection extends BaseInspection implements Cl
if (last instanceof PsiJavaToken && ((PsiJavaToken)last).getTokenType() == JavaTokenType.RPARENTH) {
final PsiElement prev = skipBackwardWhiteSpacesAndComments(last);
if (prev instanceof PsiJavaToken && ((PsiJavaToken)prev).getTokenType() == JavaTokenType.SEMICOLON) {
- registerError(prev);
+ registerError(prev, ProblemHighlightType.LIKE_UNUSED_SYMBOL);
}
}
}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/HighlightUtils.java b/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/HighlightUtils.java
index 1894986e9a5b..6444ff8b0660 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/HighlightUtils.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/HighlightUtils.java
@@ -34,6 +34,7 @@ import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.wm.StatusBar;
import com.intellij.openapi.wm.WindowManager;
@@ -41,6 +42,7 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiNameIdentifierOwner;
import com.intellij.psi.PsiReference;
import com.intellij.psi.util.PsiUtilCore;
+import com.intellij.util.containers.ContainerUtil;
import com.siyeh.InspectionGadgetsBundle;
import org.jetbrains.annotations.NotNull;
@@ -68,7 +70,12 @@ public class HighlightUtils {
final PsiElement[] elements =
PsiUtilCore.toPsiElementArray(elementCollection);
final PsiElement firstElement = elements[0];
- if (!firstElement.isValid()) {
+ if (ContainerUtil.exists(elements, new Condition<PsiElement>() {
+ @Override
+ public boolean value(PsiElement element) {
+ return !element.isValid();
+ }
+ })) {
return;
}
final Project project = firstElement.getProject();
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/ui/TextField.java b/plugins/InspectionGadgets/src/com/siyeh/ig/ui/TextField.java
index 47344f5cc861..28c947e24ac0 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/ui/TextField.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/ui/TextField.java
@@ -16,13 +16,13 @@
package com.siyeh.ig.ui;
import com.intellij.codeInspection.InspectionProfileEntry;
+import com.intellij.util.ReflectionUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
-import java.lang.reflect.Field;
public class TextField extends JTextField {
@@ -36,35 +36,13 @@ public class TextField extends JTextField {
private static String getPropertyValue(InspectionProfileEntry owner,
String property) {
- try {
- final Class<? extends InspectionProfileEntry> aClass =
- owner.getClass();
- final Field field = aClass.getField(property);
- return (String)field.get(owner);
- }
- catch (IllegalAccessException ignore) {
- return null;
- }
- catch (NoSuchFieldException ignore) {
- return null;
- }
+ return ReflectionUtil.getField(owner.getClass(), owner, String.class, property);
}
private static void setPropertyValue(InspectionProfileEntry owner,
String property,
String value) {
- try {
- final Class<? extends InspectionProfileEntry> aClass =
- owner.getClass();
- final Field field = aClass.getField(property);
- field.set(owner, value);
- }
- catch (IllegalAccessException ignore) {
- // do nothing
- }
- catch (NoSuchFieldException ignore) {
- // do nothing
- }
+ ReflectionUtil.setField(owner.getClass(), owner, String.class, property, value);
}
private class TextFieldDocumentListener implements DocumentListener {
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/AmbiguousFieldAccess.html b/plugins/InspectionGadgets/src/inspectionDescriptions/AmbiguousFieldAccess.html
index b22ad3712458..b0f698b74e7e 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/AmbiguousFieldAccess.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/AmbiguousFieldAccess.html
@@ -12,8 +12,8 @@ accessed, when in fact a field from the super class is accessed. To make the int
<b>class</b> Y {
<b>void</b> foo(String s) {
<b>new</b> X() {{
- System.out.println(s); // problem indicated here
- }}
+ System.out.println(s); // here the field is accessed not the parameter
+ }};
}
}
</code></pre>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/PropertyValueSetToItself.html b/plugins/InspectionGadgets/src/inspectionDescriptions/PropertyValueSetToItself.html
new file mode 100644
index 000000000000..c72e160a9b8c
--- /dev/null
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/PropertyValueSetToItself.html
@@ -0,0 +1,10 @@
+<html>
+<body>
+Reports calls on a setter with the value of same objects getter.
+For example: <code>bean.setPayerId(bean.getPayerId());</code>
+In regular circumstances this code is a no-op and probably not what was intented..
+<!-- tooltip end -->
+<p>
+ <small>New in 14</small>
+</body>
+</html> \ No newline at end of file
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/ReturnNull.html b/plugins/InspectionGadgets/src/inspectionDescriptions/ReturnNull.html
index 70255c1e9440..c36afbcd8886 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/ReturnNull.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/ReturnNull.html
@@ -3,14 +3,14 @@
Reports return statements with <b>null</b> values.
While occasionally useful, this construct may make the code more prone
to failing with a <b>NullPointerException</b>, and often indicates that the
-developer doesn't really understand the classes intended semantics.
+developer doesn't really understand the class's intended semantics.
<!-- tooltip end -->
<p>
-Use the first control below to let this inspection ignore private methods.
+Use the first checkbox below to let this inspection ignore private methods.
<p>
-Use bottom three controls to specify whether this inspection should report
+Use the bottom three checkboxes to specify whether
<b>null</b> values on array returns, collection
-object returns, plain object returns, or a combination of the three.
+object returns, plain object returns, or a combination of the three should be reported.
<p>
</body>
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/MethodCallOnString.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/MethodCallOnString.after.java
new file mode 100644
index 000000000000..4ced8b802fc5
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/MethodCallOnString.after.java
@@ -0,0 +1,5 @@
+public class MethodCallOnString {
+ public static void main(String... args) {
+ int length = "ABC".length();
+ }
+} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/MethodCallOnString.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/MethodCallOnString.java
new file mode 100644
index 000000000000..2ff02036eced
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/replace_with_string/MethodCallOnString.java
@@ -0,0 +1,6 @@
+public class MethodCallOnString {
+ public static void main(String... args) {
+ StringBuilder theBuilder<caret> = new StringBuilder("ABC");
+ int length = theBuilder.toString().length();
+ }
+} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/declare_collection_as_interface/DeclareCollectionAsInterface.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/declare_collection_as_interface/DeclareCollectionAsInterface.java
index e5c11992d86c..f21cc080de25 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/declare_collection_as_interface/DeclareCollectionAsInterface.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/declare_collection_as_interface/DeclareCollectionAsInterface.java
@@ -60,4 +60,14 @@ public class DeclareCollectionAsInterface
<warning descr="Declaration of 'HashSet' should probably be weakened to 'java.util.Set'">HashSet</warning><String> set = new HashSet<>();
set.add("foo");
}
+
+ public static Properties stringToProperties(String propertiesAsString) { return null; }
+ public static Properties stringToProperties2(String propertiesAsString) { return null; }
+ public static Properties stringToProperties3(String propertiesAsString) { return null; }
+
+ void m() {
+ stringToProperties("");
+ <error descr="Incompatible types. Found: 'java.util.Properties', required: 'java.lang.String'">String s = stringToProperties2("");</error>
+ <error descr="Incompatible types. Found: 'java.util.Properties', required: 'java.lang.String'">s = stringToProperties3("")</error>;
+ }
}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/AutoClosableTest.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/AutoClosableTest.java
index 3d9b0a2fd811..7c96abd2260c 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/AutoClosableTest.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/AutoClosableTest.java
@@ -31,13 +31,13 @@ class AutoClosableTest2
public static class Bar extends Foo {}
public static void test() {
- try (Bar bar = new Bar()) {
+ try (Bar <warning descr="Type of variable 'bar' may be weakened to 'com.siyeh.igtest.abstraction.weaken_type.AutoClosableTest2.Foo'">bar</warning> = new Bar()) {
bar.go();
}
}
void dodo() throws java.io.IOException {
- try (java.io.Reader reader = new java.io.FileReader("/home/steve/foo.txt")) {
+ try (java.io.Reader <warning descr="Type of variable 'reader' may be weakened to 'java.io.Closeable'">reader</warning> = new java.io.FileReader("/home/steve/foo.txt")) {
System.out.println(reader);
}
}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/NumberAdderDemo.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/NumberAdderDemo.java
index 0a009777a810..4b3547198e83 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/NumberAdderDemo.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/NumberAdderDemo.java
@@ -1,6 +1,6 @@
-package com.siyeh.igtest.abstraction.weaken_type;
+package weaken_type;
-import com.siyeh.igtest.abstraction.weaken_type.sub.NumberAdderExtension;
+import weaken_type.sub.NumberAdderExtension;
public class NumberAdderDemo {
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/TypeMayBeWeakened.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/TypeMayBeWeakened.java
index aeb2e1a5f811..370aba53a19c 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/TypeMayBeWeakened.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/TypeMayBeWeakened.java
@@ -52,7 +52,7 @@ public class TypeMayBeWeakened {
foo(new WeakBoolean());
}
- void foo(WeakBoolean b) {
+ void foo(WeakBoolean <warning descr="Type of parameter 'b' may be weakened to 'java.lang.Object'">b</warning>) {
System.out.println("b: " + b);
}
@@ -65,7 +65,7 @@ public class TypeMayBeWeakened {
FileInputStream fis=new FileInputStream("/etc/modules");
}
catch(FileNotFoundException fnfex) {
- IllegalArgumentException iaex=new IllegalArgumentException("Exception Message");
+ IllegalArgumentException <warning descr="Type of variable 'iaex' may be weakened to 'java.lang.RuntimeException'">iaex</warning>=new IllegalArgumentException("Exception Message");
iaex.initCause(fnfex);
throw iaex;
}
@@ -82,7 +82,7 @@ public class TypeMayBeWeakened {
void foo() { Test f = new Test(); f.x++; }
}
- void listy(ArrayList list) {
+ void listy(ArrayList <warning descr="Type of parameter 'list' may be weakened to 'java.lang.Iterable'">list</warning>) {
for (Object o : list) {
}
@@ -130,7 +130,7 @@ class MyClass {
public MyClass(java.util.Date date, String[] classNames) {}
- static MyClass readMyClass(final ObjectInputStream objectInput) {
+ static MyClass readMyClass(final ObjectInputStream <warning descr="Type of parameter 'objectInput' may be weakened to 'com.siyeh.igtest.abstraction.weaken_type.DataInput'">objectInput</warning>) {
final long time = objectInput.readLong();
final int size = objectInput.readInt();
final String[] classNames = new String[size];
@@ -150,4 +150,16 @@ abstract class ObjectInputStream implements DataInput {
public String readUTF() {
return null;
}
-} \ No newline at end of file
+}
+class Test implements Foo2 {
+ void test(Test <warning descr="Type of parameter 't' may be weakened to 'com.siyeh.igtest.abstraction.weaken_type.Foo2'">t</warning>) {
+ t.bar();
+ }
+ public void bar() {
+ }
+}
+@Deprecated
+interface Foo {
+ void bar();
+}
+interface Foo2 extends Foo {} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/sub/NumberAdder.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/sub/NumberAdder.java
deleted file mode 100644
index 8f15c784c12a..000000000000
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/sub/NumberAdder.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package com.siyeh.igtest.abstraction.weaken_type.sub;
-
-/**
- * Created by IntelliJ IDEA. User: HONOURK Date: 21-Aug-2008 Time: 12:15:41 To change this template
- * use File | Settings | File Templates.
- */
-public interface NumberAdder {
- int doSomething();
-}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/sub/NumberAdderExtension.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/sub/NumberAdderExtension.java
deleted file mode 100644
index 21bdf2988a11..000000000000
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/sub/NumberAdderExtension.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.siyeh.igtest.abstraction.weaken_type.sub;
-
-/**
- * Created by IntelliJ IDEA. User: HONOURK Date: 21-Aug-2008 Time: 12:15:41 To change this template
- * use File | Settings | File Templates.
- */
-public class NumberAdderExtension extends NumberAdderImpl {
- @Override
- public int getNumberOne() {
- return super.getNumberOne();
- }
-}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/sub/NumberAdderImpl.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/sub/NumberAdderImpl.java
deleted file mode 100644
index 669373d0342f..000000000000
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type/sub/NumberAdderImpl.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.siyeh.igtest.abstraction.weaken_type.sub;
-
-public class NumberAdderImpl implements NumberAdder {
-
- public int doSomething() {
- return getNumberOne() + 1;
- }
-
- protected int getNumberOne() {
- return 1;
- }
-}
-
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/castConflictingInstanceof/orInstanceofOrInstanceof/OrInstanceofOrInstanceof.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/castConflictingInstanceof/orInstanceofOrInstanceof/OrInstanceofOrInstanceof.java
new file mode 100644
index 000000000000..228fe5c10117
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/castConflictingInstanceof/orInstanceofOrInstanceof/OrInstanceofOrInstanceof.java
@@ -0,0 +1,30 @@
+package com.siyeh.igtest.bugs.castConflictingInstanceof.andAnd;
+
+class Test {
+
+ public void test(Object o)
+ {
+
+ if (!(o instanceof Number) ||
+ ((Number)o).intValue() == 0 ||
+ !(o instanceof Integer) ||
+ ((Integer) o).byteValue() == 9) {
+ System.out.println();
+ }
+
+ if (!(o instanceof Number) ||
+ ((Number)o).intValue() == 0 ||
+ !(o instanceof Integer) ||
+ !(o instanceof Number) ||
+ ((Integer) o).byteValue() == 9) {
+ System.out.println();
+ }
+
+ if (!(o instanceof Integer) ||
+ ((Number)o).intValue() == 0 ||
+ !(o instanceof Number) ||
+ ((Integer) o).byteValue() == 9) {
+ System.out.println();
+ }
+ }
+}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/castConflictingInstanceof/orInstanceofOrInstanceof/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/castConflictingInstanceof/orInstanceofOrInstanceof/expected.xml
new file mode 100644
index 000000000000..e8f00e82629f
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/castConflictingInstanceof/orInstanceofOrInstanceof/expected.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<problems>
+
+</problems> \ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/mismatched_array_read_write/MismatchedArrayReadWrite.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/mismatched_array_read_write/MismatchedArrayReadWrite.java
index beed034bc1ba..33683aaa4d1f 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/mismatched_array_read_write/MismatchedArrayReadWrite.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/mismatched_array_read_write/MismatchedArrayReadWrite.java
@@ -183,4 +183,17 @@ class Ferrari458Spider implements java.io.Serializable {
private static final java.io.ObjectStreamField[] serialPersistentFields = {
new java.io.ObjectStreamField("b", String.class)
};
+}
+
+class TestIDEA128098 {
+ private static final String[] CONSTANT_ARRAY = new String[]{""}; // warning is on this constant
+
+
+ enum SomeEnum {
+ ITEM( CONSTANT_ARRAY);
+ private final String[] myPatterns;
+ SomeEnum(String... patterns) {
+ myPatterns = patterns;
+ }
+ }
} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/simplifiable_annotation/SimplifiableAnnotation.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/simplifiable_annotation/SimplifiableAnnotation.java
index b40289507a08..1fe15e0f3eeb 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/simplifiable_annotation/SimplifiableAnnotation.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/simplifiable_annotation/SimplifiableAnnotation.java
@@ -2,8 +2,8 @@ package com.siyeh.igtest.style.simplifiable_annotation;
public class SimplifiableAnnotation {
- <warning descr="Annotation '@ SuppressWarnings(value = \\"blabla\\")' can be simplified">@ SuppressWarnings(value = "blabla")</warning>
- <warning descr="Annotation '@ Deprecated()' can be simplified">@ Deprecated()</warning>
+ @<warning descr="Unnecessary whitespace in annotation"> </warning>SuppressWarnings(<warning descr="Unnecessary 'value =' in annotation">value = </warning>"blabla")
+ @<warning descr="Unnecessary whitespace in annotation"> </warning>Deprecated<warning descr="Unnecessary '()' in annotation">()</warning>
Object foo() {
return null;
}
@@ -14,8 +14,8 @@ public class SimplifiableAnnotation {
@interface ArrayAnnotation {
String[] array();
}
-<warning descr="Annotation '@ValueAnnotation({\\"the value\\"})' can be simplified">@ValueAnnotation({"the value"})</warning>
-<warning descr="Annotation '@ArrayAnnotation(array = {\\"first\\"})' can be simplified">@ArrayAnnotation(array = {"first"})</warning>
+@ValueAnnotation(<warning descr="Unnecessary '{' in annotation">{</warning>"the value"<warning descr="Unnecessary '}' in annotation">}</warning>)
+@ArrayAnnotation(array = <warning descr="Unnecessary '{' in annotation">{</warning>"first"<warning descr="Unnecessary '}' in annotation">}</warning>)
class MyClass {
@ <error descr="'value' missing though required">ValueAnnotation</error>
@@ -23,7 +23,7 @@ class MyClass {
return -1;
}
- <warning descr="Annotation '@Two(i={1}, j = 2)' can be simplified">@Two(i={1}, j = 2)</warning>
+ @Two(i=<warning descr="Unnecessary '{' in annotation">{</warning>1<warning descr="Unnecessary '}' in annotation">}</warning>, j = 2)
String s;
}
@interface Two {
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/abstraction/TypeMayBeWeakenedInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/abstraction/TypeMayBeWeakenedInspectionTest.java
index fec91135e731..df0048a5218f 100644
--- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/abstraction/TypeMayBeWeakenedInspectionTest.java
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/abstraction/TypeMayBeWeakenedInspectionTest.java
@@ -1,24 +1,48 @@
package com.siyeh.ig.abstraction;
-import com.intellij.openapi.roots.LanguageLevelProjectExtension;
-import com.intellij.pom.java.LanguageLevel;
-import com.siyeh.ig.IGInspectionTestCase;
+import com.intellij.codeInspection.InspectionProfileEntry;
+import com.siyeh.ig.LightInspectionTestCase;
+import org.jetbrains.annotations.Nullable;
-public class TypeMayBeWeakenedInspectionTest extends IGInspectionTestCase {
+public class TypeMayBeWeakenedInspectionTest extends LightInspectionTestCase {
- public void test() throws Exception {
- final TypeMayBeWeakenedInspection inspection =
- new TypeMayBeWeakenedInspection();
+ public void testTypeMayBeWeakened() { doTest(); }
+ public void testNumberAdderDemo() { doTest(); }
+ public void testAutoClosableTest() { doTest(); }
+
+ @Override
+ protected String[] getEnvironmentClasses() {
+ return new String[] {
+ "package weaken_type.sub;\n" +
+ "public class NumberAdderImpl implements NumberAdder {\n" +
+ " public int doSomething() {\n" +
+ " return getNumberOne() + 1;\n" +
+ " }\n" +
+ " protected int getNumberOne() {\n" +
+ " return 1;\n" +
+ " }\n" +
+ "}",
+ "package weaken_type.sub;\n" +
+ "public class NumberAdderExtension extends NumberAdderImpl {\n" +
+ " @Override\n" +
+ " public int getNumberOne() {\n" +
+ " return super.getNumberOne();\n" +
+ " }\n" +
+ "}"
+ };
+ }
+
+ @Override
+ protected String getBasePath() {
+ return "/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/weaken_type";
+ }
+
+ @Nullable
+ @Override
+ protected InspectionProfileEntry getInspection() {
+ final TypeMayBeWeakenedInspection inspection = new TypeMayBeWeakenedInspection();
inspection.doNotWeakenToJavaLangObject = false;
inspection.onlyWeakentoInterface = false;
- final LanguageLevelProjectExtension levelProjectExtension = LanguageLevelProjectExtension.getInstance(getProject());
- final LanguageLevel level = levelProjectExtension.getLanguageLevel();
- try {
- levelProjectExtension.setLanguageLevel(LanguageLevel.JDK_1_7);
- doTest("com/siyeh/igtest/abstraction/weaken_type", inspection);
- }
- finally {
- levelProjectExtension.setLanguageLevel(level);
- }
+ return inspection;
}
} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/CastConflictsWithInstanceofInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/CastConflictsWithInstanceofInspectionTest.java
index ff6d488a6fd9..079bda6ac35f 100644
--- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/CastConflictsWithInstanceofInspectionTest.java
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/CastConflictsWithInstanceofInspectionTest.java
@@ -43,6 +43,10 @@ public class CastConflictsWithInstanceofInspectionTest extends IGInspectionTestC
doTest();
}
+ public void testOrInstanceofOrInstanceof() throws Exception {
+ doTest();
+ }
+
private void doTest() throws Exception {
doTest("com/siyeh/igtest/bugs/castConflictingInstanceof/" + getTestName(true), new CastConflictsWithInstanceofInspection());
}
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/style/StringBufferReplaceableByStringFixTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/style/StringBufferReplaceableByStringFixTest.java
index f49e16b89c4a..8c7920b9567d 100644
--- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/style/StringBufferReplaceableByStringFixTest.java
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/style/StringBufferReplaceableByStringFixTest.java
@@ -32,4 +32,5 @@ public class StringBufferReplaceableByStringFixTest extends IGQuickFixesTestCase
public void testCharLiteral() { doTest(InspectionGadgetsBundle.message("string.builder.replaceable.by.string.quickfix")); }
public void testEscape() { doTest(InspectionGadgetsBundle.message("string.builder.replaceable.by.string.quickfix")); }
public void testUnescape() { doTest(InspectionGadgetsBundle.message("string.builder.replaceable.by.string.quickfix")); }
+ public void testMethodCallOnString() { doTest(InspectionGadgetsBundle.message("string.builder.replaceable.by.string.quickfix")); }
}
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/inheritance/ExtendsConcreteCollectionInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/inheritance/ExtendsConcreteCollectionInspectionTest.java
index 99c6a2480928..a2b334c2661c 100644
--- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/inheritance/ExtendsConcreteCollectionInspectionTest.java
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/inheritance/ExtendsConcreteCollectionInspectionTest.java
@@ -31,7 +31,7 @@ public class ExtendsConcreteCollectionInspectionTest extends LightInspectionTest
protected String[] getEnvironmentClasses() {
return new String[] {
"package java.util;" +
- "public class LinkedHashMap<K, V> {" +
+ "public class LinkedHashMap<K, V> extends HashMap<K,V> implements Map<K,V>{" +
" protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {\n" +
" return false;\n" +
" }" +
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/javabeans/PropertyValueSetToItselfInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/javabeans/PropertyValueSetToItselfInspectionTest.java
new file mode 100644
index 000000000000..d17387119ae1
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/javabeans/PropertyValueSetToItselfInspectionTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.siyeh.ig.javabeans;
+
+import com.intellij.codeInspection.InspectionProfileEntry;
+import com.siyeh.ig.LightInspectionTestCase;
+import org.jetbrains.annotations.Nullable;
+
+public class PropertyValueSetToItselfInspectionTest extends LightInspectionTestCase {
+
+ public void testSimple() {
+ doTest("class Bean {\n" +
+ " private String x;\n" +
+ " public void setX(String x) {\n" +
+ " this.x = x;\n" +
+ " }\n" +
+ " public String getX() { return x; }\n" +
+ " void m(Bean b) {\n" +
+ " (b)./*Property value set to itself*/setX/**/(b.getX());\n" +
+ " this./*Property value set to itself*/setX/**/(getX());\n" +
+ " }\n" +
+ "}");
+ }
+
+ public void testNoWarn() {
+ doTest("class Bean {\n" +
+ " private String x;\n" +
+ " public void setX(String x) {\n" +
+ " this.x = x;\n" +
+ " }\n" +
+ " public String getX() { return x; }\n" +
+ " void m(Bean b, Bean c) {\n" +
+ " (b).setX(c.getX());\n" +
+ " }\n" +
+ "}");
+ }
+
+ @Nullable
+ @Override
+ protected InspectionProfileEntry getInspection() {
+ return new PropertyValueSetToItselfInspection();
+ }
+} \ No newline at end of file
diff --git a/plugins/IntelliLang/java-support/resources/javaInjections.xml b/plugins/IntelliLang/java-support/resources/javaInjections.xml
index 4b66c8b13713..97ba2e624ac6 100644
--- a/plugins/IntelliLang/java-support/resources/javaInjections.xml
+++ b/plugins/IntelliLang/java-support/resources/javaInjections.xml
@@ -130,6 +130,13 @@
<place><![CDATA[psiParameter().ofMethod(1, psiMethod().withName("PrintStream").withParameters("java.lang.String", "java.lang.String").definedInClass("java.io.PrintStream"))]]></place>
<place><![CDATA[psiParameter().ofMethod(1, psiMethod().withName("encode").withParameters("java.lang.String", "java.lang.String").definedInClass("java.net.URLEncoder"))]]></place>
<place><![CDATA[psiParameter().ofMethod(1, psiMethod().withName("decode").withParameters("java.lang.String", "java.lang.String").definedInClass("java.net.URLDecoder"))]]></place>
+ <place><![CDATA[psiParameter().ofMethod(0, psiMethod().withName("setCharacterEncoding").withParameters("java.lang.String").definedInClass("javax.servlet.ServletResponse"))]]></place>
+ <place><![CDATA[psiParameter().ofMethod(1, psiMethod().withName("newReader").withParameters("java.nio.channels.ReadableByteChannel", "java.lang.String").definedInClass("java.nio.channels.Channels"))]]></place>
+ <place><![CDATA[psiParameter().ofMethod(1, psiMethod().withName("newWriter").withParameters("java.nio.channels.WritableByteChannel", "java.lang.String").definedInClass("java.nio.channels.Channels"))]]></place>
+ <place><![CDATA[psiParameter().ofMethod(1, psiMethod().withName("createXMLEventReader").withParameters("java.io.InputStream", "java.lang.String").definedInClass("javax.xml.stream.XMLInputFactory"))]]></place>
+ <place><![CDATA[psiParameter().ofMethod(1, psiMethod().withName("createXMLStreamReader").withParameters("java.io.InputStream", "java.lang.String").definedInClass("javax.xml.stream.XMLInputFactory"))]]></place>
+ <place><![CDATA[psiParameter().ofMethod(1, psiMethod().withName("createXMLEventWriter").withParameters("java.io.OutputStream", "java.lang.String").definedInClass("javax.xml.stream.XMLInputFactory"))]]></place>
+ <place><![CDATA[psiParameter().ofMethod(1, psiMethod().withName("createXMLStreamWriter").withParameters("java.io.OutputStream", "java.lang.String").definedInClass("javax.xml.stream.XMLInputFactory"))]]></place>
</injection>
</component>
diff --git a/plugins/IntelliLang/src/META-INF/plugin.xml b/plugins/IntelliLang/src/META-INF/plugin.xml
index 8f8806a8b2ec..4caafeba1815 100644
--- a/plugins/IntelliLang/src/META-INF/plugin.xml
+++ b/plugins/IntelliLang/src/META-INF/plugin.xml
@@ -20,7 +20,6 @@
<depends optional="true" config-file="intellilang-xpath-support.xml">XPathView</depends>
<depends optional="true" config-file="intellilang-java-support.xml">com.intellij.modules.java</depends>
<depends optional="true" config-file="intellilang-xml-support.xml">com.intellij.modules.xml</depends>
- <depends optional="true" config-file="intellilang-python-support.xml">com.intellij.modules.python</depends>
<extensionPoints>
<extensionPoint name="languageSupport" interface="org.intellij.plugins.intelliLang.inject.LanguageInjectionSupport"/>
diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectorUtils.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectorUtils.java
index 48ee3b51fac2..1b4e43ec4df1 100644
--- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectorUtils.java
+++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectorUtils.java
@@ -226,7 +226,7 @@ public class InjectorUtils {
}
@Nullable
- public static BaseInjection findCommentInjection(PsiElement context, final String supportId, final Ref<PsiElement> causeRef) {
+ public static BaseInjection findCommentInjection(@NotNull PsiElement context, @NotNull String supportId, @Nullable Ref<PsiElement> causeRef) {
PsiElement target = CompletionUtil.getOriginalOrSelf(context);
PsiFile file = target.getContainingFile();
TreeMap<TextRange, BaseInjection> map = getInjectionMap(file);
@@ -247,17 +247,17 @@ public class InjectorUtils {
// make sure comment is close enough and ...
int off1 = r0.getEndOffset();
int off2 = e2.getTextRange().getStartOffset();
- if (off2 - off1 > 120) return null;
- if (off2 - off1 > 2) {
- // ... there's nothing in between on the top level and ...
- for (PsiElement e = e1; e != e2; e = e.getNextSibling()) {
- if (!isWhitespaceCommentOrBlank(e)) return null;
- }
- // ... there's no non-empty host in the left (comment) subtree
- Producer<PsiElement> producer = prevWalker(PsiTreeUtil.getDeepestLast(e1), e1);
+ if (off2 - off1 > 120) {
+ return null;
+ }
+ else if (off2 - off1 > 2) {
+ // ... there's no non-empty valid host in between comment and e2
+ Producer<PsiElement> producer = prevWalker(e2, commonParent);
PsiElement e;
while ( (e = producer.produce()) != null && e != psiComment) {
- if (e instanceof PsiLanguageInjectionHost && !StringUtil.isEmptyOrSpaces(e.getText())) {
+ if (e instanceof PsiLanguageInjectionHost &&
+ ((PsiLanguageInjectionHost)e).isValidHost() &&
+ !StringUtil.isEmptyOrSpaces(e.getText())) {
return null;
}
}
@@ -268,12 +268,9 @@ public class InjectorUtils {
return new BaseInjection(supportId).copyFrom(entry.getValue());
}
- protected static boolean isWhitespaceCommentOrBlank(PsiElement e) {
- return e instanceof PsiWhiteSpace || e instanceof PsiComment ||
- e instanceof PsiLanguageInjectionHost && StringUtil.isEmptyOrSpaces(e.getText());
- }
-
- protected static TreeMap<TextRange, BaseInjection> getInjectionMap(final PsiFile file) {
+ @Nullable
+ private static TreeMap<TextRange, BaseInjection> getInjectionMap(@Nullable final PsiFile file) {
+ if (file == null) return null; // e.g. null for synthetic groovy variables
return CachedValuesManager.getCachedValue(file, new CachedValueProvider<TreeMap<TextRange, BaseInjection>>() {
@Nullable
@Override
@@ -293,8 +290,6 @@ public class InjectorUtils {
CharSequence contents = file.getViewProvider().getContents();
final char[] contentsArray = CharArrayUtil.fromSequenceWithoutCopying(contents);
- //long time = System.currentTimeMillis();
-
int s0 = 0, s1 = contents.length();
for (int idx = searcher.scan(contents, contentsArray, s0, s1);
idx != -1;
@@ -309,30 +304,6 @@ public class InjectorUtils {
}
}
}
-
- //VirtualFile virtualFile = file.getVirtualFile();
- //Document document = FileDocumentManager.getInstance().getDocument(virtualFile);
- //EditorHighlighter highlighter = EditorHighlighterCache.getEditorHighlighterForCachesBuilding(document);
- //
- //ParserDefinition definition = LanguageParserDefinitions.INSTANCE.forLanguage(file.getLanguage());
- //TokenSet commentTokens = definition.getCommentTokens();
- //HighlighterIterator it = highlighter != null && PlatformIdTableBuilding.checkCanUseCachedEditorHighlighter(contents, highlighter) ?
- // highlighter.createIterator(0) : null;
- //
- //do {
- // if (it != null) {
- // while (!it.atEnd() && !commentTokens.contains(it.getTokenType())) it.advance();
- // if (it.atEnd()) break;
- // }
- // int s0 = it == null ? 0 : it.getStart();
- // int s1 = it == null ? contents.length() : it.getEnd();
- //
- // for () { .. }
- //
- // if (it != null && !it.atEnd()) it.advance();
- //} while (it != null && !it.atEnd());
-
- //System.out.println(Thread.currentThread().getName() + ": " + file.getName() + "@" + file.hashCode() + " indexed: " + (System.currentTimeMillis() - time));
return injectionMap;
}
@@ -373,18 +344,11 @@ public class InjectorUtils {
if (e == null || e == scope) return null;
PsiElement prev = e.getPrevSibling();
if (prev != null) {
- e = prev;
- while (true) {
- PsiElement lastChild = e.getLastChild();
- if (lastChild == null) break;
- e = lastChild;
- }
- return e;
+ return e = PsiTreeUtil.getDeepestLast(prev);
}
else {
PsiElement parent = e.getParent();
- e = parent == scope || parent instanceof PsiFile ? null : parent;
- return e;
+ return e = parent == scope || parent instanceof PsiFile ? null : parent;
}
}
};
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/IntentionPowerPackBundle.properties b/plugins/IntentionPowerPak/src/com/siyeh/IntentionPowerPackBundle.properties
index dc1b4c6f62d8..30e64929f8b2 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/IntentionPowerPackBundle.properties
+++ b/plugins/IntentionPowerPak/src/com/siyeh/IntentionPowerPackBundle.properties
@@ -145,7 +145,7 @@ convert.j.unit3.test.case.to.j.unit4.intention.name=Convert to JUnit4 Test Case
if.to.assertion.intention.family.name=Replace If with Assert Statement
if.to.assertion.intention.name=Replace 'if' with 'assert' statement
expand.to.normal.annotation.intention.family.name=Expand Annotation to Normal Form
-expand.to.normal.annotation.name=Expand to ''{0}''
+expand.to.normal.annotation.intention.name=Add 'value=' to annotation attribute
annotate.overridden.methods.intention.family.name=Annotate overriding methods and their parameters
annotate.overridden.methods.intention.method.name=Annotate overriding methods as ''@{0}''
annotate.overridden.methods.intention.parameters.name=Annotate same parameter of overriding methods as ''@{0}''
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/annotation/ExpandToNormalAnnotationIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/annotation/ExpandToNormalAnnotationIntention.java
index e9cd879df58e..a1563b807212 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/annotation/ExpandToNormalAnnotationIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/annotation/ExpandToNormalAnnotationIntention.java
@@ -15,25 +15,12 @@
*/
package com.siyeh.ipp.annotation;
-import com.intellij.openapi.editor.CaretModel;
-import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.fileEditor.FileEditorManager;
-import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
-import com.siyeh.IntentionPowerPackBundle;
-import com.siyeh.ipp.base.MutablyNamedIntention;
+import com.siyeh.ipp.base.Intention;
import com.siyeh.ipp.base.PsiElementPredicate;
import org.jetbrains.annotations.NotNull;
-public class ExpandToNormalAnnotationIntention extends MutablyNamedIntention {
-
- @Override
- protected String getTextForElement(PsiElement element) {
- final PsiNameValuePair annotation = (PsiNameValuePair)element;
- final String text = buildReplacementText(annotation);
- return IntentionPowerPackBundle.message(
- "expand.to.normal.annotation.name", text);
- }
+public class ExpandToNormalAnnotationIntention extends Intention {
@NotNull
@Override
@@ -41,38 +28,28 @@ public class ExpandToNormalAnnotationIntention extends MutablyNamedIntention {
return new ExpandToNormalAnnotationPredicate();
}
- public static String buildReplacementText(PsiNameValuePair attribute) {
+ public static String buildReplacementText(PsiAnnotationParameterList annotationParameterList) {
final StringBuilder text = new StringBuilder();
- final PsiAnnotationMemberValue value = attribute.getValue();
- text.append("value = ");
- if (value != null) {
- text.append(value.getText());
+ for (PsiNameValuePair nameValuePair : annotationParameterList.getAttributes()) {
+ if (text.length() != 0) {
+ text.append(',');
+ }
+ final String name = nameValuePair.getName();
+ text.append(name != null ? name : "value").append('=');
+ final PsiAnnotationMemberValue value = nameValuePair.getValue();
+ if (value != null) {
+ text.append(value.getText());
+ }
}
return text.toString();
}
@Override
protected void processIntention(@NotNull PsiElement element) {
- final PsiNameValuePair attribute = (PsiNameValuePair)element;
- final int textOffset = attribute.getTextOffset();
- final Project project = attribute.getProject();
- final String text = buildReplacementText(attribute);
- final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
- final PsiAnnotation newAnnotation = factory.createAnnotationFromText("@A(" + text +" )", attribute);
- final PsiAnnotationParameterList parent = (PsiAnnotationParameterList)attribute.getParent();
- for (PsiElement child = parent.getFirstChild(); child != null; child = child.getNextSibling()) {
- if (child instanceof PsiErrorElement) {
- child.delete();
- break;
- }
- }
- attribute.replace(newAnnotation.getParameterList().getAttributes()[0]);
- final FileEditorManager editorManager = FileEditorManager.getInstance(project);
- final Editor editor = editorManager.getSelectedTextEditor();
- if (editor == null) {
- return;
- }
- final CaretModel caretModel = editor.getCaretModel();
- caretModel.moveToOffset(textOffset + text.length() - 1);
+ final PsiAnnotationParameterList annotationParameterList = (PsiAnnotationParameterList)element.getParent();
+ final String text = buildReplacementText(annotationParameterList);
+ final PsiElementFactory factory = JavaPsiFacade.getElementFactory(annotationParameterList.getProject());
+ final PsiAnnotation newAnnotation = factory.createAnnotationFromText("@A(" + text +" )", element);
+ annotationParameterList.replace(newAnnotation.getParameterList());
}
}
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/asserttoif/ObjectsRequireNonNullIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/asserttoif/ObjectsRequireNonNullIntention.java
index 10caec211a5d..e3617711d6c0 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/asserttoif/ObjectsRequireNonNullIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/asserttoif/ObjectsRequireNonNullIntention.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@ import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.siyeh.ig.PsiReplacementUtil;
+import com.siyeh.ig.psiutils.ClassUtils;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import com.siyeh.ig.psiutils.VariableAccessUtils;
import com.siyeh.ipp.base.Intention;
@@ -58,6 +59,9 @@ public class ObjectsRequireNonNullIntention extends Intention {
annotation.delete();
} else {
final PsiStatement referenceStatement = PsiTreeUtil.getParentOfType(referenceExpression, PsiStatement.class);
+ if (referenceStatement == null) {
+ return;
+ }
final PsiElement parent = referenceStatement.getParent();
if (!(parent instanceof PsiCodeBlock)) {
return;
@@ -103,6 +107,9 @@ public class ObjectsRequireNonNullIntention extends Intention {
return false;
}
final PsiVariable variable = (PsiVariable)target;
+ if (ClassUtils.findClass("java.util.Objects", element) == null) {
+ return false;
+ }
if (NullableNotNullManager.isNotNull(variable)) {
return true;
}
diff --git a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/annotation/ExpandToNormalAnnotationIntentionTest.java b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/annotation/ExpandToNormalAnnotationIntentionTest.java
index dea52b1d28d3..31a5b061f291 100644
--- a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/annotation/ExpandToNormalAnnotationIntentionTest.java
+++ b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/annotation/ExpandToNormalAnnotationIntentionTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,6 +17,9 @@ package com.siyeh.ipp.annotation;
import com.siyeh.ipp.IPPTestCase;
+/**
+ * @see ExpandToNormalAnnotationIntention
+ */
public class ExpandToNormalAnnotationIntentionTest extends IPPTestCase {
public void testOneAttr() throws Exception {
doTest();
@@ -32,7 +35,7 @@ public class ExpandToNormalAnnotationIntentionTest extends IPPTestCase {
@Override
protected String getIntentionName() {
- return "Expand to 'value = \"foo\"'";
+ return "Add 'value=' to annotation attribute";
}
@Override
diff --git a/plugins/ant/jps-plugin/testSrc/org/jetbrains/jps/ant/JpsAntArtifactBuilderTaskTest.java b/plugins/ant/jps-plugin/testSrc/org/jetbrains/jps/ant/JpsAntArtifactBuilderTaskTest.java
index 426604fdfe97..baff66317278 100644
--- a/plugins/ant/jps-plugin/testSrc/org/jetbrains/jps/ant/JpsAntArtifactBuilderTaskTest.java
+++ b/plugins/ant/jps-plugin/testSrc/org/jetbrains/jps/ant/JpsAntArtifactBuilderTaskTest.java
@@ -18,6 +18,7 @@ package org.jetbrains.jps.ant;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.application.ex.PathManagerEx;
import com.intellij.openapi.util.io.FileUtil;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.incremental.artifacts.ArtifactBuilderTestCase;
import org.jetbrains.jps.model.serialization.JpsGlobalLoader;
@@ -26,6 +27,7 @@ import org.jetbrains.jps.model.serialization.PathMacroUtil;
import java.io.File;
import java.io.IOException;
+import java.util.Collections;
import java.util.Map;
import static com.intellij.util.io.TestFileSystemBuilder.fs;
@@ -61,8 +63,9 @@ public class JpsAntArtifactBuilderTaskTest extends ArtifactBuilderTestCase {
return PathManagerEx.findFileUnderProjectHome("plugins/ant/jps-plugin/testData", getClass()).getAbsolutePath();
}
+ @NotNull
@Override
- protected void addPathVariables(Map<String, String> pathVariables) {
- pathVariables.put("ARTIFACTS_OUT", FileUtil.toSystemIndependentName(myArtifactsOutput.getAbsolutePath()));
+ protected Map<String, String> getAdditionalPathVariables() {
+ return Collections.singletonMap("ARTIFACTS_OUT", FileUtil.toSystemIndependentName(myArtifactsOutput.getAbsolutePath()));
}
}
diff --git a/plugins/ant/src/com/intellij/lang/ant/AntIntrospector.java b/plugins/ant/src/com/intellij/lang/ant/AntIntrospector.java
index 234a734b08ec..ef0fa80192b1 100644
--- a/plugins/ant/src/com/intellij/lang/ant/AntIntrospector.java
+++ b/plugins/ant/src/com/intellij/lang/ant/AntIntrospector.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,12 +17,12 @@ package com.intellij.lang.ant;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.util.Alarm;
+import com.intellij.util.ReflectionUtil;
import org.apache.tools.ant.IntrospectionHelper;
import org.apache.tools.ant.TaskContainer;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
-import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
@@ -231,8 +231,7 @@ public final class AntIntrospector {
catch (Throwable e) {
try {
// assume it is older version of ant
- final Field helpersField = helperClass.getDeclaredField("helpers");
- final Map helpersCollection = (Map)helpersField.get(null);
+ Map helpersCollection = ReflectionUtil.getField(helperClass, null, null, "helpers");
helpersCollection.clear();
}
catch (Throwable _e) {
diff --git a/plugins/ant/src/com/intellij/lang/ant/config/execution/OutputParser.java b/plugins/ant/src/com/intellij/lang/ant/config/execution/OutputParser.java
index 6f2fb8549eb8..3af6d25c5c82 100644
--- a/plugins/ant/src/com/intellij/lang/ant/config/execution/OutputParser.java
+++ b/plugins/ant/src/com/intellij/lang/ant/config/execution/OutputParser.java
@@ -25,6 +25,8 @@ import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
+import com.intellij.problems.Problem;
+import com.intellij.problems.WolfTheProblemSolver;
import com.intellij.rt.ant.execution.IdeaAntLogger2;
import com.intellij.util.text.StringTokenizer;
import org.jetbrains.annotations.NonNls;
@@ -32,6 +34,7 @@ import org.jetbrains.annotations.Nullable;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
public class OutputParser{
@@ -193,7 +196,7 @@ public class OutputParser{
return -1;
}
- private static void processJavacMessages(final List<String> javacMessages, final AntBuildMessageView messageView, Project project) {
+ private static void processJavacMessages(final List<String> javacMessages, final AntBuildMessageView messageView, final Project project) {
if (javacMessages == null) {
return;
}
@@ -241,6 +244,12 @@ public class OutputParser{
public void run() {
VirtualFile file = url == null ? null : VirtualFileManager.getInstance().findFileByUrl(url);
messageView.outputJavacMessage(convertCategory(category), strings, file, url, lineNum, columnNum);
+
+ if (file != null && category == CompilerMessageCategory.ERROR) {
+ final WolfTheProblemSolver wolf = WolfTheProblemSolver.getInstance(project);
+ final Problem problem = wolf.convertToProblem(file, lineNum, columnNum, strings);
+ wolf.weHaveGotNonIgnorableProblems(file, Collections.singletonList(problem));
+ }
}
});
}
diff --git a/plugins/coverage-common/src/com/intellij/coverage/SrcFileAnnotator.java b/plugins/coverage-common/src/com/intellij/coverage/SrcFileAnnotator.java
index 479211ec82f1..c327d760e10d 100644
--- a/plugins/coverage-common/src/com/intellij/coverage/SrcFileAnnotator.java
+++ b/plugins/coverage-common/src/com/intellij/coverage/SrcFileAnnotator.java
@@ -25,7 +25,7 @@ import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.TextEditor;
import com.intellij.openapi.fileEditor.impl.LoadTextUtil;
import com.intellij.openapi.module.Module;
-import com.intellij.openapi.module.ModuleUtil;
+import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.ProjectRootManager;
@@ -223,7 +223,7 @@ public class SrcFileAnnotator implements Disposable {
}
public void showCoverageInformation(final CoverageSuitesBundle suite) {
- if (myEditor == null) return;
+ if (myEditor == null || myFile == null) return;
final MarkupModel markupModel = DocumentMarkupModel.forDocument(myDocument, myProject, true);
final List<RangeHighlighter> highlighters = new ArrayList<RangeHighlighter>();
final ProjectData data = suite.getCoverageData();
@@ -278,7 +278,7 @@ public class SrcFileAnnotator implements Disposable {
@Nullable
@Override
public Module compute() {
- return ModuleUtil.findModuleForPsiElement(myFile);
+ return ModuleUtilCore.findModuleForPsiElement(myFile);
}
});
if (module != null) {
diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/actions/merge/MergeAction.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/actions/merge/MergeAction.java
index e76f2f061485..80efbd46f8fa 100644
--- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/actions/merge/MergeAction.java
+++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/actions/merge/MergeAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -58,13 +58,13 @@ public class MergeAction extends AnAction {
final VcsContext context = CvsContextWrapper.createCachedInstance(e);
final VirtualFile[] files = context.getSelectedFiles();
- if (files == null || files.length == 0) return;
+ if (files.length == 0) return;
+ final Project project = context.getProject();
final ReadonlyStatusHandler.OperationStatus operationStatus =
- ReadonlyStatusHandler.getInstance(context.getProject()).ensureFilesWritable(files);
+ ReadonlyStatusHandler.getInstance(project).ensureFilesWritable(files);
if (operationStatus.hasReadonlyFiles()) {
return;
}
- final Project project = context.getProject();
AbstractVcsHelper.getInstance(project).showMergeDialog(Arrays.asList(files), new CvsMergeProvider());
}
catch (Exception e1) {
diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsstatuses/CvsChangeProvider.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsstatuses/CvsChangeProvider.java
index a2e055b7b283..a652289a59c7 100644
--- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsstatuses/CvsChangeProvider.java
+++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsstatuses/CvsChangeProvider.java
@@ -33,13 +33,8 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.progress.ProgressIndicator;
-import com.intellij.openapi.roots.ProjectFileIndex;
-import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.Comparing;
-import com.intellij.openapi.vcs.FilePath;
-import com.intellij.openapi.vcs.FileStatus;
-import com.intellij.openapi.vcs.ObjectsConvertor;
-import com.intellij.openapi.vcs.VcsException;
+import com.intellij.openapi.vcs.*;
import com.intellij.openapi.vcs.actions.VcsContextFactory;
import com.intellij.openapi.vcs.changes.*;
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
@@ -63,13 +58,13 @@ public class CvsChangeProvider implements ChangeProvider {
private final CvsVcs2 myVcs;
private final CvsEntriesManager myEntriesManager;
- private final ProjectFileIndex myFileIndex;
+ private final ProjectLevelVcsManager myVcsManager;
private final ChangeListManager myChangeListManager;
public CvsChangeProvider(final CvsVcs2 vcs, CvsEntriesManager entriesManager) {
myVcs = vcs;
myEntriesManager = entriesManager;
- myFileIndex = ProjectRootManager.getInstance(vcs.getProject()).getFileIndex();
+ myVcsManager = ProjectLevelVcsManager.getInstance(vcs.getProject());
myChangeListManager = ChangeListManager.getInstance(vcs.getProject());
}
@@ -169,7 +164,7 @@ public class CvsChangeProvider implements ChangeProvider {
for (VirtualFile file : children) {
progress.checkCanceled();
if (file.isDirectory()) {
- final boolean isIgnored = myFileIndex.isExcluded(file);
+ final boolean isIgnored = myVcsManager.isIgnored(file);
if (!isIgnored) {
processEntriesIn(file, scope, builder, true, progress);
}
@@ -284,7 +279,7 @@ public class CvsChangeProvider implements ChangeProvider {
private void checkSwitchedDir(final VirtualFile dir, final ChangelistBuilder builder, final VcsDirtyScope scope) {
final VirtualFile parentDir = dir.getParent();
- if (parentDir == null || !myFileIndex.isInContent(parentDir)) {
+ if (parentDir == null || !myVcsManager.isFileInContent(parentDir)) {
return;
}
final CvsInfo info = myEntriesManager.getCvsInfoFor(dir);
@@ -317,7 +312,7 @@ public class CvsChangeProvider implements ChangeProvider {
private void checkSwitchedFile(final FilePath filePath, final ChangelistBuilder builder, final VirtualFile dir, final Entry entry) {
// if content root itself is switched, ignore
- if (!myFileIndex.isInContent(dir)) {
+ if (!myVcsManager.isFileInContent(dir)) {
return;
}
final String dirTag = myEntriesManager.getCvsInfoFor(dir).getStickyTag();
diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/ui/experts/importToCvs/ImportTree.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/ui/experts/importToCvs/ImportTree.java
index 3877a78a0d35..eb30dd74752c 100644
--- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/ui/experts/importToCvs/ImportTree.java
+++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/ui/experts/importToCvs/ImportTree.java
@@ -30,9 +30,8 @@ import com.intellij.openapi.fileChooser.FileElement;
import com.intellij.openapi.fileChooser.FileSystemTree;
import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.roots.ProjectFileIndex;
-import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.IconLoader;
+import com.intellij.openapi.vcs.ProjectLevelVcsManager;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
@@ -150,12 +149,11 @@ public class ImportTree extends NodeRenderer {
if (myProject == null) {
return;
}
- final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(myProject).getFileIndex();
- if (!fileIndex.isExcluded(selectedFile)) {
+ if (!isIgnoredByVcs(selectedFile)) {
return;
}
final VirtualFile parent = selectedFile.getParent();
- if (parent != null && fileIndex.isExcluded(parent)) {
+ if (parent != null && isIgnoredByVcs(parent)) {
return;
}
for (final VirtualFile excludedFile : myExcludedFiles) {
@@ -182,12 +180,11 @@ public class ImportTree extends NodeRenderer {
if (myProject == null) {
continue;
}
- final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(myProject).getFileIndex();
- if (!fileIndex.isExcluded(selectedFile)) {
+ if (!isIgnoredByVcs(selectedFile)) {
continue;
}
final VirtualFile parent = selectedFile.getParent();
- if (parent == null || fileIndex.isExcluded(parent) || myExcludedFiles.contains(parent)) {
+ if (parent == null || isIgnoredByVcs(parent) || myExcludedFiles.contains(parent)) {
continue;
}
if (!myIncludedFiles.contains(selectedFile)) {
@@ -211,7 +208,7 @@ public class ImportTree extends NodeRenderer {
return true;
}
}
- if (myProject == null || !ProjectRootManager.getInstance(myProject).getFileIndex().isExcluded(file)) {
+ if (myProject == null || !isIgnoredByVcs(file)) {
return false;
}
for (VirtualFile includedFile : myIncludedFiles) {
@@ -242,7 +239,7 @@ public class ImportTree extends NodeRenderer {
if (FileTypeManager.getInstance().isFileIgnored(abstractFileObject.getName())) return true;
if (myProject != null && !includedFiles.contains(file)) {
final VirtualFile vFile = LocalFileSystem.getInstance().findFileByIoFile(file);
- if (vFile != null && ProjectRootManager.getInstance(myProject).getFileIndex().isExcluded(vFile)) {
+ if (vFile != null && isIgnoredByVcs(vFile)) {
return true;
}
}
@@ -257,4 +254,8 @@ public class ImportTree extends NodeRenderer {
}
};
}
+
+ private boolean isIgnoredByVcs(VirtualFile vFile) {
+ return myProject != null && ProjectLevelVcsManager.getInstance(myProject).isIgnored(vFile);
+ }
}
diff --git a/plugins/devkit/resources/META-INF/plugin.xml b/plugins/devkit/resources/META-INF/plugin.xml
index 9bb838c8e02c..0a9501ebef94 100644
--- a/plugins/devkit/resources/META-INF/plugin.xml
+++ b/plugins/devkit/resources/META-INF/plugin.xml
@@ -12,7 +12,7 @@
<depends>com.intellij.properties</depends>
- <resource-bundle>DevKitBundle</resource-bundle>
+ <resource-bundle>org.jetbrains.idea.devkit.DevKitBundle</resource-bundle>
<extensions defaultExtensionNs="com.intellij">
<errorHandler implementation="com.intellij.diagnostic.ITNReporter"/>
@@ -56,52 +56,44 @@
implementationClass="org.jetbrains.idea.devkit.references.extensions.ExtensionPointDocumentationProvider"/>
<localInspection language="XML" shortName="PluginXmlValidity" displayName="Plugin.xml Validity"
- bundle="DevKitBundle"
groupKey="inspections.group.name" enabledByDefault="true" level="ERROR"
implementationClass="org.jetbrains.idea.devkit.inspections.PluginXmlDomInspection"/>
- <localInspection language="JAVA" shortName="ComponentNotRegistered" bundle="DevKitBundle"
+ <localInspection language="JAVA" shortName="ComponentNotRegistered"
key="inspections.component.not.registered.name" groupKey="inspections.group.name" enabledByDefault="true"
level="WARNING" implementationClass="org.jetbrains.idea.devkit.inspections.ComponentNotRegisteredInspection"/>
<localInspection language="JAVA" shortName="InspectionDescriptionNotFoundInspection" displayName="Inspection Description Checker"
- bundle="DevKitBundle"
groupKey="inspections.group.name" enabledByDefault="true" level="WARNING"
implementationClass="org.jetbrains.idea.devkit.inspections.InspectionDescriptionNotFoundInspection"/>
<localInspection language="JAVA" shortName="InspectionUsingGrayColors" displayName="Using new Color(a,a,a)"
- bundle="DevKitBundle"
groupKey="inspections.group.name" enabledByDefault="true" level="WARNING"
implementationClass="org.jetbrains.idea.devkit.inspections.UseGrayInspection"/>
<localInspection language="JAVA" shortName="IntentionDescriptionNotFoundInspection" displayName="Intention Description Checker"
- bundle="DevKitBundle"
groupKey="inspections.group.name" enabledByDefault="true" level="WARNING"
implementationClass="org.jetbrains.idea.devkit.inspections.IntentionDescriptionNotFoundInspection"/>
<localInspection language="JAVA"
key="inspections.component.postfix.template.not.found.description.name"
- bundle="DevKitBundle"
groupKey="inspections.group.name"
enabledByDefault="true"
level="WARNING"
implementationClass="org.jetbrains.idea.devkit.inspections.PostfixTemplateDescriptionNotFoundInspection"/>
<localInspection shortName="ComponentRegistrationProblems"
- bundle="DevKitBundle" key="inspections.registration.problems.name"
+ key="inspections.registration.problems.name"
groupKey="inspections.group.name"
enabledByDefault="true" level="ERROR"
implementationClass="org.jetbrains.idea.devkit.inspections.RegistrationProblemsInspection"/>
<localInspection language="JAVA" shortName="DialogTitleCapitalization"
- bundle="DevKitBundle"
groupKey="inspections.group.name"
displayName="Incorrect dialog title capitalization"
enabledByDefault="true"
level="WARNING"
implementationClass="org.jetbrains.idea.devkit.inspections.TitleCapitalizationInspection"/>
<localInspection language="XML" shortName="InspectionMappingConsistency"
- bundle="DevKitBundle"
groupKey="inspections.group.name"
displayName="&lt;inspection&gt; tag consistency"
enabledByDefault="true"
level="WARNING"
implementationClass="org.jetbrains.idea.devkit.inspections.InspectionMappingConsistencyInspection"/>
<localInspection language="XML" shortName="ExtensionPointBeanClass"
- bundle="DevKitBundle"
groupKey="inspections.group.name"
displayName="&lt;extensionPoint&gt; beanClass specification"
enabledByDefault="true"
@@ -109,42 +101,34 @@
implementationClass="org.jetbrains.idea.devkit.inspections.ExtensionPointBeanClassInspection"/>
<localInspection language="JAVA" shortName="UndesirableClassUsage" displayName="Undesirable class usage"
- bundle="DevKitBundle"
groupKey="inspections.group.name"
enabledByDefault="true" level="WARNING"
implementationClass="org.jetbrains.idea.devkit.inspections.internal.UndesirableClassUsageInspection"/>
<localInspection language="JAVA" shortName="FileEqualsUsage" displayName="File.equals() usage"
- bundle="DevKitBundle"
groupKey="inspections.group.name"
enabledByDefault="true" level="WARNING"
implementationClass="org.jetbrains.idea.devkit.inspections.internal.FileEqualsUsageInspection"/>
<localInspection language="JAVA" shortName="GtkPreferredJComboBoxRenderer" displayName="Preferred JComboBox renderer"
- bundle="DevKitBundle"
groupKey="inspections.group.name"
enabledByDefault="true" level="WARNING"
implementationClass="org.jetbrains.idea.devkit.inspections.internal.GtkPreferredJComboBoxRendererInspection"/>
<localInspection language="JAVA" shortName="UnsafeVfsRecursion" displayName="Unsafe VFS recursion"
- bundle="DevKitBundle"
groupKey="inspections.group.name"
enabledByDefault="true" level="WARNING"
implementationClass="org.jetbrains.idea.devkit.inspections.internal.UnsafeVfsRecursionInspection"/>
<localInspection language="JAVA" shortName="UseJBColor" displayName="Use Darcula aware JBColor"
- bundle="DevKitBundle"
groupKey="inspections.group.name"
enabledByDefault="true" level="WARNING"
implementationClass="org.jetbrains.idea.devkit.inspections.internal.UseJBColorInspection"/>
<localInspection language="JAVA" shortName="UseCouple" displayName="Use Couple instead of Pair"
- bundle="DevKitBundle"
groupKey="inspections.group.name"
enabledByDefault="false" level="WARNING"
implementationClass="org.jetbrains.idea.devkit.inspections.internal.UseCoupleInspection"/>
<localInspection language="JAVA" shortName="DontUsePairConstructor" displayName="Don't use constructor of Pair class"
- bundle="DevKitBundle"
groupKey="inspections.group.name"
enabledByDefault="true" level="WARNING"
implementationClass="org.jetbrains.idea.devkit.inspections.internal.DontUseNewPairInspection"/>
<localInspection language="JAVA" shortName="UseVirtualFileEquals" displayName="Use VirtualFile.equals"
- bundle="DevKitBundle"
groupKey="inspections.group.name"
enabledByDefault="true" level="WARNING"
implementationClass="org.jetbrains.idea.devkit.inspections.internal.UseVirtualFileEqualsInspection"/>
diff --git a/plugins/devkit/resources/DevKitBundle.properties b/plugins/devkit/resources/org/jetbrains/idea/devkit/DevKitBundle.properties
index 6799f6d2415f..6799f6d2415f 100644
--- a/plugins/devkit/resources/DevKitBundle.properties
+++ b/plugins/devkit/resources/org/jetbrains/idea/devkit/DevKitBundle.properties
diff --git a/plugins/devkit/src/DevKitBundle.java b/plugins/devkit/src/DevKitBundle.java
index 013fd2f43e6b..d5460ad123f9 100644
--- a/plugins/devkit/src/DevKitBundle.java
+++ b/plugins/devkit/src/DevKitBundle.java
@@ -26,7 +26,7 @@ public class DevKitBundle extends AbstractBundle {
return ourInstance.getMessage(key, params);
}
- @NonNls private static final String BUNDLE = "DevKitBundle";
+ @NonNls private static final String BUNDLE = "org.jetbrains.idea.devkit.DevKitBundle";
private static final DevKitBundle ourInstance = new DevKitBundle();
private DevKitBundle() {
diff --git a/plugins/devkit/src/actions/ShowSerializedXmlAction.java b/plugins/devkit/src/actions/ShowSerializedXmlAction.java
index 888042424295..e718eb74989d 100644
--- a/plugins/devkit/src/actions/ShowSerializedXmlAction.java
+++ b/plugins/devkit/src/actions/ShowSerializedXmlAction.java
@@ -41,6 +41,7 @@ import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.containers.FList;
import com.intellij.util.lang.UrlClassLoader;
import com.intellij.util.xmlb.Accessor;
+import com.intellij.util.xmlb.XmlSerializationException;
import com.intellij.util.xmlb.XmlSerializer;
import com.intellij.util.xmlb.XmlSerializerUtil;
import org.jdom.Element;
@@ -121,7 +122,16 @@ public class ShowSerializedXmlAction extends DumbAwareAction {
return;
}
- final Element element = XmlSerializer.serialize(o);
+ final Element element;
+ try {
+ element = XmlSerializer.serialize(o);
+ }
+ catch (XmlSerializationException e) {
+ LOG.info(e);
+ Throwable cause = e.getCause();
+ Messages.showErrorDialog(project, e.getMessage() + (cause != null ? ": " + cause.getMessage() : ""), CommonBundle.getErrorTitle());
+ return;
+ }
final String text = JDOMUtil.writeElement(element, "\n");
Messages.showIdeaMessageDialog(project, text, "Serialized XML for '" + className + "'",
new String[]{CommonBundle.getOkButtonText()}, 0, Messages.getInformationIcon(), null);
diff --git a/plugins/devkit/src/build/PrepareToDeployAction.java b/plugins/devkit/src/build/PrepareToDeployAction.java
index b501331596b5..37bedb4d1d3a 100644
--- a/plugins/devkit/src/build/PrepareToDeployAction.java
+++ b/plugins/devkit/src/build/PrepareToDeployAction.java
@@ -164,6 +164,7 @@ public class PrepareToDeployAction extends AnAction {
else {
FileUtil.copy(jarFile, dstFile);
}
+ LocalFileSystem.getInstance().refreshIoFiles(Collections.singleton(dstFile), true, false, null);
successMessages.add(DevKitBundle.message("saved.message", isZip ? 1 : 2, pluginName, dstPath));
}
catch (final IOException e) {
diff --git a/plugins/devkit/src/dom/DependencyConfigFileConverter.java b/plugins/devkit/src/dom/DependencyConfigFileConverter.java
index 214d21e6e819..b9cb283a1ac5 100644
--- a/plugins/devkit/src/dom/DependencyConfigFileConverter.java
+++ b/plugins/devkit/src/dom/DependencyConfigFileConverter.java
@@ -93,12 +93,12 @@ public class DependencyConfigFileConverter extends PathReferenceConverter {
public Collection<PsiFileSystemItem> computeDefaultContexts() {
final PsiFile containingFile = getContainingFile();
if (containingFile == null) {
- return super.getDefaultContexts();
+ return Collections.emptyList();
}
final Module module = ModuleUtilCore.findModuleForPsiElement(getElement());
if (module == null) {
- return super.getDefaultContexts();
+ return Collections.emptyList();
}
final Set<VirtualFile> roots = new HashSet<VirtualFile>();
diff --git a/plugins/devkit/src/dom/impl/PluginXmlDomFileDescription.java b/plugins/devkit/src/dom/impl/PluginXmlDomFileDescription.java
index 80a3aabce8f3..b3d7fda2c19a 100644
--- a/plugins/devkit/src/dom/impl/PluginXmlDomFileDescription.java
+++ b/plugins/devkit/src/dom/impl/PluginXmlDomFileDescription.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,16 +21,20 @@ import com.intellij.lang.annotation.Annotation;
import com.intellij.lang.annotation.HighlightSeverity;
import com.intellij.openapi.util.Iconable;
import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiField;
import com.intellij.util.xml.DomElement;
import com.intellij.util.xml.DomFileDescription;
import com.intellij.util.xml.DomUtil;
import com.intellij.util.xml.GenericAttributeValue;
import com.intellij.util.xml.highlighting.DomElementAnnotationHolder;
import com.intellij.util.xml.highlighting.DomElementsAnnotator;
+import com.intellij.util.xml.reflect.DomAttributeChildDescription;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.devkit.dom.*;
import javax.swing.*;
+import java.util.List;
/**
* @author mike
@@ -73,12 +77,29 @@ public class PluginXmlDomFileDescription extends DomFileDescription<IdeaPlugin>
final ExtensionPoint extensionPoint = extension.getExtensionPoint();
if (extensionPoint == null) return;
final GenericAttributeValue<PsiClass> interfaceAttribute = extensionPoint.getInterface();
- if (!DomUtil.hasXml(interfaceAttribute)) return;
+ if (DomUtil.hasXml(interfaceAttribute)) {
+ final PsiClass value = interfaceAttribute.getValue();
+ if (value != null && value.isDeprecated()) {
+ final Annotation annotation = holder.createAnnotation(extension, HighlightSeverity.WARNING, "Deprecated EP");
+ annotation.setHighlightType(ProblemHighlightType.LIKE_DEPRECATED);
+ return;
+ }
+ }
- final PsiClass value = interfaceAttribute.getValue();
- if (value != null && value.isDeprecated()) {
- final Annotation annotation = holder.createAnnotation(extension, HighlightSeverity.WARNING, "Deprecated EP");
- annotation.setHighlightType(ProblemHighlightType.LIKE_DEPRECATED);
+ final List<? extends DomAttributeChildDescription> descriptions = extension.getGenericInfo().getAttributeChildrenDescriptions();
+ for (DomAttributeChildDescription attributeDescription : descriptions) {
+ final GenericAttributeValue attributeValue = attributeDescription.getDomAttributeValue(extension);
+ if (attributeValue == null || !DomUtil.hasXml(attributeValue)) continue;
+
+ final PsiElement declaration = attributeDescription.getDeclaration(extension.getManager().getProject());
+ if (declaration instanceof PsiField) {
+ PsiField psiField = (PsiField)declaration;
+ if (psiField.isDeprecated()) {
+ final Annotation annotation = holder.createAnnotation(attributeValue, HighlightSeverity.WARNING,
+ "Deprecated attribute '" + attributeDescription.getName() + "'");
+ annotation.setHighlightType(ProblemHighlightType.LIKE_DEPRECATED);
+ }
+ }
}
}
diff --git a/plugins/devkit/testData/codeInsight/deprecatedExtensionAttribute.xml b/plugins/devkit/testData/codeInsight/deprecatedExtensionAttribute.xml
index 6ea4867e4bdf..5466b7ee4485 100644
--- a/plugins/devkit/testData/codeInsight/deprecatedExtensionAttribute.xml
+++ b/plugins/devkit/testData/codeInsight/deprecatedExtensionAttribute.xml
@@ -6,7 +6,7 @@
</extensionPoints>
<extensions defaultExtensionNs="com.intellij.myPlugin">
- <myExt <warning descr="'myOld' is deprecated">old</warning>="java.lang.Runnable" attr="value"/>
+ <myExt <warning descr="Deprecated attribute 'old'">old="java.lang.Runnable"</warning> attr="value"/>
</extensions>
</idea-plugin> \ No newline at end of file
diff --git a/plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudGitDeploymentRuntime.java b/plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudGitDeploymentRuntime.java
index 874360a86c5b..9846393b99a8 100644
--- a/plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudGitDeploymentRuntime.java
+++ b/plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudGitDeploymentRuntime.java
@@ -16,6 +16,7 @@ import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.remoteServer.agent.util.CloudGitApplication;
+import com.intellij.remoteServer.agent.util.CloudLoggingHandler;
import com.intellij.remoteServer.configuration.deployment.DeploymentSource;
import com.intellij.remoteServer.runtime.deployment.DeploymentLogManager;
import com.intellij.remoteServer.runtime.deployment.DeploymentTask;
@@ -348,6 +349,11 @@ public class CloudGitDeploymentRuntime extends CloudDeploymentRuntime {
};
}
+ @Override
+ protected CloudLoggingHandler getLoggingHandler() {
+ return super.getLoggingHandler();
+ }
+
protected void addGitRemote(CloudGitApplication application) throws ServerRuntimeException {
doGitRemote(getRemoteName(), application, "add", CloudBundle.getText("failed.add.remote", getRemoteName()));
}
diff --git a/plugins/git4idea/src/META-INF/plugin.xml b/plugins/git4idea/src/META-INF/plugin.xml
index 32d254f6fb67..dc12d0e03ad0 100644
--- a/plugins/git4idea/src/META-INF/plugin.xml
+++ b/plugins/git4idea/src/META-INF/plugin.xml
@@ -92,12 +92,13 @@
<separator/>
</group>
- <action id="Git.CherryPick" class="git4idea.cherrypick.GitCherryPickAction" text="Cherry-Pick" icon="Git4ideaIcons.CherryPick"/>
+ <action id="Git.CherryPick" class="git4idea.cherrypick.GitCherryPickAction" icon="Git4ideaIcons.CherryPick"/>
<action class="git4idea.actions.GitCheckoutRevisionAction" id="Git.CheckoutRevision" text="Checkout Revision"/>
- <action class="git4idea.actions.GitCreateNewBranchAction" id="Git.CreateNewBranch" text="New Branch"
+ <action class="git4idea.actions.GitCreateNewBranchAction" id="Git.CreateNewBranch" text="New Branch..."
description="Create new branch starting from the selected commit"/>
- <action class="git4idea.actions.GitCreateTagAction" id="Git.CreateNewTag" text="New Tag"
+ <action class="git4idea.actions.GitCreateTagAction" id="Git.CreateNewTag" text="New Tag..."
description="Create new tag pointing to this commit"/>
+ <action id="Git.Reset.In.Log" class="git4idea.reset.GitResetAction" text="Reset Current Branch to Here..." />
<group id="Git.Log.ContextMenu">
<separator/>
@@ -105,6 +106,8 @@
<reference id="Git.CheckoutRevision"/>
<reference id="Git.CreateNewBranch" />
<reference id="Git.CreateNewTag" />
+ <separator/>
+ <reference id="Git.Reset.In.Log" />
<add-to-group group-id="Vcs.Log.ContextMenu" />
</group>
@@ -121,7 +124,9 @@
<project-components>
<component>
+ <interface-class>git4idea.repo.GitRepositoryManager</interface-class>
<implementation-class>git4idea.repo.GitRepositoryManager</implementation-class>
+ <headless-implementation-class>git4idea.test.GitTestRepositoryManager</headless-implementation-class>
</component>
</project-components>
diff --git a/plugins/git4idea/src/git4idea/GitUtil.java b/plugins/git4idea/src/git4idea/GitUtil.java
index 5f56de5674e1..4ff61fb4a68b 100644
--- a/plugins/git4idea/src/git4idea/GitUtil.java
+++ b/plugins/git4idea/src/git4idea/GitUtil.java
@@ -37,7 +37,6 @@ import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vcs.changes.ChangeListManager;
import com.intellij.openapi.vcs.changes.ChangeListManagerEx;
-import com.intellij.openapi.vcs.changes.FilePathsHelper;
import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
import com.intellij.openapi.vcs.vfs.AbstractVcsVirtualFile;
import com.intellij.openapi.vfs.LocalFileSystem;
@@ -778,6 +777,8 @@ public class GitUtil {
/**
* Returns absolute paths which have changed remotely comparing to the current branch, i.e. performs
* <code>git diff --name-only master..origin/master</code>
+ * <p/>
+ * Paths are absolute, Git-formatted (i.e. with forward slashes).
*/
@NotNull
public static Collection<String> getPathsDiffBetweenRefs(@NotNull Git git, @NotNull GitRepository repository,
@@ -797,7 +798,7 @@ public class GitUtil {
continue;
}
final String path = repository.getRoot().getPath() + "/" + unescapePath(relative);
- remoteChanges.add(FilePathsHelper.convertPath(path));
+ remoteChanges.add(path);
}
return remoteChanges;
}
@@ -1024,4 +1025,14 @@ public class GitUtil {
ApplicationManager.getApplication().getMessageBus().syncPublisher(BatchFileChangeListener.TOPIC).batchChangeCompleted(project);
}
+ @NotNull
+ public static String cleanupErrorPrefixes(@NotNull String msg) {
+ final String[] PREFIXES = { "fatal:", "error:" };
+ for (String prefix : PREFIXES) {
+ if (msg.startsWith(prefix)) {
+ return msg.substring(prefix.length()).trim();
+ }
+ }
+ return msg;
+ }
}
diff --git a/plugins/git4idea/src/git4idea/actions/GitLogSingleCommitAction.java b/plugins/git4idea/src/git4idea/actions/GitLogSingleCommitAction.java
index 39cfb2a625ad..83512de71d1f 100644
--- a/plugins/git4idea/src/git4idea/actions/GitLogSingleCommitAction.java
+++ b/plugins/git4idea/src/git4idea/actions/GitLogSingleCommitAction.java
@@ -15,77 +15,21 @@
*/
package git4idea.actions;
-import com.intellij.dvcs.DvcsUtil;
-import com.intellij.openapi.actionSystem.AnActionEvent;
-import com.intellij.openapi.actionSystem.CommonDataKeys;
+import com.intellij.dvcs.ui.VcsLogSingleCommitAction;
import com.intellij.openapi.components.ServiceManager;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
-import com.intellij.vcs.log.VcsFullCommitDetails;
-import com.intellij.vcs.log.VcsLog;
-import com.intellij.vcs.log.VcsLogDataKeys;
-import git4idea.GitVcs;
+import com.intellij.openapi.vfs.VirtualFile;
import git4idea.repo.GitRepository;
import git4idea.repo.GitRepositoryManager;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
-import java.util.List;
-
-/**
- * @author Kirill Likhodedov
- */
-public abstract class GitLogSingleCommitAction extends DumbAwareAction {
-
- private static final Logger LOG = Logger.getInstance(GitLogSingleCommitAction.class);
-
- protected abstract void actionPerformed(@NotNull GitRepository repository, @NotNull VcsFullCommitDetails commit);
-
- @Override
- public void actionPerformed(AnActionEvent e) {
- Data data = Data.collect(e);
- if (!data.isValid()) {
- return;
- }
-
- List<VcsFullCommitDetails> details = data.log.getSelectedDetails();
- if (details.size() != 1) {
- return;
- }
- VcsFullCommitDetails commit = details.get(0);
-
- GitRepositoryManager repositoryManager = ServiceManager.getService(data.project, GitRepositoryManager.class);
- final GitRepository repository = repositoryManager.getRepositoryForRoot(commit.getRoot());
- if (repository == null) {
- DvcsUtil.noVcsRepositoryForRoot(LOG, commit.getRoot(), data.project, repositoryManager, GitVcs.getInstance(data.project));
- return;
- }
-
- actionPerformed(repository, commit);
- }
+public abstract class GitLogSingleCommitAction extends VcsLogSingleCommitAction<GitRepository> {
@Override
- public void update(AnActionEvent e) {
- Data data = Data.collect(e);
- boolean enabled = data.isValid() && data.log.getSelectedCommits().size() == 1;
- e.getPresentation().setVisible(data.isValid());
- e.getPresentation().setEnabled(enabled);
- }
-
- private static class Data {
- Project project;
- VcsLog log;
-
- static Data collect(AnActionEvent e) {
- Data data = new Data();
- data.project = e.getData(CommonDataKeys.PROJECT);
- data.log = e.getData(VcsLogDataKeys.VSC_LOG);
- return data;
- }
-
- boolean isValid() {
- return project != null && log != null && DvcsUtil.logHasRootForVcs(log, GitVcs.getKey());
- }
+ @Nullable
+ protected GitRepository getRepositoryForRoot(@NotNull Project project, @NotNull VirtualFile root) {
+ return ServiceManager.getService(project, GitRepositoryManager.class).getRepositoryForRoot(root);
}
}
diff --git a/plugins/git4idea/src/git4idea/branch/GitBranchOperation.java b/plugins/git4idea/src/git4idea/branch/GitBranchOperation.java
index 7c2f77eeebd2..9147054ba7b9 100644
--- a/plugins/git4idea/src/git4idea/branch/GitBranchOperation.java
+++ b/plugins/git4idea/src/git4idea/branch/GitBranchOperation.java
@@ -15,6 +15,7 @@
*/
package git4idea.branch;
+import com.intellij.dvcs.repo.RepositoryUtil;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.project.Project;
@@ -25,6 +26,9 @@ import com.intellij.openapi.vcs.VcsNotifier;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.MultiMap;
+import git4idea.GitLocalBranch;
import git4idea.GitPlatformFacade;
import git4idea.GitUtil;
import git4idea.commands.Git;
@@ -32,6 +36,7 @@ import git4idea.commands.GitMessageWithFilesDetector;
import git4idea.config.GitVcsSettings;
import git4idea.repo.GitRepository;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.util.*;
@@ -50,7 +55,7 @@ abstract class GitBranchOperation {
@NotNull protected final Git myGit;
@NotNull protected final GitBranchUiHandler myUiHandler;
@NotNull private final Collection<GitRepository> myRepositories;
- @NotNull protected final String myCurrentBranchOrRev;
+ @NotNull protected final Map<GitRepository, String> myCurrentHeads;
private final GitVcsSettings mySettings;
@NotNull private final Collection<GitRepository> mySuccessfulRepositories;
@@ -63,7 +68,13 @@ abstract class GitBranchOperation {
myGit = git;
myUiHandler = uiHandler;
myRepositories = repositories;
- myCurrentBranchOrRev = GitBranchUtil.getCurrentBranchOrRev(repositories);
+ myCurrentHeads = ContainerUtil.map2Map(repositories, new Function<GitRepository, Pair<GitRepository, String>>() {
+ @Override
+ public Pair<GitRepository, String> fun(GitRepository repository) {
+ GitLocalBranch currentBranch = repository.getCurrentBranch();
+ return Pair.create(repository, currentBranch == null ? repository.getCurrentRevision() : currentBranch.getName());
+ }
+ });
mySuccessfulRepositories = new ArrayList<GitRepository>();
myRemainingRepositories = new ArrayList<GitRepository>(myRepositories);
mySettings = myFacade.getSettings(myProject);
@@ -220,11 +231,28 @@ abstract class GitBranchOperation {
protected void updateRecentBranch() {
if (getRepositories().size() == 1) {
GitRepository repository = myRepositories.iterator().next();
- mySettings.setRecentBranchOfRepository(repository.getRoot().getPath(), myCurrentBranchOrRev);
+ mySettings.setRecentBranchOfRepository(repository.getRoot().getPath(), myCurrentHeads.get(repository));
}
else {
- mySettings.setRecentCommonBranch(myCurrentBranchOrRev);
+ String recentCommonBranch = getRecentCommonBranch();
+ if (recentCommonBranch != null) {
+ mySettings.setRecentCommonBranch(recentCommonBranch);
+ }
+ }
+ }
+
+ @Nullable
+ private String getRecentCommonBranch() {
+ String recentCommonBranch = null;
+ for (String branch : myCurrentHeads.values()) {
+ if (recentCommonBranch == null) {
+ recentCommonBranch = branch;
+ }
+ else if (!recentCommonBranch.equals(branch)) {
+ return null;
+ }
}
+ return recentCommonBranch;
}
private void showUnmergedFilesDialogWithRollback() {
@@ -340,4 +368,35 @@ abstract class GitBranchOperation {
return Pair.create(allConflictingRepositories, affectedChanges);
}
+
+ @NotNull
+ protected static String stringifyBranchesByRepos(@NotNull Map<GitRepository, String> heads) {
+ MultiMap<String, VirtualFile> grouped = groupByBranches(heads);
+ if (grouped.size() == 1) {
+ return grouped.keySet().iterator().next();
+ }
+ return StringUtil.join(grouped.entrySet(), new Function<Map.Entry<String, Collection<VirtualFile>>, String>() {
+ @Override
+ public String fun(Map.Entry<String, Collection<VirtualFile>> entry) {
+ String roots = StringUtil.join(entry.getValue(), new Function<VirtualFile, String>() {
+ @Override
+ public String fun(VirtualFile file) {
+ return file.getName();
+ }
+ }, ", ");
+ return entry.getKey() + " (in " + roots + ")";
+ }
+ }, "<br/>");
+ }
+
+ @NotNull
+ private static MultiMap<String, VirtualFile> groupByBranches(@NotNull Map<GitRepository, String> heads) {
+ MultiMap<String, VirtualFile> result = MultiMap.createLinked();
+ List<GitRepository> sortedRepos = RepositoryUtil.sortRepositories(heads.keySet());
+ for (GitRepository repo : sortedRepos) {
+ result.putValue(heads.get(repo), repo.getRoot());
+ }
+ return result;
+ }
+
}
diff --git a/plugins/git4idea/src/git4idea/branch/GitBranchUiHandler.java b/plugins/git4idea/src/git4idea/branch/GitBranchUiHandler.java
index 3b694c455c7b..95546f0547e8 100644
--- a/plugins/git4idea/src/git4idea/branch/GitBranchUiHandler.java
+++ b/plugins/git4idea/src/git4idea/branch/GitBranchUiHandler.java
@@ -22,6 +22,7 @@ import com.intellij.openapi.vfs.VirtualFile;
import git4idea.GitCommit;
import git4idea.repo.GitRepository;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.List;
@@ -68,14 +69,15 @@ public interface GitBranchUiHandler {
* Shows the dialog proposing to execute the operation (checkout or merge) smartly, i.e. stash-execute-unstash.
*
* @param project
- * @param changes local changes that would be overwritten by checkout or merge.
- * @param paths paths reported by Git (in most cases this is covered by {@code changes}.
- * @param operation operation name: checkout or merge
- * @param isForcePossible can the operation be executed force (force checkout is possible, force merge - not).
+ * @param changes local changes that would be overwritten by checkout or merge.
+ * @param paths paths reported by Git (in most cases this is covered by {@code changes}.
+ * @param operation operation name: checkout or merge
+ * @param forceButtonTitle if the operation can be executed force (force checkout is possible),
+ * specify the title of the force button; otherwise (force merge is not possible) pass null.
* @return the code of the decision.
*/
int showSmartOperationDialog(@NotNull Project project, @NotNull List<Change> changes, @NotNull Collection<String> paths,
- @NotNull String operation, boolean isForcePossible);
+ @NotNull String operation, @Nullable String forceButtonTitle);
boolean showBranchIsNotFullyMergedDialog(@NotNull Project project, @NotNull Map<GitRepository, List<GitCommit>> history,
@NotNull String unmergedBranch, @NotNull List<String> mergedToBranches,
diff --git a/plugins/git4idea/src/git4idea/branch/GitBranchUiHandlerImpl.java b/plugins/git4idea/src/git4idea/branch/GitBranchUiHandlerImpl.java
index cea2b55596e0..20e207d14ba1 100644
--- a/plugins/git4idea/src/git4idea/branch/GitBranchUiHandlerImpl.java
+++ b/plugins/git4idea/src/git4idea/branch/GitBranchUiHandlerImpl.java
@@ -172,7 +172,7 @@ public class GitBranchUiHandlerImpl implements GitBranchUiHandler {
@Override
public int showSmartOperationDialog(@NotNull Project project, @NotNull List<Change> changes, @NotNull Collection<String> paths,
- @NotNull String operation, boolean isForcePossible) {
+ @NotNull String operation, @Nullable String forceButtonTitle) {
JComponent fileBrowser;
if (!changes.isEmpty()) {
fileBrowser = new ChangesBrowserWithRollback(project, changes);
@@ -180,7 +180,7 @@ public class GitBranchUiHandlerImpl implements GitBranchUiHandler {
else {
fileBrowser = new GitSimplePathsBrowser(project, paths);
}
- return GitSmartOperationDialog.showAndGetAnswer(myProject, fileBrowser, operation, isForcePossible);
+ return GitSmartOperationDialog.showAndGetAnswer(myProject, fileBrowser, operation, forceButtonTitle);
}
@Override
diff --git a/plugins/git4idea/src/git4idea/branch/GitCheckoutNewBranchOperation.java b/plugins/git4idea/src/git4idea/branch/GitCheckoutNewBranchOperation.java
index 22e486e6eab0..cdc4f7711801 100644
--- a/plugins/git4idea/src/git4idea/branch/GitCheckoutNewBranchOperation.java
+++ b/plugins/git4idea/src/git4idea/branch/GitCheckoutNewBranchOperation.java
@@ -89,7 +89,7 @@ class GitCheckoutNewBranchOperation extends GitBranchOperation {
protected String getRollbackProposal() {
return "However checkout has succeeded for the following " + repositories() + ":<br/>" +
successfulRepositoriesJoined() +
- "<br/>You may rollback (checkout back to " + myCurrentBranchOrRev + " and delete " + myNewBranchName + ") not to let branches diverge.";
+ "<br/>You may rollback (checkout previous branch back, and delete " + myNewBranchName + ") not to let branches diverge.";
}
@NotNull
@@ -104,7 +104,7 @@ class GitCheckoutNewBranchOperation extends GitBranchOperation {
GitCompoundResult deleteResult = new GitCompoundResult(myProject);
Collection<GitRepository> repositories = getSuccessfulRepositories();
for (GitRepository repository : repositories) {
- GitCommandResult result = myGit.checkout(repository, myCurrentBranchOrRev, null, true);
+ GitCommandResult result = myGit.checkout(repository, myCurrentHeads.get(repository), null, true);
checkoutResult.append(repository, result);
if (result.success()) {
deleteResult.append(repository, myGit.branchDelete(repository, myNewBranchName, false));
@@ -113,7 +113,7 @@ class GitCheckoutNewBranchOperation extends GitBranchOperation {
}
if (checkoutResult.totalSuccess() && deleteResult.totalSuccess()) {
VcsNotifier.getInstance(myProject).notifySuccess("Rollback successful", String
- .format("Checked out %s and deleted %s on %s %s", code(myCurrentBranchOrRev), code(myNewBranchName),
+ .format("Checked out %s and deleted %s on %s %s", stringifyBranchesByRepos(myCurrentHeads), code(myNewBranchName),
StringUtil.pluralize("root", repositories.size()), successfulRepositoriesJoined()));
}
else {
diff --git a/plugins/git4idea/src/git4idea/branch/GitCheckoutOperation.java b/plugins/git4idea/src/git4idea/branch/GitCheckoutOperation.java
index 2441bf7d46cf..b772434959e8 100644
--- a/plugins/git4idea/src/git4idea/branch/GitCheckoutOperation.java
+++ b/plugins/git4idea/src/git4idea/branch/GitCheckoutOperation.java
@@ -47,7 +47,7 @@ import static git4idea.util.GitUIUtil.code;
*/
class GitCheckoutOperation extends GitBranchOperation {
- public static final String ROLLBACK_PROPOSAL_FORMAT = "You may rollback (checkout back to %s) not to let branches diverge.";
+ public static final String ROLLBACK_PROPOSAL_FORMAT = "You may rollback (checkout back to previous branch) not to let branches diverge.";
@NotNull private final String myStartPointReference;
@Nullable private final String myNewBranch;
@@ -115,12 +115,14 @@ class GitCheckoutOperation extends GitBranchOperation {
private boolean smartCheckoutOrNotify(@NotNull GitRepository repository,
@NotNull GitMessageWithFilesDetector localChangesOverwrittenByCheckout) {
Pair<List<GitRepository>, List<Change>> conflictingRepositoriesAndAffectedChanges =
- getConflictingRepositoriesAndAffectedChanges(repository, localChangesOverwrittenByCheckout, myCurrentBranchOrRev, myStartPointReference);
+ getConflictingRepositoriesAndAffectedChanges(repository, localChangesOverwrittenByCheckout, myCurrentHeads.get(repository),
+ myStartPointReference);
List<GitRepository> allConflictingRepositories = conflictingRepositoriesAndAffectedChanges.getFirst();
List<Change> affectedChanges = conflictingRepositoriesAndAffectedChanges.getSecond();
Collection<String> absolutePaths = GitUtil.toAbsolute(repository.getRoot(), localChangesOverwrittenByCheckout.getRelativeFilePaths());
- int smartCheckoutDecision = myUiHandler.showSmartOperationDialog(myProject, affectedChanges, absolutePaths, "checkout", true);
+ int smartCheckoutDecision = myUiHandler.showSmartOperationDialog(myProject, affectedChanges, absolutePaths, "checkout",
+ "&Force Checkout");
if (smartCheckoutDecision == GitSmartOperationDialog.SMART_EXIT_CODE) {
boolean smartCheckedOutSuccessfully = smartCheckout(allConflictingRepositories, myStartPointReference, myNewBranch, getIndicator());
if (smartCheckedOutSuccessfully) {
@@ -153,8 +155,7 @@ class GitCheckoutOperation extends GitBranchOperation {
@Override
protected String getRollbackProposal() {
return "However checkout has succeeded for the following " + repositories() + ":<br/>" +
- successfulRepositoriesJoined() +
- "<br/>" + String.format(ROLLBACK_PROPOSAL_FORMAT, myCurrentBranchOrRev);
+ successfulRepositoriesJoined() + "<br/>" + ROLLBACK_PROPOSAL_FORMAT;
}
@NotNull
@@ -168,7 +169,7 @@ class GitCheckoutOperation extends GitBranchOperation {
GitCompoundResult checkoutResult = new GitCompoundResult(myProject);
GitCompoundResult deleteResult = new GitCompoundResult(myProject);
for (GitRepository repository : getSuccessfulRepositories()) {
- GitCommandResult result = myGit.checkout(repository, myCurrentBranchOrRev, null, true);
+ GitCommandResult result = myGit.checkout(repository, myCurrentHeads.get(repository), null, true);
checkoutResult.append(repository, result);
if (result.success() && myNewBranch != null) {
/*
@@ -183,7 +184,7 @@ class GitCheckoutOperation extends GitBranchOperation {
if (!checkoutResult.totalSuccess() || !deleteResult.totalSuccess()) {
StringBuilder message = new StringBuilder();
if (!checkoutResult.totalSuccess()) {
- message.append("Errors during checking out ").append(myCurrentBranchOrRev).append(": ");
+ message.append("Errors during checkout: ");
message.append(checkoutResult.getErrorOutputWithReposIndication());
}
if (!deleteResult.totalSuccess()) {
diff --git a/plugins/git4idea/src/git4idea/branch/GitDeleteBranchOperation.java b/plugins/git4idea/src/git4idea/branch/GitDeleteBranchOperation.java
index d3501caf7089..1dba1e07f6ac 100644
--- a/plugins/git4idea/src/git4idea/branch/GitDeleteBranchOperation.java
+++ b/plugins/git4idea/src/git4idea/branch/GitDeleteBranchOperation.java
@@ -68,7 +68,7 @@ class GitDeleteBranchOperation extends GitBranchOperation {
else if (notFullyMergedDetector.hasHappened()) {
String baseBranch = notMergedToUpstreamDetector.getBaseBranch();
if (baseBranch == null) { // GitBranchNotMergedToUpstreamDetector didn't happen
- baseBranch = myCurrentBranchOrRev;
+ baseBranch = myCurrentHeads.get(repository);
}
Collection<GitRepository> remainingRepositories = getRemainingRepositories();
diff --git a/plugins/git4idea/src/git4idea/branch/GitMergeOperation.java b/plugins/git4idea/src/git4idea/branch/GitMergeOperation.java
index 89a50cfd6054..1b8f382d1dd8 100644
--- a/plugins/git4idea/src/git4idea/branch/GitMergeOperation.java
+++ b/plugins/git4idea/src/git4idea/branch/GitMergeOperation.java
@@ -34,6 +34,7 @@ import git4idea.commands.*;
import git4idea.merge.GitMergeCommittingConflictResolver;
import git4idea.merge.GitMerger;
import git4idea.repo.GitRepository;
+import git4idea.reset.GitResetMode;
import git4idea.util.GitPreservingProcess;
import org.jetbrains.annotations.NotNull;
@@ -189,12 +190,13 @@ class GitMergeOperation extends GitBranchOperation {
private boolean proposeSmartMergePerformAndNotify(@NotNull GitRepository repository,
@NotNull GitMessageWithFilesDetector localChangesOverwrittenByMerge) {
Pair<List<GitRepository>, List<Change>> conflictingRepositoriesAndAffectedChanges =
- getConflictingRepositoriesAndAffectedChanges(repository, localChangesOverwrittenByMerge, myCurrentBranchOrRev, myBranchToMerge);
+ getConflictingRepositoriesAndAffectedChanges(repository, localChangesOverwrittenByMerge, myCurrentHeads.get(repository),
+ myBranchToMerge);
List<GitRepository> allConflictingRepositories = conflictingRepositoriesAndAffectedChanges.getFirst();
List<Change> affectedChanges = conflictingRepositoriesAndAffectedChanges.getSecond();
Collection<String> absolutePaths = GitUtil.toAbsolute(repository.getRoot(), localChangesOverwrittenByMerge.getRelativeFilePaths());
- int smartCheckoutDecision = myUiHandler.showSmartOperationDialog(myProject, affectedChanges, absolutePaths, "merge", false);
+ int smartCheckoutDecision = myUiHandler.showSmartOperationDialog(myProject, affectedChanges, absolutePaths, "merge", null);
if (smartCheckoutDecision == GitSmartOperationDialog.SMART_EXIT_CODE) {
return doSmartMerge(allConflictingRepositories);
}
@@ -322,7 +324,7 @@ class GitMergeOperation extends GitBranchOperation {
@NotNull
private GitCommandResult rollback(@NotNull GitRepository repository) {
- return myGit.resetHard(repository, myCurrentRevisionsBeforeMerge.get(repository));
+ return myGit.reset(repository, GitResetMode.HARD, myCurrentRevisionsBeforeMerge.get(repository));
}
@NotNull
@@ -339,7 +341,8 @@ class GitMergeOperation extends GitBranchOperation {
@NotNull
@Override
public String getSuccessMessage() {
- return String.format("Merged <b><code>%s</code></b> to <b><code>%s</code></b>", myBranchToMerge, myCurrentBranchOrRev);
+ return String.format("Merged <b><code>%s</code></b> to <b><code>%s</code></b>",
+ myBranchToMerge, stringifyBranchesByRepos(myCurrentHeads));
}
@NotNull
diff --git a/plugins/git4idea/src/git4idea/branch/GitSmartOperationDialog.java b/plugins/git4idea/src/git4idea/branch/GitSmartOperationDialog.java
index 9c2ef4a8d107..4f5073027624 100644
--- a/plugins/git4idea/src/git4idea/branch/GitSmartOperationDialog.java
+++ b/plugins/git4idea/src/git4idea/branch/GitSmartOperationDialog.java
@@ -24,6 +24,7 @@ import com.intellij.ui.components.JBLabel;
import com.intellij.util.ui.UIUtil;
import git4idea.GitPlatformFacade;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.event.ActionEvent;
@@ -44,18 +45,18 @@ public class GitSmartOperationDialog extends DialogWrapper {
@NotNull private final JComponent myFileBrowser;
@NotNull private final String myOperationTitle;
- private final boolean myShowForceButton;
+ @Nullable private final String myForceButton;
/**
* Shows the dialog with the list of local changes preventing merge/checkout and returns the dialog exit code.
*/
static int showAndGetAnswer(@NotNull final Project project, @NotNull final JComponent fileBrowser,
- @NotNull final String operationTitle, final boolean showForceButton) {
+ @NotNull final String operationTitle, @Nullable final String forceButtonTitle) {
final AtomicInteger exitCode = new AtomicInteger();
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
@Override
public void run() {
- GitSmartOperationDialog dialog = new GitSmartOperationDialog(project, fileBrowser, operationTitle, showForceButton);
+ GitSmartOperationDialog dialog = new GitSmartOperationDialog(project, fileBrowser, operationTitle, forceButtonTitle);
ServiceManager.getService(project, GitPlatformFacade.class).showDialog(dialog);
exitCode.set(dialog.getExitCode());
}
@@ -64,11 +65,11 @@ public class GitSmartOperationDialog extends DialogWrapper {
}
private GitSmartOperationDialog(@NotNull Project project, @NotNull JComponent fileBrowser, @NotNull String operationTitle,
- boolean showForceButton) {
+ @Nullable String forceButton) {
super(project);
myFileBrowser = fileBrowser;
myOperationTitle = operationTitle;
- myShowForceButton = showForceButton;
+ myForceButton = forceButton;
String capitalizedOperation = capitalize(myOperationTitle);
setTitle("Git " + capitalizedOperation + " Problem");
@@ -82,8 +83,8 @@ public class GitSmartOperationDialog extends DialogWrapper {
@NotNull
@Override
protected Action[] createLeftSideActions() {
- if (myShowForceButton) {
- return new Action[] {new ForceCheckoutAction(myOperationTitle) };
+ if (myForceButton != null) {
+ return new Action[]{new ForceCheckoutAction(myForceButton, myOperationTitle)};
}
return new Action[0];
}
@@ -110,8 +111,8 @@ public class GitSmartOperationDialog extends DialogWrapper {
private class ForceCheckoutAction extends AbstractAction {
- ForceCheckoutAction(@NotNull String operationTitle) {
- super("&Force " + capitalize(operationTitle));
+ ForceCheckoutAction(@NotNull String buttonTitle, @NotNull String operationTitle) {
+ super(buttonTitle);
putValue(Action.SHORT_DESCRIPTION, capitalize(operationTitle) + " and overwrite local changes");
}
diff --git a/plugins/git4idea/src/git4idea/changes/GitCommittedChangeListProvider.java b/plugins/git4idea/src/git4idea/changes/GitCommittedChangeListProvider.java
index f1ab1d476c6f..31e731f44937 100644
--- a/plugins/git4idea/src/git4idea/changes/GitCommittedChangeListProvider.java
+++ b/plugins/git4idea/src/git4idea/changes/GitCommittedChangeListProvider.java
@@ -22,7 +22,7 @@ import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.*;
import com.intellij.openapi.vcs.changes.Change;
-import com.intellij.openapi.vcs.changes.ContentRevision;
+import com.intellij.openapi.vcs.changes.ChangesUtil;
import com.intellij.openapi.vcs.changes.committed.DecoratorManager;
import com.intellij.openapi.vcs.changes.committed.VcsCommittedListsZipper;
import com.intellij.openapi.vcs.changes.committed.VcsCommittedViewAuxiliary;
@@ -199,13 +199,7 @@ public class GitCommittedChangeListProvider implements CommittedChangesProvider<
final Collection<Change> changes = commit.getChanges();
if (changes.size() == 1) {
Change change = changes.iterator().next();
- ContentRevision revision = change.getAfterRevision();
- if (revision == null) {
- revision = change.getBeforeRevision();
- }
- assert revision != null : "Revision can't be null in " + change;
- FilePath filePathInRevision = revision.getFile();
- return Pair.create(commit, filePathInRevision);
+ return Pair.create(commit, ChangesUtil.getFilePath(change));
}
for (Change change : changes) {
if (change.getAfterRevision() != null && FileUtil.filesEqual(filePath.getIOFile(), change.getAfterRevision().getFile().getIOFile())) {
diff --git a/plugins/git4idea/src/git4idea/checkin/GitCheckinEnvironment.java b/plugins/git4idea/src/git4idea/checkin/GitCheckinEnvironment.java
index 3bb008a2f95f..448dd25ef7ab 100644
--- a/plugins/git4idea/src/git4idea/checkin/GitCheckinEnvironment.java
+++ b/plugins/git4idea/src/git4idea/checkin/GitCheckinEnvironment.java
@@ -226,10 +226,7 @@ public class GitCheckinEnvironment implements CheckinEnvironment {
@NotNull
private static VcsException cleanupExceptionText(VcsException original) {
String msg = original.getMessage();
- final String FATAL_PREFIX = "fatal:";
- if (msg.startsWith(FATAL_PREFIX)) {
- msg = msg.substring(FATAL_PREFIX.length());
- }
+ msg = GitUtil.cleanupErrorPrefixes(msg);
final String DURING_EXECUTING_SUFFIX = GitSimpleHandler.DURING_EXECUTING_ERROR_MESSAGE;
int suffix = msg.indexOf(DURING_EXECUTING_SUFFIX);
if (suffix > 0) {
diff --git a/plugins/git4idea/src/git4idea/checkin/GitCommitAuthorCorrector.java b/plugins/git4idea/src/git4idea/checkin/GitCommitAuthorCorrector.java
index e46e98a7887f..ac9834efc3ce 100644
--- a/plugins/git4idea/src/git4idea/checkin/GitCommitAuthorCorrector.java
+++ b/plugins/git4idea/src/git4idea/checkin/GitCommitAuthorCorrector.java
@@ -35,7 +35,7 @@ class GitCommitAuthorCorrector {
if (at < 0) {
return author;
}
- int email = author.substring(0, at).lastIndexOf(' ');
+ int email = author.lastIndexOf(' ', at - 1);
if (email < 0) {
return author;
}
diff --git a/plugins/git4idea/src/git4idea/cherrypick/GitCherryPickAction.java b/plugins/git4idea/src/git4idea/cherrypick/GitCherryPickAction.java
index aa3e1e440277..b4250a0d142b 100644
--- a/plugins/git4idea/src/git4idea/cherrypick/GitCherryPickAction.java
+++ b/plugins/git4idea/src/git4idea/cherrypick/GitCherryPickAction.java
@@ -49,6 +49,8 @@ import java.util.*;
* @author Kirill Likhodedov
*/
public class GitCherryPickAction extends DumbAwareAction {
+
+ private static final String NAME = "Cherry-Pick";
private static final Logger LOG = Logger.getInstance(GitCherryPickAction.class);
@NotNull private final GitPlatformFacade myPlatformFacade;
@@ -56,7 +58,7 @@ public class GitCherryPickAction extends DumbAwareAction {
@NotNull private final Set<Hash> myIdsInProgress;
public GitCherryPickAction() {
- super("Cherry-pick", "Cherry-pick", Git4ideaIcons.CherryPick);
+ super(NAME, null, Git4ideaIcons.CherryPick);
myGit = ServiceManager.getService(Git.class);
myPlatformFacade = ServiceManager.getService(GitPlatformFacade.class);
myIdsInProgress = ContainerUtil.newHashSet();
@@ -81,9 +83,8 @@ public class GitCherryPickAction extends DumbAwareAction {
new Task.Backgroundable(project, "Cherry-picking", false) {
public void run(@NotNull ProgressIndicator indicator) {
try {
- boolean autoCommit = GitVcsSettings.getInstance(myProject).isAutoCommitOnCherryPick();
Map<GitRepository, List<VcsFullCommitDetails>> commitsInRoots = sortCommits(groupCommitsByRoots(project, commits));
- new GitCherryPicker(myProject, myGit, myPlatformFacade, autoCommit).cherryPick(commitsInRoots);
+ new GitCherryPicker(project, myGit, myPlatformFacade, isAutoCommit(project)).cherryPick(commitsInRoots);
}
finally {
ApplicationManager.getApplication().invokeLater(new Runnable() {
@@ -130,15 +131,21 @@ public class GitCherryPickAction extends DumbAwareAction {
return groupedCommits;
}
+ private static boolean isAutoCommit(@NotNull Project project) {
+ return GitVcsSettings.getInstance(project).isAutoCommitOnCherryPick();
+ }
+
@Override
public void update(AnActionEvent e) {
super.update(e);
- final VcsLog log = getVcsLog(e);
- if (log != null && !DvcsUtil.logHasRootForVcs(log, GitVcs.getKey())) {
+ VcsLog log = getVcsLog(e);
+ Project project = getEventProject(e);
+ if (project == null || log == null || !DvcsUtil.logHasRootForVcs(log, GitVcs.getKey())) {
e.getPresentation().setEnabledAndVisible(false);
}
else {
e.getPresentation().setEnabled(enabled(e));
+ e.getPresentation().setText(isAutoCommit(project) ? NAME : NAME + "...");
}
}
diff --git a/plugins/git4idea/src/git4idea/commands/Git.java b/plugins/git4idea/src/git4idea/commands/Git.java
index 284ccc1e20c5..830f73b4508f 100644
--- a/plugins/git4idea/src/git4idea/commands/Git.java
+++ b/plugins/git4idea/src/git4idea/commands/Git.java
@@ -22,6 +22,7 @@ import com.intellij.openapi.vfs.VirtualFile;
import git4idea.GitCommit;
import git4idea.push.GitPushSpec;
import git4idea.repo.GitRepository;
+import git4idea.reset.GitResetMode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -93,7 +94,8 @@ public interface Git {
GitCommandResult branchCreate(@NotNull GitRepository repository, @NotNull String branchName);
@NotNull
- GitCommandResult resetHard(@NotNull GitRepository repository, @NotNull String revision);
+ GitCommandResult reset(@NotNull GitRepository repository, @NotNull GitResetMode mode, @NotNull String target,
+ @NotNull GitLineHandlerListener... listeners);
@NotNull
GitCommandResult resetMerge(@NotNull GitRepository repository, @Nullable String revision);
diff --git a/plugins/git4idea/src/git4idea/commands/GitCommandResult.java b/plugins/git4idea/src/git4idea/commands/GitCommandResult.java
index f89a4890a76b..0683d738a9bf 100644
--- a/plugins/git4idea/src/git4idea/commands/GitCommandResult.java
+++ b/plugins/git4idea/src/git4idea/commands/GitCommandResult.java
@@ -16,10 +16,14 @@
package git4idea.commands;
import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
+import git4idea.GitUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -64,9 +68,10 @@ public class GitCommandResult {
@NotNull
public String getErrorOutputAsHtmlString() {
- return StringUtil.join(myErrorOutput, "<br/>");
+ return StringUtil.join(cleanup(myErrorOutput), "<br/>");
}
-
+
+ @NotNull
public String getErrorOutputAsJoinedString() {
return StringUtil.join(myErrorOutput, "\n");
}
@@ -90,4 +95,14 @@ public class GitCommandResult {
return false; // will be implemented later
}
+ @NotNull
+ private static Collection<String> cleanup(@NotNull Collection<String> errorOutput) {
+ return ContainerUtil.map(errorOutput, new Function<String, String>() {
+ @Override
+ public String fun(String errorMessage) {
+ return GitUtil.cleanupErrorPrefixes(errorMessage);
+ }
+ });
+ }
+
}
diff --git a/plugins/git4idea/src/git4idea/commands/GitHandler.java b/plugins/git4idea/src/git4idea/commands/GitHandler.java
index 3350b74b1c6a..c2d85b7e3126 100644
--- a/plugins/git4idea/src/git4idea/commands/GitHandler.java
+++ b/plugins/git4idea/src/git4idea/commands/GitHandler.java
@@ -18,7 +18,6 @@ package git4idea.commands;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
@@ -103,7 +102,6 @@ public abstract class GitHandler {
private long myStartTime; // git execution start timestamp
private static final long LONG_TIME = 10 * 1000;
- @Nullable private ModalityState myState;
@Nullable private String myUrl;
private boolean myHttpAuthFailed;
@@ -423,7 +421,7 @@ public abstract class GitHandler {
}
else {
LOG.debug("cd " + myWorkingDirectory);
- LOG.debug(printableCommandLine());
+ LOG.debug("[" + myWorkingDirectory.getName() + "] " + printableCommandLine());
}
// setup environment
@@ -431,7 +429,7 @@ public abstract class GitHandler {
if (remoteProtocol == GitRemoteProtocol.SSH && myProjectSettings.isIdeaSsh()) {
GitXmlRpcSshService ssh = ServiceManager.getService(GitXmlRpcSshService.class);
myEnv.put(GitSSHHandler.GIT_SSH_ENV, ssh.getScriptPath().getPath());
- myHandlerNo = ssh.registerHandler(new GitSSHGUIHandler(myProject, myState));
+ myHandlerNo = ssh.registerHandler(new GitSSHGUIHandler(myProject));
myEnvironmentCleanedUp = false;
myEnv.put(GitSSHHandler.SSH_HANDLER_ENV, Integer.toString(myHandlerNo));
int port = ssh.getXmlRcpPort();
@@ -458,7 +456,7 @@ public abstract class GitHandler {
GitHttpAuthService service = ServiceManager.getService(GitHttpAuthService.class);
myEnv.put(GitAskPassXmlRpcHandler.GIT_ASK_PASS_ENV, service.getScriptPath().getPath());
assert myUrl != null : "myUrl can't be null here";
- GitHttpAuthenticator httpAuthenticator = service.createAuthenticator(myProject, myState, myCommand, myUrl);
+ GitHttpAuthenticator httpAuthenticator = service.createAuthenticator(myProject, myCommand, myUrl);
myHandlerNo = service.registerHandler(httpAuthenticator);
myEnvironmentCleanedUp = false;
myEnv.put(GitAskPassXmlRpcHandler.GIT_ASK_PASS_HANDLER_ENV, Integer.toString(myHandlerNo));
@@ -474,7 +472,9 @@ public abstract class GitHandler {
startHandlingStreams();
}
catch (Throwable t) {
- LOG.error(t);
+ if (!ApplicationManager.getApplication().isUnitTestMode() || !myProject.isDisposed()) {
+ LOG.error(t); // will surely happen if called during unit test disposal, because the working dir is simply removed then
+ }
cleanupEnv();
myListeners.getMulticaster().startFailed(t);
}
@@ -715,10 +715,6 @@ public abstract class GitHandler {
myResumeAction.run();
}
- public void setModalityState(@Nullable ModalityState state) {
- myState = state;
- }
-
/**
* @return true if the command line is too big
*/
diff --git a/plugins/git4idea/src/git4idea/commands/GitHttpAuthService.java b/plugins/git4idea/src/git4idea/commands/GitHttpAuthService.java
index 69be489be44b..712582339405 100644
--- a/plugins/git4idea/src/git4idea/commands/GitHttpAuthService.java
+++ b/plugins/git4idea/src/git4idea/commands/GitHttpAuthService.java
@@ -15,10 +15,8 @@
*/
package git4idea.commands;
-import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
import org.jetbrains.git4idea.http.GitAskPassApp;
import org.jetbrains.git4idea.http.GitAskPassXmlRpcHandler;
import org.jetbrains.git4idea.ssh.GitXmlRpcHandlerService;
@@ -47,8 +45,7 @@ public abstract class GitHttpAuthService extends GitXmlRpcHandlerService<GitHttp
* Creates new {@link GitHttpAuthenticator} that will be requested to handle username and password requests from Git.
*/
@NotNull
- public abstract GitHttpAuthenticator createAuthenticator(@NotNull Project project, @Nullable ModalityState state,
- @NotNull GitCommand command, @NotNull String url);
+ public abstract GitHttpAuthenticator createAuthenticator(@NotNull Project project, @NotNull GitCommand command, @NotNull String url);
/**
* Internal handler implementation class, it is made public to be accessible via XML RPC.
diff --git a/plugins/git4idea/src/git4idea/commands/GitHttpAuthServiceImpl.java b/plugins/git4idea/src/git4idea/commands/GitHttpAuthServiceImpl.java
index 06374bf78864..cda188d64e4b 100644
--- a/plugins/git4idea/src/git4idea/commands/GitHttpAuthServiceImpl.java
+++ b/plugins/git4idea/src/git4idea/commands/GitHttpAuthServiceImpl.java
@@ -15,10 +15,8 @@
*/
package git4idea.commands;
-import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
/**
* @author Kirill Likhodedov
@@ -27,9 +25,8 @@ class GitHttpAuthServiceImpl extends GitHttpAuthService {
@Override
@NotNull
- public GitHttpAuthenticator createAuthenticator(@NotNull Project project, @Nullable ModalityState state, @NotNull GitCommand command,
- @NotNull String url) {
- return new GitHttpGuiAuthenticator(project, state, command, url);
+ public GitHttpAuthenticator createAuthenticator(@NotNull Project project, @NotNull GitCommand command, @NotNull String url) {
+ return new GitHttpGuiAuthenticator(project, command, url);
}
}
diff --git a/plugins/git4idea/src/git4idea/commands/GitHttpGuiAuthenticator.java b/plugins/git4idea/src/git4idea/commands/GitHttpGuiAuthenticator.java
index e0312e5471fc..c5931f98df10 100644
--- a/plugins/git4idea/src/git4idea/commands/GitHttpGuiAuthenticator.java
+++ b/plugins/git4idea/src/git4idea/commands/GitHttpGuiAuthenticator.java
@@ -57,7 +57,6 @@ class GitHttpGuiAuthenticator implements GitHttpAuthenticator {
private static final Class<GitHttpAuthenticator> PASS_REQUESTER = GitHttpAuthenticator.class;
@NotNull private final Project myProject;
- @Nullable private final ModalityState myModalityState;
@NotNull private final String myTitle;
@NotNull private final String myUrlFromCommand;
@@ -69,10 +68,8 @@ class GitHttpGuiAuthenticator implements GitHttpAuthenticator {
@Nullable private GitHttpAuthDataProvider myDataProvider;
private boolean myWasCancelled;
- GitHttpGuiAuthenticator(@NotNull Project project, @Nullable ModalityState modalityState, @NotNull GitCommand command,
- @NotNull String url) {
+ GitHttpGuiAuthenticator(@NotNull Project project, @NotNull GitCommand command, @NotNull String url) {
myProject = project;
- myModalityState = modalityState;
myTitle = "Git " + StringUtil.capitalize(command.name());
myUrlFromCommand = url;
}
@@ -87,7 +84,7 @@ class GitHttpGuiAuthenticator implements GitHttpAuthenticator {
return "";
}
url = adjustUrl(url);
- Pair<GitHttpAuthDataProvider, AuthData> authData = findBestAuthData(url, myModalityState);
+ Pair<GitHttpAuthDataProvider, AuthData> authData = findBestAuthData(url);
if (authData != null && authData.second.getPassword() != null) {
String password = authData.second.getPassword();
myDataProvider = authData.first;
@@ -97,7 +94,7 @@ class GitHttpGuiAuthenticator implements GitHttpAuthenticator {
String prompt = "Enter the password for " + url;
myPasswordKey = url;
- String password = PasswordSafePromptDialog.askPassword(myProject, myModalityState, myTitle, prompt, PASS_REQUESTER, url, false, null);
+ String password = PasswordSafePromptDialog.askPassword(myProject, myTitle, prompt, PASS_REQUESTER, url, false, null);
if (password == null) {
myWasCancelled = true;
return "";
@@ -114,7 +111,7 @@ class GitHttpGuiAuthenticator implements GitHttpAuthenticator {
@NotNull
public String askUsername(@NotNull String url) {
url = adjustUrl(url);
- Pair<GitHttpAuthDataProvider, AuthData> authData = findBestAuthData(url, myModalityState);
+ Pair<GitHttpAuthDataProvider, AuthData> authData = findBestAuthData(url);
String login = null;
String password = null;
if (authData != null) {
@@ -152,7 +149,7 @@ class GitHttpGuiAuthenticator implements GitHttpAuthenticator {
dialog.set(new AuthDialog(myProject, myTitle, "Enter credentials for " + url, login, null, true));
dialog.get().show();
}
- }, myModalityState == null ? ModalityState.defaultModalityState() : myModalityState);
+ }, ModalityState.any());
return dialog.get();
}
@@ -223,10 +220,10 @@ class GitHttpGuiAuthenticator implements GitHttpAuthenticator {
// return the first that knows username + password; otherwise return the first that knows just the username
@Nullable
- private Pair<GitHttpAuthDataProvider, AuthData> findBestAuthData(@NotNull String url, @Nullable ModalityState modalityState) {
+ private Pair<GitHttpAuthDataProvider, AuthData> findBestAuthData(@NotNull String url) {
Pair<GitHttpAuthDataProvider, AuthData> candidate = null;
for (GitHttpAuthDataProvider provider : getProviders()) {
- AuthData data = provider.getAuthData(url, modalityState);
+ AuthData data = provider.getAuthData(url);
if (data != null) {
Pair<GitHttpAuthDataProvider, AuthData> pair = Pair.create(provider, data);
if (data.getPassword() != null) {
@@ -268,12 +265,12 @@ class GitHttpGuiAuthenticator implements GitHttpAuthenticator {
@Nullable
@Override
- public AuthData getAuthData(@NotNull String url, @Nullable ModalityState modalityState) {
+ public AuthData getAuthData(@NotNull String url) {
String userName = getUsername(url);
String key = makeKey(url, userName);
final PasswordSafe passwordSafe = PasswordSafe.getInstance();
try {
- String password = passwordSafe.getPassword(myProject, PASS_REQUESTER, key, modalityState);
+ String password = passwordSafe.getPassword(myProject, PASS_REQUESTER, key);
return new AuthData(StringUtil.notNullize(userName), password);
}
catch (PasswordSafeException e) {
diff --git a/plugins/git4idea/src/git4idea/commands/GitImpl.java b/plugins/git4idea/src/git4idea/commands/GitImpl.java
index c873e71ff94b..09e254f5392b 100644
--- a/plugins/git4idea/src/git4idea/commands/GitImpl.java
+++ b/plugins/git4idea/src/git4idea/commands/GitImpl.java
@@ -32,6 +32,7 @@ import git4idea.history.GitHistoryUtils;
import git4idea.push.GitPushSpec;
import git4idea.repo.GitRemote;
import git4idea.repo.GitRepository;
+import git4idea.reset.GitResetMode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -338,20 +339,26 @@ public class GitImpl implements Git {
@Override
@NotNull
- public GitCommandResult resetHard(@NotNull GitRepository repository, @NotNull String revision) {
- final GitLineHandler handler = new GitLineHandler(repository.getProject(), repository.getRoot(), GitCommand.RESET);
- handler.addParameters("--hard", revision);
- return run(handler);
+ public GitCommandResult reset(@NotNull GitRepository repository, @NotNull GitResetMode mode, @NotNull String target,
+ @NotNull GitLineHandlerListener... listeners) {
+ return reset(repository, mode.getArgument(), target, listeners);
}
@Override
@NotNull
public GitCommandResult resetMerge(@NotNull GitRepository repository, @Nullable String revision) {
+ return reset(repository, "--merge", revision);
+ }
+
+ @NotNull
+ private static GitCommandResult reset(@NotNull GitRepository repository, @NotNull String argument, @Nullable String target,
+ @NotNull GitLineHandlerListener... listeners) {
final GitLineHandler handler = new GitLineHandler(repository.getProject(), repository.getRoot(), GitCommand.RESET);
- handler.addParameters("--merge");
- if (revision != null) {
- handler.addParameters(revision);
+ handler.addParameters(argument);
+ if (target != null) {
+ handler.addParameters(target);
}
+ addListeners(handler, listeners);
return run(handler);
}
diff --git a/plugins/git4idea/src/git4idea/commands/GitLocalChangesWouldBeOverwrittenDetector.java b/plugins/git4idea/src/git4idea/commands/GitLocalChangesWouldBeOverwrittenDetector.java
index b62f12806761..e9d8df89614a 100644
--- a/plugins/git4idea/src/git4idea/commands/GitLocalChangesWouldBeOverwrittenDetector.java
+++ b/plugins/git4idea/src/git4idea/commands/GitLocalChangesWouldBeOverwrittenDetector.java
@@ -40,6 +40,13 @@ public class GitLocalChangesWouldBeOverwrittenDetector extends GitMessageWithFil
".*Your local changes to '(.*)' would be overwritten by merge.*"
);
+ private static final Pattern[] RESET_PATTERNS = new Pattern[]{Pattern.compile(
+ ".*Entry '(.*)' not uptodate. Cannot merge.*"
+ ),
+ Pattern.compile(
+ ".*Entry '(.*)' would be overwritten by merge.*"
+ )};
+
// common for checkout and merge
public static final Event NEW_PATTERN = new Event(
"Your local changes to the following files would be overwritten by",
@@ -49,17 +56,18 @@ public class GitLocalChangesWouldBeOverwrittenDetector extends GitMessageWithFil
public enum Operation {
CHECKOUT(OLD_CHECKOUT_PATTERN),
- MERGE(OLD_MERGE_PATTERN);
+ MERGE(OLD_MERGE_PATTERN),
+ RESET(RESET_PATTERNS);
- @NotNull private final Pattern myPattern;
+ @NotNull private final Pattern[] myPatterns;
- Operation(@NotNull Pattern pattern) {
- myPattern = pattern;
+ Operation(@NotNull Pattern... patterns) {
+ myPatterns = patterns;
}
@NotNull
- public Pattern getPattern() {
- return myPattern;
+ Pattern[] getPatterns() {
+ return myPatterns;
}
}
@@ -71,10 +79,13 @@ public class GitLocalChangesWouldBeOverwrittenDetector extends GitMessageWithFil
@Override
public void onLineAvailable(@NotNull String line, @NotNull Key outputType) {
super.onLineAvailable(line, outputType);
- Matcher m = myOperation.getPattern().matcher(line);
- if (m.matches()) {
- myMessageDetected = true;
- myAffectedFiles.add(m.group(1));
+ for (Pattern pattern : myOperation.getPatterns()) {
+ Matcher m = pattern.matcher(line);
+ if (m.matches()) {
+ myMessageDetected = true;
+ myAffectedFiles.add(m.group(1));
+ break;
+ }
}
}
}
diff --git a/plugins/git4idea/src/git4idea/commands/GitSSHGUIHandler.java b/plugins/git4idea/src/git4idea/commands/GitSSHGUIHandler.java
index 982270421968..4d1c13415ec2 100644
--- a/plugins/git4idea/src/git4idea/commands/GitSSHGUIHandler.java
+++ b/plugins/git4idea/src/git4idea/commands/GitSSHGUIHandler.java
@@ -16,7 +16,6 @@
package git4idea.commands;
import com.intellij.ide.passwordSafe.ui.PasswordSafePromptDialog;
-import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
@@ -39,17 +38,9 @@ import java.util.concurrent.atomic.AtomicReference;
*/
public class GitSSHGUIHandler {
@Nullable private final Project myProject;
- @Nullable private final ModalityState myState;
- /**
- * A constructor
- *
- * @param project a project to use
- * @param state modality state using which any prompts initiated by the git process should be shown in the UI.
- */
- GitSSHGUIHandler(@Nullable Project project, @Nullable ModalityState state) {
+ GitSSHGUIHandler(@Nullable Project project) {
myProject = project;
- myState = state;
}
public boolean verifyServerHostKey(final String hostname,
@@ -76,7 +67,7 @@ public class GitSSHGUIHandler {
@Nullable
public String askPassphrase(final String username, final String keyPath, boolean resetPassword, final String lastError) {
String error = processLastError(resetPassword, lastError);
- return PasswordSafePromptDialog.askPassphrase(myProject, myState, GitBundle.getString("ssh.ask.passphrase.title"),
+ return PasswordSafePromptDialog.askPassphrase(myProject, GitBundle.getString("ssh.ask.passphrase.title"),
GitBundle.message("ssh.askPassphrase.message", keyPath, username),
GitSSHGUIHandler.class, "PASSPHRASE:" + keyPath, resetPassword, error
);
@@ -165,7 +156,7 @@ public class GitSSHGUIHandler {
@Nullable
public String askPassword(final String username, boolean resetPassword, final String lastError) {
String error = processLastError(resetPassword, lastError);
- return PasswordSafePromptDialog.askPassword(myProject, myState, GitBundle.getString("ssh.password.title"),
+ return PasswordSafePromptDialog.askPassword(myProject, GitBundle.getString("ssh.password.title"),
GitBundle.message("ssh.password.message", username),
GitSSHGUIHandler.class, "PASSWORD:" + username, resetPassword, error);
}
diff --git a/plugins/git4idea/src/git4idea/commands/GitTask.java b/plugins/git4idea/src/git4idea/commands/GitTask.java
index c22ce07819c9..79f8e33ef55e 100644
--- a/plugins/git4idea/src/git4idea/commands/GitTask.java
+++ b/plugins/git4idea/src/git4idea/commands/GitTask.java
@@ -324,7 +324,6 @@ public class GitTask {
@Override
public final void run(@NotNull ProgressIndicator indicator) {
- myHandler.setModalityState(indicator.getModalityState());
myDelegate.run(indicator);
}
diff --git a/plugins/git4idea/src/git4idea/config/GitVcsSettings.java b/plugins/git4idea/src/git4idea/config/GitVcsSettings.java
index 4f74f7ca94f3..1b5860631e59 100644
--- a/plugins/git4idea/src/git4idea/config/GitVcsSettings.java
+++ b/plugins/git4idea/src/git4idea/config/GitVcsSettings.java
@@ -19,6 +19,7 @@ import com.intellij.lifecycle.PeriodicalTasksCloser;
import com.intellij.openapi.components.*;
import com.intellij.openapi.project.Project;
import com.intellij.util.ArrayUtil;
+import git4idea.reset.GitResetMode;
import git4idea.ui.branch.GitBranchSyncSetting;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -61,6 +62,7 @@ public class GitVcsSettings implements PersistentStateComponent<GitVcsSettings.S
public String RECENT_COMMON_BRANCH = null;
public boolean AUTO_COMMIT_ON_CHERRY_PICK = false;
public boolean WARN_ABOUT_CRLF = true;
+ public GitResetMode RESET_MODE = null;
}
public GitVcsSettings(GitVcsApplicationSettings appSettings) {
@@ -177,6 +179,15 @@ public class GitVcsSettings implements PersistentStateComponent<GitVcsSettings.S
myState.WARN_ABOUT_CRLF = warn;
}
+ @Nullable
+ public GitResetMode getResetMode() {
+ return myState.RESET_MODE;
+ }
+
+ public void setResetMode(@NotNull GitResetMode mode) {
+ myState.RESET_MODE = mode;
+ }
+
/**
* Provides migration from project settings.
* This method is to be removed in IDEA 13: it should be moved to {@link GitVcsApplicationSettings}
diff --git a/plugins/git4idea/src/git4idea/history/GitDiffFromHistoryHandler.java b/plugins/git4idea/src/git4idea/history/GitDiffFromHistoryHandler.java
index 87edd30ae077..a6488d4ce3d0 100644
--- a/plugins/git4idea/src/git4idea/history/GitDiffFromHistoryHandler.java
+++ b/plugins/git4idea/src/git4idea/history/GitDiffFromHistoryHandler.java
@@ -22,25 +22,22 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.DialogBuilder;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.ui.popup.ListPopup;
-import com.intellij.openapi.util.Couple;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vcs.changes.ContentRevision;
-import com.intellij.openapi.vcs.changes.ui.ChangesBrowser;
-import com.intellij.openapi.vcs.history.CurrentRevision;
+import com.intellij.openapi.vcs.history.BaseDiffFromHistoryHandler;
import com.intellij.openapi.vcs.history.DiffFromHistoryHandler;
import com.intellij.openapi.vcs.history.VcsFileRevision;
-import com.intellij.openapi.vcs.history.VcsHistoryUtil;
import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Consumer;
+import com.intellij.util.containers.ContainerUtil;
import git4idea.GitFileRevision;
import git4idea.GitRevisionNumber;
import git4idea.GitUtil;
@@ -67,71 +64,59 @@ import java.util.List;
*
* @author Kirill Likhodedov
*/
-public class GitDiffFromHistoryHandler implements DiffFromHistoryHandler {
+public class GitDiffFromHistoryHandler extends BaseDiffFromHistoryHandler<GitFileRevision> {
private static final Logger LOG = Logger.getInstance(GitDiffFromHistoryHandler.class);
- @NotNull private final Project myProject;
@NotNull private final Git myGit;
@NotNull private final GitRepositoryManager myRepositoryManager;
public GitDiffFromHistoryHandler(@NotNull Project project) {
- myProject = project;
+ super(project);
myGit = ServiceManager.getService(project, Git.class);
myRepositoryManager = GitUtil.getRepositoryManager(project);
}
@Override
- public void showDiffForOne(@NotNull AnActionEvent e, @NotNull FilePath filePath,
- @NotNull VcsFileRevision previousRevision, @NotNull VcsFileRevision revision) {
+ public void showDiffForOne(@NotNull AnActionEvent e,
+ @NotNull FilePath filePath,
+ @NotNull VcsFileRevision previousRevision,
+ @NotNull VcsFileRevision revision) {
GitFileRevision rev = (GitFileRevision)revision;
Collection<String> parents = rev.getParents();
if (parents.size() < 2) {
- doShowDiff(filePath, previousRevision, revision, false);
+ super.showDiffForOne(e, filePath, previousRevision, revision);
}
else { // merge
showDiffForMergeCommit(e, filePath, rev, parents);
}
}
+ @NotNull
@Override
- public void showDiffForTwo(@NotNull FilePath filePath, @NotNull VcsFileRevision revision1, @NotNull VcsFileRevision revision2) {
- doShowDiff(filePath, revision1, revision2, true);
- }
+ protected List<Change> getChangesBetweenRevisions(@NotNull FilePath path, @NotNull GitFileRevision rev1, @Nullable GitFileRevision rev2)
+ throws VcsException {
+ GitRepository repository = getRepository(path);
+ String hash1 = rev1.getHash();
+ String hash2 = rev2 != null ? rev2.getHash() : null;
- private void doShowDiff(@NotNull FilePath filePath, @NotNull VcsFileRevision revision1, @NotNull VcsFileRevision revision2,
- boolean autoSort) {
- if (!filePath.isDirectory()) {
- VcsHistoryUtil.showDifferencesInBackground(myProject, filePath, revision1, revision2, autoSort);
- }
- else if (revision2 instanceof CurrentRevision) {
- GitFileRevision left = (GitFileRevision)revision1;
- showDiffForDirectory(filePath, left.getHash(), null);
- }
- else if (revision1.equals(VcsFileRevision.NULL)) {
- GitFileRevision right = (GitFileRevision)revision2;
- showDiffForDirectory(filePath, null, right.getHash());
- }
- else {
- GitFileRevision left = (GitFileRevision)revision1;
- GitFileRevision right = (GitFileRevision)revision2;
- if (autoSort) {
- Couple<VcsFileRevision> pair = VcsHistoryUtil.sortRevisions(revision1, revision2);
- left = (GitFileRevision)pair.first;
- right = (GitFileRevision)pair.second;
- }
- showDiffForDirectory(filePath, left.getHash(), right.getHash());
- }
+ return ContainerUtil
+ .newArrayList(GitChangeUtils.getDiff(repository.getProject(), repository.getRoot(), hash1, hash2, Collections.singletonList(path)));
}
- private void showDiffForDirectory(@NotNull final FilePath path, @Nullable final String hash1, @Nullable final String hash2) {
+ @NotNull
+ @Override
+ protected List<Change> getAffectedChanges(@NotNull FilePath path, @NotNull GitFileRevision rev) throws VcsException {
GitRepository repository = getRepository(path);
- calculateDiffInBackground(repository, path, hash1, hash2, new Consumer<List<Change>>() {
- @Override
- public void consume(List<Change> changes) {
- showDirDiffDialog(path, hash1, hash2, changes);
- }
- });
+
+ return ContainerUtil.newArrayList(
+ GitChangeUtils.getRevisionChanges(repository.getProject(), repository.getRoot(), rev.getHash(), false, true, true).getChanges());
+ }
+
+ @NotNull
+ @Override
+ protected String getPresentableName(@NotNull GitFileRevision revision) {
+ return GitUtil.getShortHash(revision.getHash());
}
@NotNull
@@ -141,63 +126,6 @@ public class GitDiffFromHistoryHandler implements DiffFromHistoryHandler {
return repository;
}
- // hash1 == null => hash2 is the initial commit
- // hash2 == null => comparing hash1 with local
- private void calculateDiffInBackground(@NotNull final GitRepository repository, @NotNull final FilePath path,
- @Nullable final String hash1, @Nullable final String hash2,
- final Consumer<List<Change>> successHandler) {
- new Task.Backgroundable(myProject, "Comparing revisions...") {
- private List<Change> myChanges;
- @Override
- public void run(@NotNull ProgressIndicator indicator) {
- try {
- if (hash1 != null) {
- // diff
- myChanges = new ArrayList<Change>(GitChangeUtils.getDiff(repository.getProject(), repository.getRoot(), hash1, hash2,
- Collections.singletonList(path)));
- }
- else {
- // show the initial commit
- myChanges = new ArrayList<Change>(GitChangeUtils.getRevisionChanges(repository.getProject(), repository.getRoot(), hash2, false,
- true, true).getChanges());
- }
- }
- catch (VcsException e) {
- showError(e, "Error during requesting diff for directory");
- }
- }
-
- @Override
- public void onSuccess() {
- successHandler.consume(myChanges);
- }
- }.queue();
- }
-
- private void showDirDiffDialog(@NotNull FilePath path, @Nullable String hash1, @Nullable String hash2, @NotNull List<Change> diff) {
- DialogBuilder dialogBuilder = new DialogBuilder(myProject);
- String title;
- if (hash2 != null) {
- if (hash1 != null) {
- title = String.format("Difference between %s and %s in %s", GitUtil.getShortHash(hash1), GitUtil.getShortHash(hash2), path.getName());
- }
- else {
- title = String.format("Initial commit %s in %s", GitUtil.getShortHash(hash2), path.getName());
- }
- }
- else {
- LOG.assertTrue(hash1 != null, "hash1 and hash2 can't both be null. Path: " + path);
- title = String.format("Difference between %s and local version in %s", GitUtil.getShortHash(hash1), path.getName());
- }
- dialogBuilder.setTitle(title);
- dialogBuilder.setActionDescriptors(new DialogBuilder.ActionDescriptor[] { new DialogBuilder.CloseDialogAction()});
- final ChangesBrowser changesBrowser = new ChangesBrowser(myProject, null, diff, null, false, true,
- null, ChangesBrowser.MyUseCase.COMMITTED_CHANGES, null);
- changesBrowser.setChangesToDisplay(diff);
- dialogBuilder.setCenterPanel(changesBrowser);
- dialogBuilder.showNotModal();
- }
-
private void showDiffForMergeCommit(@NotNull final AnActionEvent event, @NotNull final FilePath filePath,
@NotNull final GitFileRevision rev, @NotNull final Collection<String> parents) {
@@ -299,12 +227,6 @@ public class GitDiffFromHistoryHandler implements DiffFromHistoryHandler {
return makeRevisionFromHash(currentRevisionPath, parentHash);
}
-
- private void showError(VcsException e, String logMessage) {
- LOG.info(logMessage, e);
- VcsBalloonProblemNotifier.showOverVersionControlView(this.myProject, e.getMessage(), MessageType.ERROR);
- }
-
private void showPopup(@NotNull AnActionEvent event, @NotNull GitFileRevision rev, @NotNull FilePath filePath,
@NotNull Collection<GitFileRevision> parents) {
ActionGroup parentActions = createActionGroup(rev, filePath, parents);
diff --git a/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java b/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java
index 114b4beb5435..8273c3e1abdc 100644
--- a/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java
+++ b/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java
@@ -520,9 +520,19 @@ public class GitHistoryUtils {
@NotNull VirtualFile root,
@NotNull final Consumer<VcsUser> userRegistry,
@NotNull List<String> parameters) throws VcsException {
+ List<TimedVcsCommit> collector = ContainerUtil.newArrayList();
+ readCommits(project, root, userRegistry, parameters, new CollectConsumer<TimedVcsCommit>(collector));
+ return collector;
+ }
+
+ public static void readCommits(@NotNull final Project project,
+ @NotNull VirtualFile root,
+ @NotNull final Consumer<VcsUser> userRegistry,
+ @NotNull List<String> parameters,
+ @NotNull final Consumer<TimedVcsCommit> commitConsumer) throws VcsException {
final VcsLogObjectsFactory factory = getObjectsFactoryWithDisposeCheck(project);
if (factory == null) {
- return Collections.emptyList();
+ return;
}
final int COMMIT_BUFFER = 1000;
@@ -536,8 +546,6 @@ public class GitHistoryUtils {
h.addParameters(parameters);
h.endOptions();
- final List<TimedVcsCommit> commits = ContainerUtil.newArrayList();
-
final StringBuilder record = new StringBuilder();
final AtomicInteger records = new AtomicInteger();
final Ref<VcsException> ex = new Ref<VcsException>();
@@ -560,7 +568,10 @@ public class GitHistoryUtils {
afterParseRemainder = line.substring(recordEnd + 1);
}
if (afterParseRemainder != null && records.incrementAndGet() > COMMIT_BUFFER) { // null means can't parse now
- commits.addAll(parseCommit(parser, record, userRegistry, factory));
+ List<TimedVcsCommit> commits = parseCommit(parser, record, userRegistry, factory);
+ for (TimedVcsCommit commit : commits) {
+ commitConsumer.consume(commit);
+ }
record.setLength(0);
record.append(afterParseRemainder);
}
@@ -573,7 +584,10 @@ public class GitHistoryUtils {
@Override
public void processTerminated(int exitCode) {
try {
- commits.addAll(parseCommit(parser, record, userRegistry, factory));
+ List<TimedVcsCommit> commits = parseCommit(parser, record, userRegistry, factory);
+ for (TimedVcsCommit commit : commits) {
+ commitConsumer.consume(commit);
+ }
}
catch (Exception e) {
ex.set(new VcsException(e));
@@ -589,7 +603,6 @@ public class GitHistoryUtils {
if (!ex.isNull()) {
throw ex.get();
}
- return commits;
}
@NotNull
diff --git a/plugins/git4idea/src/git4idea/i18n/GitBundle.properties b/plugins/git4idea/src/git4idea/i18n/GitBundle.properties
index 79e7f70df250..03803fbf985c 100644
--- a/plugins/git4idea/src/git4idea/i18n/GitBundle.properties
+++ b/plugins/git4idea/src/git4idea/i18n/GitBundle.properties
@@ -491,9 +491,9 @@ git.executable.filechooser.description=Specify the full path to Git executable
git.push.active.close=Close
git.unstash.clear.confirmation.message=Remove all stashes? This cannot be undone.
-git.unstash.clear.confirmation.title=Remove all stashes?
+git.unstash.clear.confirmation.title=Remove All Stashes?
git.unstash.drop.confirmation.message=<html>Do you want to remove {0}?<br/>"{1}"</html>
-git.unstash.drop.confirmation.title=Remove stash {0}?
+git.unstash.drop.confirmation.title=Remove Stash {0}?
branch.delete.not_fully_merged.description=The branch <code><b>{0}</b></code> is not fully merged to the branch <code><b>{1}</b></code>.<br/>Below is the list of unmerged commits.
branch.delete.not_fully_merged.description.not_on_branch=You are currently not on the branch (<code>{1}</code>). <br>\
diff --git a/plugins/git4idea/src/git4idea/log/GitBekParentFixer.java b/plugins/git4idea/src/git4idea/log/GitBekParentFixer.java
index e469e61ca315..054ed9f90b48 100644
--- a/plugins/git4idea/src/git4idea/log/GitBekParentFixer.java
+++ b/plugins/git4idea/src/git4idea/log/GitBekParentFixer.java
@@ -27,49 +27,34 @@ import org.jetbrains.annotations.Nullable;
import java.util.*;
class GitBekParentFixer {
- @NotNull
- private final static String MAGIC_TEXT = "Merge remote";
- @NotNull
- private final VcsLogFilterCollection MAGIC_FILTER = createVcsLogFilterCollection();
+ @NotNull private static final String MAGIC_TEXT = "Merge remote";
+ @NotNull private static final VcsLogFilterCollection MAGIC_FILTER = createVcsLogFilterCollection();
- @NotNull
- private final VirtualFile myRoot;
- @NotNull
- private final GitLogProvider myGitLogProvider;
- @NotNull
- private final List<TimedVcsCommit> myAllCommits;
+ @NotNull private final Set<Hash> myWrongCommits;
- GitBekParentFixer(@NotNull VirtualFile root, @NotNull GitLogProvider gitLogProvider, @NotNull List<TimedVcsCommit> allCommits) {
- myRoot = root;
- myGitLogProvider = gitLogProvider;
- myAllCommits = allCommits;
+ private GitBekParentFixer(@NotNull Set<Hash> wrongCommits) {
+ myWrongCommits = wrongCommits;
}
@NotNull
- List<TimedVcsCommit> getCorrectCommits() throws VcsException {
- if (!BekSorter.isBekEnabled())
- return myAllCommits;
-
- final Set<Hash> wrongCommits = getWrongCommits();
- return new AbstractList<TimedVcsCommit>() {
- @Override
- public TimedVcsCommit get(int index) {
- TimedVcsCommit commit = myAllCommits.get(index);
- if (!wrongCommits.contains(commit.getId()))
- return commit;
-
- return reverseParents(commit);
- }
+ static GitBekParentFixer prepare(@NotNull VirtualFile root, @NotNull GitLogProvider provider) throws VcsException {
+ if (!BekSorter.isBekEnabled()) {
+ return new GitBekParentFixer(Collections.<Hash>emptySet());
+ }
+ return new GitBekParentFixer(getWrongCommits(provider, root));
+ }
- @Override
- public int size() {
- return myAllCommits.size();
- }
- };
+ @NotNull
+ TimedVcsCommit fixCommit(@NotNull TimedVcsCommit commit) {
+ if (!myWrongCommits.contains(commit.getId())) {
+ return commit;
+ }
+ return reverseParents(commit);
}
- private Set<Hash> getWrongCommits() throws VcsException {
- List<TimedVcsCommit> commitsMatchingFilter = myGitLogProvider.getCommitsMatchingFilter(myRoot, MAGIC_FILTER, -1);
+ @NotNull
+ private static Set<Hash> getWrongCommits(@NotNull GitLogProvider provider, @NotNull VirtualFile root) throws VcsException {
+ List<TimedVcsCommit> commitsMatchingFilter = provider.getCommitsMatchingFilter(root, MAGIC_FILTER, -1);
return ContainerUtil.map2Set(commitsMatchingFilter, new Function<TimedVcsCommit, Hash>() {
@Override
public Hash fun(TimedVcsCommit timedVcsCommit) {
diff --git a/plugins/git4idea/src/git4idea/log/GitLogProvider.java b/plugins/git4idea/src/git4idea/log/GitLogProvider.java
index ecc4709be5d3..435313fa5c7d 100644
--- a/plugins/git4idea/src/git4idea/log/GitLogProvider.java
+++ b/plugins/git4idea/src/git4idea/log/GitLogProvider.java
@@ -154,18 +154,23 @@ public class GitLogProvider implements VcsLogProvider {
});
}
- @NotNull
@Override
- public List<TimedVcsCommit> readAllHashes(@NotNull VirtualFile root, @NotNull Consumer<VcsUser> userRegistry) throws VcsException {
+ public void readAllHashes(@NotNull VirtualFile root, @NotNull Consumer<VcsUser> userRegistry,
+ @NotNull final Consumer<TimedVcsCommit> commitConsumer) throws VcsException {
if (!isRepositoryReady(root)) {
- return Collections.emptyList();
+ return;
}
List<String> parameters = new ArrayList<String>(GitHistoryUtils.LOG_ALL);
parameters.add("--sparse");
- List<TimedVcsCommit> timedVcsCommits = GitHistoryUtils.readCommits(myProject, root, userRegistry, parameters);
- return new GitBekParentFixer(root, this, timedVcsCommits).getCorrectCommits();
+ final GitBekParentFixer parentFixer = GitBekParentFixer.prepare(root, this);
+ GitHistoryUtils.readCommits(myProject, root, userRegistry, parameters, new Consumer<TimedVcsCommit>() {
+ @Override
+ public void consume(TimedVcsCommit commit) {
+ commitConsumer.consume(parentFixer.fixCommit(commit));
+ }
+ });
}
@NotNull
diff --git a/plugins/git4idea/src/git4idea/merge/GitPullDialog.java b/plugins/git4idea/src/git4idea/merge/GitPullDialog.java
index f9d8085cfab8..68b16164b335 100644
--- a/plugins/git4idea/src/git4idea/merge/GitPullDialog.java
+++ b/plugins/git4idea/src/git4idea/merge/GitPullDialog.java
@@ -44,66 +44,23 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
-/**
- * Git pull dialog
- */
public class GitPullDialog extends DialogWrapper {
private static final Logger LOG = Logger.getInstance(GitPullDialog.class);
- /**
- * root panel
- */
private JPanel myPanel;
- /**
- * The selected git root
- */
private JComboBox myGitRoot;
- /**
- * Current branch label
- */
private JLabel myCurrentBranch;
- /**
- * The merge strategy
- */
private JComboBox myStrategy;
- /**
- * No commit option
- */
private JCheckBox myNoCommitCheckBox;
- /**
- * Squash commit option
- */
private JCheckBox mySquashCommitCheckBox;
- /**
- * No fast forward option
- */
private JCheckBox myNoFastForwardCheckBox;
- /**
- * Add log info to commit option
- */
private JCheckBox myAddLogInformationCheckBox;
- /**
- * Selected remote option
- */
private JComboBox myRemote;
- /**
- * The branch chooser
- */
private ElementsChooser<String> myBranchChooser;
- /**
- * The context project
- */
private final Project myProject;
private final GitRepositoryManager myRepositoryManager;
- /**
- * A constructor
- *
- * @param project a project to select
- * @param roots a git repository roots for the project
- * @param defaultRoot a guessed default root
- */
public GitPullDialog(Project project, List<VirtualFile> roots, VirtualFile defaultRoot) {
super(project, true);
setTitle(GitBundle.getString("pull.title"));
@@ -138,9 +95,6 @@ public class GitPullDialog extends DialogWrapper {
init();
}
- /**
- * Validate dialog and enable buttons
- */
private void validateDialog() {
String selectedRemote = getRemote();
if (StringUtil.isEmptyOrSpaces(selectedRemote)) {
@@ -150,9 +104,6 @@ public class GitPullDialog extends DialogWrapper {
setOKActionEnabled(myBranchChooser.getMarkedElements().size() != 0);
}
- /**
- * @return a pull handler configured according to dialog options
- */
public GitLineHandler makeHandler(@NotNull String url) {
GitLineHandler h = new GitLineHandler(myProject, gitRoot(), GitCommand.PULL);
// ignore merge failure for the pull
@@ -232,9 +183,6 @@ public class GitPullDialog extends DialogWrapper {
return branch.getName().startsWith(remote + "/");
}
- /**
- * Update remotes for the git root
- */
private void updateRemotes() {
GitRepository repository = getRepository();
if (repository == null) {
@@ -331,39 +279,23 @@ public class GitPullDialog extends DialogWrapper {
};
}
- /**
- * @return a currently selected git root
- */
public VirtualFile gitRoot() {
return (VirtualFile)myGitRoot.getSelectedItem();
}
-
- /**
- * Create branch chooser
- */
private void createUIComponents() {
myBranchChooser = new ElementsChooser<String>(true);
}
- /**
- * {@inheritDoc}
- */
protected JComponent createCenterPanel() {
return myPanel;
}
- /**
- * {@inheritDoc}
- */
@Override
protected String getDimensionServiceKey() {
return getClass().getName();
}
- /**
- * {@inheritDoc}
- */
@Override
protected String getHelpId() {
return "reference.VersionControl.Git.Pull";
diff --git a/plugins/git4idea/src/git4idea/remote/GitHttpAuthDataProvider.java b/plugins/git4idea/src/git4idea/remote/GitHttpAuthDataProvider.java
index 281d69b772c3..6c0860ccf20a 100644
--- a/plugins/git4idea/src/git4idea/remote/GitHttpAuthDataProvider.java
+++ b/plugins/git4idea/src/git4idea/remote/GitHttpAuthDataProvider.java
@@ -15,7 +15,6 @@
*/
package git4idea.remote;
-import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.util.AuthData;
import org.jetbrains.annotations.NotNull;
@@ -32,7 +31,7 @@ public interface GitHttpAuthDataProvider {
ExtensionPointName<GitHttpAuthDataProvider> EP_NAME = ExtensionPointName.create("Git4Idea.GitHttpAuthDataProvider");
@Nullable
- AuthData getAuthData(@NotNull String url, @Nullable ModalityState modalityState);
+ AuthData getAuthData(@NotNull String url);
void forgetPassword(@NotNull String url);
diff --git a/plugins/git4idea/src/git4idea/repo/GitRepositoryImpl.java b/plugins/git4idea/src/git4idea/repo/GitRepositoryImpl.java
index 29f2c4cf3e2e..e401334416d6 100644
--- a/plugins/git4idea/src/git4idea/repo/GitRepositoryImpl.java
+++ b/plugins/git4idea/src/git4idea/repo/GitRepositoryImpl.java
@@ -34,7 +34,7 @@ import java.util.Collection;
/**
* @author Kirill Likhodedov
*/
-public class GitRepositoryImpl extends RepositoryImpl implements GitRepository, Disposable {
+public class GitRepositoryImpl extends RepositoryImpl implements GitRepository {
@NotNull private final GitPlatformFacade myPlatformFacade;
@NotNull private final GitRepositoryReader myReader;
diff --git a/plugins/git4idea/src/git4idea/repo/GitUntrackedFilesHolder.java b/plugins/git4idea/src/git4idea/repo/GitUntrackedFilesHolder.java
index 0cf82d9a521f..4ad12d8a121f 100644
--- a/plugins/git4idea/src/git4idea/repo/GitUntrackedFilesHolder.java
+++ b/plugins/git4idea/src/git4idea/repo/GitUntrackedFilesHolder.java
@@ -237,9 +237,6 @@ public class GitUntrackedFilesHolder implements Disposable, BulkFileListener {
break;
}
String path = event.getPath();
- if (path == null) {
- continue;
- }
if (totalRefreshNeeded(path)) {
allChanged = true;
}
@@ -253,7 +250,7 @@ public class GitUntrackedFilesHolder implements Disposable, BulkFileListener {
// if index has changed, no need to refresh specific files - we get the full status of all files
if (allChanged) {
- LOG.info(String.format("GitUntrackedFilesHolder: Index has changed, marking %s recursively dirty", myRoot));
+ LOG.debug(String.format("GitUntrackedFilesHolder: Index has changed, marking %s recursively dirty", myRoot));
myDirtyScopeManager.dirDirtyRecursively(myRoot);
synchronized (LOCK) {
myReady = false;
diff --git a/plugins/git4idea/src/git4idea/reset/GitNewResetDialog.java b/plugins/git4idea/src/git4idea/reset/GitNewResetDialog.java
new file mode 100644
index 000000000000..5e2cb18e7c7e
--- /dev/null
+++ b/plugins/git4idea/src/git4idea/reset/GitNewResetDialog.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package git4idea.reset;
+
+import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.DialogWrapper;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.ui.components.JBLabel;
+import com.intellij.ui.components.JBRadioButton;
+import com.intellij.util.ui.GridBag;
+import com.intellij.util.ui.RadioButtonEnumModel;
+import com.intellij.util.ui.UIUtil;
+import com.intellij.vcs.log.VcsFullCommitDetails;
+import com.intellij.xml.util.XmlStringUtil;
+import git4idea.GitUtil;
+import git4idea.repo.GitRepository;
+import git4idea.repo.GitRepositoryManager;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.awt.*;
+import java.util.Map;
+
+import static com.intellij.dvcs.DvcsUtil.getShortRepositoryName;
+
+public class GitNewResetDialog extends DialogWrapper {
+
+ private static final String DIALOG_ID = "git.new.reset.dialog";
+
+ @NotNull private final Project myProject;
+ @NotNull private final Map<GitRepository, VcsFullCommitDetails> myCommits;
+ @NotNull private final GitResetMode myDefaultMode;
+ @NotNull private final ButtonGroup myButtonGroup;
+
+ private RadioButtonEnumModel<GitResetMode> myEnumModel;
+
+ protected GitNewResetDialog(@NotNull Project project, @NotNull Map<GitRepository, VcsFullCommitDetails> commits,
+ @NotNull GitResetMode defaultMode) {
+ super(project);
+ myProject = project;
+ myCommits = commits;
+ myDefaultMode = defaultMode;
+ myButtonGroup = new ButtonGroup();
+
+ init();
+ setTitle("Git Reset");
+ setOKButtonText("Reset");
+ setOKButtonMnemonic('R');
+ setResizable(false);
+ }
+
+ @Nullable
+ @Override
+ protected JComponent createCenterPanel() {
+ JPanel panel = new JPanel(new GridBagLayout());
+ GridBag gb = new GridBag().
+ setDefaultAnchor(GridBagConstraints.LINE_START).
+ setDefaultInsets(0, UIUtil.DEFAULT_HGAP, UIUtil.LARGE_VGAP, 0);
+
+ String description = prepareDescription(myProject, myCommits);
+ panel.add(new JBLabel(XmlStringUtil.wrapInHtml(description)), gb.nextLine().next().coverLine());
+
+ String explanation = "This will reset the current branch head to the selected commit, <br/>" +
+ "and update the working tree and the index according to the selected mode:";
+ panel.add(new JBLabel(XmlStringUtil.wrapInHtml(explanation), UIUtil.ComponentStyle.SMALL), gb.nextLine().next().coverLine());
+
+ for (GitResetMode mode : GitResetMode.values()) {
+ JBRadioButton button = new JBRadioButton(mode.getName());
+ button.setMnemonic(mode.getName().charAt(0));
+ myButtonGroup.add(button);
+ panel.add(button, gb.nextLine().next());
+ panel.add(new JBLabel(XmlStringUtil.wrapInHtml(mode.getDescription()), UIUtil.ComponentStyle.SMALL), gb.next());
+ }
+
+ myEnumModel = RadioButtonEnumModel.bindEnum(GitResetMode.class, myButtonGroup);
+ myEnumModel.setSelected(myDefaultMode);
+ return panel;
+ }
+
+ @Nullable
+ @Override
+ protected String getHelpId() {
+ return DIALOG_ID;
+ }
+
+ @NotNull
+ private static String prepareDescription(@NotNull Project project, @NotNull Map<GitRepository, VcsFullCommitDetails> commits) {
+ if (commits.size() == 1 && !isMultiRepo(project)) {
+ Map.Entry<GitRepository, VcsFullCommitDetails> entry = commits.entrySet().iterator().next();
+ return String.format("%s -> %s", getSourceText(entry.getKey()), getTargetText(entry.getValue()));
+ }
+
+ StringBuilder desc = new StringBuilder("");
+ for (Map.Entry<GitRepository, VcsFullCommitDetails> entry : commits.entrySet()) {
+ GitRepository repository = entry.getKey();
+ VcsFullCommitDetails commit = entry.getValue();
+ desc.append(String.format("%s in %s -> %s<br/>", getSourceText(repository),
+ getShortRepositoryName(repository), getTargetText(commit)));
+ }
+ return desc.toString();
+ }
+
+ @NotNull
+ private static String getTargetText(@NotNull VcsFullCommitDetails commit) {
+ String commitMessage = StringUtil.shortenTextWithEllipsis(commit.getSubject(), 20, 0);
+ return String.format("<code><b>%s</b> \"%s\"</code> by <code>%s</code>",
+ commit.getId().toShortString(), commitMessage, commit.getAuthor().getName());
+ }
+
+ @NotNull
+ private static String getSourceText(@NotNull GitRepository repository) {
+ String currentRevision = repository.getCurrentRevision();
+ assert currentRevision != null;
+ String text = repository.getCurrentBranch() == null ?
+ "HEAD (" + GitUtil.getShortHash(currentRevision) + ")" :
+ repository.getCurrentBranch().getName();
+ return "<b>" + text + "</b>";
+ }
+
+ private static boolean isMultiRepo(@NotNull Project project) {
+ return ServiceManager.getService(project, GitRepositoryManager.class).moreThanOneRoot();
+ }
+
+ @NotNull
+ public GitResetMode getResetMode() {
+ return myEnumModel.getSelected();
+ }
+
+}
diff --git a/plugins/git4idea/src/git4idea/reset/GitResetAction.java b/plugins/git4idea/src/git4idea/reset/GitResetAction.java
new file mode 100644
index 000000000000..749acd7e7c7c
--- /dev/null
+++ b/plugins/git4idea/src/git4idea/reset/GitResetAction.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package git4idea.reset;
+
+import com.intellij.dvcs.ui.VcsLogOneCommitPerRepoAction;
+import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.Task;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.ObjectUtils;
+import com.intellij.vcs.log.VcsFullCommitDetails;
+import git4idea.config.GitVcsSettings;
+import git4idea.repo.GitRepository;
+import git4idea.repo.GitRepositoryManager;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Map;
+
+public class GitResetAction extends VcsLogOneCommitPerRepoAction<GitRepository> {
+
+ @Nullable
+ @Override
+ protected GitRepository getRepositoryForRoot(@NotNull Project project, @NotNull VirtualFile root) {
+ return getRepoManager(project).getRepositoryForRoot(root);
+ }
+
+ @Override
+ protected void actionPerformed(@NotNull final Project project, @NotNull final Map<GitRepository, VcsFullCommitDetails> commits) {
+ GitVcsSettings settings = GitVcsSettings.getInstance(project);
+ GitResetMode defaultMode = ObjectUtils.notNull(settings.getResetMode(), GitResetMode.getDefault());
+ GitNewResetDialog dialog = new GitNewResetDialog(project, commits, defaultMode);
+ dialog.show();
+ if (dialog.isOK()) {
+ final GitResetMode selectedMode = dialog.getResetMode();
+ settings.setResetMode(selectedMode);
+ new Task.Backgroundable(project, "Git reset", false) {
+ @Override
+ public void run(@NotNull ProgressIndicator indicator) {
+ new GitResetOperation(project, commits, selectedMode, indicator).execute();
+ }
+ }.queue();
+ }
+ }
+
+ @NotNull
+ private static GitRepositoryManager getRepoManager(@NotNull Project project) {
+ return ServiceManager.getService(project, GitRepositoryManager.class);
+ }
+
+}
diff --git a/plugins/git4idea/src/git4idea/reset/GitResetMode.java b/plugins/git4idea/src/git4idea/reset/GitResetMode.java
new file mode 100644
index 000000000000..c10d95707073
--- /dev/null
+++ b/plugins/git4idea/src/git4idea/reset/GitResetMode.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package git4idea.reset;
+
+import org.jetbrains.annotations.NotNull;
+
+public enum GitResetMode {
+
+ SOFT("Soft", "--soft", "Files won't change, differences will be staged for commit."),
+ MIXED("Mixed", "--mixed", "Files won't change, differences won't be staged."),
+ HARD("Hard", "--hard", "Files will be reverted to the state of the selected commit.<br/>" +
+ "Warning: any local changes will be lost."),
+ KEEP("Keep", "--keep", "Files will be reverted to the state of the selected commit,<br/>" +
+ "but local changes will be kept intact.");
+
+ @NotNull private final String myName;
+ @NotNull private final String myArgument;
+ @NotNull private final String myDescription;
+
+ GitResetMode(@NotNull String name, @NotNull String argument, @NotNull String description) {
+ myName = name;
+ myArgument = argument;
+ myDescription = description;
+ }
+
+ @NotNull
+ public static GitResetMode getDefault() {
+ return MIXED;
+ }
+
+ @NotNull
+ public String getName() {
+ return myName;
+ }
+
+ @NotNull
+ public String getArgument() {
+ return myArgument;
+ }
+
+ @NotNull
+ public String getDescription() {
+ return myDescription;
+ }
+
+}
diff --git a/plugins/git4idea/src/git4idea/reset/GitResetOperation.java b/plugins/git4idea/src/git4idea/reset/GitResetOperation.java
new file mode 100644
index 000000000000..9c66a5225a52
--- /dev/null
+++ b/plugins/git4idea/src/git4idea/reset/GitResetOperation.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package git4idea.reset;
+
+import com.intellij.dvcs.repo.RepositoryUtil;
+import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vcs.VcsNotifier;
+import com.intellij.openapi.vcs.changes.Change;
+import com.intellij.openapi.vfs.VfsUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.MultiMap;
+import com.intellij.util.ui.UIUtil;
+import com.intellij.vcs.log.VcsFullCommitDetails;
+import git4idea.GitPlatformFacade;
+import git4idea.GitUtil;
+import git4idea.branch.GitBranchUiHandlerImpl;
+import git4idea.branch.GitSmartOperationDialog;
+import git4idea.commands.Git;
+import git4idea.commands.GitCommandResult;
+import git4idea.commands.GitLocalChangesWouldBeOverwrittenDetector;
+import git4idea.repo.GitRepository;
+import git4idea.util.GitPreservingProcess;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import static git4idea.commands.GitLocalChangesWouldBeOverwrittenDetector.Operation.RESET;
+
+public class GitResetOperation {
+
+ @NotNull private final Project myProject;
+ @NotNull private final Map<GitRepository, VcsFullCommitDetails> myCommits;
+ @NotNull private final GitResetMode myMode;
+ @NotNull private final ProgressIndicator myIndicator;
+ @NotNull private final Git myGit;
+ @NotNull private final VcsNotifier myNotifier;
+ @NotNull private final GitPlatformFacade myFacade;
+ @NotNull private final GitBranchUiHandlerImpl myUiHandler;
+
+ public GitResetOperation(@NotNull Project project, @NotNull Map<GitRepository, VcsFullCommitDetails> targetCommits,
+ @NotNull GitResetMode mode, @NotNull ProgressIndicator indicator) {
+ myProject = project;
+ myCommits = targetCommits;
+ myMode = mode;
+ myIndicator = indicator;
+ myGit = ServiceManager.getService(Git.class);
+ myNotifier = VcsNotifier.getInstance(project);
+ myFacade = ServiceManager.getService(GitPlatformFacade.class);
+ myUiHandler = new GitBranchUiHandlerImpl(myProject, myFacade, myGit, indicator);
+ }
+
+ public void execute() {
+ saveAllDocuments();
+ GitUtil.workingTreeChangeStarted(myProject);
+ Map<GitRepository, GitCommandResult> results = ContainerUtil.newHashMap();
+ try {
+ for (Map.Entry<GitRepository, VcsFullCommitDetails> entry : myCommits.entrySet()) {
+ GitRepository repository = entry.getKey();
+ VirtualFile root = repository.getRoot();
+ String target = entry.getValue().getId().asString();
+ GitLocalChangesWouldBeOverwrittenDetector detector = new GitLocalChangesWouldBeOverwrittenDetector(root, RESET);
+
+ GitCommandResult result = myGit.reset(repository, myMode, target, detector);
+ if (!result.success() && detector.wasMessageDetected()) {
+ GitCommandResult smartResult = proposeSmartReset(detector, repository, target);
+ if (smartResult != null) {
+ result = smartResult;
+ }
+ }
+ results.put(repository, result);
+ repository.update();
+ VfsUtil.markDirtyAndRefresh(true, true, false, root);
+ }
+ }
+ finally {
+ GitUtil.workingTreeChangeFinished(myProject);
+ }
+ notifyResult(results);
+ }
+
+ private GitCommandResult proposeSmartReset(@NotNull GitLocalChangesWouldBeOverwrittenDetector detector,
+ @NotNull final GitRepository repository, @NotNull final String target) {
+ Collection<String> absolutePaths = GitUtil.toAbsolute(repository.getRoot(), detector.getRelativeFilePaths());
+ List<Change> affectedChanges = GitUtil.findLocalChangesForPaths(myProject, repository.getRoot(), absolutePaths, false);
+ int choice = myUiHandler.showSmartOperationDialog(myProject, affectedChanges, absolutePaths, "reset", "&Hard Reset");
+ if (choice == GitSmartOperationDialog.SMART_EXIT_CODE) {
+ final Ref<GitCommandResult> result = Ref.create();
+ new GitPreservingProcess(myProject, myFacade, myGit, Collections.singleton(repository), "reset", target, myIndicator, new Runnable() {
+ @Override
+ public void run() {
+ result.set(myGit.reset(repository, myMode, target));
+ }
+ }).execute();
+ return result.get();
+ }
+ if (choice == GitSmartOperationDialog.FORCE_EXIT_CODE) {
+ return myGit.reset(repository, GitResetMode.HARD, target);
+ }
+ return null;
+ }
+
+ private void notifyResult(@NotNull Map<GitRepository, GitCommandResult> results) {
+ Map<GitRepository, GitCommandResult> successes = ContainerUtil.newHashMap();
+ Map<GitRepository, GitCommandResult> errors = ContainerUtil.newHashMap();
+ for (Map.Entry<GitRepository, GitCommandResult> entry : results.entrySet()) {
+ GitCommandResult result = entry.getValue();
+ GitRepository repository = entry.getKey();
+ if (result.success()) {
+ successes.put(repository, result);
+ }
+ else {
+ errors.put(repository, result);
+ }
+ }
+
+ if (errors.isEmpty()) {
+ myNotifier.notifySuccess("", "Reset successful");
+ }
+ else if (!successes.isEmpty()) {
+ myNotifier.notifyImportantWarning("Reset partially failed",
+ "Reset was successful for " + joinRepos(successes.keySet())
+ + "<br/>but failed for " + joinRepos(errors.keySet()) + ": <br/>" + formErrorReport(errors));
+ }
+ else {
+ myNotifier.notifyError("Reset Failed", formErrorReport(errors));
+ }
+ }
+
+ @NotNull
+ private static String formErrorReport(@NotNull Map<GitRepository, GitCommandResult> errorResults) {
+ MultiMap<String, GitRepository> grouped = groupByResult(errorResults);
+ if (grouped.size() == 1) {
+ return "<code>" + grouped.keySet().iterator().next() + "</code>";
+ }
+ return StringUtil.join(grouped.entrySet(), new Function<Map.Entry<String, Collection<GitRepository>>, String>() {
+ @NotNull
+ @Override
+ public String fun(@NotNull Map.Entry<String, Collection<GitRepository>> entry) {
+ return joinRepos(entry.getValue()) + ":<br/><code>" + entry.getKey() + "</code>";
+ }
+ }, "<br/>");
+ }
+
+ // to avoid duplicate error reports if they are the same for different repositories
+ @NotNull
+ private static MultiMap<String, GitRepository> groupByResult(@NotNull Map<GitRepository, GitCommandResult> results) {
+ MultiMap<String, GitRepository> grouped = MultiMap.create();
+ for (Map.Entry<GitRepository, GitCommandResult> entry : results.entrySet()) {
+ grouped.putValue(entry.getValue().getErrorOutputAsHtmlString(), entry.getKey());
+ }
+ return grouped;
+ }
+
+ @NotNull
+ private static String joinRepos(@NotNull Collection<GitRepository> repositories) {
+ return StringUtil.join(RepositoryUtil.sortRepositories(repositories), ", ");
+ }
+
+ private static void saveAllDocuments() {
+ UIUtil.invokeAndWaitIfNeeded(new Runnable() {
+ @Override
+ public void run() {
+ FileDocumentManager.getInstance().saveAllDocuments();
+ }
+ });
+ }
+
+}
diff --git a/plugins/git4idea/src/git4idea/ui/GitUnstashDialog.java b/plugins/git4idea/src/git4idea/ui/GitUnstashDialog.java
index 9b13bb6cdb65..eccaa446b0ed 100644
--- a/plugins/git4idea/src/git4idea/ui/GitUnstashDialog.java
+++ b/plugins/git4idea/src/git4idea/ui/GitUnstashDialog.java
@@ -72,65 +72,25 @@ import java.util.concurrent.atomic.AtomicBoolean;
* The unstash dialog
*/
public class GitUnstashDialog extends DialogWrapper {
- /**
- * Git root selector
- */
private JComboBox myGitRootComboBox;
- /**
- * The current branch label
- */
private JLabel myCurrentBranch;
- /**
- * The view stash button
- */
private JButton myViewButton;
- /**
- * The drop stash button
- */
private JButton myDropButton;
- /**
- * The clear stashes button
- */
private JButton myClearButton;
- /**
- * The pop stash checkbox
- */
private JCheckBox myPopStashCheckBox;
- /**
- * The branch text field
- */
private JTextField myBranchTextField;
- /**
- * The root panel of the dialog
- */
private JPanel myPanel;
- /**
- * The stash list
- */
private JList myStashList;
- /**
- * If this checkbox is selected, the index is reinstated as well as working tree
- */
private JCheckBox myReinstateIndexCheckBox;
/**
* Set of branches for the current root
*/
private final HashSet<String> myBranches = new HashSet<String>();
- /**
- * The project
- */
private final Project myProject;
private GitVcs myVcs;
private static final Logger LOG = Logger.getInstance(GitUnstashDialog.class);
- /**
- * A constructor
- *
- * @param project the project
- * @param roots the list of the roots
- * @param defaultRoot the default root to select
- */
public GitUnstashDialog(final Project project, final List<VirtualFile> roots, final VirtualFile defaultRoot) {
super(project, true);
setModal(false);
@@ -310,9 +270,6 @@ public class GitUnstashDialog extends DialogWrapper {
setOKActionEnabled(true);
}
- /**
- * Refresh stash list
- */
private void refreshStashList() {
final DefaultListModel listModel = (DefaultListModel)myStashList.getModel();
listModel.clear();
@@ -334,16 +291,10 @@ public class GitUnstashDialog extends DialogWrapper {
myStashList.setSelectedIndex(0);
}
- /**
- * @return the selected git root
- */
private VirtualFile getGitRoot() {
return (VirtualFile)myGitRootComboBox.getSelectedItem();
}
- /**
- * @return unstash handler
- */
private GitLineHandler handler() {
GitLineHandler h = new GitLineHandler(myProject, getGitRoot(), GitCommand.STASH);
String branch = myBranchTextField.getText();
@@ -361,32 +312,19 @@ public class GitUnstashDialog extends DialogWrapper {
return h;
}
- /**
- * @return selected stash
- * @throws NullPointerException if no stash is selected
- */
private StashInfo getSelectedStash() {
return (StashInfo)myStashList.getSelectedValue();
}
- /**
- * {@inheritDoc}
- */
protected JComponent createCenterPanel() {
return myPanel;
}
- /**
- * {@inheritDoc}
- */
@Override
protected String getDimensionServiceKey() {
return getClass().getName();
}
- /**
- * {@inheritDoc}
- */
@Override
protected String getHelpId() {
return "reference.VersionControl.Git.Unstash";
@@ -418,6 +356,7 @@ public class GitUnstashDialog extends DialogWrapper {
final Ref<GitCommandResult> result = Ref.create();
ProgressManager.getInstance().run(new Task.Modal(h.project(), GitBundle.getString("unstash.unstashing"), false) {
public void run(@NotNull final ProgressIndicator indicator) {
+ indicator.setIndeterminate(true);
h.addLineListener(new GitHandlerUtil.GitLineHandlerListenerProgress(indicator, h, "stash", false));
Git git = ServiceManager.getService(Git.class);
result.set(git.runCommand(new Computable.PredefinedValueComputable<GitLineHandler>(h)));
diff --git a/plugins/git4idea/src/git4idea/ui/branch/GitBranchWidget.java b/plugins/git4idea/src/git4idea/ui/branch/GitBranchWidget.java
index 80074fb64a28..4d3497fae299 100644
--- a/plugins/git4idea/src/git4idea/ui/branch/GitBranchWidget.java
+++ b/plugins/git4idea/src/git4idea/ui/branch/GitBranchWidget.java
@@ -136,7 +136,7 @@ public class GitBranchWidget extends EditorBasedWidget implements StatusBarWidge
@Override
public void run() {
Project project = getProject();
- if (project == null) {
+ if (project == null || project.isDisposed()) {
emptyTextAndTooltip();
return;
}
diff --git a/plugins/git4idea/src/git4idea/update/GitMergeUpdater.java b/plugins/git4idea/src/git4idea/update/GitMergeUpdater.java
index 4315e65227a3..08c5103007d2 100644
--- a/plugins/git4idea/src/git4idea/update/GitMergeUpdater.java
+++ b/plugins/git4idea/src/git4idea/update/GitMergeUpdater.java
@@ -19,15 +19,21 @@ import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.FilePathImpl;
import com.intellij.openapi.vcs.VcsException;
-import com.intellij.openapi.vcs.changes.*;
+import com.intellij.openapi.vcs.changes.Change;
+import com.intellij.openapi.vcs.changes.ChangeListManager;
+import com.intellij.openapi.vcs.changes.ContentRevision;
+import com.intellij.openapi.vcs.changes.LocalChangeList;
import com.intellij.openapi.vcs.changes.ui.ChangeListViewerDialog;
import com.intellij.openapi.vcs.update.UpdatedFiles;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.UIUtil;
import git4idea.GitUtil;
import git4idea.branch.GitBranchPair;
@@ -173,9 +179,14 @@ public class GitMergeUpdater extends GitUpdater {
final Collection<String> remotelyChanged = GitUtil.getPathsDiffBetweenRefs(ServiceManager.getService(Git.class), repository,
currentBranch, remoteBranch);
final List<File> locallyChanged = myChangeListManager.getAffectedPaths();
- for (File localPath : locallyChanged) {
- if (remotelyChanged.contains(FilePathsHelper.convertPath(localPath.getPath()))) {
- // found a file which was changed locally and remotely => need to save
+ for (final File localPath : locallyChanged) {
+ if (ContainerUtil.exists(remotelyChanged, new Condition<String>() {
+ @Override
+ public boolean value(String remotelyChangedPath) {
+ return FileUtil.pathsEqual(localPath.getPath(), remotelyChangedPath);
+ }
+ })) {
+ // found a file which was changed locally and remotely => need to save
return true;
}
}
diff --git a/plugins/git4idea/tests/git4idea/branch/GitBranchWorkerTest.groovy b/plugins/git4idea/tests/git4idea/branch/GitBranchWorkerTest.groovy
index 35acc41fc3cc..9a2bad2ad663 100644
--- a/plugins/git4idea/tests/git4idea/branch/GitBranchWorkerTest.groovy
+++ b/plugins/git4idea/tests/git4idea/branch/GitBranchWorkerTest.groovy
@@ -14,16 +14,14 @@
* limitations under the License.
*/
package git4idea.branch
-import com.intellij.dvcs.test.MockVirtualFile
+
import com.intellij.openapi.progress.ProgressIndicator
import com.intellij.openapi.progress.util.ProgressIndicatorBase
import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.DialogWrapper
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.util.text.StringUtil
-import com.intellij.openapi.vcs.FilePathImpl
import com.intellij.openapi.vcs.changes.Change
-import com.intellij.openapi.vcs.changes.CurrentContentRevision
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.util.Function
import com.intellij.util.LineSeparator
@@ -35,12 +33,11 @@ import git4idea.config.GitVersionSpecialty
import git4idea.repo.GitRepository
import git4idea.test.GitPlatformTest
import org.jetbrains.annotations.NotNull
+import org.jetbrains.annotations.Nullable
import java.util.regex.Matcher
-import static com.intellij.openapi.vcs.Executor.*
-import static git4idea.test.GitExecutor.cd
-import static git4idea.test.GitExecutor.git
+import static git4idea.test.GitExecutor.*
import static git4idea.test.GitScenarios.*
class GitBranchWorkerTest extends GitPlatformTest {
@@ -248,7 +245,7 @@ class GitBranchWorkerTest extends GitPlatformTest {
List<Change> changes = null;
checkoutOrMerge(operation, "feature", [
- showSmartOperationDialog: { Project p, List<Change> cs, Collection<String> paths, String op, boolean force ->
+ showSmartOperationDialog: { Project p, List<Change> cs, Collection<String> paths, String op, String force ->
changes = cs
DialogWrapper.CANCEL_EXIT_CODE
}
@@ -270,17 +267,6 @@ class GitBranchWorkerTest extends GitPlatformTest {
return !GitVersionSpecialty.OLD_STYLE_OF_UNTRACKED_AND_LOCAL_CHANGES_WOULD_BE_OVERWRITTEN.existsIn(GitVersion.parse(git("version")));
}
- Change[] changesFromFiles(Collection<String> paths) {
- paths.collect {
- toChange(it)
- }
- }
-
- Change toChange(String relPath) {
- // we don't care about the before revision
- new Change(null, CurrentContentRevision.create(new FilePathImpl(new MockVirtualFile(myProjectRoot + "/" + relPath))))
- }
-
public void "test agree to smart checkout should smart checkout"() {
def localChanges = agree_to_smart_operation("checkout", "Checked out <b><code>feature</code></b>")
@@ -345,7 +331,7 @@ class GitBranchWorkerTest extends GitPlatformTest {
prepareLocalChangesOverwrittenBy(myUltimate)
checkoutOrMerge(operation, "feature", [
- showSmartOperationDialog: { Project p, List<Change> cs, Collection<String> paths, String op, boolean f
+ showSmartOperationDialog: { Project p, List<Change> cs, Collection<String> paths, String op, String force
-> GitSmartOperationDialog.CANCEL_EXIT_CODE
},
] as GitBranchUiHandler )
@@ -371,7 +357,7 @@ class GitBranchWorkerTest extends GitPlatformTest {
def rollbackMsg = null
checkoutOrMerge(operation, "feature", [
showSmartOperationDialog : {
- Project p, List<Change> cs, Collection<String> paths, String op, boolean f -> GitSmartOperationDialog.CANCEL_EXIT_CODE
+ Project p, List<Change> cs, Collection<String> paths, String op, String f -> GitSmartOperationDialog.CANCEL_EXIT_CODE
},
notifyErrorWithRollbackProposal: { String t, String m, String rp -> rollbackMsg = m; false }
] as GitBranchUiHandler )
@@ -384,7 +370,7 @@ class GitBranchWorkerTest extends GitPlatformTest {
prepareLocalChangesOverwrittenBy(myUltimate)
def uiHandler = [
- showSmartOperationDialog: { Project p, List<Change> cs, Collection<String> paths, String op, boolean force ->
+ showSmartOperationDialog: { Project p, List<Change> cs, Collection<String> paths, String op, String force ->
GitSmartOperationDialog.FORCE_EXIT_CODE;
},
] as GitBranchUiHandler
@@ -611,6 +597,39 @@ class GitBranchWorkerTest extends GitPlatformTest {
assertEquals "Merge in ultimate should have been reset", ultimateTipAfterMerge, tip(myUltimate)
}
+ public void test_checkout_in_detached_head() {
+ cd(myCommunity);
+ touch("file.txt", "some content");
+ add("file.txt");
+ commit("msg");
+ git(myCommunity, "checkout HEAD^");
+
+ checkoutBranch("master", []);
+ assertCurrentBranch("master");
+ }
+
+ // inspired by IDEA-127472
+ public void test_checkout_to_common_branch_when_branches_have_diverged() {
+ branchWithCommit(myUltimate, "feature", "feature-file.txt", "feature_content", false);
+ branchWithCommit(myCommunity, "newbranch", "newbranch-file.txt", "newbranch_content", false);
+ checkoutBranch("master", [])
+ assertCurrentBranch("master");
+ }
+
+ public void test_rollback_checkout_from_diverged_branches_should_return_to_proper_branches() {
+ branchWithCommit(myUltimate, "feature", "feature-file.txt", "feature_content", false);
+ branchWithCommit(myCommunity, "newbranch", "newbranch-file.txt", "newbranch_content", false);
+ unmergedFiles(myContrib)
+
+ checkoutBranch "master", [
+ showUnmergedFilesMessageWithRollback: { String s1, String s2 -> true },
+ ]
+
+ assertCurrentBranch(myUltimate, "feature");
+ assertCurrentBranch(myCommunity, "newbranch");
+ assertCurrentBranch(myContrib, "master");
+ }
+
static def assertCurrentBranch(GitRepository repository, String name) {
def curBranch = git(repository, "branch").split("\n").find { it -> it.contains("*") }.replace('*', ' ').trim()
assertEquals("Current branch is incorrect in ${repository}", name, curBranch)
@@ -716,7 +735,7 @@ class GitBranchWorkerTest extends GitPlatformTest {
@NotNull List<Change> changes,
@NotNull Collection<String> paths,
@NotNull String operation,
- boolean isForcePossible) {
+ @Nullable String forceButton) {
GitSmartOperationDialog.SMART_EXIT_CODE
}
diff --git a/plugins/git4idea/tests/git4idea/log/GitLogProviderTest.java b/plugins/git4idea/tests/git4idea/log/GitLogProviderTest.java
index 797e0271b430..0bb67671622b 100644
--- a/plugins/git4idea/tests/git4idea/log/GitLogProviderTest.java
+++ b/plugins/git4idea/tests/git4idea/log/GitLogProviderTest.java
@@ -20,6 +20,7 @@ import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.util.ArrayUtil;
+import com.intellij.util.CollectConsumer;
import com.intellij.util.Consumer;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
@@ -84,9 +85,10 @@ public class GitLogProviderTest extends GitSingleRepoTest {
prepareSomeHistory();
createTaggedBranch();
List<VcsCommitMetadata> expectedLog = log();
- @SuppressWarnings("unchecked")
- List<TimedVcsCommit> actualLog = myLogProvider.readAllHashes(myProjectRoot, Consumer.EMPTY_CONSUMER);
- assertOrderedEquals(expectedLog, actualLog);
+ List<TimedVcsCommit> collector = ContainerUtil.newArrayList();
+ //noinspection unchecked
+ myLogProvider.readAllHashes(myProjectRoot, Consumer.EMPTY_CONSUMER, new CollectConsumer<TimedVcsCommit>(collector));
+ assertOrderedEquals(expectedLog, collector);
}
public void test_get_current_user() throws Exception {
diff --git a/plugins/git4idea/tests/git4idea/log/GitRefManagerTest.java b/plugins/git4idea/tests/git4idea/log/GitRefManagerTest.java
index 707e97265267..14d88315c596 100644
--- a/plugins/git4idea/tests/git4idea/log/GitRefManagerTest.java
+++ b/plugins/git4idea/tests/git4idea/log/GitRefManagerTest.java
@@ -15,7 +15,7 @@ import git4idea.GitLocalBranch;
import git4idea.GitRemoteBranch;
import git4idea.branch.GitBranchesCollection;
import git4idea.repo.*;
-import git4idea.test.GitTestRepositoryManager;
+import git4idea.test.GitMockRepositoryManager;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -145,7 +145,7 @@ public class GitRefManagerTest extends UsefulTestCase {
}
private static List<VcsRef> sort(final Collection<VcsRef> refs) {
- final GitTestRepositoryManager manager = new GitTestRepositoryManager();
+ final GitMockRepositoryManager manager = new GitMockRepositoryManager();
manager.add(new MockGitRepository() {
@NotNull
@Override
@@ -304,5 +304,9 @@ public class GitRefManagerTest extends UsefulTestCase {
public String toLogString() {
throw new UnsupportedOperationException();
}
+
+ @Override
+ public void dispose() {
+ }
}
}
diff --git a/plugins/git4idea/tests/git4idea/test/GitExecutor.java b/plugins/git4idea/tests/git4idea/test/GitExecutor.java
index 7c561c39ebc5..f1b042ae0565 100644
--- a/plugins/git4idea/tests/git4idea/test/GitExecutor.java
+++ b/plugins/git4idea/tests/git4idea/test/GitExecutor.java
@@ -53,11 +53,12 @@ public class GitExecutor extends Executor {
printVersionTheFirstTime();
List<String> split = splitCommandInParameters(command);
split.add(0, PathHolder.GIT_EXECUTABLE);
- debug("# git " + command);
+ File workingDir = ourCurrentDir();
+ debug("[" + workingDir.getName() + "] # git " + command);
for (int attempt = 0; attempt < MAX_RETRIES; attempt++) {
String stdout;
try {
- stdout = run(split, ignoreNonZeroExitCode);
+ stdout = run(workingDir, split, ignoreNonZeroExitCode);
if (!isIndexLockFileError(stdout)) {
return stdout;
}
@@ -97,7 +98,7 @@ public class GitExecutor extends Executor {
}
public static void add(@NotNull String path) {
- git("add " + path);
+ git("add --verbose " + path);
}
public static void addCommit(@NotNull String message) {
diff --git a/plugins/git4idea/tests/git4idea/test/GitHttpAuthTestService.java b/plugins/git4idea/tests/git4idea/test/GitHttpAuthTestService.java
index b6f25e75e307..8723ce280269 100644
--- a/plugins/git4idea/tests/git4idea/test/GitHttpAuthTestService.java
+++ b/plugins/git4idea/tests/git4idea/test/GitHttpAuthTestService.java
@@ -15,13 +15,11 @@
*/
package git4idea.test;
-import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.project.Project;
import git4idea.commands.GitCommand;
import git4idea.commands.GitHttpAuthService;
import git4idea.commands.GitHttpAuthenticator;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
/**
* @author Kirill Likhodedov
@@ -61,8 +59,7 @@ public class GitHttpAuthTestService extends GitHttpAuthService {
@NotNull
@Override
- public GitHttpAuthenticator createAuthenticator(@NotNull Project project, @Nullable ModalityState state, @NotNull GitCommand command,
- @NotNull String url) {
+ public GitHttpAuthenticator createAuthenticator(@NotNull Project project, @NotNull GitCommand command, @NotNull String url) {
return myAuthenticator;
}
diff --git a/plugins/git4idea/tests/git4idea/test/GitMockRepositoryManager.java b/plugins/git4idea/tests/git4idea/test/GitMockRepositoryManager.java
new file mode 100644
index 000000000000..21ed4da7bdfb
--- /dev/null
+++ b/plugins/git4idea/tests/git4idea/test/GitMockRepositoryManager.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package git4idea.test;
+
+import com.intellij.dvcs.repo.RepositoryManager;
+import com.intellij.openapi.vcs.FilePath;
+import com.intellij.openapi.vfs.VirtualFile;
+import git4idea.repo.GitRepository;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Kirill Likhodedov
+ */
+public class GitMockRepositoryManager implements RepositoryManager<GitRepository> {
+ private final List<GitRepository> myRepositories = new ArrayList<GitRepository>();
+
+ public void add(GitRepository repository) {
+ myRepositories.add(repository);
+ }
+
+ @Override
+ public GitRepository getRepositoryForRoot(@Nullable VirtualFile root) {
+ for (GitRepository repository : myRepositories) {
+ if (repository.getRoot().equals(root)) {
+ return repository;
+ }
+ }
+
+ return null;
+ }
+
+ @Override
+ public GitRepository getRepositoryForFile(@NotNull VirtualFile file) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public GitRepository getRepositoryForFile(@NotNull FilePath file) {
+ throw new UnsupportedOperationException();
+ }
+
+ @NotNull
+ @Override
+ public List<GitRepository> getRepositories() {
+ return myRepositories;
+ }
+
+ @Override
+ public boolean moreThanOneRoot() {
+ return myRepositories.size() > 1;
+ }
+
+ @Override
+ public void updateRepository(VirtualFile root) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void updateAllRepositories() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void waitUntilInitialized() {
+ }
+
+}
diff --git a/plugins/git4idea/tests/git4idea/test/GitPlatformTest.java b/plugins/git4idea/tests/git4idea/test/GitPlatformTest.java
index ef3f963c9c7e..c02ec553dd8f 100644
--- a/plugins/git4idea/tests/git4idea/test/GitPlatformTest.java
+++ b/plugins/git4idea/tests/git4idea/test/GitPlatformTest.java
@@ -19,6 +19,7 @@ import com.intellij.openapi.components.ProjectComponent;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.*;
import com.intellij.openapi.vcs.changes.ChangeListManager;
import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager;
@@ -51,19 +52,19 @@ public abstract class GitPlatformTest extends UsefulTestCase {
private static final Logger LOG = Logger.getInstance(GitPlatformTest.class);
- @NotNull protected Project myProject;
- @NotNull protected VirtualFile myProjectRoot;
- @NotNull protected String myProjectPath;
- @NotNull protected GitRepositoryManager myGitRepositoryManager;
- @NotNull protected GitVcsSettings myGitSettings;
- @NotNull protected GitPlatformFacade myPlatformFacade;
- @NotNull protected Git myGit;
- @NotNull protected GitVcs myVcs;
+ protected Project myProject;
+ protected VirtualFile myProjectRoot;
+ protected String myProjectPath;
+ protected GitRepositoryManager myGitRepositoryManager;
+ protected GitVcsSettings myGitSettings;
+ protected GitPlatformFacade myPlatformFacade;
+ protected Git myGit;
+ protected GitVcs myVcs;
- @NotNull protected TestDialogManager myDialogManager;
- @NotNull protected TestVcsNotifier myVcsNotifier;
+ protected TestDialogManager myDialogManager;
+ protected TestVcsNotifier myVcsNotifier;
- @NotNull private IdeaProjectTestFixture myProjectFixture;
+ private IdeaProjectTestFixture myProjectFixture;
private String myTestStartedIndicator;
@SuppressWarnings({"JUnitTestCaseWithNonTrivialConstructors", "UnusedDeclaration"})
@@ -86,35 +87,41 @@ public abstract class GitPlatformTest extends UsefulTestCase {
throw e;
}
- myProject = myProjectFixture.getProject();
- myProjectRoot = myProject.getBaseDir();
- myProjectPath = myProjectRoot.getPath();
-
- myGitSettings = GitVcsSettings.getInstance(myProject);
- myGitSettings.getAppSettings().setPathToGit(GitExecutor.PathHolder.GIT_EXECUTABLE);
-
- myDialogManager = (TestDialogManager)ServiceManager.getService(DialogManager.class);
- myVcsNotifier = (TestVcsNotifier)ServiceManager.getService(myProject, VcsNotifier.class);
-
- myGitRepositoryManager = GitUtil.getRepositoryManager(myProject);
- myPlatformFacade = ServiceManager.getService(myProject, GitPlatformFacade.class);
- myGit = ServiceManager.getService(myProject, Git.class);
- myVcs = ObjectUtils.assertNotNull(GitVcs.getInstance(myProject));
- myVcs.doActivate();
-
- GitTestUtil.assumeSupportedGitVersion(myVcs);
- initChangeListManager();
- addSilently();
- removeSilently();
+ try {
+ myProject = myProjectFixture.getProject();
+ myProjectRoot = myProject.getBaseDir();
+ myProjectPath = myProjectRoot.getPath();
+
+ myGitSettings = GitVcsSettings.getInstance(myProject);
+ myGitSettings.getAppSettings().setPathToGit(GitExecutor.PathHolder.GIT_EXECUTABLE);
+
+ myDialogManager = (TestDialogManager)ServiceManager.getService(DialogManager.class);
+ myVcsNotifier = (TestVcsNotifier)ServiceManager.getService(myProject, VcsNotifier.class);
+
+ myGitRepositoryManager = GitUtil.getRepositoryManager(myProject);
+ myPlatformFacade = ServiceManager.getService(myProject, GitPlatformFacade.class);
+ myGit = ServiceManager.getService(myProject, Git.class);
+ myVcs = ObjectUtils.assertNotNull(GitVcs.getInstance(myProject));
+ myVcs.doActivate();
+
+ GitTestUtil.assumeSupportedGitVersion(myVcs);
+ initChangeListManager();
+ addSilently();
+ removeSilently();
+ }
+ catch (Exception e) {
+ tearDown();
+ throw e;
+ }
}
@Override
@NotNull
public String getTestName(boolean lowercaseFirstLetter) {
String name = super.getTestName(lowercaseFirstLetter);
- name = name.trim().replace(' ', '_');
- if (name.length() > 50) {
- name = name.substring(0, 50);
+ name = StringUtil.shortenTextWithEllipsis(name.trim().replace(" ", "_"), 12, 6, "_");
+ if (name.startsWith("_")) {
+ name = name.substring(1);
}
return name;
}
@@ -127,16 +134,25 @@ public abstract class GitPlatformTest extends UsefulTestCase {
@Override
protected void tearDown() throws Exception {
try {
- myDialogManager.cleanup();
- myVcsNotifier.cleanup();
- myProjectFixture.tearDown();
-
- String tempTestIndicator = myTestStartedIndicator;
- clearFields(this);
- myTestStartedIndicator = tempTestIndicator;
+ if (myDialogManager != null) {
+ myDialogManager.cleanup();
+ }
+ if (myVcsNotifier != null) {
+ myVcsNotifier.cleanup();
+ }
+ if (myProjectFixture != null) {
+ myProjectFixture.tearDown();
+ }
}
finally {
- super.tearDown();
+ try {
+ String tempTestIndicator = myTestStartedIndicator;
+ clearFields(this);
+ myTestStartedIndicator = tempTestIndicator;
+ }
+ finally {
+ super.tearDown();
+ }
}
}
diff --git a/plugins/git4idea/tests/git4idea/test/GitScenarios.groovy b/plugins/git4idea/tests/git4idea/test/GitScenarios.groovy
index 77ecf0bc9e20..1fe574ad863d 100644
--- a/plugins/git4idea/tests/git4idea/test/GitScenarios.groovy
+++ b/plugins/git4idea/tests/git4idea/test/GitScenarios.groovy
@@ -38,14 +38,17 @@ class GitScenarios {
/**
* Create a branch with a commit and return back to master.
*/
- static def branchWithCommit(GitRepository repository, String name, String file = "branch_file.txt", String content = "branch content") {
+ static def branchWithCommit(GitRepository repository, String name, String file = "branch_file.txt", String content = "branch content",
+ boolean returnToMaster = true) {
cd repository
git("checkout -b $name")
touch(file, content)
git("add $file")
git("commit -m branch_content")
- git("checkout master")
+ if (returnToMaster) {
+ git("checkout master")
+ }
}
/**
diff --git a/plugins/git4idea/tests/git4idea/test/GitTestRepositoryManager.java b/plugins/git4idea/tests/git4idea/test/GitTestRepositoryManager.java
index 52bf562280fe..b02e952926c2 100644
--- a/plugins/git4idea/tests/git4idea/test/GitTestRepositoryManager.java
+++ b/plugins/git4idea/tests/git4idea/test/GitTestRepositoryManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,70 +15,46 @@
*/
package git4idea.test;
-import com.intellij.dvcs.repo.RepositoryManager;
-import com.intellij.openapi.vcs.FilePath;
+import com.intellij.dvcs.repo.RepoStateException;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Disposer;
+import com.intellij.openapi.vcs.ProjectLevelVcsManager;
import com.intellij.openapi.vfs.VirtualFile;
+import git4idea.GitPlatformFacade;
import git4idea.repo.GitRepository;
+import git4idea.repo.GitRepositoryImpl;
+import git4idea.repo.GitRepositoryManager;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import java.util.ArrayList;
-import java.util.List;
+public class GitTestRepositoryManager extends GitRepositoryManager {
-/**
- * @author Kirill Likhodedov
- */
-public class GitTestRepositoryManager implements RepositoryManager<GitRepository> {
- private final List<GitRepository> myRepositories = new ArrayList<GitRepository>();
+ @NotNull private final Project myProject;
+ @NotNull private final GitPlatformFacade myFacade;
- public void add(GitRepository repository) {
- myRepositories.add(repository);
- }
-
- @Override
- public GitRepository getRepositoryForRoot(@Nullable VirtualFile root) {
- for (GitRepository repository : myRepositories) {
- if (repository.getRoot().equals(root)) {
- return repository;
- }
- }
-
- return null;
- }
-
- @Override
- public GitRepository getRepositoryForFile(@NotNull VirtualFile file) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public GitRepository getRepositoryForFile(@NotNull FilePath file) {
- throw new UnsupportedOperationException();
+ public GitTestRepositoryManager(@NotNull Project project,
+ @NotNull GitPlatformFacade platformFacade,
+ @NotNull ProjectLevelVcsManager vcsManager) {
+ super(project, platformFacade, vcsManager);
+ myProject = project;
+ myFacade = platformFacade;
}
@NotNull
@Override
- public List<GitRepository> getRepositories() {
- return myRepositories;
- }
-
- @Override
- public boolean moreThanOneRoot() {
- return myRepositories.size() > 1;
- }
-
- @Override
- public void updateRepository(VirtualFile root) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void updateAllRepositories() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void waitUntilInitialized() {
+ protected GitRepository createRepository(@NotNull VirtualFile root) {
+ return new GitRepositoryImpl(root, myFacade, myProject, this, false) {
+ @Override
+ public void update() {
+ try {
+ super.update();
+ }
+ catch (RepoStateException e) {
+ if (!Disposer.isDisposed(this)) { // project dir will simply be removed during dispose
+ throw e;
+ }
+ }
+ }
+ };
}
}
diff --git a/plugins/git4idea/tests/git4idea/test/GitTestUtil.java b/plugins/git4idea/tests/git4idea/test/GitTestUtil.java
index 842b1b1a2bae..3525ad18f0fd 100644
--- a/plugins/git4idea/tests/git4idea/test/GitTestUtil.java
+++ b/plugins/git4idea/tests/git4idea/test/GitTestUtil.java
@@ -22,6 +22,7 @@ import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import git4idea.GitUtil;
import git4idea.GitVcs;
+import git4idea.config.GitVersion;
import git4idea.repo.GitRepository;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.ide.BuiltInServerManagerImpl;
@@ -111,6 +112,7 @@ public class GitTestUtil {
}
public static void assumeSupportedGitVersion(@NotNull GitVcs vcs) {
- assumeTrue(vcs.getVersion().isSupported());
+ GitVersion version = vcs.getVersion();
+ assumeTrue("Unsupported Git version: " + version, version.isSupported());
}
}
diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java
index 714191d06b98..bfceb0ceec39 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java
@@ -195,7 +195,7 @@ public class GithubRebaseAction extends DumbAwareAction {
}
try {
- return GithubUtil.runTask(project, GithubAuthDataHolder.createFromSettings(indicator.getModalityState()), indicator,
+ return GithubUtil.runTask(project, GithubAuthDataHolder.createFromSettings(), indicator,
new ThrowableConvertor<GithubAuthData, GithubRepoDetailed, IOException>() {
@NotNull
@Override
diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubShareAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubShareAction.java
index 7c18b3bf7ffc..cca5afa0f5e5 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/GithubShareAction.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/GithubShareAction.java
@@ -23,10 +23,10 @@ import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.roots.FileIndexFacade;
import com.intellij.openapi.ui.Splitter;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.vcs.ProjectLevelVcsManager;
import com.intellij.openapi.vcs.VcsDataKeys;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.changes.ChangeListManager;
@@ -54,7 +54,6 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.github.api.GithubApiUtil;
import org.jetbrains.plugins.github.api.GithubRepo;
import org.jetbrains.plugins.github.api.GithubUserDetailed;
-import org.jetbrains.plugins.github.exceptions.GithubOperationCanceledException;
import org.jetbrains.plugins.github.ui.GithubShareDialog;
import org.jetbrains.plugins.github.util.*;
@@ -125,7 +124,7 @@ public class GithubShareAction extends DumbAwareAction {
externalRemoteDetected = !gitRepository.getRemotes().isEmpty();
}
- final GithubAuthDataHolder authHolder = GithubAuthDataHolder.createFromSettings(null);
+ final GithubAuthDataHolder authHolder = GithubAuthDataHolder.createFromSettings();
// get available GitHub repos with modal progress
final GithubInfo githubInfo = loadGithubInfoWithModal(authHolder, project);
@@ -351,11 +350,11 @@ public class GithubShareAction extends DumbAwareAction {
@NotNull
private static Collection<VirtualFile> filterOutIgnored(@NotNull Project project, @NotNull Collection<VirtualFile> files) {
final ChangeListManager changeListManager = ChangeListManager.getInstance(project);
- final FileIndexFacade fileIndex = FileIndexFacade.getInstance(project);
+ final ProjectLevelVcsManager vcsManager = ProjectLevelVcsManager.getInstance(project);
return ContainerUtil.filter(files, new Condition<VirtualFile>() {
@Override
public boolean value(VirtualFile file) {
- return !changeListManager.isIgnoredFile(file) && !fileIndex.isExcludedFile(file);
+ return !changeListManager.isIgnoredFile(file) && !vcsManager.isIgnored(file);
}
});
}
diff --git a/plugins/github/src/org/jetbrains/plugins/github/extensions/GithubCheckoutProvider.java b/plugins/github/src/org/jetbrains/plugins/github/extensions/GithubCheckoutProvider.java
index 115258d9bee2..6b3f73f5f8be 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/extensions/GithubCheckoutProvider.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/extensions/GithubCheckoutProvider.java
@@ -61,7 +61,7 @@ public class GithubCheckoutProvider implements CheckoutProvider {
@NotNull
@Override
public List<GithubRepo> convert(ProgressIndicator indicator) throws IOException {
- return GithubUtil.runTask(project, GithubAuthDataHolder.createFromSettings(indicator.getModalityState()), indicator,
+ return GithubUtil.runTask(project, GithubAuthDataHolder.createFromSettings(), indicator,
new ThrowableConvertor<GithubAuthData, List<GithubRepo>, IOException>() {
@NotNull
@Override
diff --git a/plugins/github/src/org/jetbrains/plugins/github/extensions/GithubHttpAuthDataProvider.java b/plugins/github/src/org/jetbrains/plugins/github/extensions/GithubHttpAuthDataProvider.java
index 47d3edcb3de5..5a7daf94a9fd 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/extensions/GithubHttpAuthDataProvider.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/extensions/GithubHttpAuthDataProvider.java
@@ -15,7 +15,6 @@
*/
package org.jetbrains.plugins.github.extensions;
-import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.AuthData;
import git4idea.remote.GitHttpAuthDataProvider;
@@ -32,7 +31,7 @@ public class GithubHttpAuthDataProvider implements GitHttpAuthDataProvider {
@Nullable
@Override
- public AuthData getAuthData(@NotNull String url, @Nullable ModalityState modalityState) {
+ public AuthData getAuthData(@NotNull String url) {
if (!GithubUrlUtil.isGithubUrl(url)) {
return null;
}
@@ -48,7 +47,7 @@ public class GithubHttpAuthDataProvider implements GitHttpAuthDataProvider {
return null;
}
- GithubAuthData auth = settings.getAuthData(modalityState);
+ GithubAuthData auth = settings.getAuthData();
switch (auth.getAuthType()) {
case BASIC:
GithubAuthData.BasicAuth basicAuth = auth.getBasicAuth();
diff --git a/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepositoryEditor.java b/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepositoryEditor.java
index 9cf3cdf4b4fe..5333d82e3baf 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepositoryEditor.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepositoryEditor.java
@@ -125,8 +125,7 @@ public class GithubRepositoryEditor extends BaseRepositoryEditor<GithubRepositor
@Override
public String convert(ProgressIndicator indicator) throws IOException {
return GithubUtil
- .runTaskWithBasicAuthForHost(myProject, GithubAuthDataHolder.createFromSettings(indicator.getModalityState()),
- indicator, getHost(),
+ .runTaskWithBasicAuthForHost(myProject, GithubAuthDataHolder.createFromSettings(), indicator, getHost(),
new ThrowableConvertor<GithubAuthData, String, IOException>() {
@NotNull
@Override
diff --git a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.java b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.java
index 229170e29ead..7de0dae30d69 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.java
@@ -130,8 +130,7 @@ public class GithubSettingsPanel {
@NotNull
@Override
public String convert(ProgressIndicator indicator) throws IOException {
- return GithubUtil.runTaskWithBasicAuthForHost(project, GithubAuthDataHolder.createFromSettings(indicator.getModalityState()),
- indicator, getHost(),
+ return GithubUtil.runTaskWithBasicAuthForHost(project, GithubAuthDataHolder.createFromSettings(), indicator, getHost(),
new ThrowableConvertor<GithubAuthData, String, IOException>() {
@NotNull
@Override
@@ -263,7 +262,7 @@ public class GithubSettingsPanel {
@NotNull
public GithubAuthData getAuthData() {
if (!myCredentialsModified) {
- return mySettings.getAuthData(null);
+ return mySettings.getAuthData();
}
Object selected = myAuthTypeComboBox.getSelectedItem();
if (AUTH_PASSWORD.equals(selected)) return GithubAuthData.createBasicAuth(getHost(), getLogin(), getPassword());
@@ -291,7 +290,7 @@ public class GithubSettingsPanel {
public void apply() {
if (myCredentialsModified) {
- mySettings.setAuthData(getAuthData(), true, null);
+ mySettings.setAuthData(getAuthData(), true);
}
mySettings.setConnectionTimeout(getConnectionTimeout());
resetCredentialsModification();
diff --git a/plugins/github/src/org/jetbrains/plugins/github/util/GithubAuthData.java b/plugins/github/src/org/jetbrains/plugins/github/util/GithubAuthData.java
index d7981b261d7c..f11044422154 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/util/GithubAuthData.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/util/GithubAuthData.java
@@ -15,7 +15,6 @@
*/
package org.jetbrains.plugins.github.util;
-import com.intellij.openapi.application.ModalityState;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.github.api.GithubApiUtil;
@@ -53,8 +52,8 @@ public class GithubAuthData {
myUseProxy = useProxy;
}
- public static GithubAuthData createFromSettings(@Nullable ModalityState state) {
- return GithubSettings.getInstance().getAuthData(state);
+ public static GithubAuthData createFromSettings() {
+ return GithubSettings.getInstance().getAuthData();
}
public static GithubAuthData createAnonymous() {
diff --git a/plugins/github/src/org/jetbrains/plugins/github/util/GithubAuthDataHolder.java b/plugins/github/src/org/jetbrains/plugins/github/util/GithubAuthDataHolder.java
index 24303a34d240..695dfe734c34 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/util/GithubAuthDataHolder.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/util/GithubAuthDataHolder.java
@@ -15,10 +15,8 @@
*/
package org.jetbrains.plugins.github.util;
-import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.util.ThrowableComputable;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
public class GithubAuthDataHolder {
@@ -42,7 +40,7 @@ public class GithubAuthDataHolder {
myAuthData = task.compute();
}
- public static GithubAuthDataHolder createFromSettings(@Nullable ModalityState state) {
- return new GithubAuthDataHolder(GithubSettings.getInstance().getAuthData(state));
+ public static GithubAuthDataHolder createFromSettings() {
+ return new GithubAuthDataHolder(GithubSettings.getInstance().getAuthData());
}
}
diff --git a/plugins/github/src/org/jetbrains/plugins/github/util/GithubSettings.java b/plugins/github/src/org/jetbrains/plugins/github/util/GithubSettings.java
index a2bdca59bbe4..3523e412a95e 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/util/GithubSettings.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/util/GithubSettings.java
@@ -19,7 +19,6 @@ import com.intellij.ide.passwordSafe.PasswordSafe;
import com.intellij.ide.passwordSafe.PasswordSafeException;
import com.intellij.ide.passwordSafe.config.PasswordSafeSettings;
import com.intellij.ide.passwordSafe.impl.PasswordSafeImpl;
-import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.components.*;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.text.StringUtil;
@@ -152,10 +151,10 @@ public class GithubSettings implements PersistentStateComponent<GithubSettings.S
}
@NotNull
- private String getPassword(@Nullable ModalityState state) {
+ private String getPassword() {
String password;
try {
- password = PasswordSafe.getInstance().getPassword(null, GithubSettings.class, GITHUB_SETTINGS_PASSWORD_KEY, state);
+ password = PasswordSafe.getInstance().getPassword(null, GithubSettings.class, GITHUB_SETTINGS_PASSWORD_KEY);
}
catch (PasswordSafeException e) {
LOG.info("Couldn't get password for key [" + GITHUB_SETTINGS_PASSWORD_KEY + "]", e);
@@ -165,10 +164,10 @@ public class GithubSettings implements PersistentStateComponent<GithubSettings.S
return StringUtil.notNullize(password);
}
- private void setPassword(@NotNull String password, boolean rememberPassword, @Nullable ModalityState state) {
+ private void setPassword(@NotNull String password, boolean rememberPassword) {
try {
if (rememberPassword) {
- PasswordSafe.getInstance().storePassword(null, GithubSettings.class, GITHUB_SETTINGS_PASSWORD_KEY, password, state);
+ PasswordSafe.getInstance().storePassword(null, GithubSettings.class, GITHUB_SETTINGS_PASSWORD_KEY, password);
}
else {
final PasswordSafeImpl passwordSafe = (PasswordSafeImpl)PasswordSafe.getInstance();
@@ -197,13 +196,13 @@ public class GithubSettings implements PersistentStateComponent<GithubSettings.S
}
@NotNull
- public GithubAuthData getAuthData(@Nullable ModalityState state) {
+ public GithubAuthData getAuthData() {
switch (getAuthType()) {
case BASIC:
//noinspection ConstantConditions
- return GithubAuthData.createBasicAuth(getHost(), getLogin(), getPassword(state));
+ return GithubAuthData.createBasicAuth(getHost(), getLogin(), getPassword());
case TOKEN:
- return GithubAuthData.createTokenAuth(getHost(), getPassword(state));
+ return GithubAuthData.createTokenAuth(getHost(), getPassword());
case ANONYMOUS:
return GithubAuthData.createAnonymous();
default:
@@ -211,7 +210,7 @@ public class GithubSettings implements PersistentStateComponent<GithubSettings.S
}
}
- public void setAuthData(@NotNull GithubAuthData auth, boolean rememberPassword, @Nullable ModalityState state) {
+ public void setAuthData(@NotNull GithubAuthData auth, boolean rememberPassword) {
setValidGitAuth(isValidGitAuth(auth));
setAuthType(auth.getAuthType());
@@ -221,16 +220,16 @@ public class GithubSettings implements PersistentStateComponent<GithubSettings.S
case BASIC:
assert auth.getBasicAuth() != null;
setLogin(auth.getBasicAuth().getLogin());
- setPassword(auth.getBasicAuth().getPassword(), rememberPassword, state);
+ setPassword(auth.getBasicAuth().getPassword(), rememberPassword);
break;
case TOKEN:
assert auth.getTokenAuth() != null;
setLogin(null);
- setPassword(auth.getTokenAuth().getToken(), rememberPassword, state);
+ setPassword(auth.getTokenAuth().getToken(), rememberPassword);
break;
case ANONYMOUS:
setLogin(null);
- setPassword("", rememberPassword, state);
+ setPassword("", rememberPassword);
break;
default:
throw new IllegalStateException("GithubSettings: setAuthData - wrong AuthType: " + auth.getAuthType());
diff --git a/plugins/github/src/org/jetbrains/plugins/github/util/GithubUtil.java b/plugins/github/src/org/jetbrains/plugins/github/util/GithubUtil.java
index e4af54f84639..edd12ab85ab6 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/util/GithubUtil.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/util/GithubUtil.java
@@ -161,7 +161,7 @@ public class GithubUtil {
if (ok[0]) {
authData[0] = dialog.getAuthData();
- GithubSettings.getInstance().setAuthData(authData[0], dialog.isSavePasswordSelected(), indicator.getModalityState());
+ GithubSettings.getInstance().setAuthData(authData[0], dialog.isSavePasswordSelected());
}
}
}, indicator.getModalityState());
@@ -195,7 +195,7 @@ public class GithubUtil {
final GithubSettings settings = GithubSettings.getInstance();
if (settings.getAuthType() != GithubAuthData.AuthType.TOKEN) {
- GithubSettings.getInstance().setAuthData(authData[0], dialog.isSavePasswordSelected(), indicator.getModalityState());
+ GithubSettings.getInstance().setAuthData(authData[0], dialog.isSavePasswordSelected());
}
}
}
@@ -247,7 +247,7 @@ public class GithubUtil {
@NotNull
public static GithubAuthDataHolder getValidAuthDataHolderFromConfig(@NotNull Project project, @NotNull ProgressIndicator indicator)
throws IOException {
- GithubAuthData auth = GithubAuthData.createFromSettings(indicator.getModalityState());
+ GithubAuthData auth = GithubAuthData.createFromSettings();
GithubAuthDataHolder authHolder = new GithubAuthDataHolder(auth);
try {
checkAuthData(project, authHolder, indicator);
diff --git a/plugins/github/test/org/jetbrains/plugins/github/GithubCreateGistTestBase.java b/plugins/github/test/org/jetbrains/plugins/github/GithubCreateGistTestBase.java
index d313398548a5..b54bd8c62b4e 100644
--- a/plugins/github/test/org/jetbrains/plugins/github/GithubCreateGistTestBase.java
+++ b/plugins/github/test/org/jetbrains/plugins/github/GithubCreateGistTestBase.java
@@ -54,12 +54,12 @@ public abstract class GithubCreateGistTestBase extends GithubTest {
@NotNull
protected GithubAuthDataHolder getAuthDataHolder() {
- return new GithubAuthDataHolder(myGitHubSettings.getAuthData(null));
+ return new GithubAuthDataHolder(myGitHubSettings.getAuthData());
}
protected void deleteGist() throws IOException {
if (GIST_ID != null) {
- GithubApiUtil.deleteGist(myGitHubSettings.getAuthData(null), GIST_ID);
+ GithubApiUtil.deleteGist(myGitHubSettings.getAuthData(), GIST_ID);
GIST = null;
GIST_ID = null;
}
@@ -82,7 +82,7 @@ public abstract class GithubCreateGistTestBase extends GithubTest {
if (GIST == null) {
try {
- GIST = GithubApiUtil.getGist(myGitHubSettings.getAuthData(null), GIST_ID);
+ GIST = GithubApiUtil.getGist(myGitHubSettings.getAuthData(), GIST_ID);
}
catch (IOException e) {
System.err.println(e.getMessage());
diff --git a/plugins/github/test/org/jetbrains/plugins/github/GithubRequestPagingTest.java b/plugins/github/test/org/jetbrains/plugins/github/GithubRequestPagingTest.java
index 97b34aa7b26c..4fec0d1c7a5c 100644
--- a/plugins/github/test/org/jetbrains/plugins/github/GithubRequestPagingTest.java
+++ b/plugins/github/test/org/jetbrains/plugins/github/GithubRequestPagingTest.java
@@ -36,7 +36,7 @@ public class GithubRequestPagingTest extends GithubTest {
public void testAvailableRepos() throws Throwable {
- List<GithubRepo> availableRepos = GithubApiUtil.getUserRepos(myGitHubSettings.getAuthData(null), myLogin2);
+ List<GithubRepo> availableRepos = GithubApiUtil.getUserRepos(myGitHubSettings.getAuthData(), myLogin2);
List<String> realData = new ArrayList<String>();
for (GithubRepo info : availableRepos) {
realData.add(info.getName());
diff --git a/plugins/github/test/org/jetbrains/plugins/github/GithubShareProjectTest.java b/plugins/github/test/org/jetbrains/plugins/github/GithubShareProjectTest.java
index e6da326777c5..c4063629cbbe 100644
--- a/plugins/github/test/org/jetbrains/plugins/github/GithubShareProjectTest.java
+++ b/plugins/github/test/org/jetbrains/plugins/github/GithubShareProjectTest.java
@@ -99,7 +99,7 @@ public class GithubShareProjectTest extends GithubShareProjectTestBase {
}
protected void checkGithubExists() throws IOException {
- GithubAuthData auth = myGitHubSettings.getAuthData(null);
+ GithubAuthData auth = myGitHubSettings.getAuthData();
GithubRepoDetailed githubInfo = GithubApiUtil.getDetailedRepoInfo(auth, myLogin1, PROJECT_NAME);
assertNotNull("GitHub repository does not exist", githubInfo);
}
diff --git a/plugins/github/test/org/jetbrains/plugins/github/GithubShareProjectTestBase.java b/plugins/github/test/org/jetbrains/plugins/github/GithubShareProjectTestBase.java
index f146b37f4208..abfb5ece3819 100644
--- a/plugins/github/test/org/jetbrains/plugins/github/GithubShareProjectTestBase.java
+++ b/plugins/github/test/org/jetbrains/plugins/github/GithubShareProjectTestBase.java
@@ -48,7 +48,7 @@ public abstract class GithubShareProjectTestBase extends GithubTest {
}
protected void deleteGithubRepo() throws IOException {
- GithubApiUtil.deleteGithubRepository(myGitHubSettings.getAuthData(null), myLogin1, PROJECT_NAME);
+ GithubApiUtil.deleteGithubRepository(myGitHubSettings.getAuthData(), myLogin1, PROJECT_NAME);
}
protected void registerDefaultShareDialogHandler() {
diff --git a/plugins/github/test/org/jetbrains/plugins/github/test/GithubTest.java b/plugins/github/test/org/jetbrains/plugins/github/test/GithubTest.java
index b728913aeacb..3d3d8201e03a 100644
--- a/plugins/github/test/org/jetbrains/plugins/github/test/GithubTest.java
+++ b/plugins/github/test/org/jetbrains/plugins/github/test/GithubTest.java
@@ -172,7 +172,7 @@ public abstract class GithubTest extends GitPlatformTest {
myAuth = GithubAuthData.createBasicAuth(host, login1, password);
myGitHubSettings = GithubSettings.getInstance();
- myGitHubSettings.setAuthData(myAuth, false, null);
+ myGitHubSettings.setAuthData(myAuth, false);
myHttpAuthService = (GitHttpAuthTestService)ServiceManager.getService(GitHttpAuthService.class);
diff --git a/plugins/google-app-engine/jps-plugin/src/org/jetbrains/jps/appengine/build/AppEngineEnhancerBuilder.java b/plugins/google-app-engine/jps-plugin/src/org/jetbrains/jps/appengine/build/AppEngineEnhancerBuilder.java
index 549aa1a5b361..e6ab8747c2a3 100644
--- a/plugins/google-app-engine/jps-plugin/src/org/jetbrains/jps/appengine/build/AppEngineEnhancerBuilder.java
+++ b/plugins/google-app-engine/jps-plugin/src/org/jetbrains/jps/appengine/build/AppEngineEnhancerBuilder.java
@@ -113,7 +113,11 @@ public class AppEngineEnhancerBuilder extends ModuleLevelBuilder {
List<String> classpath = new ArrayList<String>();
classpath.add(extension.getToolsApiJarPath());
classpath.add(PathManager.getJarPathForClass(EnhancerRunner.class));
+ boolean removeOrmJars = Boolean.parseBoolean(System.getProperty("jps.appengine.enhancer.remove.orm.jars", "true"));
for (File file : JpsJavaExtensionService.dependencies(module).recursively().compileOnly().productionOnly().classes().getRoots()) {
+ if (removeOrmJars && FileUtil.isAncestor(new File(extension.getOrmLibPath()), file, true)) {
+ continue;
+ }
classpath.add(file.getAbsolutePath());
}
diff --git a/plugins/google-app-engine/jps-plugin/src/org/jetbrains/jps/appengine/model/JpsAppEngineModuleExtension.java b/plugins/google-app-engine/jps-plugin/src/org/jetbrains/jps/appengine/model/JpsAppEngineModuleExtension.java
index 0c68b4139ff6..beb54b57cc7c 100644
--- a/plugins/google-app-engine/jps-plugin/src/org/jetbrains/jps/appengine/model/JpsAppEngineModuleExtension.java
+++ b/plugins/google-app-engine/jps-plugin/src/org/jetbrains/jps/appengine/model/JpsAppEngineModuleExtension.java
@@ -26,6 +26,8 @@ import java.util.List;
public interface JpsAppEngineModuleExtension extends JpsElement {
JpsModule getModule();
+ String getOrmLibPath();
+
String getSdkHomePath();
boolean isRunEnhancerOnMake();
diff --git a/plugins/google-app-engine/jps-plugin/src/org/jetbrains/jps/appengine/model/impl/JpsAppEngineModuleExtensionImpl.java b/plugins/google-app-engine/jps-plugin/src/org/jetbrains/jps/appengine/model/impl/JpsAppEngineModuleExtensionImpl.java
index e52d54db2bee..d40f7c007959 100644
--- a/plugins/google-app-engine/jps-plugin/src/org/jetbrains/jps/appengine/model/impl/JpsAppEngineModuleExtensionImpl.java
+++ b/plugins/google-app-engine/jps-plugin/src/org/jetbrains/jps/appengine/model/impl/JpsAppEngineModuleExtensionImpl.java
@@ -71,6 +71,11 @@ public class JpsAppEngineModuleExtensionImpl extends JpsElementBase<JpsAppEngine
}
@Override
+ public String getOrmLibPath() {
+ return FileUtil.toSystemDependentName(JpsArtifactPathUtil.appendToPath(getSdkHomePath(), "/lib/user/orm"));
+ }
+
+ @Override
public String getSdkHomePath() {
return myProperties.mySdkHomePath;
}
diff --git a/plugins/google-app-engine/source/com/intellij/appengine/actions/UploadApplicationAction.java b/plugins/google-app-engine/source/com/intellij/appengine/actions/UploadApplicationAction.java
index afe24f134587..e3a7762fa539 100644
--- a/plugins/google-app-engine/source/com/intellij/appengine/actions/UploadApplicationAction.java
+++ b/plugins/google-app-engine/source/com/intellij/appengine/actions/UploadApplicationAction.java
@@ -21,6 +21,7 @@ import com.intellij.appengine.util.AppEngineUtil;
import com.intellij.facet.ProjectFacetManager;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.packaging.artifacts.Artifact;
@@ -67,8 +68,12 @@ public class UploadApplicationAction extends AnAction {
}
@Override
- public void errorOccurred(@NotNull String errorMessage) {
- Messages.showErrorDialog(project, errorMessage, CommonBundle.getErrorTitle());
+ public void errorOccurred(@NotNull final String errorMessage) {
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ public void run() {
+ Messages.showErrorDialog(project, errorMessage, CommonBundle.getErrorTitle());
+ }
+ });
}
}, null);
if (uploader != null) {
diff --git a/plugins/gradle/gradle.iml b/plugins/gradle/gradle.iml
index 878ec399b87c..9e9fb73cdd72 100644
--- a/plugins/gradle/gradle.iml
+++ b/plugins/gradle/gradle.iml
@@ -14,6 +14,7 @@
<orderEntry type="module" module-name="external-system-impl" exported="" />
<orderEntry type="module" module-name="gradle-tooling-extension-api" exported="" />
<orderEntry type="module" module-name="gradle-tooling-extension-impl" />
+ <orderEntry type="module" module-name="gradle-jps-plugin" />
<orderEntry type="module" module-name="idea-ui" />
<orderEntry type="module" module-name="lang-api" />
<orderEntry type="module" module-name="compiler-openapi" />
@@ -105,6 +106,9 @@
<orderEntry type="module" module-name="testFramework-java" scope="TEST" />
<orderEntry type="module" module-name="junit" />
<orderEntry type="module" module-name="smRunner" />
+ <orderEntry type="library" name="Kryo" level="project" />
+ <orderEntry type="library" name="Ant" level="project" />
+ <orderEntry type="library" name="gson" level="project" />
</component>
</module>
diff --git a/plugins/gradle/jps-plugin/gradle-jps-plugin.iml b/plugins/gradle/jps-plugin/gradle-jps-plugin.iml
new file mode 100644
index 000000000000..0d1d5300e84b
--- /dev/null
+++ b/plugins/gradle/jps-plugin/gradle-jps-plugin.iml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="module" module-name="util" />
+ <orderEntry type="module" module-name="jps-builders" />
+ <orderEntry type="module" module-name="jps-model-impl" />
+ <orderEntry type="module" module-name="jps-model-api" />
+ <orderEntry type="module" module-name="jps-model-serialization" />
+ <orderEntry type="module-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../lib/gradle-tooling-api-2.0.jar!/" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-core-2.0.jar!/" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-messaging-2.0.jar!/" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-wrapper-2.0.jar!/" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-base-services-2.0.jar!/" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-base-services-groovy-2.0.jar!/" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-native-2.0.jar!/" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-resources-2.0.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES>
+ <root url="jar://$MODULE_DIR$/../lib/gradle-2.0-src.zip!/gradle-2.0/subprojects/tooling-api/src/main/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-2.0-src.zip!/gradle-2.0/subprojects/core/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-2.0-src.zip!/gradle-2.0/subprojects/messaging/src/main/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-2.0-src.zip!/gradle-2.0/subprojects/wrapper/src/main/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-2.0-src.zip!/gradle-2.0/subprojects/base-services/src/main/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-2.0-src.zip!/gradle-2.0/subprojects/base-services-groovy/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-2.0-src.zip!/gradle-2.0/subprojects/native/src/main/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-2.0-src.zip!/gradle-2.0/subprojects/resources/src/main/java" />
+ </SOURCES>
+ </library>
+ </orderEntry>
+ <orderEntry type="library" exported="" name="Ant" level="project" />
+ <orderEntry type="library" name="gson" level="project" />
+ </component>
+</module>
+
diff --git a/plugins/gradle/jps-plugin/src/META-INF/services/org.jetbrains.jps.gradle.model.JpsGradleExtensionService b/plugins/gradle/jps-plugin/src/META-INF/services/org.jetbrains.jps.gradle.model.JpsGradleExtensionService
new file mode 100644
index 000000000000..526afcc9d0a9
--- /dev/null
+++ b/plugins/gradle/jps-plugin/src/META-INF/services/org.jetbrains.jps.gradle.model.JpsGradleExtensionService
@@ -0,0 +1,16 @@
+#
+# Copyright 2000-2014 JetBrains s.r.o.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+org.jetbrains.jps.gradle.model.impl.JpsGradleExtensionServiceImpl \ No newline at end of file
diff --git a/plugins/gradle/jps-plugin/src/META-INF/services/org.jetbrains.jps.incremental.BuilderService b/plugins/gradle/jps-plugin/src/META-INF/services/org.jetbrains.jps.incremental.BuilderService
new file mode 100644
index 000000000000..90e686daeaca
--- /dev/null
+++ b/plugins/gradle/jps-plugin/src/META-INF/services/org.jetbrains.jps.incremental.BuilderService
@@ -0,0 +1,16 @@
+#
+# Copyright 2000-2014 JetBrains s.r.o.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+org.jetbrains.jps.gradle.compiler.GradleBuilderService \ No newline at end of file
diff --git a/plugins/gradle/jps-plugin/src/META-INF/services/org.jetbrains.jps.model.java.impl.JpsJavaDependenciesEnumerationHandler$Factory b/plugins/gradle/jps-plugin/src/META-INF/services/org.jetbrains.jps.model.java.impl.JpsJavaDependenciesEnumerationHandler$Factory
new file mode 100644
index 000000000000..f1518a33d329
--- /dev/null
+++ b/plugins/gradle/jps-plugin/src/META-INF/services/org.jetbrains.jps.model.java.impl.JpsJavaDependenciesEnumerationHandler$Factory
@@ -0,0 +1,16 @@
+#
+# Copyright 2000-2014 JetBrains s.r.o.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+org.jetbrains.jps.gradle.model.impl.JpsGradleDependenciesEnumerationHandler$GradleFactory \ No newline at end of file
diff --git a/plugins/gradle/jps-plugin/src/META-INF/services/org.jetbrains.jps.model.serialization.JpsModelSerializerExtension b/plugins/gradle/jps-plugin/src/META-INF/services/org.jetbrains.jps.model.serialization.JpsModelSerializerExtension
new file mode 100644
index 000000000000..a86ddcf7d451
--- /dev/null
+++ b/plugins/gradle/jps-plugin/src/META-INF/services/org.jetbrains.jps.model.serialization.JpsModelSerializerExtension
@@ -0,0 +1,16 @@
+#
+# Copyright 2000-2014 JetBrains s.r.o.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+org.jetbrains.jps.gradle.model.impl.JpsGradleModelSerializationExtension \ No newline at end of file
diff --git a/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/compiler/ChainingFilterTransformer.java b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/compiler/ChainingFilterTransformer.java
new file mode 100644
index 000000000000..c717fe16c792
--- /dev/null
+++ b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/compiler/ChainingFilterTransformer.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.gradle.compiler;
+
+import com.intellij.openapi.util.Ref;
+import org.gradle.api.Transformer;
+import org.gradle.util.ConfigureUtil;
+import org.jetbrains.jps.gradle.model.impl.ResourceRootFilter;
+import org.jetbrains.jps.incremental.CompileContext;
+import org.jetbrains.jps.incremental.messages.BuildMessage;
+import org.jetbrains.jps.incremental.messages.CompilerMessage;
+
+import java.io.File;
+import java.io.FilterReader;
+import java.io.Reader;
+import java.lang.reflect.Constructor;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.regex.Matcher;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/24/2014
+ */
+public class ChainingFilterTransformer implements Transformer<Reader, Reader> {
+ private final Collection<ResourceRootFilter> myFilters = new ArrayList<ResourceRootFilter>();
+ private final CompileContext myContext;
+ private final Ref<File> myOutputFileRef;
+
+
+ public ChainingFilterTransformer(CompileContext context, Collection<ResourceRootFilter> filters, Ref<File> outputFileRef) {
+ myContext = context;
+ myOutputFileRef = outputFileRef;
+ myFilters.addAll(filters);
+ }
+
+ public ChainingFilterTransformer(CompileContext context, Collection<ResourceRootFilter> filters) {
+ this(context, filters, null);
+ }
+
+ public void addAll(Collection<ResourceRootFilter> filters) {
+ myFilters.addAll(filters);
+ }
+
+ public void add(ResourceRootFilter... filters) {
+ Collections.addAll(myFilters, filters);
+ }
+
+ @Override
+ public Reader transform(Reader original) {
+ Reader value = original;
+ for (ResourceRootFilter filter : myFilters) {
+ value = doTransform(filter, value);
+ }
+ return value;
+ }
+
+ private Reader doTransform(ResourceRootFilter filter, Reader original) {
+ if ("RenamingCopyFilter" .equals(filter.filterType)) {
+ final Matcher matcher = (Matcher)filter.getProperties().get("matcher");
+ final String replacement = (String)filter.getProperties().get("replacement");
+ if (matcher == null || replacement == null) return original;
+
+ matcher.reset(myOutputFileRef.get().getName());
+ if (matcher.find()) {
+ final String newFileName = matcher.replaceFirst(replacement);
+ myOutputFileRef.set(new File(myOutputFileRef.get().getParentFile(), newFileName));
+ }
+ return original;
+ }
+ try {
+ Class<?> clazz = Class.forName(filter.filterType);
+ if (!FilterReader.class.isAssignableFrom(clazz)) {
+ myContext.processMessage(
+ new CompilerMessage(
+ GradleResourcesBuilder.BUILDER_NAME, BuildMessage.Kind.WARNING,
+ String.format("Error - Invalid filter specification for %s. It should extend java.io.FilterReader.", filter.filterType), null)
+ );
+ }
+ Constructor constructor = clazz.getConstructor(Reader.class);
+ FilterReader result = (FilterReader)constructor.newInstance(original);
+ final Map<Object, Object> properties = filter.getProperties();
+ if (!properties.isEmpty()) {
+ ConfigureUtil.configureByMap(properties, result);
+ }
+ return result;
+ }
+ catch (Throwable th) {
+ myContext.processMessage(new CompilerMessage(
+ GradleResourcesBuilder.BUILDER_NAME, BuildMessage.Kind.WARNING,
+ String.format("Error - Failed to apply filter(%s): %s", filter.filterType, th.getMessage()), null)
+ );
+ }
+ return original;
+ }
+}
diff --git a/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/compiler/GradleBuilderService.java b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/compiler/GradleBuilderService.java
new file mode 100644
index 000000000000..5219a2ccad7b
--- /dev/null
+++ b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/compiler/GradleBuilderService.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.gradle.compiler;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.builders.BuildTargetType;
+import org.jetbrains.jps.gradle.model.impl.GradleResourcesTargetType;
+import org.jetbrains.jps.incremental.BuilderService;
+import org.jetbrains.jps.incremental.TargetBuilder;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/10/2014
+ */
+public class GradleBuilderService extends BuilderService {
+ @NotNull
+ @Override
+ public List<? extends BuildTargetType<?>> getTargetTypes() {
+ return Arrays.asList(GradleResourcesTargetType.PRODUCTION, GradleResourcesTargetType.TEST);
+ }
+
+ @NotNull
+ @Override
+ public List<? extends TargetBuilder<?, ?>> createBuilders() {
+ return Collections.singletonList(new GradleResourcesBuilder());
+ }
+}
diff --git a/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/compiler/GradleResourceFileProcessor.java b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/compiler/GradleResourceFileProcessor.java
new file mode 100644
index 000000000000..dadfa21906a0
--- /dev/null
+++ b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/compiler/GradleResourceFileProcessor.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.gradle.compiler;
+
+import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.io.StreamUtil;
+import org.apache.tools.ant.util.ReaderInputStream;
+import org.jetbrains.jps.gradle.model.impl.GradleModuleResourceConfiguration;
+import org.jetbrains.jps.gradle.model.impl.GradleProjectConfiguration;
+import org.jetbrains.jps.gradle.model.impl.ResourceRootConfiguration;
+import org.jetbrains.jps.gradle.model.impl.ResourceRootFilter;
+import org.jetbrains.jps.incremental.CompileContext;
+import org.jetbrains.jps.incremental.messages.BuildMessage;
+import org.jetbrains.jps.incremental.messages.CompilerMessage;
+import org.jetbrains.jps.model.JpsEncodingConfigurationService;
+import org.jetbrains.jps.model.JpsEncodingProjectConfiguration;
+import org.jetbrains.jps.model.JpsProject;
+
+import java.io.*;
+import java.util.List;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/10/2014
+ */
+public class GradleResourceFileProcessor {
+ private static final int FILTERING_SIZE_LIMIT = 10 * 1024 * 1024 /*10 mb*/;
+ protected final JpsEncodingProjectConfiguration myEncodingConfig;
+ protected final GradleProjectConfiguration myProjectConfig;
+ protected final GradleModuleResourceConfiguration myModuleConfiguration;
+
+ public GradleResourceFileProcessor(GradleProjectConfiguration projectConfiguration, JpsProject project,
+ GradleModuleResourceConfiguration moduleConfiguration) {
+ myProjectConfig = projectConfiguration;
+ myEncodingConfig = JpsEncodingConfigurationService.getInstance().getEncodingConfiguration(project);
+ myModuleConfiguration = moduleConfiguration;
+ }
+
+ public void copyFile(File file, Ref<File> targetFileRef, ResourceRootConfiguration rootConfiguration, CompileContext context,
+ FileFilter filteringFilter) throws IOException {
+ boolean shouldFilter = rootConfiguration.isFiltered && !rootConfiguration.filters.isEmpty() && filteringFilter.accept(file);
+ if (shouldFilter && file.length() > FILTERING_SIZE_LIMIT) {
+ context.processMessage(new CompilerMessage(
+ GradleResourcesBuilder.BUILDER_NAME, BuildMessage.Kind.WARNING,
+ "File is too big to be filtered. Most likely it is a binary file and should be excluded from filtering", file.getPath())
+ );
+ shouldFilter = false;
+ }
+ if (shouldFilter) {
+ copyWithFiltering(file, targetFileRef, rootConfiguration.filters, context);
+ }
+ else {
+ FileUtil.copyContent(file, targetFileRef.get());
+ }
+ }
+
+ private static void copyWithFiltering(File file, Ref<File> outputFileRef, List<ResourceRootFilter> filters, CompileContext context)
+ throws IOException {
+ final FileInputStream originalInputStream = new FileInputStream(file);
+ try {
+ final InputStream inputStream = transform(filters, originalInputStream, outputFileRef, context);
+ FileUtil.createIfDoesntExist(outputFileRef.get());
+ FileOutputStream outputStream = new FileOutputStream(outputFileRef.get());
+ try {
+ FileUtil.copy(inputStream, outputStream);
+ }
+ finally {
+ StreamUtil.closeStream(inputStream);
+ StreamUtil.closeStream(outputStream);
+ }
+ }
+ finally {
+ StreamUtil.closeStream(originalInputStream);
+ }
+ }
+
+ private static InputStream transform(List<ResourceRootFilter> filters, FileInputStream original, Ref<File> outputFileRef, CompileContext context) {
+ return new ReaderInputStream(new ChainingFilterTransformer(context, filters, outputFileRef).transform(new InputStreamReader(original)));
+ }
+} \ No newline at end of file
diff --git a/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/compiler/GradleResourcesBuilder.java b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/compiler/GradleResourcesBuilder.java
new file mode 100644
index 000000000000..295c8bab8133
--- /dev/null
+++ b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/compiler/GradleResourcesBuilder.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.gradle.compiler;
+
+import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.io.FileUtilRt;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.builders.BuildOutputConsumer;
+import org.jetbrains.jps.builders.DirtyFilesHolder;
+import org.jetbrains.jps.builders.FileProcessor;
+import org.jetbrains.jps.builders.storage.BuildDataPaths;
+import org.jetbrains.jps.gradle.model.JpsGradleExtensionService;
+import org.jetbrains.jps.gradle.model.impl.*;
+import org.jetbrains.jps.incremental.CompileContext;
+import org.jetbrains.jps.incremental.ProjectBuildException;
+import org.jetbrains.jps.incremental.TargetBuilder;
+import org.jetbrains.jps.incremental.messages.ProgressMessage;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/10/2014
+ */
+public class GradleResourcesBuilder extends TargetBuilder<GradleResourceRootDescriptor, GradleResourcesTarget> {
+ public static final String BUILDER_NAME = "Gradle Resources Compiler";
+
+ public GradleResourcesBuilder() {
+ super(Arrays.asList(GradleResourcesTargetType.PRODUCTION, GradleResourcesTargetType.TEST));
+ }
+
+ @Override
+ public void build(@NotNull final GradleResourcesTarget target,
+ @NotNull final DirtyFilesHolder<GradleResourceRootDescriptor, GradleResourcesTarget> holder,
+ @NotNull final BuildOutputConsumer outputConsumer,
+ @NotNull final CompileContext context) throws ProjectBuildException, IOException {
+ final BuildDataPaths dataPaths = context.getProjectDescriptor().dataManager.getDataPaths();
+ final GradleProjectConfiguration projectConfig = JpsGradleExtensionService.getInstance().getGradleProjectConfiguration(dataPaths);
+ final GradleModuleResourceConfiguration config = target.getModuleResourcesConfiguration(dataPaths);
+ if (config == null) return;
+
+ final Map<GradleResourceRootDescriptor, List<File>> files = new HashMap<GradleResourceRootDescriptor, List<File>>();
+
+ holder.processDirtyFiles(new FileProcessor<GradleResourceRootDescriptor, GradleResourcesTarget>() {
+
+ @Override
+ public boolean apply(GradleResourcesTarget t, File file, GradleResourceRootDescriptor rd) throws IOException {
+ assert target == t;
+
+ List<File> fileList = files.get(rd);
+ if (fileList == null) {
+ fileList = new ArrayList<File>();
+ files.put(rd, fileList);
+ }
+
+ fileList.add(file);
+ return true;
+ }
+ });
+
+ GradleResourceRootDescriptor[] roots = files.keySet().toArray(new GradleResourceRootDescriptor[files.keySet().size()]);
+ Arrays.sort(roots, new Comparator<GradleResourceRootDescriptor>() {
+ @Override
+ public int compare(GradleResourceRootDescriptor r1, GradleResourceRootDescriptor r2) {
+ int res = r1.getIndexInPom() - r2.getIndexInPom();
+ if (r1.isOverwrite()) {
+ assert r2.isOverwrite();
+ return res;
+ }
+
+ if (r1.getConfiguration().isFiltered && !r2.getConfiguration().isFiltered) return 1;
+ if (!r1.getConfiguration().isFiltered && r2.getConfiguration().isFiltered) return -1;
+
+ if (!r1.getConfiguration().isFiltered) {
+ res = -res;
+ }
+
+ return res;
+ }
+ });
+
+ GradleResourceFileProcessor fileProcessor = new GradleResourceFileProcessor(projectConfig, target.getModule().getProject(), config);
+
+ for (GradleResourceRootDescriptor rd : roots) {
+ for (File file : files.get(rd)) {
+
+ String relPath = FileUtil.getRelativePath(rd.getRootFile(), file);
+ if (relPath == null) continue;
+
+ final File outputDir =
+ GradleResourcesTarget.getOutputDir(target.getModuleOutputDir(), rd.getConfiguration(), config.outputDirectory);
+ if (outputDir == null) continue;
+
+ context.processMessage(new ProgressMessage("Copying resources... [" + target.getModule().getName() + "]"));
+
+ final Ref<File> fileRef = Ref.create(new File(outputDir, relPath));
+ fileProcessor.copyFile(file, fileRef, rd.getConfiguration(), context, FileUtilRt.ALL_FILES);
+ outputConsumer.registerOutputFile(fileRef.get(), Collections.singleton(file.getPath()));
+
+ if (context.getCancelStatus().isCanceled()) return;
+ }
+ }
+
+ context.checkCanceled();
+ context.processMessage(new ProgressMessage(""));
+ }
+
+ @NotNull
+ public String getPresentableName() {
+ return BUILDER_NAME;
+ }
+}
diff --git a/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/JpsGradleExtensionService.java b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/JpsGradleExtensionService.java
new file mode 100644
index 000000000000..126cf5758ac1
--- /dev/null
+++ b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/JpsGradleExtensionService.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.gradle.model;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.builders.storage.BuildDataPaths;
+import org.jetbrains.jps.gradle.model.impl.GradleProjectConfiguration;
+import org.jetbrains.jps.model.module.JpsDependencyElement;
+import org.jetbrains.jps.model.module.JpsModule;
+import org.jetbrains.jps.service.JpsServiceManager;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/10/2014
+ */
+public abstract class JpsGradleExtensionService {
+ public static JpsGradleExtensionService getInstance() {
+ return JpsServiceManager.getInstance().getService(JpsGradleExtensionService.class);
+ }
+
+ @Nullable
+ public abstract JpsGradleModuleExtension getExtension(@NotNull JpsModule module);
+
+ @NotNull
+ public abstract JpsGradleModuleExtension getOrCreateExtension(@NotNull JpsModule module);
+
+ public abstract void setProductionOnTestDependency(@NotNull JpsDependencyElement dependency, boolean value);
+
+ public abstract boolean isProductionOnTestDependency(@NotNull JpsDependencyElement dependency);
+
+ public abstract boolean hasGradleProjectConfiguration(@NotNull BuildDataPaths paths);
+
+ @NotNull
+ public abstract GradleProjectConfiguration getGradleProjectConfiguration(BuildDataPaths paths);
+}
diff --git a/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/JpsGradleModuleExtension.java b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/JpsGradleModuleExtension.java
new file mode 100644
index 000000000000..c673e4c0d27c
--- /dev/null
+++ b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/JpsGradleModuleExtension.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.gradle.model;
+
+import org.jetbrains.jps.model.JpsElement;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/10/2014
+ */
+public interface JpsGradleModuleExtension extends JpsElement {
+}
diff --git a/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/FilePattern.java b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/FilePattern.java
new file mode 100644
index 000000000000..98938f596d05
--- /dev/null
+++ b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/FilePattern.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.gradle.model.impl;
+
+import com.intellij.util.xmlb.annotations.AbstractCollection;
+import com.intellij.util.xmlb.annotations.Tag;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/10/2014
+ */
+public class FilePattern {
+
+ @Tag("includes")
+ @AbstractCollection(surroundWithTag = false, elementTag = "pattern")
+ public Set<String> includes = new HashSet<String>();
+
+ @Tag("excludes")
+ @AbstractCollection(surroundWithTag = false, elementTag = "pattern")
+ public Set<String> excludes = new HashSet<String>();
+
+}
diff --git a/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/GradleModuleResourceConfiguration.java b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/GradleModuleResourceConfiguration.java
new file mode 100644
index 000000000000..9b6732a6d5d5
--- /dev/null
+++ b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/GradleModuleResourceConfiguration.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.gradle.model.impl;
+
+import com.intellij.util.xmlb.annotations.AbstractCollection;
+import com.intellij.util.xmlb.annotations.OptionTag;
+import com.intellij.util.xmlb.annotations.Tag;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/10/2014
+ */
+public class GradleModuleResourceConfiguration {
+ @NotNull
+ @Tag("id")
+ public ModuleVersion id;
+
+ @Nullable
+ @Tag("parentId")
+ public ModuleVersion parentId;
+
+ @NotNull
+ @Tag("directory")
+ public String directory;
+
+ @OptionTag
+ public boolean overwrite;
+
+ @OptionTag
+ public String outputDirectory = null;
+
+ @Tag("resources")
+ @AbstractCollection(surroundWithTag = false, elementTag = "resource")
+ public List<ResourceRootConfiguration> resources = new ArrayList<ResourceRootConfiguration>();
+
+ @Tag("test-resources")
+ @AbstractCollection(surroundWithTag = false, elementTag = "resource")
+ public List<ResourceRootConfiguration> testResources = new ArrayList<ResourceRootConfiguration>();
+
+ public int computeConfigurationHash(boolean forTestResources) {
+ int result = computeModuleConfigurationHash();
+
+ final List<ResourceRootConfiguration> _resources = forTestResources ? testResources : resources;
+ result = 31 * result;
+ for (ResourceRootConfiguration resource : _resources) {
+ result += resource.computeConfigurationHash();
+ }
+ return result;
+ }
+
+ public int computeModuleConfigurationHash() {
+ int result = id.hashCode();
+ result = 31 * result + (parentId != null ? parentId.hashCode() : 0);
+ result = 31 * result + directory.hashCode();
+ result = 31 * result + (outputDirectory != null ? outputDirectory.hashCode() : 0);
+ result = 31 * result + (overwrite ? 1 : 0);
+ return result;
+ }
+}
+
+
+
diff --git a/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/GradleProjectConfiguration.java b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/GradleProjectConfiguration.java
new file mode 100644
index 000000000000..083bba570d8a
--- /dev/null
+++ b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/GradleProjectConfiguration.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.gradle.model.impl;
+
+import com.intellij.util.xmlb.annotations.MapAnnotation;
+import com.intellij.util.xmlb.annotations.Tag;
+import gnu.trove.THashMap;
+
+import java.util.Map;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/10/2014
+ */
+public class GradleProjectConfiguration {
+ public static final String CONFIGURATION_FILE_RELATIVE_PATH = "gradle/configuration.xml";
+
+ @Tag("resource-processing")
+ @MapAnnotation(surroundWithTag = false, surroundKeyWithTag = false, surroundValueWithTag = false, entryTagName = "gradle-module",
+ keyAttributeName = "name")
+ public Map<String, GradleModuleResourceConfiguration> moduleConfigurations = new THashMap<String, GradleModuleResourceConfiguration>();
+}
diff --git a/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/GradleResourceFileFilter.java b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/GradleResourceFileFilter.java
new file mode 100644
index 000000000000..60e7fd295daa
--- /dev/null
+++ b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/GradleResourceFileFilter.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.gradle.model.impl;
+
+import com.intellij.openapi.util.io.FileUtil;
+import org.gradle.api.file.RelativePath;
+import org.gradle.api.internal.file.pattern.PatternMatcherFactory;
+import org.gradle.api.specs.Spec;
+import org.gradle.api.specs.Specs;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.regex.Pattern;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/10/2014
+ */
+public class GradleResourceFileFilter implements FileFilter {
+ private FilePattern myFilePattern;
+ private File myRoot;
+ private final Spec<RelativePath> myFileFilterSpec;
+
+ public GradleResourceFileFilter(@NotNull File rootFile, @NotNull FilePattern filePattern) {
+ myFilePattern = filePattern;
+ myRoot = rootFile;
+ myFileFilterSpec = getAsSpec();
+ }
+
+ @Override
+ public boolean accept(@NotNull File file) {
+ final String relPath = FileUtil.getRelativePath(myRoot, file);
+ return relPath != null && isIncluded(relPath);
+ }
+
+ private boolean isIncluded(@NotNull String relativePath) {
+ RelativePath path = new RelativePath(true, relativePath.split(Pattern.quote(File.separator)));
+ return myFileFilterSpec.isSatisfiedBy(path);
+ }
+
+ private Spec<RelativePath> getAsSpec() {
+ return Specs.and(getAsIncludeSpec(true), Specs.not(getAsExcludeSpec(true)));
+ }
+
+ private Spec<RelativePath> getAsExcludeSpec(boolean caseSensitive) {
+ Collection<String> allExcludes = new LinkedHashSet<String>(myFilePattern.excludes);
+ List<Spec<RelativePath>> matchers = new ArrayList<Spec<RelativePath>>();
+ for (String exclude : allExcludes) {
+ Spec<RelativePath> patternMatcher = PatternMatcherFactory.getPatternMatcher(false, caseSensitive, exclude);
+ matchers.add(patternMatcher);
+ }
+ return Specs.or(false, matchers);
+ }
+
+ private Spec<RelativePath> getAsIncludeSpec(boolean caseSensitive) {
+ List<Spec<RelativePath>> matchers = new ArrayList<Spec<RelativePath>>();
+ for (String include : myFilePattern.includes) {
+ Spec<RelativePath> patternMatcher = PatternMatcherFactory.getPatternMatcher(true, caseSensitive, include);
+ matchers.add(patternMatcher);
+ }
+ return Specs.or(true, matchers);
+ }
+} \ No newline at end of file
diff --git a/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/GradleResourceRootDescriptor.java b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/GradleResourceRootDescriptor.java
new file mode 100644
index 000000000000..e8ae0d701200
--- /dev/null
+++ b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/GradleResourceRootDescriptor.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.gradle.model.impl;
+
+import com.intellij.openapi.util.io.FileUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.builders.BuildRootDescriptor;
+
+import java.io.File;
+import java.io.FileFilter;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/10/2014
+ */
+public class GradleResourceRootDescriptor extends BuildRootDescriptor {
+ private final GradleResourcesTarget myTarget;
+ private final ResourceRootConfiguration myConfig;
+ private final File myFile;
+ private final String myId;
+ private final boolean myOverwrite;
+
+ private final int myIndexInPom;
+
+ public GradleResourceRootDescriptor(@NotNull GradleResourcesTarget target,
+ ResourceRootConfiguration config,
+ int indexInPom,
+ boolean overwrite) {
+ myTarget = target;
+ myConfig = config;
+ final String path = FileUtil.toCanonicalPath(config.directory);
+ myFile = new File(path);
+ myId = path;
+ myIndexInPom = indexInPom;
+ myOverwrite = overwrite;
+ }
+
+ public ResourceRootConfiguration getConfiguration() {
+ return myConfig;
+ }
+
+ @Override
+ public String getRootId() {
+ return myId;
+ }
+
+ @Override
+ public File getRootFile() {
+ return myFile;
+ }
+
+ @Override
+ public GradleResourcesTarget getTarget() {
+ return myTarget;
+ }
+
+ @NotNull
+ @Override
+ public FileFilter createFileFilter() {
+ return new GradleResourceFileFilter(myFile, myConfig);
+ }
+
+ @Override
+ public boolean canUseFileCache() {
+ return true;
+ }
+
+ public int getIndexInPom() {
+ return myIndexInPom;
+ }
+
+ public boolean isOverwrite() {
+ return myOverwrite;
+ }
+}
diff --git a/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/GradleResourcesTarget.java b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/GradleResourcesTarget.java
new file mode 100644
index 000000000000..344c83080186
--- /dev/null
+++ b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/GradleResourcesTarget.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.gradle.model.impl;
+
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import gnu.trove.THashSet;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.builders.*;
+import org.jetbrains.jps.builders.storage.BuildDataPaths;
+import org.jetbrains.jps.cmdline.ProjectDescriptor;
+import org.jetbrains.jps.gradle.model.JpsGradleExtensionService;
+import org.jetbrains.jps.incremental.CompileContext;
+import org.jetbrains.jps.indices.IgnoredFileIndex;
+import org.jetbrains.jps.indices.ModuleExcludeIndex;
+import org.jetbrains.jps.model.JpsModel;
+import org.jetbrains.jps.model.java.JpsJavaExtensionService;
+import org.jetbrains.jps.model.module.JpsModule;
+import org.jetbrains.jps.util.JpsPathUtil;
+
+import java.io.File;
+import java.io.PrintWriter;
+import java.util.*;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/10/2014
+ */
+public class GradleResourcesTarget extends ModuleBasedTarget<GradleResourceRootDescriptor> {
+
+ GradleResourcesTarget(final GradleResourcesTargetType type, @NotNull JpsModule module) {
+ super(type, module);
+ }
+
+ @Override
+ public String getId() {
+ return myModule.getName();
+ }
+
+ @Override
+ public Collection<BuildTarget<?>> computeDependencies(BuildTargetRegistry targetRegistry, TargetOutputIndex outputIndex) {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public boolean isCompiledBeforeModuleLevelBuilders() {
+ return true;
+ }
+
+ @NotNull
+ @Override
+ public List<GradleResourceRootDescriptor> computeRootDescriptors(JpsModel model, ModuleExcludeIndex index, IgnoredFileIndex ignoredFileIndex, BuildDataPaths dataPaths) {
+ final List<GradleResourceRootDescriptor> result = new ArrayList<GradleResourceRootDescriptor>();
+
+ GradleProjectConfiguration projectConfig = JpsGradleExtensionService.getInstance().getGradleProjectConfiguration(dataPaths);
+ GradleModuleResourceConfiguration moduleConfig = projectConfig.moduleConfigurations.get(myModule.getName());
+ if (moduleConfig == null) return Collections.emptyList();
+
+ int i = 0;
+
+ for (ResourceRootConfiguration resource : getRootConfigurations(moduleConfig)) {
+ result.add(new GradleResourceRootDescriptor(this, resource, i++, moduleConfig.overwrite));
+ }
+ return result;
+ }
+
+ private Collection<ResourceRootConfiguration> getRootConfigurations(@Nullable GradleModuleResourceConfiguration moduleConfig) {
+ if (moduleConfig != null) {
+ return isTests() ? moduleConfig.testResources : moduleConfig.resources;
+ }
+ return Collections.emptyList();
+ }
+
+ public GradleModuleResourceConfiguration getModuleResourcesConfiguration(BuildDataPaths dataPaths) {
+ final GradleProjectConfiguration projectConfig = JpsGradleExtensionService.getInstance().getGradleProjectConfiguration(dataPaths);
+ return projectConfig.moduleConfigurations.get(myModule.getName());
+ }
+
+ public boolean isTests() {
+ return ((GradleResourcesTargetType)getTargetType()).isTests();
+ }
+
+ @Nullable
+ @Override
+ public GradleResourceRootDescriptor findRootDescriptor(String rootId, BuildRootIndex rootIndex) {
+ for (GradleResourceRootDescriptor descriptor : rootIndex.getTargetRoots(this, null)) {
+ if (descriptor.getRootId().equals(rootId)) {
+ return descriptor;
+ }
+ }
+ return null;
+ }
+
+ @NotNull
+ @Override
+ public String getPresentableName() {
+ return getTargetType().getTypeId() + ":" + myModule.getName();
+ }
+
+ @NotNull
+ @Override
+ public Collection<File> getOutputRoots(CompileContext context) {
+ GradleModuleResourceConfiguration configuration =
+ getModuleResourcesConfiguration(context.getProjectDescriptor().dataManager.getDataPaths());
+ final Set<File> result = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);
+ final File moduleOutput = getModuleOutputDir();
+ for (ResourceRootConfiguration resConfig : getRootConfigurations(configuration)) {
+ final File output = getOutputDir(moduleOutput, resConfig, configuration.outputDirectory);
+ if (output != null) {
+ result.add(output);
+ }
+ }
+ return result;
+ }
+
+ @Nullable
+ public File getModuleOutputDir() {
+ return JpsJavaExtensionService.getInstance().getOutputDirectory(myModule, isTests());
+ }
+
+ @Nullable
+ public static File getOutputDir(@Nullable File moduleOutput, ResourceRootConfiguration config, @Nullable String outputDirectory) {
+ if(outputDirectory != null) {
+ moduleOutput = JpsPathUtil.urlToFile(outputDirectory);
+ }
+
+ if (moduleOutput == null) {
+ return null;
+ }
+ String targetPath = config.targetPath;
+ if (StringUtil.isEmptyOrSpaces(targetPath)) {
+ return moduleOutput;
+ }
+ final File targetPathFile = new File(targetPath);
+ final File outputFile = targetPathFile.isAbsolute() ? targetPathFile : new File(moduleOutput, targetPath);
+ return new File(FileUtil.toCanonicalPath(outputFile.getPath()));
+ }
+
+ @Override
+ public void writeConfiguration(ProjectDescriptor pd, PrintWriter out) {
+ final BuildDataPaths dataPaths = pd.getTargetsState().getDataPaths();
+ final GradleModuleResourceConfiguration configuration = getModuleResourcesConfiguration(dataPaths);
+ if (configuration != null) {
+ out.write(Integer.toHexString(configuration.computeConfigurationHash(isTests())));
+ }
+ }
+}
diff --git a/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/GradleResourcesTargetType.java b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/GradleResourcesTargetType.java
new file mode 100644
index 000000000000..bd399a164d31
--- /dev/null
+++ b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/GradleResourcesTargetType.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.gradle.model.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.builders.BuildTargetLoader;
+import org.jetbrains.jps.builders.ModuleBasedBuildTargetType;
+import org.jetbrains.jps.gradle.model.JpsGradleExtensionService;
+import org.jetbrains.jps.model.JpsModel;
+import org.jetbrains.jps.model.module.JpsModule;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/10/2014
+ */
+public class GradleResourcesTargetType extends ModuleBasedBuildTargetType<GradleResourcesTarget> {
+ public static final GradleResourcesTargetType PRODUCTION = new GradleResourcesTargetType("gradle-resources-production", false);
+ public static final GradleResourcesTargetType TEST = new GradleResourcesTargetType("gradle-resources-test", true);
+
+ private final boolean myIsTests;
+
+ private GradleResourcesTargetType(final String typeId, boolean isTests) {
+ super(typeId);
+ myIsTests = isTests;
+ }
+
+ public boolean isTests() {
+ return myIsTests;
+ }
+
+ @NotNull
+ @Override
+ public List<GradleResourcesTarget> computeAllTargets(@NotNull JpsModel model) {
+ final List<GradleResourcesTarget> targets = new ArrayList<GradleResourcesTarget>();
+ for (JpsModule module : model.getProject().getModules()) {
+ if (JpsGradleExtensionService.getInstance().getExtension(module) != null) {
+ targets.add(new GradleResourcesTarget(this, module));
+ }
+ }
+ return targets;
+ }
+
+ @NotNull
+ @Override
+ public BuildTargetLoader<GradleResourcesTarget> createLoader(@NotNull JpsModel model) {
+ final Map<String, JpsModule> modules = new HashMap<String, JpsModule>();
+ for (JpsModule module : model.getProject().getModules()) {
+ modules.put(module.getName(), module);
+ }
+ return new BuildTargetLoader<GradleResourcesTarget>() {
+ @Nullable
+ @Override
+ public GradleResourcesTarget createTarget(@NotNull String targetId) {
+ final JpsModule module = modules.get(targetId);
+ return module != null ? new GradleResourcesTarget(GradleResourcesTargetType.this, module) : null;
+ }
+ };
+ }
+}
diff --git a/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/JpsGradleDependenciesEnumerationHandler.java b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/JpsGradleDependenciesEnumerationHandler.java
new file mode 100644
index 000000000000..af0fd08fb6cf
--- /dev/null
+++ b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/JpsGradleDependenciesEnumerationHandler.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.gradle.model.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.gradle.model.JpsGradleExtensionService;
+import org.jetbrains.jps.model.java.impl.JpsJavaDependenciesEnumerationHandler;
+import org.jetbrains.jps.model.module.JpsDependencyElement;
+import org.jetbrains.jps.model.module.JpsModule;
+
+import java.util.Collection;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/10/2014
+ */
+public class JpsGradleDependenciesEnumerationHandler extends JpsJavaDependenciesEnumerationHandler {
+ private static final JpsGradleDependenciesEnumerationHandler INSTANCE = new JpsGradleDependenciesEnumerationHandler();
+
+ @Override
+ public boolean shouldAddRuntimeDependenciesToTestCompilationClasspath() {
+ return true;
+ }
+
+ @Override
+ public boolean isProductionOnTestsDependency(JpsDependencyElement element) {
+ return JpsGradleExtensionService.getInstance().isProductionOnTestDependency(element);
+ }
+
+ public static class GradleFactory extends Factory {
+ @Nullable
+ @Override
+ public JpsJavaDependenciesEnumerationHandler createHandler(@NotNull Collection<JpsModule> modules) {
+ JpsGradleExtensionService service = JpsGradleExtensionService.getInstance();
+ for (JpsModule module : modules) {
+ if (service.getExtension(module) != null) {
+ return INSTANCE;
+ }
+ }
+ return null;
+ }
+ }
+}
diff --git a/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/JpsGradleExtensionServiceImpl.java b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/JpsGradleExtensionServiceImpl.java
new file mode 100644
index 000000000000..81ed9076f13e
--- /dev/null
+++ b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/JpsGradleExtensionServiceImpl.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.gradle.model.impl;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.JDOMUtil;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.util.containers.ConcurrentFactoryMap;
+import com.intellij.util.containers.FactoryMap;
+import com.intellij.util.xmlb.XmlSerializer;
+import gnu.trove.THashMap;
+import org.jdom.Document;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.builders.storage.BuildDataPaths;
+import org.jetbrains.jps.gradle.model.JpsGradleExtensionService;
+import org.jetbrains.jps.gradle.model.JpsGradleModuleExtension;
+import org.jetbrains.jps.incremental.resources.ResourcesBuilder;
+import org.jetbrains.jps.incremental.resources.StandardResourceBuilderEnabler;
+import org.jetbrains.jps.model.JpsElementChildRole;
+import org.jetbrains.jps.model.JpsElementFactory;
+import org.jetbrains.jps.model.JpsSimpleElement;
+import org.jetbrains.jps.model.ex.JpsElementChildRoleBase;
+import org.jetbrains.jps.model.module.JpsDependencyElement;
+import org.jetbrains.jps.model.module.JpsModule;
+
+import java.io.File;
+import java.util.Map;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/10/2014
+ */
+public class JpsGradleExtensionServiceImpl extends JpsGradleExtensionService {
+ private static final Logger LOG = Logger.getInstance(JpsGradleExtensionServiceImpl.class);
+ private static final JpsElementChildRole<JpsSimpleElement<Boolean>> PRODUCTION_ON_TEST_ROLE = JpsElementChildRoleBase.create("production on test");
+ private final Map<File, GradleProjectConfiguration> myLoadedConfigs =
+ new THashMap<File, GradleProjectConfiguration>(FileUtil.FILE_HASHING_STRATEGY);
+ private final FactoryMap<File, Boolean> myConfigFileExists = new ConcurrentFactoryMap<File, Boolean>() {
+ @Nullable
+ @Override
+ protected Boolean create(File key) {
+ return key.exists();
+ }
+ };
+
+ public JpsGradleExtensionServiceImpl() {
+ ResourcesBuilder.registerEnabler(new StandardResourceBuilderEnabler() {
+ @Override
+ public boolean isResourceProcessingEnabled(JpsModule module) {
+ // enable standard resource processing only if this is not a gradle module
+ // for gradle modules use gradle-aware resource builder
+ return getExtension(module) == null;
+ }
+ });
+ }
+
+ @Nullable
+ @Override
+ public JpsGradleModuleExtension getExtension(@NotNull JpsModule module) {
+ return module.getContainer().getChild(JpsGradleModuleExtensionImpl.ROLE);
+ }
+
+ @NotNull
+ @Override
+ public JpsGradleModuleExtension getOrCreateExtension(@NotNull JpsModule module) {
+ JpsGradleModuleExtension extension = module.getContainer().getChild(JpsGradleModuleExtensionImpl.ROLE);
+ if (extension == null) {
+ extension = new JpsGradleModuleExtensionImpl();
+ module.getContainer().setChild(JpsGradleModuleExtensionImpl.ROLE, extension);
+ }
+ return extension;
+ }
+
+ @Override
+ public void setProductionOnTestDependency(@NotNull JpsDependencyElement dependency, boolean value) {
+ if (value) {
+ dependency.getContainer().setChild(PRODUCTION_ON_TEST_ROLE, JpsElementFactory.getInstance().createSimpleElement(true));
+ }
+ else {
+ dependency.getContainer().removeChild(PRODUCTION_ON_TEST_ROLE);
+ }
+ }
+
+ @Override
+ public boolean isProductionOnTestDependency(@NotNull JpsDependencyElement dependency) {
+ JpsSimpleElement<Boolean> child = dependency.getContainer().getChild(PRODUCTION_ON_TEST_ROLE);
+ return child != null && child.getData();
+ }
+
+ @Override
+ public boolean hasGradleProjectConfiguration(@NotNull BuildDataPaths paths) {
+ return myConfigFileExists.get(new File(paths.getDataStorageRoot(), GradleProjectConfiguration.CONFIGURATION_FILE_RELATIVE_PATH));
+ }
+
+ @NotNull
+ @Override
+ public GradleProjectConfiguration getGradleProjectConfiguration(BuildDataPaths paths) {
+ final File dataStorageRoot = paths.getDataStorageRoot();
+ return getGradleProjectConfiguration(dataStorageRoot);
+ }
+
+ @NotNull
+ public GradleProjectConfiguration getGradleProjectConfiguration(@NotNull File dataStorageRoot) {
+ final File configFile = new File(dataStorageRoot, GradleProjectConfiguration.CONFIGURATION_FILE_RELATIVE_PATH);
+ GradleProjectConfiguration config;
+ synchronized (myLoadedConfigs) {
+ config = myLoadedConfigs.get(configFile);
+ if (config == null) {
+ config = new GradleProjectConfiguration();
+ try {
+ final Document document = JDOMUtil.loadDocument(configFile);
+ XmlSerializer.deserializeInto(config, document.getRootElement());
+ }
+ catch (Exception e) {
+ LOG.info(e);
+ }
+ myLoadedConfigs.put(configFile, config);
+ }
+ }
+ return config;
+ }
+}
diff --git a/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/JpsGradleModelSerializationExtension.java b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/JpsGradleModelSerializationExtension.java
new file mode 100644
index 000000000000..cebd00878b19
--- /dev/null
+++ b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/JpsGradleModelSerializationExtension.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.gradle.model.impl;
+
+import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.gradle.model.JpsGradleExtensionService;
+import org.jetbrains.jps.model.module.JpsDependencyElement;
+import org.jetbrains.jps.model.module.JpsModule;
+import org.jetbrains.jps.model.serialization.JpsModelSerializerExtension;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/10/2014
+ */
+public class JpsGradleModelSerializationExtension extends JpsModelSerializerExtension {
+ private static final String PRODUCTION_ON_TEST_ATTRIBUTE = "production-on-test";
+
+ @Override
+ public void loadModuleOptions(@NotNull JpsModule module, @NotNull Element rootElement) {
+ if ("GRADLE".equals(rootElement.getAttributeValue("external.system.id"))) {
+ JpsGradleExtensionService.getInstance().getOrCreateExtension(module);
+ }
+ }
+
+ @Override
+ public void saveModuleOptions(@NotNull JpsModule module, @NotNull Element rootElement) {
+ if (JpsGradleExtensionService.getInstance().getExtension(module) != null) {
+ rootElement.setAttribute("external.system.id", "GRADLE");
+ }
+ }
+
+ @Override
+ public void loadModuleDependencyProperties(JpsDependencyElement dependency, Element orderEntry) {
+ if (orderEntry.getAttributeValue(PRODUCTION_ON_TEST_ATTRIBUTE) != null) {
+ JpsGradleExtensionService.getInstance().setProductionOnTestDependency(dependency, true);
+ }
+ }
+
+ @Override
+ public void saveModuleDependencyProperties(JpsDependencyElement dependency, Element orderEntry) {
+ if (JpsGradleExtensionService.getInstance().isProductionOnTestDependency(dependency)) {
+ orderEntry.setAttribute(PRODUCTION_ON_TEST_ATTRIBUTE, "");
+ }
+ }
+}
diff --git a/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/JpsGradleModuleExtensionImpl.java b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/JpsGradleModuleExtensionImpl.java
new file mode 100644
index 000000000000..ecdd04fce10e
--- /dev/null
+++ b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/JpsGradleModuleExtensionImpl.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.gradle.model.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.gradle.model.JpsGradleModuleExtension;
+import org.jetbrains.jps.model.JpsElementChildRole;
+import org.jetbrains.jps.model.ex.JpsElementBase;
+import org.jetbrains.jps.model.ex.JpsElementChildRoleBase;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/10/2014
+ */
+public class JpsGradleModuleExtensionImpl extends JpsElementBase<JpsGradleModuleExtensionImpl> implements JpsGradleModuleExtension {
+ public static final JpsElementChildRole<JpsGradleModuleExtension> ROLE = JpsElementChildRoleBase.create("gradle");
+
+ public JpsGradleModuleExtensionImpl() {
+ }
+
+ @NotNull
+ @Override
+ public JpsGradleModuleExtensionImpl createCopy() {
+ return new JpsGradleModuleExtensionImpl();
+ }
+
+ @Override
+ public void applyChanges(@NotNull JpsGradleModuleExtensionImpl modified) {
+ }
+}
diff --git a/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/ModuleVersion.java b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/ModuleVersion.java
new file mode 100644
index 000000000000..dbb696d8c33c
--- /dev/null
+++ b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/ModuleVersion.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.gradle.model.impl;
+
+import com.intellij.util.xmlb.annotations.Tag;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/10/2014
+ */
+public class ModuleVersion {
+ @Tag("groupId")
+ public String groupId;
+
+ @Tag("artifactId")
+ public String artifactId;
+
+ @Tag("version")
+ public String version;
+
+ public ModuleVersion() {
+ }
+
+ public ModuleVersion(String groupId, String artifactId, String version) {
+ this.groupId = groupId;
+ this.artifactId = artifactId;
+ this.version = version;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ ModuleVersion bean = (ModuleVersion)o;
+
+ if (artifactId != null ? !artifactId.equals(bean.artifactId) : bean.artifactId != null) return false;
+ if (groupId != null ? !groupId.equals(bean.groupId) : bean.groupId != null) return false;
+ if (version != null ? !version.equals(bean.version) : bean.version != null) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = groupId != null ? groupId.hashCode() : 0;
+ result = 31 * result + (artifactId != null ? artifactId.hashCode() : 0);
+ result = 31 * result + (version != null ? version.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/ResourceRootConfiguration.java b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/ResourceRootConfiguration.java
new file mode 100644
index 000000000000..efd419175dc3
--- /dev/null
+++ b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/ResourceRootConfiguration.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.gradle.model.impl;
+
+import com.intellij.util.xmlb.annotations.AbstractCollection;
+import com.intellij.util.xmlb.annotations.Attribute;
+import com.intellij.util.xmlb.annotations.Tag;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/10/2014
+ */
+@Tag("resource")
+public class ResourceRootConfiguration extends FilePattern {
+ @Tag("directory")
+ @NotNull
+ public String directory;
+
+ @Tag("targetPath")
+ @Nullable
+ public String targetPath;
+
+ @Attribute("filtered")
+ public boolean isFiltered;
+
+ @Tag("filters")
+ @AbstractCollection(surroundWithTag = false, elementTag = "filter")
+ public List<ResourceRootFilter> filters = new ArrayList<ResourceRootFilter>();
+
+ public int computeConfigurationHash() {
+ int result = directory.hashCode();
+ result = 31 * result + (targetPath != null ? targetPath.hashCode() : 0);
+ result = 31 * result + (isFiltered ? 1 : 0);
+ result = 31 * result + includes.hashCode();
+ result = 31 * result + excludes.hashCode();
+ for (ResourceRootFilter filter : filters) {
+ result = 31 * result + filter.computeConfigurationHash();
+ }
+ return result;
+ }
+}
diff --git a/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/ResourceRootFilter.java b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/ResourceRootFilter.java
new file mode 100644
index 000000000000..e8c39e32417e
--- /dev/null
+++ b/plugins/gradle/jps-plugin/src/org/jetbrains/jps/gradle/model/impl/ResourceRootFilter.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.gradle.model.impl;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonParseException;
+import com.google.gson.JsonSyntaxException;
+import com.google.gson.reflect.TypeToken;
+import com.intellij.util.xmlb.annotations.Tag;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/22/2014
+ */
+@Tag("filter")
+public class ResourceRootFilter {
+ @Tag("filterType")
+ @NotNull
+ public String filterType;
+ @Tag("properties")
+ @NotNull
+ public String properties;
+
+ private transient Map<Object, Object> propertiesMap;
+
+ public int computeConfigurationHash() {
+ int result = filterType.hashCode();
+ result = 31 * result + properties.hashCode();
+ return result;
+ }
+
+ @NotNull
+ public Map<Object, Object> getProperties() {
+ if (propertiesMap == null) {
+ try {
+ Gson gson = new GsonBuilder().create();
+ propertiesMap = gson.fromJson(
+ properties,
+ new TypeToken<Map<Object, Object>>() {
+ }.getType());
+
+ if("RenamingCopyFilter".equals(filterType)) {
+ final Object pattern = propertiesMap.get("pattern");
+ final Matcher matcher = Pattern.compile(pattern instanceof String ? (String)pattern : "").matcher("");
+ propertiesMap.put("matcher", matcher);
+ }
+ }
+ catch (JsonSyntaxException e) {
+ throw new RuntimeException("Unsupported filter: " + properties , e);
+ } catch (JsonParseException e) {
+ throw new RuntimeException("Unsupported filter: " + properties , e);
+ }
+ }
+ return propertiesMap;
+ }
+}
diff --git a/plugins/gradle/src/META-INF/gradle-maven-integration.xml b/plugins/gradle/src/META-INF/gradle-maven-integration.xml
index 72f46b785ea7..b8fad2f5c3be 100644
--- a/plugins/gradle/src/META-INF/gradle-maven-integration.xml
+++ b/plugins/gradle/src/META-INF/gradle-maven-integration.xml
@@ -21,7 +21,6 @@
<postStartupActivity implementation="org.jetbrains.plugins.gradle.integrations.maven.GradleProjectStartupActivity"/>
<externalSystemTaskNotificationListener
implementation="org.jetbrains.plugins.gradle.integrations.maven.GradleMavenProjectImportNotificationListener"/>
- <externalProjectDataService implementation="com.intellij.openapi.externalSystem.service.project.manage.ModuleDataService"/>
<completion.contributor language="Groovy" order="first"
implementationClass="org.jetbrains.plugins.gradle.integrations.maven.codeInsight.completion.MavenDependenciesGradleCompletionContributor"/>
</extensions>
diff --git a/plugins/gradle/src/META-INF/plugin.xml b/plugins/gradle/src/META-INF/plugin.xml
index de6937c18c6c..f15f424a10b8 100644
--- a/plugins/gradle/src/META-INF/plugin.xml
+++ b/plugins/gradle/src/META-INF/plugin.xml
@@ -67,6 +67,11 @@
<extensions defaultExtensionNs="com.intellij">
<postStartupActivity implementation="org.jetbrains.plugins.gradle.service.project.GradleStartupActivity"/>
+
+ <orderEnumerationHandlerFactory implementation="org.jetbrains.plugins.gradle.execution.GradleOrderEnumeratorHandler$FactoryImpl"/>
+ <compileServer.plugin classpath="gradle-jps-plugin.jar"/>
+ <buildProcess.parametersProvider implementation="org.jetbrains.plugins.gradle.compiler.GradleBuildProcessParametersProvider"/>
+
<resolveScopeEnlarger implementation="org.jetbrains.plugins.gradle.config.GradleBuildClasspathResolveScopeEnlarger"/>
<errorHandler implementation="com.intellij.diagnostic.ITNReporter"/>
@@ -95,6 +100,7 @@
<externalSystemConfigLocator implementation="org.jetbrains.plugins.gradle.service.settings.GradleConfigLocator"/>
<externalSystemManager implementation="org.jetbrains.plugins.gradle.GradleManager"/>
<externalProjectDataService implementation="org.jetbrains.plugins.gradle.service.project.data.BuildClasspathModuleGradleDataService"/>
+ <externalProjectDataService implementation="org.jetbrains.plugins.gradle.service.project.data.ExternalProjectDataService"/>
<externalSystemNotificationExtension implementation="org.jetbrains.plugins.gradle.service.notification.GradleNotificationExtension" order="last"/>
<externalSystemTaskNotificationListener implementation="org.jetbrains.plugins.gradle.service.project.GradleProjectImportNotificationListener"/>
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/compiler/GradleBuildProcessParametersProvider.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/compiler/GradleBuildProcessParametersProvider.java
new file mode 100644
index 000000000000..4337686235f5
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/compiler/GradleBuildProcessParametersProvider.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.plugins.gradle.compiler;
+
+import com.google.gson.Gson;
+import com.intellij.compiler.server.BuildProcessParametersProvider;
+import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.PathUtil;
+import com.intellij.util.containers.ContainerUtil;
+import groovy.lang.GroovyObject;
+import org.apache.tools.ant.taskdefs.Ant;
+import org.gradle.tooling.ProjectConnection;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.gradle.util.GradleConstants;
+
+import java.io.File;
+import java.util.List;
+
+/**
+ * Adds Gradle build dependencies to the project build process' classpath.
+ *
+ * @author Vladislav.Soroka
+ * @since 7/22/2014
+ */
+public class GradleBuildProcessParametersProvider extends BuildProcessParametersProvider {
+ @NotNull private final Project myProject;
+
+ private List<String> myClasspath;
+
+ public GradleBuildProcessParametersProvider(@NotNull Project project) {
+ myProject = project;
+ }
+
+ @Override
+ @NotNull
+ public List<String> getClassPath() {
+ if (myClasspath == null) {
+ myClasspath = ContainerUtil.newArrayList();
+ addGradleClassPath(myClasspath);
+ final ModuleManager moduleManager = ModuleManager.getInstance(myProject);
+ for (Module module : moduleManager.getModules()) {
+ if (ExternalSystemApiUtil.isExternalSystemAwareModule(GradleConstants.SYSTEM_ID, module)) {
+ addOtherClassPath(myClasspath);
+ break;
+ }
+ }
+ }
+ return myClasspath;
+ }
+
+ private static void addGradleClassPath(@NotNull final List<String> classpath) {
+ String gradleLibDirPath = null;
+ String gradleToolingApiJarPath = PathUtil.getJarPathForClass(ProjectConnection.class);
+ if (!StringUtil.isEmpty(gradleToolingApiJarPath)) {
+ gradleLibDirPath = PathUtil.getParentPath(gradleToolingApiJarPath);
+ }
+ if (gradleLibDirPath == null || gradleLibDirPath.isEmpty()) return;
+
+ File gradleLibDir = new File(gradleLibDirPath);
+ if (!gradleLibDir.isDirectory()) return;
+
+ File[] children = FileUtil.notNullize(gradleLibDir.listFiles());
+ for (File child : children) {
+ if (child.isFile() && child.getName().endsWith(".jar")) {
+ classpath.add(child.getAbsolutePath());
+ }
+ }
+ }
+
+ private static void addOtherClassPath(@NotNull final List<String> classpath) {
+ classpath.add(PathUtil.getJarPathForClass(Ant.class));
+ classpath.add(PathUtil.getJarPathForClass(GroovyObject.class));
+ classpath.add(PathUtil.getJarPathForClass(Gson.class));
+ }
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleResourceCompilerConfigurationGenerator.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleResourceCompilerConfigurationGenerator.java
new file mode 100644
index 000000000000..01c5275f3828
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleResourceCompilerConfigurationGenerator.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.plugins.gradle.config;
+
+import com.intellij.compiler.server.BuildManager;
+import com.intellij.openapi.compiler.CompileContext;
+import com.intellij.openapi.compiler.CompilerMessageCategory;
+import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.externalSystem.model.ExternalFilter;
+import com.intellij.openapi.externalSystem.model.ExternalProject;
+import com.intellij.openapi.externalSystem.model.ExternalSourceDirectorySet;
+import com.intellij.openapi.externalSystem.model.ExternalSourceSet;
+import com.intellij.openapi.externalSystem.model.project.ExternalSystemSourceType;
+import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager;
+import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
+import com.intellij.openapi.externalSystem.util.ExternalSystemConstants;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.CompilerModuleExtension;
+import com.intellij.openapi.util.JDOMUtil;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.vfs.VfsUtilCore;
+import com.intellij.util.containers.FactoryMap;
+import com.intellij.util.xmlb.XmlSerializer;
+import org.jdom.Document;
+import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.gradle.model.impl.*;
+import org.jetbrains.plugins.gradle.service.project.data.ExternalProjectDataService;
+import org.jetbrains.plugins.gradle.util.GradleConstants;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/10/2014
+ */
+public class GradleResourceCompilerConfigurationGenerator {
+
+ private static Logger LOG = Logger.getInstance(GradleResourceCompilerConfigurationGenerator.class);
+
+ @NotNull private final Project myProject;
+ @NotNull private final CompileContext myContext;
+ @NotNull private final Map<String, ExternalProject> myExternalProjectMap;
+ private final ExternalProjectDataService myExternalProjectDataService;
+
+ public GradleResourceCompilerConfigurationGenerator(@NotNull final Project project, @NotNull final CompileContext context) {
+ myProject = project;
+ myContext = context;
+ myExternalProjectDataService =
+ (ExternalProjectDataService)ServiceManager.getService(ProjectDataManager.class).getDataService(ExternalProjectDataService.KEY);
+ assert myExternalProjectDataService != null;
+
+ myExternalProjectMap = new FactoryMap<String, ExternalProject>() {
+ @Nullable
+ @Override
+ protected ExternalProject create(String gradleProjectPath) {
+ return myExternalProjectDataService.getOrImportRootExternalProject(project, GradleConstants.SYSTEM_ID, new File(gradleProjectPath));
+ }
+ };
+ }
+
+ public void generateBuildConfiguration() {
+ if (!hasGradleModules()) return;
+
+ final BuildManager buildManager = BuildManager.getInstance();
+ final File projectSystemDir = buildManager.getProjectSystemDirectory(myProject);
+ if (projectSystemDir == null) return;
+
+ final File gradleConfigFile = new File(projectSystemDir, GradleProjectConfiguration.CONFIGURATION_FILE_RELATIVE_PATH);
+
+ GradleProjectConfiguration projectConfig = new GradleProjectConfiguration();
+ for (Module module : myContext.getCompileScope().getAffectedModules()) {
+ if (!ExternalSystemApiUtil.isExternalSystemAwareModule(GradleConstants.SYSTEM_ID, module)) continue;
+
+ final String gradleProjectPath = module.getOptionValue(ExternalSystemConstants.ROOT_PROJECT_PATH_KEY);
+ assert gradleProjectPath != null;
+ final ExternalProject externalRootProject = myExternalProjectMap.get(gradleProjectPath);
+ if (externalRootProject == null) {
+ myContext.addMessage(CompilerMessageCategory.ERROR,
+ String.format("Unable to make the module: %s, related gradle module configuration was not imported",
+ module.getName()),
+ VfsUtilCore.pathToUrl(gradleProjectPath), -1, -1);
+ continue;
+ }
+
+ ExternalProject externalProject = myExternalProjectDataService.findExternalProject(externalRootProject, module);
+ if (externalProject == null) {
+ LOG.warn("Unable to find config for module: " + module.getName());
+ continue;
+ }
+
+ final CompilerModuleExtension compilerModuleExtension = CompilerModuleExtension.getInstance(module);
+ assert compilerModuleExtension != null;
+
+ GradleModuleResourceConfiguration resourceConfig = new GradleModuleResourceConfiguration();
+ resourceConfig.id = new ModuleVersion(externalProject.getGroup(), externalProject.getName(), externalProject.getVersion());
+ resourceConfig.directory = FileUtil.toSystemIndependentName(externalProject.getProjectDir().getPath());
+
+ final ExternalSourceSet mainSourcesSet = externalProject.getSourceSets().get("main");
+ addResources(resourceConfig.resources, mainSourcesSet, ExternalSystemSourceType.RESOURCE);
+
+ final ExternalSourceSet testSourcesSet = externalProject.getSourceSets().get("test");
+ addResources(resourceConfig.testResources, testSourcesSet, ExternalSystemSourceType.TEST_RESOURCE);
+
+ projectConfig.moduleConfigurations.put(module.getName(), resourceConfig);
+ }
+
+ final Document document = new Document(new Element("gradle-project-configuration"));
+ XmlSerializer.serializeInto(projectConfig, document.getRootElement());
+ buildManager.runCommand(new Runnable() {
+ @Override
+ public void run() {
+ buildManager.clearState(myProject);
+ FileUtil.createIfDoesntExist(gradleConfigFile);
+ try {
+ JDOMUtil.writeDocument(document, gradleConfigFile, "\n");
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
+ }
+
+ private boolean hasGradleModules() {
+ for (Module module : myContext.getCompileScope().getAffectedModules()) {
+ if (ExternalSystemApiUtil.isExternalSystemAwareModule(GradleConstants.SYSTEM_ID, module)) return true;
+ }
+ return false;
+ }
+
+ private static void addResources(@NotNull List<ResourceRootConfiguration> container,
+ @Nullable ExternalSourceSet externalSourceSet,
+ @NotNull ExternalSystemSourceType sourceType) {
+ if (externalSourceSet == null) return;
+ final ExternalSourceDirectorySet directorySet = externalSourceSet.getSources().get(sourceType);
+ if (directorySet == null) return;
+
+ for (File file : directorySet.getSrcDirs()) {
+ final String dir = file.getPath();
+ final ResourceRootConfiguration rootConfiguration = new ResourceRootConfiguration();
+ rootConfiguration.directory = FileUtil.toSystemIndependentName(dir);
+ final String target = directorySet.getOutputDir().getPath();
+ rootConfiguration.targetPath = FileUtil.toSystemIndependentName(target);
+
+ rootConfiguration.includes.clear();
+ for (String include : directorySet.getIncludes()) {
+ rootConfiguration.includes.add(include.trim());
+ }
+ rootConfiguration.excludes.clear();
+ for (String exclude : directorySet.getExcludes()) {
+ rootConfiguration.excludes.add(exclude.trim());
+ }
+
+ rootConfiguration.isFiltered = !directorySet.getFilters().isEmpty();
+ rootConfiguration.filters.clear();
+ for (ExternalFilter filter : directorySet.getFilters()) {
+ final ResourceRootFilter resourceRootFilter = new ResourceRootFilter();
+ resourceRootFilter.filterType = filter.getFilterType();
+ resourceRootFilter.properties = filter.getPropertiesAsJsonMap();
+ rootConfiguration.filters.add(resourceRootFilter);
+ }
+
+ container.add(rootConfiguration);
+ }
+ }
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/GradleOrderEnumeratorHandler.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/GradleOrderEnumeratorHandler.java
new file mode 100644
index 000000000000..113e49a61a25
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/GradleOrderEnumeratorHandler.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.plugins.gradle.execution;
+
+import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.externalSystem.model.ExternalProject;
+import com.intellij.openapi.externalSystem.model.ExternalSourceDirectorySet;
+import com.intellij.openapi.externalSystem.model.ExternalSourceSet;
+import com.intellij.openapi.externalSystem.model.project.ExternalSystemSourceType;
+import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager;
+import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
+import com.intellij.openapi.externalSystem.util.ExternalSystemConstants;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.ModuleRootModel;
+import com.intellij.openapi.roots.OrderEnumerationHandler;
+import com.intellij.openapi.roots.OrderRootType;
+import com.intellij.openapi.vfs.VfsUtilCore;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.gradle.service.project.data.ExternalProjectDataService;
+import org.jetbrains.plugins.gradle.util.GradleConstants;
+
+import java.io.File;
+import java.util.Collection;
+
+public class GradleOrderEnumeratorHandler extends OrderEnumerationHandler {
+ private static final Logger LOG = Logger.getInstance(GradleOrderEnumeratorHandler.class);
+
+ public static class FactoryImpl extends Factory {
+ @Override
+ public boolean isApplicable(@NotNull Project project) {
+ return true;
+ }
+
+ @Override
+ public boolean isApplicable(@NotNull Module module) {
+ return ExternalSystemApiUtil.isExternalSystemAwareModule(GradleConstants.SYSTEM_ID, module);
+ }
+
+ @Override
+ public OrderEnumerationHandler createHandler(@Nullable Module module) {
+ return INSTANCE;
+ }
+ }
+
+ private static final GradleOrderEnumeratorHandler INSTANCE = new GradleOrderEnumeratorHandler();
+
+ @Override
+ public boolean addCustomModuleRoots(@NotNull OrderRootType type,
+ @NotNull ModuleRootModel rootModel,
+ @NotNull Collection<String> result,
+ boolean includeProduction,
+ boolean includeTests) {
+ if (!type.equals(OrderRootType.CLASSES)) return false;
+ if (!ExternalSystemApiUtil.isExternalSystemAwareModule(GradleConstants.SYSTEM_ID, rootModel.getModule())) return false;
+
+ final String gradleProjectPath = rootModel.getModule().getOptionValue(ExternalSystemConstants.ROOT_PROJECT_PATH_KEY);
+ if (gradleProjectPath == null) {
+ LOG.error("Root project path of the Gradle project not found for " + rootModel.getModule());
+ return false;
+ }
+
+ final ExternalProjectDataService externalProjectDataService =
+ (ExternalProjectDataService)ServiceManager.getService(ProjectDataManager.class).getDataService(ExternalProjectDataService.KEY);
+
+ assert externalProjectDataService != null;
+ final ExternalProject externalRootProject =
+ externalProjectDataService.getRootExternalProject(GradleConstants.SYSTEM_ID, new File(gradleProjectPath));
+ if (externalRootProject == null) {
+ LOG.debug("Root external project was not yep imported for the project path: " + gradleProjectPath);
+ return false;
+ }
+
+ ExternalProject externalProject = externalProjectDataService.findExternalProject(externalRootProject, rootModel.getModule());
+ if (externalProject == null) return false;
+
+ if (includeProduction) {
+ addOutputRoots(externalProject.getSourceSets().get("main"), ExternalSystemSourceType.RESOURCE, result);
+ }
+
+ if (includeTests) {
+ addOutputRoots(externalProject.getSourceSets().get("test"), ExternalSystemSourceType.TEST_RESOURCE, result);
+ }
+
+ return true;
+ }
+
+ private static void addOutputRoots(@Nullable ExternalSourceSet externalSourceSet,
+ @NotNull ExternalSystemSourceType sourceType,
+ @NotNull Collection<String> result) {
+ if (externalSourceSet == null) return;
+ final ExternalSourceDirectorySet directorySet = externalSourceSet.getSources().get(sourceType);
+ if (directorySet == null) return;
+
+ result.add(VfsUtilCore.pathToUrl(directorySet.getOutputDir().getAbsolutePath()));
+ }
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/AbstractProjectResolverExtension.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/AbstractProjectResolverExtension.java
index 1d8addd31369..9603470a0878 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/AbstractProjectResolverExtension.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/AbstractProjectResolverExtension.java
@@ -28,6 +28,7 @@ import com.intellij.openapi.externalSystem.util.Order;
import com.intellij.openapi.util.KeyValue;
import com.intellij.util.Consumer;
import org.gradle.tooling.model.idea.IdeaModule;
+import org.gradle.tooling.model.idea.IdeaProject;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -80,6 +81,11 @@ public abstract class AbstractProjectResolverExtension implements GradleProjectR
return nextResolver.createJavaProjectData();
}
+ @Override
+ public void populateProjectExtraModels(@NotNull IdeaProject gradleProject, @NotNull DataNode<ProjectData> ideProject) {
+ nextResolver.populateProjectExtraModels(gradleProject, ideProject);
+ }
+
@NotNull
@Override
public ModuleData createModule(@NotNull IdeaModule gradleModule, @NotNull ProjectData projectData) {
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java
index 6f43559f7a11..ad7ade6a3c58 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java
@@ -15,14 +15,13 @@
*/
package org.jetbrains.plugins.gradle.service.project;
+import com.google.gson.GsonBuilder;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.configurations.SimpleJavaParameters;
import com.intellij.externalSystem.JavaProjectData;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.externalSystem.model.DataNode;
-import com.intellij.openapi.externalSystem.model.ExternalSystemException;
-import com.intellij.openapi.externalSystem.model.ProjectKeys;
+import com.intellij.openapi.externalSystem.model.*;
import com.intellij.openapi.externalSystem.model.project.*;
import com.intellij.openapi.externalSystem.model.task.TaskData;
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
@@ -56,6 +55,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.model.*;
import org.jetbrains.plugins.gradle.model.data.BuildScriptClasspathData;
+import org.jetbrains.plugins.gradle.service.project.data.ExternalProjectDataService;
import org.jetbrains.plugins.gradle.tooling.builder.ModelBuildScriptClasspathBuilderImpl;
import org.jetbrains.plugins.gradle.tooling.internal.init.Init;
import org.jetbrains.plugins.gradle.util.GradleBundle;
@@ -79,6 +79,8 @@ public class BaseGradleProjectResolverExtension implements GradleProjectResolver
private static final Logger LOG = Logger.getInstance("#" + BaseGradleProjectResolverExtension.class.getName());
@NotNull @NonNls private static final String UNRESOLVED_DEPENDENCY_PREFIX = "unresolved dependency - ";
+ private static final String MAIN_SOURCE_SET = "main";
+ private static final String TEST_SOURCE_SET = "test";
@NotNull private ProjectResolverContext resolverCtx;
@NotNull private final BaseProjectImportErrorHandler myErrorHandler = new BaseProjectImportErrorHandler();
@@ -120,6 +122,14 @@ public class BaseGradleProjectResolverExtension implements GradleProjectResolver
return javaProjectData;
}
+ @Override
+ public void populateProjectExtraModels(@NotNull IdeaProject gradleProject, @NotNull DataNode<ProjectData> ideProject) {
+ final ExternalProject externalProject = resolverCtx.getExtraProject(ExternalProject.class);
+ if (externalProject != null) {
+ ideProject.createChild(ExternalProjectDataService.KEY, externalProject);
+ }
+ }
+
@NotNull
@Override
public ModuleData createModule(@NotNull IdeaModule gradleModule, @NotNull ProjectData projectData) {
@@ -220,6 +230,8 @@ public class BaseGradleProjectResolverExtension implements GradleProjectResolver
File sourceCompileOutputPath = null;
File testCompileOutputPath = null;
+ File resourceCompileOutputPath;
+ File testResourceCompileOutputPath;
boolean inheritOutputDirs = false;
ModuleData moduleData = ideModule.getData();
@@ -229,30 +241,71 @@ public class BaseGradleProjectResolverExtension implements GradleProjectResolver
inheritOutputDirs = moduleCompilerOutput.getInheritOutputDirs();
}
+ ExternalProject externalProject = resolverCtx.getExtraProject(gradleModule, ExternalProject.class);
+ if (externalProject != null) {
+ externalProject = new DefaultExternalProject(externalProject);
+ }
+
if (!inheritOutputDirs && (sourceCompileOutputPath == null || testCompileOutputPath == null)) {
- ModuleExtendedModel moduleExtendedModel = resolverCtx.getExtraProject(gradleModule, ModuleExtendedModel.class);
- if (moduleExtendedModel != null) {
- ExtIdeaCompilerOutput output = moduleExtendedModel.getCompilerOutput();
- if (output != null) {
- if (sourceCompileOutputPath == null) {
- sourceCompileOutputPath = output.getMainClassesDir();
+ sourceCompileOutputPath = getCompileOutputPath(externalProject, MAIN_SOURCE_SET, ExternalSystemSourceType.SOURCE);
+ resourceCompileOutputPath = getCompileOutputPath(externalProject, MAIN_SOURCE_SET, ExternalSystemSourceType.RESOURCE);
+ testCompileOutputPath = getCompileOutputPath(externalProject, TEST_SOURCE_SET, ExternalSystemSourceType.TEST);
+ testResourceCompileOutputPath = getCompileOutputPath(externalProject, TEST_SOURCE_SET, ExternalSystemSourceType.TEST_RESOURCE);
+ }
+ else {
+ resourceCompileOutputPath = sourceCompileOutputPath;
+ testResourceCompileOutputPath = testCompileOutputPath;
+
+ if (externalProject != null) {
+ final ExternalSourceSet mainSourceSet = externalProject.getSourceSets().get(MAIN_SOURCE_SET);
+ if (mainSourceSet != null) {
+ final ExternalSourceDirectorySet resourceDirectories = mainSourceSet.getSources().get(ExternalSystemSourceType.RESOURCE);
+ if (resourceDirectories instanceof DefaultExternalSourceDirectorySet) {
+ ((DefaultExternalSourceDirectorySet)resourceDirectories).setOutputDir(sourceCompileOutputPath);
}
- if (testCompileOutputPath == null) {
- testCompileOutputPath = output.getTestClassesDir();
+ }
+ final ExternalSourceSet testSourceSet = externalProject.getSourceSets().get(TEST_SOURCE_SET);
+ if (testSourceSet != null) {
+ final ExternalSourceDirectorySet testResourceDirectories = testSourceSet.getSources().get(ExternalSystemSourceType.TEST_RESOURCE);
+ if (testResourceDirectories instanceof DefaultExternalSourceDirectorySet) {
+ ((DefaultExternalSourceDirectorySet)testResourceDirectories).setOutputDir(testCompileOutputPath);
}
}
+
+ final DataNode<ProjectData> projectDataNode = ExternalSystemApiUtil.findParent(ideModule, ProjectKeys.PROJECT);
+ assert projectDataNode != null;
+ projectDataNode.createOrReplaceChild(ExternalProjectDataService.KEY, externalProject);
}
}
if (sourceCompileOutputPath != null) {
moduleData.setCompileOutputPath(ExternalSystemSourceType.SOURCE, sourceCompileOutputPath.getAbsolutePath());
}
+ if (resourceCompileOutputPath != null) {
+ moduleData.setCompileOutputPath(ExternalSystemSourceType.RESOURCE, resourceCompileOutputPath.getAbsolutePath());
+ }
if (testCompileOutputPath != null) {
moduleData.setCompileOutputPath(ExternalSystemSourceType.TEST, testCompileOutputPath.getAbsolutePath());
}
+ if (testResourceCompileOutputPath != null) {
+ moduleData.setCompileOutputPath(ExternalSystemSourceType.TEST_RESOURCE, testResourceCompileOutputPath.getAbsolutePath());
+ }
+
moduleData.setInheritProjectCompileOutputPath(inheritOutputDirs || sourceCompileOutputPath == null);
}
+ @Nullable
+ private static File getCompileOutputPath(@Nullable ExternalProject externalProject,
+ @NotNull String sourceSetName,
+ @NotNull ExternalSystemSourceType sourceType) {
+ if (externalProject == null) return null;
+ final ExternalSourceSet sourceSet = externalProject.getSourceSets().get(sourceSetName);
+ if(sourceSet == null) return null;
+
+ final ExternalSourceDirectorySet directorySet = sourceSet.getSources().get(sourceType);
+ return directorySet != null ? directorySet.getOutputDir() : null;
+ }
+
@Override
public void populateModuleDependencies(@NotNull IdeaModule gradleModule,
@NotNull DataNode<ModuleData> ideModule,
@@ -319,17 +372,19 @@ public class BaseGradleProjectResolverExtension implements GradleProjectResolver
@Override
public Set<Class> getExtraProjectModelClasses() {
return ContainerUtil.<Class>set(
- GradleBuild.class, ModuleExtendedModel.class, BuildScriptClasspathModel.class);
+ GradleBuild.class, ExternalProject.class, ModuleExtendedModel.class, BuildScriptClasspathModel.class);
}
@NotNull
@Override
public Set<Class> getToolingExtensionsClasses() {
return ContainerUtil.<Class>set(
+ ExternalProject.class,
// gradle-tooling-extension-api jar
ProjectImportAction.class,
// gradle-tooling-extension-impl jar
- ModelBuildScriptClasspathBuilderImpl.class
+ ModelBuildScriptClasspathBuilderImpl.class,
+ GsonBuilder.class
);
}
@@ -416,6 +471,8 @@ public class BaseGradleProjectResolverExtension implements GradleProjectResolver
List<String> additionalEntries = ContainerUtilRt.newArrayList();
ContainerUtilRt.addIfNotNull(additionalEntries, PathUtil.getJarPathForClass(GroovyObject.class));
+ ContainerUtilRt.addIfNotNull(additionalEntries, PathUtil.getJarPathForClass(GsonBuilder.class));
+ ContainerUtilRt.addIfNotNull(additionalEntries, PathUtil.getJarPathForClass(ExternalProject.class));
ContainerUtilRt.addIfNotNull(additionalEntries, PathUtil.getJarPathForClass(JavaProjectData.class));
ContainerUtilRt.addIfNotNull(additionalEntries, PathUtil.getJarPathForClass(LanguageLevel.class));
ContainerUtilRt.addIfNotNull(additionalEntries, PathUtil.getJarPathForClass(StdModuleTypes.class));
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java
index 8a2ffaae36c9..24c8e126ed3f 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java
@@ -199,6 +199,9 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver<Grad
projectDataNode.createChild(JavaProjectData.KEY, javaProjectData);
IdeaProject ideaProject = resolverCtx.getModels().getIdeaProject();
+
+ projectResolverChain.populateProjectExtraModels(ideaProject, projectDataNode);
+
DomainObjectSet<? extends IdeaModule> gradleModules = ideaProject.getModules();
if (gradleModules == null || gradleModules.isEmpty()) {
throw new IllegalStateException("No modules found for the target project: " + ideaProject);
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolverExtension.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolverExtension.java
index b727005db845..6dd201b839fb 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolverExtension.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolverExtension.java
@@ -27,6 +27,7 @@ import com.intellij.openapi.externalSystem.service.ParametersEnhancer;
import com.intellij.openapi.util.KeyValue;
import com.intellij.util.Consumer;
import org.gradle.tooling.model.idea.IdeaModule;
+import org.gradle.tooling.model.idea.IdeaProject;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.GradleManager;
@@ -62,6 +63,8 @@ public interface GradleProjectResolverExtension extends ParametersEnhancer {
@NotNull
JavaProjectData createJavaProjectData();
+ void populateProjectExtraModels(@NotNull IdeaProject gradleProject, @NotNull DataNode<ProjectData> ideProject);
+
@NotNull
ModuleData createModule(@NotNull IdeaModule gradleModule, @NotNull ProjectData projectData);
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleStartupActivity.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleStartupActivity.java
index 81ceaa3177e2..0e5fcc12f3dc 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleStartupActivity.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleStartupActivity.java
@@ -21,6 +21,11 @@ import com.intellij.ide.util.newProjectWizard.AddModuleWizard;
import com.intellij.notification.Notification;
import com.intellij.notification.NotificationListener;
import com.intellij.notification.NotificationType;
+import com.intellij.openapi.application.AccessToken;
+import com.intellij.openapi.application.ReadAction;
+import com.intellij.openapi.compiler.CompileContext;
+import com.intellij.openapi.compiler.CompileTask;
+import com.intellij.openapi.compiler.CompilerManager;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.externalSystem.model.ExternalSystemDataKeys;
import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager;
@@ -30,6 +35,8 @@ import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.idea.maven.project.MavenResourceCompilerConfigurationGenerator;
+import org.jetbrains.plugins.gradle.config.GradleResourceCompilerConfigurationGenerator;
import org.jetbrains.plugins.gradle.service.GradleBuildClasspathManager;
import org.jetbrains.plugins.gradle.service.project.wizard.GradleProjectImportBuilder;
import org.jetbrains.plugins.gradle.service.project.wizard.GradleProjectImportProvider;
@@ -52,9 +59,22 @@ public class GradleStartupActivity implements StartupActivity {
private static final String DO_NOT_SHOW_EVENT_DESCRIPTION = "do.not.show";
@Override
- public void runActivity(@NotNull Project project) {
+ public void runActivity(@NotNull final Project project) {
configureBuildClasspath(project);
showNotificationForUnlinkedGradleProject(project);
+ CompilerManager.getInstance(project).addBeforeTask(new CompileTask() {
+ @Override
+ public boolean execute(CompileContext context) {
+ AccessToken token = ReadAction.start();
+ try {
+ new GradleResourceCompilerConfigurationGenerator(project, context).generateBuildConfiguration();
+ }
+ finally {
+ token.finish();
+ }
+ return true;
+ }
+ });
}
private static void configureBuildClasspath(@NotNull final Project project) {
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/ProjectResolverContext.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/ProjectResolverContext.java
index b7f94dd57122..3aa0027185bf 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/ProjectResolverContext.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/ProjectResolverContext.java
@@ -19,6 +19,7 @@ import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskId;
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationListener;
import org.gradle.tooling.ProjectConnection;
import org.gradle.tooling.model.idea.IdeaModule;
+import org.gradle.tooling.model.idea.IdeaProject;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.model.ProjectImportAction;
@@ -93,7 +94,12 @@ public class ProjectResolverContext {
}
@Nullable
- public <T> T getExtraProject(@NotNull IdeaModule module, Class<T> modelClazz) {
+ public <T> T getExtraProject(Class<T> modelClazz) {
+ return myModels.getExtraProject(null, modelClazz);
+ }
+
+ @Nullable
+ public <T> T getExtraProject(@Nullable IdeaModule module, Class<T> modelClazz) {
return myModels.getExtraProject(module, modelClazz);
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/data/ExternalProjectDataService.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/data/ExternalProjectDataService.java
new file mode 100644
index 000000000000..fae9ee0d88c1
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/data/ExternalProjectDataService.java
@@ -0,0 +1,233 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.plugins.gradle.service.project.data;
+
+import com.intellij.CommonBundle;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.externalSystem.model.*;
+import com.intellij.openapi.externalSystem.model.project.ProjectData;
+import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationListener;
+import com.intellij.openapi.externalSystem.service.internal.ExternalSystemResolveProjectTask;
+import com.intellij.openapi.externalSystem.service.notification.ExternalSystemNotificationManager;
+import com.intellij.openapi.externalSystem.service.notification.NotificationSource;
+import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager;
+import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataService;
+import com.intellij.openapi.externalSystem.settings.ExternalProjectSettings;
+import com.intellij.openapi.externalSystem.util.*;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.Task;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.ex.ProjectRootManagerEx;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.util.Function;
+import com.intellij.util.containers.ConcurrentFactoryMap;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.File;
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/17/2014
+ */
+@Order(ExternalSystemConstants.BUILTIN_SERVICE_ORDER)
+public class ExternalProjectDataService implements ProjectDataService<ExternalProject, Project> {
+ private static final Logger LOG = Logger.getInstance(ExternalProjectDataService.class);
+
+ @NotNull public static final Key<ExternalProject> KEY = Key.create(ExternalProject.class, ProjectKeys.TASK.getProcessingWeight() + 1);
+
+ @NotNull private final Map<Pair<ProjectSystemId, File>, ExternalProject> myExternalRootProjects;
+
+ @NotNull private ProjectDataManager myProjectDataManager;
+
+ public ExternalProjectDataService(@NotNull ProjectDataManager projectDataManager) {
+ myProjectDataManager = projectDataManager;
+ myExternalRootProjects = new ConcurrentFactoryMap<Pair<ProjectSystemId, File>, ExternalProject>() {
+ @Nullable
+ @Override
+ protected ExternalProject create(Pair<ProjectSystemId, File> key) {
+ return new ExternalProjectSerializer().load(key.first, key.second);
+ }
+
+ @Override
+ public ExternalProject put(Pair<ProjectSystemId, File> key, ExternalProject value) {
+ new ExternalProjectSerializer().save(value);
+ return super.put(key, value);
+ }
+ };
+ }
+
+ @NotNull
+ @Override
+ public Key<ExternalProject> getTargetDataKey() {
+ return KEY;
+ }
+
+ public void importData(@NotNull final Collection<DataNode<ExternalProject>> toImport,
+ @NotNull final Project project,
+ final boolean synchronous) {
+ if (toImport.size() != 1) {
+ throw new IllegalArgumentException(
+ String.format("Expected to get a single external project but got %d: %s", toImport.size(), toImport));
+ }
+ saveExternalProject(toImport.iterator().next().getData());
+ }
+
+ @Override
+ public void removeData(@NotNull final Collection<? extends Project> modules, @NotNull Project project, boolean synchronous) {
+ }
+
+ @Nullable
+ public ExternalProject getOrImportRootExternalProject(@NotNull Project project,
+ @NotNull ProjectSystemId systemId,
+ @NotNull File projectRootDir) {
+ final ExternalProject externalProject = getRootExternalProject(systemId, projectRootDir);
+ return externalProject != null ? externalProject : importExternalProject(project, systemId, projectRootDir);
+ }
+
+ @Nullable
+ private ExternalProject importExternalProject(@NotNull final Project project,
+ @NotNull final ProjectSystemId projectSystemId,
+ @NotNull final File projectRootDir) {
+ final Boolean result = UIUtil.invokeAndWaitIfNeeded(new Computable<Boolean>() {
+ @Override
+ public Boolean compute() {
+ final Ref<Boolean> result = new Ref<Boolean>(false);
+ if (project.isDisposed()) return false;
+
+ final String linkedProjectPath = FileUtil.toCanonicalPath(projectRootDir.getPath());
+ final ExternalProjectSettings projectSettings =
+ ExternalSystemApiUtil.getSettings(project, projectSystemId).getLinkedProjectSettings(linkedProjectPath);
+ if (projectSettings == null) {
+ LOG.warn("Unable to get project settings for project path: " + linkedProjectPath);
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Available projects paths: " + ContainerUtil.map(
+ ExternalSystemApiUtil.getSettings(project, projectSystemId).getLinkedProjectsSettings(),
+ new Function<ExternalProjectSettings, String>() {
+ @Override
+ public String fun(ExternalProjectSettings settings) {
+ return settings.getExternalProjectPath();
+ }
+ }));
+ }
+ return false;
+ }
+
+ final File projectFile = new File(linkedProjectPath);
+ final String projectName;
+ if (projectFile.isFile()) {
+ projectName = projectFile.getParentFile().getName();
+ }
+ else {
+ projectName = projectFile.getName();
+ }
+
+ // ask a user for the project import if auto-import is disabled
+ if (!projectSettings.isUseAutoImport()) {
+ String message = String.format("Project '%s' require synchronization with %s configuration. \nImport the project?",
+ projectName, projectSystemId.getReadableName());
+ int returnValue = Messages.showOkCancelDialog(
+ message, "Import Project", CommonBundle.getOkButtonText(), CommonBundle.getCancelButtonText(), Messages.getQuestionIcon()
+ );
+ if (returnValue != Messages.OK) return false;
+ }
+
+ final String title = ExternalSystemBundle.message("progress.import.text", linkedProjectPath, projectSystemId.getReadableName());
+ new Task.Modal(project, title, false) {
+ @Override
+ public void run(@NotNull ProgressIndicator indicator) {
+ if (project.isDisposed()) return;
+
+ ExternalSystemNotificationManager.getInstance(project)
+ .clearNotifications(null, NotificationSource.PROJECT_SYNC, projectSystemId);
+ ExternalSystemResolveProjectTask task =
+ new ExternalSystemResolveProjectTask(projectSystemId, project, linkedProjectPath, false);
+ task.execute(indicator, ExternalSystemTaskNotificationListener.EP_NAME.getExtensions());
+ if (project.isDisposed()) return;
+
+ final Throwable error = task.getError();
+ if (error != null) {
+ ExternalSystemNotificationManager.getInstance(project)
+ .processExternalProjectRefreshError(error, projectName, projectSystemId);
+ return;
+ }
+ final DataNode<ProjectData> projectDataDataNode = task.getExternalProject();
+ if (projectDataDataNode == null) return;
+
+ final Collection<DataNode<ExternalProject>> nodes = ExternalSystemApiUtil.findAll(projectDataDataNode, KEY);
+ if (nodes.size() != 1) {
+ throw new IllegalArgumentException(
+ String.format("Expected to get a single external project but got %d: %s", nodes.size(), nodes));
+ }
+
+ ProjectRootManagerEx.getInstanceEx(myProject).mergeRootsChangesDuring(new Runnable() {
+ @Override
+ public void run() {
+ myProjectDataManager.importData(KEY, nodes, project, true);
+ }
+ });
+
+ result.set(true);
+ }
+ }.queue();
+
+ return result.get();
+ }
+ });
+
+ return result ? getRootExternalProject(projectSystemId, projectRootDir) : null;
+ }
+
+ @Nullable
+ public ExternalProject getRootExternalProject(@NotNull ProjectSystemId systemId, @NotNull File projectRootDir) {
+ return myExternalRootProjects.get(Pair.create(systemId, projectRootDir));
+ }
+
+ public void saveExternalProject(@NotNull ExternalProject externalProject) {
+ myExternalRootProjects.put(
+ Pair.create(new ProjectSystemId(externalProject.getExternalSystemId()), externalProject.getProjectDir()),
+ new DefaultExternalProject(externalProject)
+ );
+ }
+
+ @Nullable
+ public ExternalProject findExternalProject(@NotNull ExternalProject parentProject, @NotNull Module module) {
+ String externalProjectId = ExternalSystemApiUtil.getExternalProjectId(module);
+ return externalProjectId != null ? findExternalProject(parentProject, externalProjectId) : null;
+ }
+
+ @Nullable
+ private static ExternalProject findExternalProject(@NotNull ExternalProject parentProject, @NotNull String externalProjectId) {
+ if (parentProject.getQName().equals(externalProjectId)) return parentProject;
+ if (parentProject.getChildProjects().containsKey(externalProjectId)) {
+ return parentProject.getChildProjects().get(externalProjectId);
+ }
+ for (ExternalProject externalProject : parentProject.getChildProjects().values()) {
+ final ExternalProject project = findExternalProject(externalProject, externalProjectId);
+ if (project != null) return project;
+ }
+ return null;
+ }
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/data/ExternalProjectSerializer.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/data/ExternalProjectSerializer.java
new file mode 100644
index 000000000000..8828b9ef5880
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/data/ExternalProjectSerializer.java
@@ -0,0 +1,262 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.plugins.gradle.service.project.data;
+
+import com.esotericsoftware.kryo.Kryo;
+import com.esotericsoftware.kryo.Serializer;
+import com.esotericsoftware.kryo.io.Input;
+import com.esotericsoftware.kryo.io.Output;
+import com.esotericsoftware.kryo.serializers.CollectionSerializer;
+import com.esotericsoftware.kryo.serializers.DefaultSerializers;
+import com.esotericsoftware.kryo.serializers.FieldSerializer;
+import com.esotericsoftware.kryo.serializers.MapSerializer;
+import com.esotericsoftware.minlog.Log;
+import com.intellij.openapi.application.PathManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.externalSystem.model.*;
+import com.intellij.openapi.externalSystem.model.project.ExternalSystemSourceType;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.io.StreamUtil;
+import gnu.trove.THashMap;
+import gnu.trove.THashSet;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.objenesis.strategy.StdInstantiatorStrategy;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.util.*;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/15/2014
+ */
+public class ExternalProjectSerializer {
+ private static final Logger LOG = Logger.getInstance(ExternalProjectSerializer.class);
+
+ private final Kryo myKryo;
+
+ public ExternalProjectSerializer() {
+ myKryo = new Kryo() {
+ @Override
+ public <T> T newInstance(Class<T> type) {
+ LOG.error("Serializing default type: " + type);
+ return super.newInstance(type);
+ }
+ };
+ configureKryo();
+ }
+
+ private void configureKryo() {
+ myKryo.setAutoReset(true);
+
+ myKryo.setRegistrationRequired(true);
+ Log.set(Log.LEVEL_WARN);
+
+ myKryo.register(ArrayList.class, new CollectionSerializer() {
+ @Override
+ protected Collection create(Kryo kryo, Input input, Class<Collection> type) {
+ return new ArrayList();
+ }
+ });
+ myKryo.register(HashMap.class, new MapSerializer() {
+ @Override
+ protected Map create(Kryo kryo, Input input, Class<Map> type) {
+ return new HashMap();
+ }
+ });
+ myKryo.register(HashSet.class, new CollectionSerializer() {
+ @Override
+ protected Collection create(Kryo kryo, Input input, Class<Collection> type) {
+ return new HashSet();
+ }
+ });
+
+ myKryo.register(File.class, new FileSerializer());
+ myKryo.register(DefaultExternalProject.class, new FieldSerializer<DefaultExternalProject>(myKryo, DefaultExternalProject.class) {
+ @Override
+ protected DefaultExternalProject create(Kryo kryo, Input input, Class<DefaultExternalProject> type) {
+ return new DefaultExternalProject();
+ }
+ });
+
+ myKryo.register(DefaultExternalTask.class, new FieldSerializer<DefaultExternalTask>(myKryo, DefaultExternalTask.class) {
+ @Override
+ protected DefaultExternalTask create(Kryo kryo, Input input, Class<DefaultExternalTask> type) {
+ return new DefaultExternalTask();
+ }
+ });
+
+ myKryo.register(DefaultExternalPlugin.class, new FieldSerializer<DefaultExternalPlugin>(myKryo, DefaultExternalPlugin.class) {
+ @Override
+ protected DefaultExternalPlugin create(Kryo kryo, Input input, Class<DefaultExternalPlugin> type) {
+ return new DefaultExternalPlugin();
+ }
+ });
+
+ myKryo.register(DefaultExternalSourceSet.class, new FieldSerializer<DefaultExternalSourceSet>(myKryo, DefaultExternalSourceSet.class) {
+ @Override
+ protected DefaultExternalSourceSet create(Kryo kryo, Input input, Class<DefaultExternalSourceSet> type) {
+ return new DefaultExternalSourceSet();
+ }
+ });
+
+ myKryo.register(
+ DefaultExternalSourceDirectorySet.class,
+ new FieldSerializer<DefaultExternalSourceDirectorySet>(myKryo, DefaultExternalSourceDirectorySet.class) {
+ @Override
+ protected DefaultExternalSourceDirectorySet create(Kryo kryo, Input input, Class<DefaultExternalSourceDirectorySet> type) {
+ return new DefaultExternalSourceDirectorySet();
+ }
+ }
+ );
+
+ myKryo.register(DefaultExternalFilter.class, new FieldSerializer<DefaultExternalFilter>(myKryo, DefaultExternalFilter.class) {
+ @Override
+ protected DefaultExternalFilter create(Kryo kryo, Input input, Class<DefaultExternalFilter> type) {
+ return new DefaultExternalFilter();
+ }
+ });
+
+ myKryo.register(ExternalSystemSourceType.class, new DefaultSerializers.EnumSerializer(ExternalSystemSourceType.class));
+
+ myKryo.register(LinkedHashSet.class, new CollectionSerializer() {
+ @Override
+ protected Collection create(Kryo kryo, Input input, Class<Collection> type) {
+ return new LinkedHashSet();
+ }
+ });
+ myKryo.register(HashSet.class, new CollectionSerializer() {
+ @Override
+ protected Collection create(Kryo kryo, Input input, Class<Collection> type) {
+ return new HashSet();
+ }
+ });
+ myKryo.register(THashSet.class, new CollectionSerializer() {
+ @Override
+ protected Collection create(Kryo kryo, Input input, Class<Collection> type) {
+ return new THashSet();
+ }
+ });
+ myKryo.register(Set.class, new CollectionSerializer() {
+ @Override
+ protected Collection create(Kryo kryo, Input input, Class<Collection> type) {
+ return new HashSet();
+ }
+ });
+ myKryo.register(THashMap.class, new MapSerializer() {
+ @Override
+ protected Map create(Kryo kryo, Input input, Class<Map> type) {
+ return new THashMap();
+ }
+ });
+ }
+
+
+ public void save(@NotNull ExternalProject externalProject) {
+ Output output = null;
+ try {
+ final String externalProjectPath = externalProject.getProjectDir().getPath();
+ final File configurationFile =
+ getProjectConfigurationFile(new ProjectSystemId(externalProject.getExternalSystemId()), externalProjectPath);
+ if (!FileUtil.createParentDirs(configurationFile)) return;
+
+ output = new Output(new FileOutputStream(configurationFile));
+ myKryo.writeObject(output, externalProject);
+ }
+ catch (FileNotFoundException e) {
+ LOG.error(e);
+ }
+ finally {
+ StreamUtil.closeStream(output);
+ }
+ }
+
+ @Nullable
+ public ExternalProject load(@NotNull ProjectSystemId externalSystemId, File externalProjectPath) {
+ Input input = null;
+ try {
+ final File configurationFile = getProjectConfigurationFile(externalSystemId, externalProjectPath.getPath());
+ if (!configurationFile.isFile()) return null;
+
+ input = new Input(new FileInputStream(configurationFile));
+ return myKryo.readObject(input, DefaultExternalProject.class);
+ }
+ catch (Exception e) {
+ LOG.error(e);
+ }
+ finally {
+ StreamUtil.closeStream(input);
+ }
+
+ return null;
+ }
+
+ private static File getProjectConfigurationFile(ProjectSystemId externalSystemId, String externalProjectPath) {
+ return new File(getProjectConfigurationDir(externalSystemId), Integer.toHexString(externalProjectPath.hashCode()) + "/project.dat");
+ }
+
+ private static File getProjectConfigurationDir(ProjectSystemId externalSystemId) {
+ return getPluginSystemDir(externalSystemId, "Projects");
+ }
+
+ private static File getPluginSystemDir(ProjectSystemId externalSystemId, String folder) {
+ return new File(PathManager.getSystemPath(), externalSystemId.getId().toLowerCase() + "/" + folder).getAbsoluteFile();
+ }
+
+ private static class FileSerializer extends Serializer<File> {
+ private final Kryo myStdKryo;
+
+ public FileSerializer() {
+ myStdKryo = new Kryo();
+ myStdKryo.register(File.class);
+ myStdKryo.setInstantiatorStrategy(new StdInstantiatorStrategy());
+ }
+
+ @Override
+ public void write(Kryo kryo, Output output, File object) {
+ myStdKryo.writeObject(output, object);
+ }
+
+ @Override
+ public File read(Kryo kryo, Input input, Class<File> type) {
+ File file = myStdKryo.readObject(input, File.class);
+ return new File(file.getPath());
+ }
+ }
+
+ private static class StdSerializer<T> extends Serializer<T> {
+ private final Kryo myStdKryo;
+
+ public StdSerializer(Class<T> clazz) {
+ myStdKryo = new Kryo();
+ myStdKryo.register(clazz);
+ myStdKryo.setInstantiatorStrategy(new StdInstantiatorStrategy());
+ }
+
+ @Override
+ public void write(Kryo kryo, Output output, T object) {
+ myStdKryo.writeObject(output, object);
+ }
+
+ @Override
+ public T read(Kryo kryo, Input input, Class<T> type) {
+ return myStdKryo.readObject(input, type);
+ }
+ }
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/wizard/GradleProjectOpenProcessor.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/wizard/GradleProjectOpenProcessor.java
index 213ba84271ef..10f766cc5e34 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/wizard/GradleProjectOpenProcessor.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/wizard/GradleProjectOpenProcessor.java
@@ -16,17 +16,26 @@
package org.jetbrains.plugins.gradle.service.project.wizard;
import com.intellij.ide.util.newProjectWizard.AddModuleWizard;
-import com.intellij.ide.util.projectWizard.ProjectBuilder;
+import com.intellij.ide.util.projectWizard.ModuleWizardStep;
import com.intellij.ide.util.projectWizard.WizardContext;
import com.intellij.ide.wizard.Step;
+import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.externalSystem.service.project.wizard.SelectExternalProjectStep;
-import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.options.ConfigurationException;
+import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.projectImport.ProjectOpenProcessorBase;
import com.intellij.util.Function;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.gradle.service.settings.GradleProjectSettingsControl;
+import org.jetbrains.plugins.gradle.service.settings.GradleSystemSettingsControl;
+import org.jetbrains.plugins.gradle.service.settings.ImportFromGradleControl;
+import org.jetbrains.plugins.gradle.settings.DistributionType;
+import org.jetbrains.plugins.gradle.settings.GradleProjectSettings;
+import org.jetbrains.plugins.gradle.settings.GradleSettings;
import org.jetbrains.plugins.gradle.util.GradleConstants;
+import static org.jetbrains.plugins.gradle.util.GradleEnvironment.Headless.*;
/**
* @author Denis Zhdanov
@@ -61,24 +70,90 @@ public class GradleProjectOpenProcessor extends ProjectOpenProcessorBase<GradleP
@Override
protected boolean doQuickImport(VirtualFile file, WizardContext wizardContext) {
- AddModuleWizard dialog = new AddModuleWizard(null, file.getPath(), new GradleProjectImportProvider(getBuilder()));
+ final GradleProjectImportProvider projectImportProvider = new GradleProjectImportProvider(getBuilder());
+ getBuilder().setFileToImport(file.getPath());
getBuilder().prepare(wizardContext);
getBuilder().getControl(null).setLinkedProjectPath(file.getPath());
- dialog.getWizardContext().setProjectBuilder(getBuilder());
- dialog.navigateToStep(new Function<Step, Boolean>() {
- @Override
- public Boolean fun(Step step) {
- return step instanceof SelectExternalProjectStep;
- }
- });
- boolean result = dialog.showAndGet();
+ final boolean result;
+ if (ApplicationManager.getApplication().isHeadlessEnvironment()) {
+ result = setupGradleProjectSettingsInHeadlessMode(file, projectImportProvider, wizardContext);
+ }
+ else {
+ AddModuleWizard dialog = new AddModuleWizard(null, file.getPath(), projectImportProvider);
+ dialog.getWizardContext().setProjectBuilder(getBuilder());
+ dialog.navigateToStep(new Function<Step, Boolean>() {
+ @Override
+ public Boolean fun(Step step) {
+ return step instanceof SelectExternalProjectStep;
+ }
+ });
+ result = dialog.showAndGet();
+ }
if (result && getBuilder().getExternalProjectNode() != null) {
wizardContext.setProjectName(getBuilder().getExternalProjectNode().getData().getInternalName());
}
return result;
}
+ private boolean setupGradleProjectSettingsInHeadlessMode(VirtualFile file,
+ GradleProjectImportProvider projectImportProvider,
+ WizardContext wizardContext) {
+ final ModuleWizardStep[] wizardSteps = projectImportProvider.createSteps(wizardContext);
+ if (wizardSteps.length > 0 && wizardSteps[0] instanceof SelectExternalProjectStep) {
+ SelectExternalProjectStep selectExternalProjectStep = (SelectExternalProjectStep)wizardSteps[0];
+ wizardContext.setProjectBuilder(getBuilder());
+ try {
+ selectExternalProjectStep.updateStep();
+ final ImportFromGradleControl importFromGradleControl = getBuilder().getControl(wizardContext.getProject());
+
+ GradleProjectSettingsControl gradleProjectSettingsControl =
+ (GradleProjectSettingsControl)importFromGradleControl.getProjectSettingsControl();
+
+ final GradleProjectSettings projectSettings = gradleProjectSettingsControl.getInitialSettings();
+
+ if (GRADLE_DISTRIBUTION_TYPE != null) {
+ for (DistributionType type : DistributionType.values()) {
+ if (type.name().equals(GRADLE_DISTRIBUTION_TYPE)) {
+ projectSettings.setDistributionType(type);
+ break;
+ }
+ }
+ }
+ if (GRADLE_HOME != null) {
+ projectSettings.setGradleHome(GRADLE_HOME);
+ }
+ gradleProjectSettingsControl.reset();
+
+ final GradleSystemSettingsControl systemSettingsControl =
+ (GradleSystemSettingsControl)importFromGradleControl.getSystemSettingsControl();
+ assert systemSettingsControl != null;
+ final GradleSettings gradleSettings = systemSettingsControl.getInitialSettings();
+ if (GRADLE_VM_OPTIONS != null) {
+ gradleSettings.setGradleVmOptions(GRADLE_VM_OPTIONS);
+ }
+ if (GRADLE_OFFLINE != null) {
+ gradleSettings.setOfflineWork(Boolean.parseBoolean(GRADLE_OFFLINE));
+ }
+ String serviceDirectory = GRADLE_SERVICE_DIRECTORY;
+ if (GRADLE_SERVICE_DIRECTORY != null) {
+ gradleSettings.setServiceDirectoryPath(serviceDirectory);
+ }
+ systemSettingsControl.reset();
+
+ if (!selectExternalProjectStep.validate()) {
+ return false;
+ }
+ }
+ catch (ConfigurationException e) {
+ Messages.showErrorDialog(wizardContext.getProject(), e.getMessage(), e.getTitle());
+ return false;
+ }
+ selectExternalProjectStep.updateDataModel();
+ }
+ return true;
+ }
+
@Override
public boolean lookForProjectsInDirectory() {
return false;
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/GradleSystemSettingsControl.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/GradleSystemSettingsControl.java
index ffdf37c74b87..ab6454c46c99 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/GradleSystemSettingsControl.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/GradleSystemSettingsControl.java
@@ -173,4 +173,9 @@ public class GradleSystemSettingsControl implements ExternalSystemSettingsContro
public void disposeUIResources() {
ExternalSystemUiUtil.disposeUi(this);
}
+
+ @NotNull
+ public GradleSettings getInitialSettings() {
+ return myInitialSettings;
+ }
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleEnvironment.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleEnvironment.java
index 2c61ac6c10eb..eb780ced4d5a 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleEnvironment.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleEnvironment.java
@@ -13,6 +13,18 @@ public class GradleEnvironment {
@NonNls public static final boolean DISABLE_ENHANCED_TOOLING_API = Boolean.getBoolean("gradle.disable.enhanced.tooling.api");
@NonNls public static final boolean ADJUST_USER_DIR = Boolean.getBoolean("gradle.adjust.userdir");
+ public static class Headless {
+ @NonNls public static final String GRADLE_DISTRIBUTION_TYPE = System.getProperty("idea.gradle.distributionType");
+ @NonNls public static final String GRADLE_HOME = System.getProperty("idea.gradle.home");
+ @NonNls public static final String GRADLE_VM_OPTIONS = System.getProperty("idea.gradle.vmOptions");
+ @NonNls public static final String GRADLE_OFFLINE = System.getProperty("idea.gradle.offline");
+ @NonNls public static final String GRADLE_SERVICE_DIRECTORY = System.getProperty("idea.gradle.serviceDirectory");
+
+ private Headless() {
+ }
+ }
+
+
private GradleEnvironment() {
}
}
diff --git a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/compiler/GradleCompilingTestCase.java b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/compiler/GradleCompilingTestCase.java
new file mode 100644
index 000000000000..3b508c8cf289
--- /dev/null
+++ b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/compiler/GradleCompilingTestCase.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.plugins.gradle.compiler;
+
+import com.intellij.compiler.artifacts.ArtifactsTestUtil;
+import com.intellij.openapi.application.AccessToken;
+import com.intellij.openapi.application.ReadAction;
+import com.intellij.openapi.compiler.CompileContext;
+import com.intellij.openapi.compiler.CompileTask;
+import com.intellij.openapi.compiler.CompilerManager;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.packaging.impl.artifacts.ArtifactUtil;
+import com.intellij.util.io.TestFileSystemItem;
+import org.jetbrains.plugins.gradle.config.GradleResourceCompilerConfigurationGenerator;
+import org.jetbrains.plugins.gradle.importing.GradleImportingTestCase;
+
+import java.io.File;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/21/2014
+ */
+public abstract class GradleCompilingTestCase extends GradleImportingTestCase {
+ @Override
+ protected void setUpInWriteAction() throws Exception {
+ super.setUpInWriteAction();
+ CompilerManager.getInstance(myProject).addBeforeTask(new CompileTask() {
+ @Override
+ public boolean execute(CompileContext context) {
+ AccessToken token = ReadAction.start();
+ try {
+ new GradleResourceCompilerConfigurationGenerator(myProject, context).generateBuildConfiguration();
+ }
+ finally {
+ token.finish();
+ }
+ return true;
+ }
+ });
+ }
+
+ protected void assertCopied(String path) {
+ assertTrue(new File(myProjectConfig.getParent().getPath(), path).exists());
+ }
+
+ protected void assertCopied(String path, String content) {
+ assertCopied(path);
+ assertSameLinesWithFile(new File(myProjectConfig.getParent().getPath(), path).getPath(), content);
+ }
+
+ protected void assertNotCopied(String path) {
+ assertFalse(new File(myProjectConfig.getParent().getPath(), path).exists());
+ }
+
+ @Override
+ protected void assertArtifactOutputPath(String artifactName, String expected) {
+ final String defaultArtifactOutputPath = ArtifactUtil.getDefaultArtifactOutputPath(artifactName, myProject);
+ assert defaultArtifactOutputPath != null;
+ final String basePath = FileUtil.toSystemIndependentName(new File(defaultArtifactOutputPath).getParent());
+ super.assertArtifactOutputPath(artifactName, basePath + expected);
+ }
+
+ protected void assertArtifactOutputFile(String artifactName, String path, String content) {
+ final String defaultArtifactOutputPath = ArtifactUtil.getDefaultArtifactOutputPath(artifactName, myProject);
+ assert defaultArtifactOutputPath != null;
+ final String basePath = FileUtil.toSystemIndependentName(new File(defaultArtifactOutputPath).getParent());
+ assertSameLinesWithFile(basePath + path, content);
+ }
+
+ protected void assertArtifactOutputFile(String artifactName, String path) {
+ final String defaultArtifactOutputPath = ArtifactUtil.getDefaultArtifactOutputPath(artifactName, myProject);
+ assert defaultArtifactOutputPath != null;
+ final String basePath = FileUtil.toSystemIndependentName(new File(defaultArtifactOutputPath).getParent());
+ assertExists(new File(basePath + path));
+ }
+}
diff --git a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/compiler/GradleResourceFilteringTest.java b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/compiler/GradleResourceFilteringTest.java
new file mode 100644
index 000000000000..df9c6a879ac7
--- /dev/null
+++ b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/compiler/GradleResourceFilteringTest.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.plugins.gradle.compiler;
+
+import org.junit.Test;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/21/2014
+ */
+@SuppressWarnings("JUnit4AnnotatedMethodInJUnit3TestCase")
+public class GradleResourceFilteringTest extends GradleCompilingTestCase {
+
+ @Test
+ public void testHeadFilter() throws Exception {
+ createProjectSubFile(
+ "src/main/resources/dir/file.txt", "1 Header\n" +
+ "2\n" +
+ "3 another text\n" +
+ "4\n" +
+ "5 another text \n" +
+ "6 another text @token@ another text\n" +
+ "7\n" +
+ "8 Footer");
+ importProject(
+ "apply plugin: 'java'\n" +
+ "\n" +
+ "import org.apache.tools.ant.filters.*\n" +
+ "processResources {\n" +
+ " filter(HeadFilter, lines:3, skip:2)\n" +
+ "}"
+ );
+ assertModules("project");
+ compileModules("project");
+
+ assertCopied("build/resources/main/dir/file.txt", "3 another text\n" +
+ "4\n" +
+ "5 another text \n");
+ }
+
+ @Test
+ public void testReplaceTokensFilter() throws Exception {
+ createProjectSubFile(
+ "src/main/resources/dir/file.txt", "1 Header\n" +
+ "2\n" +
+ "3 #token1#another text\n" +
+ "4\n" +
+ "5 another text \n" +
+ "6 another text #token2# another text\n" +
+ "7\n" +
+ "8 Footer");
+ importProject(
+ "apply plugin: 'java'\n" +
+ "\n" +
+ "import org.apache.tools.ant.filters.*\n" +
+ "processResources {\n" +
+ " filter(ReplaceTokens, tokens:[token1:'<11111>', token2:'<2222>'], beginToken: '#', endToken: '#')\n" +
+ "}"
+ );
+ assertModules("project");
+ compileModules("project");
+
+ assertCopied("build/resources/main/dir/file.txt", "1 Header\n" +
+ "2\n" +
+ "3 <11111>another text\n" +
+ "4\n" +
+ "5 another text \n" +
+ "6 another text <2222> another text\n" +
+ "7\n" +
+ "8 Footer");
+ }
+
+ @Test
+ public void testRenameFilter() throws Exception {
+ createProjectSubFile("src/main/resources/dir/file.txt");
+ importProject(
+ "apply plugin: 'java'\n" +
+ "\n" +
+ "import org.apache.tools.ant.filters.*\n" +
+ "processResources {\n" +
+ " rename 'file.txt', 'file001.txt'\n" +
+ "}"
+ );
+ assertModules("project");
+ compileModules("project");
+
+ assertCopied("build/resources/main/dir/file001.txt");
+ }
+
+ @Test
+ public void testFiltersChain() throws Exception {
+ createProjectSubFile(
+ "src/main/resources/dir/file.txt", "1 Header\n" +
+ "2\n" +
+ "3 another text@token1@\n" +
+ "4\n" +
+ "5 another text \n" +
+ "6 another text @token2@ another text\n" +
+ "7\n" +
+ "8 Footer");
+ importProject(
+ "apply plugin: 'java'\n" +
+ "\n" +
+ "import org.apache.tools.ant.filters.*\n" +
+ "processResources {\n" +
+ " filter(HeadFilter, lines:4, skip:2)\n" +
+ " filter(ReplaceTokens, tokens:[token1:'<11111>', token2:'<2222>'])\n" +
+ " rename 'file.txt', 'file001.txt'\n" +
+ "}"
+ );
+ assertModules("project");
+ compileModules("project");
+
+ assertCopied("build/resources/main/dir/file001.txt", "3 another text<11111>\n" +
+ "4\n" +
+ "5 another text \n" +
+ "6 another text <2222> another text");
+ }
+} \ No newline at end of file
diff --git a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/compiler/GradleResourceProcessingTest.java b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/compiler/GradleResourceProcessingTest.java
new file mode 100644
index 000000000000..873234425e30
--- /dev/null
+++ b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/compiler/GradleResourceProcessingTest.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.plugins.gradle.compiler;
+
+import org.junit.Test;
+
+import java.io.IOException;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 7/21/2014
+ */
+@SuppressWarnings("JUnit4AnnotatedMethodInJUnit3TestCase")
+public class GradleResourceProcessingTest extends GradleCompilingTestCase {
+
+ @Test
+ public void testBasicResourceCopying() throws Exception {
+ createProjectSubFile("src/main/resources/dir/file.properties");
+ createProjectSubFile("src/test/resources/dir/file-test.properties");
+ importProject(
+ "apply plugin: 'java'"
+ );
+ assertModules("project");
+ compileModules("project");
+
+ assertCopied("build/resources/main/dir/file.properties");
+ assertCopied("build/resources/test/dir/file-test.properties");
+ }
+
+ @Test
+ public void testResourceProcessingWithIdeaGradlePluginCustomization() throws Exception {
+ createProjectSubFile("src/main/resources/dir/file.properties");
+ createProjectSubFile("src/test/resources/dir/file-test.properties");
+ importProject(
+ "apply plugin: 'java'\n" +
+ "apply plugin: 'idea'\n" +
+ "idea {\n" +
+ " module {\n" +
+ " inheritOutputDirs = false\n" +
+ " outputDir = file('muchBetterOutputDir')\n" +
+ " testOutputDir = file('muchBetterTestOutputDir')\n" +
+ " }\n" +
+ "}"
+ );
+ assertModules("project");
+ compileModules("project");
+
+ assertCopied("muchBetterOutputDir/dir/file.properties");
+ assertCopied("muchBetterTestOutputDir/dir/file-test.properties");
+ }
+
+ @Test
+ public void testIncludesAndExcludesInSourceSets() throws Exception {
+ createFilesForIncludesAndExcludesTest();
+
+ importProject(
+ "apply plugin: 'java'\n" +
+ "\n" +
+ "sourceSets {\n" +
+ " main {\n" +
+ " resources {\n" +
+ " include '**/*.yyy'\n" +
+ " include '**/*.xxx'\n" +
+ " exclude 'dir/*.yyy'\n" +
+ " exclude '*.xxx'\n" +
+ " }\n" +
+ " }\n" +
+ " test {\n" +
+ " resources {\n" +
+ " include '**/*.yyy'\n" +
+ " include '**/*.xxx'\n" +
+ " exclude 'dir/*.yyy'\n" +
+ " exclude '*.xxx'\n" +
+ " }\n" +
+ " }\n" +
+ "}"
+ );
+ assertModules("project");
+ compileModules("project");
+
+ assertCopiedResources();
+ }
+
+ @Test
+ public void testIncludesAndExcludesInAllSourceSets() throws Exception {
+ createFilesForIncludesAndExcludesTest();
+
+ importProject(
+ "apply plugin: 'java'\n" +
+ "\n" +
+ "sourceSets.all {\n" +
+ " resources {\n" +
+ " include '**/*.yyy'\n" +
+ " include '**/*.xxx'\n" +
+ " exclude 'dir/*.yyy'\n" +
+ " exclude '*.xxx'\n" +
+ " }\n" +
+ "}"
+ );
+ assertModules("project");
+ compileModules("project");
+
+ assertCopiedResources();
+ }
+
+
+ @Test
+ public void testIncludesAndExcludesInResourcesTask() throws Exception {
+ createFilesForIncludesAndExcludesTest();
+
+ importProject(
+ "apply plugin: 'java'\n" +
+ "\n" +
+ "processResources {\n" +
+ " include '**/*.yyy'\n" +
+ " include '**/*.xxx'\n" +
+ " exclude 'dir/*.yyy'\n" +
+ " exclude '*.xxx'\n" +
+ "}\n" +
+ "\n" +
+ "processTestResources {\n" +
+ " include '**/*.yyy'\n" +
+ " include '**/*.xxx'\n" +
+ " exclude 'dir/*.yyy'\n" +
+ " exclude '*.xxx'\n" +
+ "}\n"
+ );
+ assertModules("project");
+ compileModules("project");
+
+ assertCopiedResources();
+ }
+
+ private void createFilesForIncludesAndExcludesTest() throws IOException {
+ createProjectSubFile("src/main/resources/dir/file.xxx");
+ createProjectSubFile("src/main/resources/dir/file.yyy");
+ createProjectSubFile("src/main/resources/file.xxx");
+ createProjectSubFile("src/main/resources/file.yyy");
+ createProjectSubFile("src/main/resources/file.zzz");
+
+ createProjectSubFile("src/test/resources/dir/file.xxx");
+ createProjectSubFile("src/test/resources/dir/file.yyy");
+ createProjectSubFile("src/test/resources/file.xxx");
+ createProjectSubFile("src/test/resources/file.yyy");
+ createProjectSubFile("src/test/resources/file.zzz");
+ }
+
+ private void assertCopiedResources() {
+ // assert production resources
+ assertCopied("build/resources/main/dir/file.xxx");
+ assertCopied("build/resources/main/file.yyy");
+ assertNotCopied("build/resources/main/dir/file.yyy");
+ assertNotCopied("build/resources/main/file.xxx");
+ assertNotCopied("build/resources/main/file.zzz");
+
+ // assert test resources
+ assertCopied("build/resources/test/dir/file.xxx");
+ assertCopied("build/resources/test/file.yyy");
+ assertNotCopied("build/resources/test/dir/file.yyy");
+ assertNotCopied("build/resources/test/file.xxx");
+ assertNotCopied("build/resources/test/file.zzz");
+ }
+}
diff --git a/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/ModuleExtendedModel.java b/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/ModuleExtendedModel.java
index 97dfd2547b73..91889d85fa9f 100644
--- a/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/ModuleExtendedModel.java
+++ b/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/ModuleExtendedModel.java
@@ -22,9 +22,12 @@ import java.io.Serializable;
import java.util.List;
/**
+ * @deprecated Use {@link com.intellij.openapi.externalSystem.model.ExternalProject} model instead.
+ *
* @author Vladislav.Soroka
* @since 11/5/13
*/
+@Deprecated()
public interface ModuleExtendedModel extends Serializable {
/**
* The group of the module.
diff --git a/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/ProjectImportAction.java b/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/ProjectImportAction.java
index af6f4fed60f4..5b20894b318d 100644
--- a/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/ProjectImportAction.java
+++ b/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/ProjectImportAction.java
@@ -48,8 +48,8 @@ public class ProjectImportAction implements BuildAction<ProjectImportAction.AllM
@Nullable
@Override
public AllModels execute(final BuildController controller) {
- Class<? extends IdeaProject> aClass1 = myIsPreviewMode ? BasicIdeaProject.class : IdeaProject.class;
- final IdeaProject ideaProject = controller.getModel(aClass1);
+ //outer conditional is needed to be compatible with 1.8
+ final IdeaProject ideaProject = myIsPreviewMode ? controller.getModel(BasicIdeaProject.class) : controller.getModel(IdeaProject.class);
if (ideaProject == null || ideaProject.getModules().isEmpty()) {
return null;
}
@@ -59,25 +59,30 @@ public class ProjectImportAction implements BuildAction<ProjectImportAction.AllM
// TODO ask gradle guys why there is always null got for BuildEnvironment model
//allModels.setBuildEnvironment(controller.findModel(BuildEnvironment.class));
+ addExtraProject(controller, allModels, null);
for (IdeaModule module : ideaProject.getModules()) {
- for (Class aClass : myExtraProjectModelClasses) {
- try {
- Object extraProject = controller.findModel(module, aClass);
- if (extraProject == null) continue;
- allModels.addExtraProject(extraProject, aClass, module);
- }
- catch (Exception e) {
- // do not fail project import in a preview mode
- if (!myIsPreviewMode) {
- throw new ExternalSystemException(e);
- }
- }
- }
+ addExtraProject(controller, allModels, module);
}
return allModels;
}
+ private void addExtraProject(@NotNull BuildController controller, @NotNull AllModels allModels, @Nullable IdeaModule model) {
+ for (Class aClass : myExtraProjectModelClasses) {
+ try {
+ Object extraProject = controller.findModel(model, aClass);
+ if (extraProject == null) continue;
+ allModels.addExtraProject(extraProject, aClass, model);
+ }
+ catch (Exception e) {
+ // do not fail project import in a preview mode
+ if (!myIsPreviewMode) {
+ throw new ExternalSystemException(e);
+ }
+ }
+ }
+ }
+
public static class AllModels implements Serializable {
@NotNull private final Map<String, Object> projectsByPath = new HashMap<String, Object>();
@NotNull private final IdeaProject myIdeaProject;
@@ -101,9 +106,13 @@ public class ProjectImportAction implements BuildAction<ProjectImportAction.AllM
myBuildEnvironment = buildEnvironment;
}
+ @Nullable
+ public <T> T getExtraProject(Class<T> modelClazz) {
+ return getExtraProject(null, modelClazz);
+ }
@Nullable
- public <T> T getExtraProject(@NotNull IdeaModule module, Class<T> modelClazz) {
+ public <T> T getExtraProject(@Nullable IdeaModule module, Class<T> modelClazz) {
Object extraProject = projectsByPath.get(extractMapKey(modelClazz, module));
if (modelClazz.isInstance(extraProject)) {
//noinspection unchecked
@@ -129,13 +138,17 @@ public class ProjectImportAction implements BuildAction<ProjectImportAction.AllM
return modules;
}
- public void addExtraProject(@NotNull Object project, @NotNull Class modelClazz, @NotNull IdeaModule module) {
+ public void addExtraProject(@NotNull Object project, @NotNull Class modelClazz) {
+ projectsByPath.put(extractMapKey(modelClazz, null), project);
+ }
+
+ public void addExtraProject(@NotNull Object project, @NotNull Class modelClazz, @Nullable IdeaModule module) {
projectsByPath.put(extractMapKey(modelClazz, module), project);
}
@NotNull
- private static String extractMapKey(Class modelClazz, @NotNull IdeaModule module) {
- return modelClazz.getName() + '@' + module.getGradleProject().getPath();
+ private String extractMapKey(Class modelClazz, @Nullable IdeaModule module) {
+ return modelClazz.getName() + '@' + (module != null ? module.getGradleProject().getPath() : "root" + myIdeaProject.getName().hashCode());
}
@NotNull
diff --git a/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/tooling/ErrorMessageBuilder.java b/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/tooling/ErrorMessageBuilder.java
index 97e449992235..da938dccdf0d 100644
--- a/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/tooling/ErrorMessageBuilder.java
+++ b/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/tooling/ErrorMessageBuilder.java
@@ -31,17 +31,21 @@ public class ErrorMessageBuilder {
public static final String EOL_TAG = "<eol>";
@NotNull private final Project myProject;
- @NotNull private final Exception myException;
+ @Nullable private final Exception myException;
@NotNull private final String myGroup;
@Nullable private String myDescription;
- private ErrorMessageBuilder(@NotNull Project project, @NotNull Exception exception, @NotNull String group) {
+ private ErrorMessageBuilder(@NotNull Project project, @Nullable Exception exception, @NotNull String group) {
myProject = project;
myException = exception;
myGroup = group;
}
- public static ErrorMessageBuilder create(@NotNull Project project, @NotNull Exception exception, @NotNull String group) {
+ public static ErrorMessageBuilder create(@NotNull Project project, @NotNull String group) {
+ return new ErrorMessageBuilder(project, null, group);
+ }
+
+ public static ErrorMessageBuilder create(@NotNull Project project, @Nullable Exception exception, @NotNull String group) {
return new ErrorMessageBuilder(project, exception, group);
}
@@ -59,7 +63,7 @@ public class ErrorMessageBuilder {
(
"<i>" +
"<b>" + myProject + ((myDescription != null) ? ": " + myDescription : "") + "</b>" +
- "\nDetails: " + getErrorMessage(myException) +
+ (myException != null ? "\nDetails: " + getErrorMessage(myException) : "") +
"</i>"
).replaceAll("\r\n|\n\r|\n|\r", EOL_TAG)
);
diff --git a/plugins/gradle/tooling-extension-impl/gradle-tooling-extension-impl.iml b/plugins/gradle/tooling-extension-impl/gradle-tooling-extension-impl.iml
index 1bcde5e35b79..ea579287b3e8 100644
--- a/plugins/gradle/tooling-extension-impl/gradle-tooling-extension-impl.iml
+++ b/plugins/gradle/tooling-extension-impl/gradle-tooling-extension-impl.iml
@@ -67,6 +67,7 @@
<SOURCES />
</library>
</orderEntry>
+ <orderEntry type="library" name="gson" level="project" />
</component>
</module>
diff --git a/plugins/gradle/tooling-extension-impl/src/META-INF/services/org.jetbrains.plugins.gradle.tooling.ModelBuilderService b/plugins/gradle/tooling-extension-impl/src/META-INF/services/org.jetbrains.plugins.gradle.tooling.ModelBuilderService
index 244e58d2128e..816ef05c1e4d 100644
--- a/plugins/gradle/tooling-extension-impl/src/META-INF/services/org.jetbrains.plugins.gradle.tooling.ModelBuilderService
+++ b/plugins/gradle/tooling-extension-impl/src/META-INF/services/org.jetbrains.plugins.gradle.tooling.ModelBuilderService
@@ -17,3 +17,4 @@ org.jetbrains.plugins.gradle.tooling.builder.WarModelBuilderImpl
org.jetbrains.plugins.gradle.tooling.builder.ModuleExtendedModelBuilderImpl
org.jetbrains.plugins.gradle.tooling.builder.ModelBuildScriptClasspathBuilderImpl
org.jetbrains.plugins.gradle.tooling.builder.ScalaModelBuilderImpl
+org.jetbrains.plugins.gradle.tooling.builder.ExternalProjectBuilderImpl
diff --git a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/ExternalProjectBuilderImpl.groovy b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/ExternalProjectBuilderImpl.groovy
new file mode 100644
index 000000000000..3bb6b471b755
--- /dev/null
+++ b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/ExternalProjectBuilderImpl.groovy
@@ -0,0 +1,231 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.plugins.gradle.tooling.builder
+
+import com.google.gson.GsonBuilder
+import com.intellij.openapi.externalSystem.model.*
+import com.intellij.openapi.externalSystem.model.project.ExternalSystemSourceType
+import org.gradle.api.Action
+import org.gradle.api.Project
+import org.gradle.api.Task
+import org.gradle.api.file.ContentFilterable
+import org.gradle.api.file.FileCopyDetails
+import org.gradle.api.tasks.SourceSet
+import org.gradle.api.tasks.SourceSetContainer
+import org.gradle.api.tasks.util.PatternFilterable
+import org.jetbrains.annotations.NotNull
+import org.jetbrains.annotations.Nullable
+import org.jetbrains.plugins.gradle.tooling.ErrorMessageBuilder
+import org.jetbrains.plugins.gradle.tooling.ModelBuilderService
+
+import java.util.concurrent.ConcurrentHashMap
+
+/**
+ * @author Vladislav.Soroka
+ * @since 12/20/13
+ */
+class ExternalProjectBuilderImpl implements ModelBuilderService {
+
+ private final cache = new ConcurrentHashMap<String, ExternalProject>()
+
+ @Override
+ public boolean canBuild(String modelName) {
+ return ExternalProject.name.equals(modelName)
+ }
+
+ @Nullable
+ @Override
+ public Object buildAll(final String modelName, final Project project) {
+ ExternalProject externalProject = cache[project.path]
+ if (externalProject != null) return externalProject
+
+ DefaultExternalProject defaultExternalProject = new DefaultExternalProject()
+ defaultExternalProject.externalSystemId = "GRADLE"
+ defaultExternalProject.name = project.name
+ defaultExternalProject.QName = ":".equals(project.path) ? project.name : project.path
+ defaultExternalProject.version = wrap(project.version)
+ defaultExternalProject.description = project.description
+ defaultExternalProject.buildDir = project.buildDir
+ defaultExternalProject.buildFile = project.buildFile
+ defaultExternalProject.group = wrap(project.group)
+ defaultExternalProject.projectDir = project.projectDir
+ defaultExternalProject.sourceSets = getSourceSets(project)
+ defaultExternalProject.tasks = getTasks(project)
+
+ defaultExternalProject.plugins = getPlugins(project)
+ //defaultExternalProject.setProperties(project.getProperties())
+
+
+ final Map<String, ExternalProject> childProjects = new HashMap<String, ExternalProject>(project.getChildProjects().size())
+ for (Map.Entry<String, Project> projectEntry : project.getChildProjects().entrySet()) {
+ final Object externalProjectChild = buildAll(modelName, projectEntry.getValue())
+ if (externalProjectChild instanceof ExternalProject) {
+ childProjects.put(projectEntry.getKey(), (ExternalProject)externalProjectChild)
+ }
+ }
+ defaultExternalProject.setChildProjects(childProjects)
+ cache.put(project.getPath(), defaultExternalProject)
+
+ defaultExternalProject
+ }
+
+ static Map<String, ExternalPlugin> getPlugins(Project project) {
+ def result = [:] as Map<String, ExternalPlugin>
+ project.convention.plugins.each { key, value ->
+ ExternalPlugin externalPlugin = new DefaultExternalPlugin()
+ externalPlugin.id = key
+ result.put(key, externalPlugin)
+ }
+
+ result
+ }
+
+ static Map<String, ExternalTask> getTasks(Project project) {
+ def result = [:] as Map<String, ExternalTask>
+
+ project.tasks.all { Task task ->
+ ExternalTask externalTask = new DefaultExternalTask()
+ externalTask.name = task.name
+ externalTask.description = task.description
+ externalTask.group = task.group
+ externalTask.QName = task.path
+ result.put(externalTask.QName, externalTask)
+ }
+
+ result
+ }
+
+ static Map<String, ExternalSourceSet> getSourceSets(Project project) {
+ def result = [:] as Map<String, ExternalSourceSet>
+ if (!project.hasProperty("sourceSets") || !(project.sourceSets instanceof SourceSetContainer)) {
+ return result
+ }
+ def sourceSets = project.sourceSets as SourceSetContainer
+
+ def (resourcesIncludes, resourcesExcludes, filterReaders) = getFilters(project, 'processResources')
+ def (testResourcesIncludes, testResourcesExcludes, testFilterReaders) = getFilters(project, 'processTestResources')
+ //def (javaIncludes,javaExcludes) = getFilters(project,'compileJava')
+
+ sourceSets.all { SourceSet sourceSet ->
+ ExternalSourceSet externalSourceSet = new DefaultExternalSourceSet()
+ externalSourceSet.name = sourceSet.name
+
+ def sources = [:] as Map<ExternalSystemSourceType, ExternalSourceDirectorySet>
+ ExternalSourceDirectorySet resourcesDirectorySet = new DefaultExternalSourceDirectorySet()
+ resourcesDirectorySet.name = sourceSet.resources.name
+ resourcesDirectorySet.srcDirs = sourceSet.resources.srcDirs
+ resourcesDirectorySet.outputDir = sourceSet.output.resourcesDir
+
+ ExternalSourceDirectorySet javaDirectorySet = new DefaultExternalSourceDirectorySet()
+ javaDirectorySet.name = sourceSet.allJava.name
+ javaDirectorySet.srcDirs = sourceSet.allJava.srcDirs
+ javaDirectorySet.outputDir = sourceSet.output.classesDir
+// javaDirectorySet.excludes = javaExcludes + sourceSet.java.excludes;
+// javaDirectorySet.includes = javaIncludes + sourceSet.java.includes;
+
+ if (SourceSet.TEST_SOURCE_SET_NAME.equals(sourceSet.name)) {
+ resourcesDirectorySet.excludes = testResourcesExcludes + sourceSet.resources.excludes;
+ resourcesDirectorySet.includes = testResourcesIncludes + sourceSet.resources.includes;
+ resourcesDirectorySet.filters = testFilterReaders
+ sources.put(ExternalSystemSourceType.TEST, javaDirectorySet)
+ sources.put(ExternalSystemSourceType.TEST_RESOURCE, resourcesDirectorySet)
+ }
+ else {
+ resourcesDirectorySet.excludes = resourcesExcludes + sourceSet.resources.excludes;
+ resourcesDirectorySet.includes = resourcesIncludes + sourceSet.resources.includes;
+ resourcesDirectorySet.filters = filterReaders
+ sources.put(ExternalSystemSourceType.SOURCE, javaDirectorySet)
+ sources.put(ExternalSystemSourceType.RESOURCE, resourcesDirectorySet)
+ }
+
+ externalSourceSet.sources = sources
+ result[sourceSet.name] = externalSourceSet
+ }
+ result
+ }
+
+ static getFilters(Project project, String taskName) {
+ def includes = []
+ def excludes = []
+ def filterReaders = [] as List<ExternalFilter>
+ def filterableTask = project.tasks.findByName(taskName)
+ if (filterableTask instanceof PatternFilterable) {
+ includes += filterableTask.includes
+ excludes += filterableTask.excludes
+ }
+
+ if(System.getProperty('idea.disable.gradle.resource.filtering', 'false').toBoolean()) {
+ return [includes, excludes, filterReaders]
+ }
+
+ try {
+ if (filterableTask instanceof ContentFilterable && filterableTask.metaClass.respondsTo(filterableTask, "getMainSpec")) {
+ def properties = filterableTask.getMainSpec().properties
+ def copyActions = properties?.allCopyActions ?: properties?.copyActions
+
+ if(copyActions) {
+ copyActions.each { Action<? super FileCopyDetails> action ->
+ if (action.hasProperty('val$filterType') && action.hasProperty('val$properties')) {
+ def filterType = (action?.val$filterType as Class).name
+ def filter = [filterType: filterType] as DefaultExternalFilter
+ def props = action?.val$properties
+ if (props) {
+ filter.propertiesAsJsonMap = new GsonBuilder().create().toJson(props);
+ }
+ filterReaders << filter
+ }
+ else if (action.class.simpleName.equals('RenamingCopyAction') && action.hasProperty('transformer')) {
+ if (action.transformer.hasProperty('matcher') && action?.transformer.hasProperty('replacement')) {
+ String pattern = action?.transformer?.matcher.pattern().pattern
+ String replacement = action?.transformer?.replacement
+ def filter = [filterType: 'RenamingCopyFilter'] as DefaultExternalFilter
+ if(pattern && replacement){
+ filter.propertiesAsJsonMap = new GsonBuilder().create().toJson([pattern: pattern, replacement: replacement]);
+ filterReaders << filter
+ }
+ }
+ }
+// else {
+// project.logger.error(
+// ErrorMessageBuilder.create(project, "Resource configuration errors")
+// .withDescription("Unsupported copy action found: " + action.class.name).build())
+// }
+ }
+ }
+ }
+ }
+ catch (Exception ignore) {
+// project.logger.error(
+// ErrorMessageBuilder.create(project, e, "Resource configuration errors")
+// .withDescription("Unable to resolve resources filtering configuration").build())
+ }
+
+ return [includes, excludes, filterReaders]
+ }
+
+
+ private static String wrap(Object o) {
+ return o instanceof CharSequence ? o.toString() : ""
+ }
+
+ @NotNull
+ @Override
+ public ErrorMessageBuilder getErrorMessageBuilder(@NotNull Project project, @NotNull Exception e) {
+ return ErrorMessageBuilder.create(
+ project, e, "Project resolve errors"
+ ).withDescription("Unable to resolve additional project configuration.")
+ }
+}
diff --git a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/WarModelBuilderImpl.groovy b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/WarModelBuilderImpl.groovy
index 00f4c8bb0b6e..2eb7137949e2 100644
--- a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/WarModelBuilderImpl.groovy
+++ b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/WarModelBuilderImpl.groovy
@@ -88,20 +88,25 @@ class WarModelBuilderImpl implements ModelBuilderService {
if (resolver.metaClass.respondsTo(resolver, 'getSourcePaths')) {
sourcePaths = resolver.getSourcePaths()
- } else if (resolver.this$0.metaClass.respondsTo(resolver, 'getSourcePaths')) {
+ } else if (resolver.hasProperty('sourcePaths')) {
+ sourcePaths = resolver.sourcePaths
+ } else if (resolver.hasProperty('this$0') && resolver.this$0.metaClass.respondsTo(resolver, 'getSourcePaths')) {
sourcePaths = resolver.this$0.getSourcePaths()
- } else {
+ } else if (resolver.hasProperty('this$0') && resolver.this$0.hasProperty('sourcePaths')) {
+ sourcePaths = resolver.this$0.sourcePaths
+ } /*else {
throw new RuntimeException("${GradleVersion.current()} is not supported by web artifact importer")
- }
+ }*/
- (sourcePaths.flatten() as List).each { def path ->
- if (path instanceof String) {
- def file = new File(warTask.project.projectDir, path)
- addPath(webResources, relativePath, "", file)
+ if(sourcePaths) {
+ (sourcePaths.flatten() as List).each { def path ->
+ if (path instanceof String) {
+ def file = new File(warTask.project.projectDir, path)
+ addPath(webResources, relativePath, "", file)
+ }
}
}
-
resolver.source.visit(new FileVisitor() {
@Override
public void visitDir(FileVisitDetails dirDetails) {
diff --git a/plugins/gradle/tooling-extension-impl/testSources/org/jetbrains/plugins/gradle/tooling/builder/AbstractModelBuilderTest.java b/plugins/gradle/tooling-extension-impl/testSources/org/jetbrains/plugins/gradle/tooling/builder/AbstractModelBuilderTest.java
index d09a9b7c5e3c..faf3a98bc3a4 100644
--- a/plugins/gradle/tooling-extension-impl/testSources/org/jetbrains/plugins/gradle/tooling/builder/AbstractModelBuilderTest.java
+++ b/plugins/gradle/tooling-extension-impl/testSources/org/jetbrains/plugins/gradle/tooling/builder/AbstractModelBuilderTest.java
@@ -15,6 +15,7 @@
*/
package org.jetbrains.plugins.gradle.tooling.builder;
+import com.intellij.openapi.externalSystem.model.ExternalProject;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.testFramework.UsefulTestCase;
@@ -127,7 +128,7 @@ public abstract class AbstractModelBuilderTest {
BuildActionExecuter<ProjectImportAction.AllModels> buildActionExecutor = connection.action(projectImportAction);
File initScript = GradleExecutionHelper.generateInitScript(false, getToolingExtensionClasses());
assertNotNull(initScript);
- buildActionExecutor.withArguments(GradleConstants.INIT_SCRIPT_CMD_OPTION, initScript.getAbsolutePath());
+ buildActionExecutor.withArguments("--recompile-scripts", GradleConstants.INIT_SCRIPT_CMD_OPTION, initScript.getAbsolutePath());
allModels = buildActionExecutor.run();
assertNotNull(allModels);
}
@@ -135,6 +136,7 @@ public abstract class AbstractModelBuilderTest {
@NotNull
private Set<Class> getToolingExtensionClasses() {
final Set<Class> classes = ContainerUtil.<Class>set(
+ ExternalProject.class,
// gradle-tooling-extension-api jar
ProjectImportAction.class,
// gradle-tooling-extension-impl jar
diff --git a/plugins/groovy/groovy-psi/src/resources/groovyInjections.xml b/plugins/groovy/groovy-psi/src/resources/groovyInjections.xml
index dcb426aa135f..910d211476f6 100644
--- a/plugins/groovy/groovy-psi/src/resources/groovyInjections.xml
+++ b/plugins/groovy/groovy-psi/src/resources/groovyInjections.xml
@@ -50,4 +50,13 @@
<display-name>RegExp</display-name>
<place><![CDATA[groovyLiteralExpression().regExpOperatorArgument()]]></place>
</injection>
+ <injection language="encoding-reference" injector-id="java">
+ <display-name>Charset Name</display-name>
+ <place><![CDATA[psiParameter().ofMethod(0, psiMethod().withName("getBytes").withParameters("java.lang.String").definedInClass("groovy.lang.GString"))]]></place>
+ <place><![CDATA[psiParameter().ofMethod(1, psiMethod().withName("newPrintWriter").withParameters("java.io.File", "java.lang.String").definedInClass("org.codehaus.groovy.runtime.DefaultGroovyMethods"))]]></place>
+ <place><![CDATA[psiParameter().ofMethod(1, psiMethod().withName("newReader").withParameters("java.io.File", "java.lang.String").definedInClass("org.codehaus.groovy.runtime.DefaultGroovyMethods"))]]></place>
+ <place><![CDATA[psiParameter().ofMethod(1, psiMethod().withName("newReader").withParameters("java.io.InputStream", "java.lang.String").definedInClass("org.codehaus.groovy.runtime.DefaultGroovyMethods"))]]></place>
+ <place><![CDATA[psiParameter().ofMethod(1, psiMethod().withName("newWriter").withParameters("java.io.File", "java.lang.String").definedInClass("org.codehaus.groovy.runtime.DefaultGroovyMethods"))]]></place>
+ <place><![CDATA[psiParameter().ofMethod(1, psiMethod().withName("newWriter").withParameters("java.io.File", "java.lang.String", "boolean").definedInClass("org.codehaus.groovy.runtime.DefaultGroovyMethods"))]]></place>
+ </injection>
</component>
diff --git a/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java b/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java
index 855deba56575..03e3b544b5ed 100644
--- a/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java
+++ b/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java
@@ -18,6 +18,7 @@ package org.jetbrains.jps.incremental.groovy;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
@@ -58,6 +59,8 @@ import org.jetbrains.jps.model.library.sdk.JpsSdk;
import org.jetbrains.jps.service.JpsServiceManager;
import org.jetbrains.jps.service.SharedThreadPool;
import org.jetbrains.org.objectweb.asm.ClassReader;
+import org.jetbrains.org.objectweb.asm.ClassVisitor;
+import org.jetbrains.org.objectweb.asm.Opcodes;
import java.io.File;
import java.io.IOException;
@@ -434,9 +437,14 @@ public class GroovyBuilder extends ModuleLevelBuilder {
final String sourcePath = FileUtil.toSystemIndependentName(item.sourcePath);
final String outputPath = FileUtil.toSystemIndependentName(item.outputPath);
final File outputFile = new File(outputPath);
- outputConsumer.registerOutputFile(target, outputFile, Collections.singleton(sourcePath));
+ final File srcFile = new File(sourcePath);
try {
- callback.associate(outputPath, sourcePath, new ClassReader(FileUtil.loadFileBytes(outputFile)));
+ final byte[] bytes = FileUtil.loadFileBytes(outputFile);
+ outputConsumer.registerCompiledClass(
+ target,
+ new CompiledClass(outputFile, srcFile, readClassName(bytes), new BinaryContent(bytes))
+ );
+ callback.associate(outputPath, sourcePath, new ClassReader(bytes));
}
catch (Throwable e) {
// need this to make sure that unexpected errors in, for example, ASM will not ruin the compilation
@@ -446,7 +454,7 @@ public class GroovyBuilder extends ModuleLevelBuilder {
myBuilderName, BuildMessage.Kind.WARNING, message + "\n" + CompilerMessage.getTextFromThrowable(e), sourcePath)
);
}
- successfullyCompiledFiles.add(new File(sourcePath));
+ successfullyCompiledFiles.add(srcFile);
}
}
}
@@ -454,6 +462,16 @@ public class GroovyBuilder extends ModuleLevelBuilder {
return JavaBuilderUtil.updateMappings(context, delta, dirtyFilesHolder, chunk, toCompile, successfullyCompiledFiles);
}
+ private static String readClassName(byte[] classBytes) throws IOException{
+ final Ref<String> nameRef = Ref.create(null);
+ new ClassReader(classBytes).accept(new ClassVisitor(Opcodes.ASM5) {
+ public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
+ nameRef.set(name.replace('/', '.'));
+ }
+ }, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
+ return nameRef.get();
+ }
+
private static Collection<String> generateClasspath(CompileContext context, ModuleChunk chunk) {
final Set<String> cp = new LinkedHashSet<String>();
//groovy_rt.jar
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyDebuggerSettings.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyDebuggerSettings.java
index 273fd4cb8531..c2538426a871 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyDebuggerSettings.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyDebuggerSettings.java
@@ -19,23 +19,31 @@ import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
import com.intellij.openapi.components.StoragePathMacros;
import com.intellij.openapi.options.Configurable;
+import com.intellij.openapi.options.SimpleConfigurable;
+import com.intellij.openapi.util.Getter;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.util.xmlb.XmlSerializerUtil;
+import com.intellij.xdebugger.settings.DebuggerSettingsCategory;
import com.intellij.xdebugger.settings.XDebuggerSettings;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.groovy.GroovyBundle;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import static java.util.Collections.singletonList;
/**
* @author ilyas
*/
@State(
- name = "GroovyDebuggerSettings",
- storages = {
+ name = "GroovyDebuggerSettings",
+ storages = {
@Storage(
- file = StoragePathMacros.APP_CONFIG + "/groovy_debug.xml"
+ file = StoragePathMacros.APP_CONFIG + "/groovy_debug.xml"
)}
)
-public class GroovyDebuggerSettings extends XDebuggerSettings<GroovyDebuggerSettings> {
+public class GroovyDebuggerSettings extends XDebuggerSettings<GroovyDebuggerSettings> implements Getter<GroovyDebuggerSettings> {
public Boolean DEBUG_DISABLE_SPECIFIC_GROOVY_METHODS = true;
public boolean ENABLE_GROOVY_HOTSWAP = Registry.is("enable.groovy.hotswap");
@@ -43,19 +51,19 @@ public class GroovyDebuggerSettings extends XDebuggerSettings<GroovyDebuggerSett
super("groovy_debugger");
}
- @Override
@NotNull
- public Configurable createConfigurable() {
- return new GroovyDebuggerSettingsConfigurable(this);
- }
-
- @Nullable
+ @SuppressWarnings("EnumSwitchStatementWhichMissesCases")
@Override
- public Configurable createConfigurable(@NotNull Category category) {
- if (category == Category.STEPPING) {
- return new GroovySteppingConfigurable();
+ public Collection<? extends Configurable> createConfigurables(@NotNull DebuggerSettingsCategory category) {
+ switch (category) {
+ case STEPPING:
+ return singletonList(SimpleConfigurable.create("reference.idesettings.debugger.groovy", GroovyBundle.message("groovy.debug.caption"),
+ "reference.idesettings.debugger.groovy", GroovySteppingConfigurableUi.class, this));
+ case HOTSWAP:
+ return singletonList(SimpleConfigurable.create("reference.idesettings.debugger.groovy", GroovyBundle.message("groovy.debug.caption"),
+ "reference.idesettings.debugger.groovy", GroovyHotSwapConfigurableUi.class, this));
}
- return null;
+ return Collections.emptyList();
}
@Override
@@ -71,4 +79,9 @@ public class GroovyDebuggerSettings extends XDebuggerSettings<GroovyDebuggerSett
public static GroovyDebuggerSettings getInstance() {
return getInstance(GroovyDebuggerSettings.class);
}
+
+ @Override
+ public GroovyDebuggerSettings get() {
+ return this;
+ }
} \ No newline at end of file
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyDebuggerSettingsConfigurable.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyDebuggerSettingsConfigurable.java
deleted file mode 100644
index 8f143d9a5fd1..000000000000
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyDebuggerSettingsConfigurable.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright 2000-2014 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jetbrains.plugins.groovy.debugger;
-
-import com.intellij.openapi.options.ConfigurationException;
-import com.intellij.openapi.options.SearchableConfigurable;
-import org.jetbrains.annotations.Nls;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.plugins.groovy.GroovyBundle;
-
-import javax.swing.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-
-/**
- * @author ilyas
- */
-public class GroovyDebuggerSettingsConfigurable implements SearchableConfigurable {
- private JPanel myPanel;
- private JCheckBox myEnableHotSwap;
- private boolean isModified = false;
- private final GroovyDebuggerSettings mySettings;
-
- public GroovyDebuggerSettingsConfigurable(final GroovyDebuggerSettings settings) {
- mySettings = settings;
-
- myEnableHotSwap.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(final ActionEvent e) {
- isModified = mySettings.ENABLE_GROOVY_HOTSWAP != myEnableHotSwap.isSelected();
- }
- });
- }
-
- @Override
- @Nls
- public String getDisplayName() {
- return GroovyBundle.message("groovy.debug.caption");
- }
-
- @Override
- @NotNull
- public String getHelpTopic() {
- return "reference.idesettings.debugger.groovy";
- }
-
- @Override
- @NotNull
- public String getId() {
- return getHelpTopic();
- }
-
- @Override
- public Runnable enableSearch(String option) {
- return null;
- }
-
- @Override
- public JComponent createComponent() {
- return myPanel;
- }
-
- @Override
- public boolean isModified() {
- return isModified;
- }
-
- @Override
- public void apply() throws ConfigurationException {
- if (isModified) {
- mySettings.ENABLE_GROOVY_HOTSWAP = myEnableHotSwap.isSelected();
- }
- isModified = false;
- }
-
- @Override
- public void reset() {
- myEnableHotSwap.setSelected(mySettings.ENABLE_GROOVY_HOTSWAP);
- }
-
- @Override
- public void disposeUIResources() {
- }
-}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyDebuggerSettingsConfigurable.form b/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyHotSwapConfigurableUi.form
index 171170b00571..cbe2154a9d31 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyDebuggerSettingsConfigurable.form
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyHotSwapConfigurableUi.form
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.plugins.groovy.debugger.GroovyDebuggerSettingsConfigurable">
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.plugins.groovy.debugger.GroovyHotSwapConfigurableUi">
<grid id="27dc6" binding="myPanel" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
@@ -19,6 +19,7 @@
</constraints>
<properties>
<componentStyle value="SMALL"/>
+ <fontColor value="BRIGHTER"/>
<text value="May cause serialization issues in the debugged application"/>
</properties>
</component>
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyHotSwapConfigurableUi.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyHotSwapConfigurableUi.java
new file mode 100644
index 000000000000..400d344bb156
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyHotSwapConfigurableUi.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.plugins.groovy.debugger;
+
+import com.intellij.openapi.options.ConfigurableUi;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+
+/**
+ * @author ilyas
+ */
+class GroovyHotSwapConfigurableUi implements ConfigurableUi<GroovyDebuggerSettings> {
+ private JPanel myPanel;
+ private JCheckBox myEnableHotSwap;
+
+ @NotNull
+ @Override
+ public JComponent getComponent() {
+ return myPanel;
+ }
+
+ @Override
+ public boolean isModified(@NotNull GroovyDebuggerSettings settings) {
+ return settings.ENABLE_GROOVY_HOTSWAP != myEnableHotSwap.isSelected();
+ }
+
+ @Override
+ public void apply(@NotNull GroovyDebuggerSettings settings) {
+ settings.ENABLE_GROOVY_HOTSWAP = myEnableHotSwap.isSelected();
+ }
+
+ @Override
+ public void reset(@NotNull GroovyDebuggerSettings settings) {
+ myEnableHotSwap.setSelected(settings.ENABLE_GROOVY_HOTSWAP);
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovySteppingConfigurable.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovySteppingConfigurable.java
deleted file mode 100644
index 0e5d99552d47..000000000000
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovySteppingConfigurable.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package org.jetbrains.plugins.groovy.debugger;
-
-import com.intellij.openapi.options.ConfigurableBase;
-import org.jetbrains.annotations.Nls;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import org.jetbrains.plugins.groovy.GroovyBundle;
-
-class GroovySteppingConfigurable extends ConfigurableBase<GroovySteppingConfigurableUi, GroovyDebuggerSettings> {
- @Override
- protected GroovyDebuggerSettings getSettings() {
- return GroovyDebuggerSettings.getInstance();
- }
-
- @Override
- protected GroovySteppingConfigurableUi createUi() {
- return new GroovySteppingConfigurableUi();
- }
-
- @NotNull
- @Override
- public String getId() {
- return "debugger.stepping.groovy";
- }
-
- @Nls
- @Override
- public String getDisplayName() {
- return GroovyBundle.message("groovy.debug.caption");
- }
-
- @Nullable
- @Override
- public String getHelpTopic() {
- return "reference.idesettings.debugger.groovy";
- }
-} \ No newline at end of file
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/GroovyReferenceCopyPasteProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/GroovyReferenceCopyPasteProcessor.java
index 63784b58f298..d4b67e1540bf 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/GroovyReferenceCopyPasteProcessor.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/GroovyReferenceCopyPasteProcessor.java
@@ -97,7 +97,7 @@ public class GroovyReferenceCopyPasteProcessor extends CopyPasteReferenceProcess
}
else {
if (reference instanceof GrReferenceExpression) {
- PsiElement referent = reference.resolve();
+ PsiElement referent = resolveReferenceIgnoreOverriding(reference);
if (!(referent instanceof PsiNamedElement)
|| !data.staticMemberName.equals(((PsiNamedElement)referent).getName())
|| !(referent instanceof PsiMember)
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/GroovySdkWizardStepBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/GroovySdkWizardStepBase.java
index 84b96c39fd78..19649574c2bc 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/GroovySdkWizardStepBase.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/GroovySdkWizardStepBase.java
@@ -23,7 +23,6 @@ import com.intellij.ide.util.projectWizard.ModuleWizardStep;
import com.intellij.ide.util.projectWizard.WizardContext;
import com.intellij.ide.wizard.CommitStepException;
import com.intellij.openapi.module.Module;
-import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.ui.configuration.projectRoot.LibrariesContainer;
@@ -51,8 +50,9 @@ public abstract class GroovySdkWizardStepBase extends ModuleWizardStep {
public GroovySdkWizardStepBase(@Nullable final MvcFramework framework, WizardContext wizardContext, String basePath) {
myBasePath = basePath;
- final Project project = wizardContext.getProject();
- myLibrariesContainer = LibrariesContainerFactory.createContainer(project);
+ myLibrariesContainer = wizardContext.getModulesProvider() == null
+ ? LibrariesContainerFactory.createContainer(wizardContext.getProject())
+ : LibrariesContainerFactory.createContainer(wizardContext, wizardContext.getModulesProvider());
myFramework = framework;
}
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTest.groovy
index 2b5933fb4d31..d6363fb560db 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTest.groovy
@@ -18,16 +18,28 @@ package org.jetbrains.plugins.groovy.compiler
import com.intellij.compiler.CompilerConfiguration
import com.intellij.compiler.CompilerConfigurationImpl
+import com.intellij.execution.executors.DefaultRunExecutor
+import com.intellij.execution.impl.DefaultJavaProgramRunner
+import com.intellij.execution.process.ProcessAdapter
+import com.intellij.execution.process.ProcessEvent
+import com.intellij.execution.process.ProcessHandler
+import com.intellij.execution.process.ProcessOutputTypes
+import com.intellij.execution.runners.ProgramRunner
import com.intellij.openapi.application.ApplicationManager
+import com.intellij.openapi.application.PathManager
import com.intellij.openapi.compiler.CompilerMessage
import com.intellij.openapi.compiler.CompilerMessageCategory
import com.intellij.openapi.compiler.options.ExcludeEntryDescription
import com.intellij.openapi.compiler.options.ExcludedEntriesConfiguration
import com.intellij.openapi.module.Module
import com.intellij.openapi.roots.ModuleRootModificationUtil
+import com.intellij.openapi.util.Key
+import com.intellij.openapi.util.Ref
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.PsiFile
+import com.intellij.testFramework.PsiTestUtil
import com.intellij.testFramework.TestLoggerFactory
+import org.jetbrains.annotations.NotNull
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile
/**
@@ -822,4 +834,35 @@ class AppTest {
def messages = make()
assert messages.find { it.message.contains("Cannot compile Groovy files: no Groovy library is defined for module 'dependent'") }
}
+
+ public void testGroovyOutputIsInstrumented() {
+ myFixture.addFileToProject("Bar.groovy",
+ "import org.jetbrains.annotations.NotNull; " +
+ "public class Bar {" +
+ "void xxx(@NotNull String param) { println param }\n" +
+ "static void main(String[] args) { new Bar().xxx(null) }"+
+ "}"
+ );
+
+ File annotations = new File(PathManager.getJarPathForClass(NotNull.class));
+ PsiTestUtil.addLibrary(myModule, "annotations", annotations.getParent(), annotations.getName());
+
+ assertEmpty(make());
+
+ final Ref<Boolean> exceptionFound = Ref.create(Boolean.FALSE);
+ ProcessHandler process = runProcess("Bar", myModule, DefaultRunExecutor.class, new ProcessAdapter() {
+ @Override
+ public void onTextAvailable(ProcessEvent event, Key outputType) {
+ if (ProcessOutputTypes.SYSTEM != outputType) {
+ if (!exceptionFound.get()) {
+ exceptionFound.set(event.getText().contains("java.lang.IllegalArgumentException: Argument for @NotNull parameter 'param' of Bar.xxx must not be null"));
+ }
+ }
+ }
+ }, ProgramRunner.PROGRAM_RUNNER_EP.findExtension(DefaultJavaProgramRunner.class));
+ process.waitFor();
+
+ assertTrue(exceptionFound.get());
+ }
+
}
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTestCase.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTestCase.java
index 7cbf9a9d665b..28b2e26949ad 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTestCase.java
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTestCase.java
@@ -44,6 +44,7 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import com.intellij.testFramework.CompilerTester;
import com.intellij.testFramework.IdeaTestUtil;
+import com.intellij.testFramework.PlatformTestUtil;
import com.intellij.testFramework.PsiTestUtil;
import com.intellij.testFramework.builders.JavaModuleFixtureBuilder;
import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase;
@@ -80,6 +81,13 @@ public abstract class GroovyCompilerTestCase extends JavaCodeInsightFixtureTestC
super.tuneFixture(moduleBuilder);
}
+ @Override
+ protected void runTest() throws Throwable {
+ if (PlatformTestUtil.COVERAGE_ENABLED_BUILD) return;
+
+ super.runTest();
+ }
+
protected static void addGroovyLibrary(final Module to) {
File jar = GroovyFacetUtil.getBundledGroovyJar();
PsiTestUtil.addLibrary(to, "groovy", jar.getParent(), jar.getName());
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/optimizeImports/OptimizeImportsTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/optimizeImports/OptimizeImportsTest.groovy
index 223927107763..ce323a17d5d9 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/optimizeImports/OptimizeImportsTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/optimizeImports/OptimizeImportsTest.groovy
@@ -15,11 +15,9 @@
*/
package org.jetbrains.plugins.groovy.refactoring.optimizeImports
-
import com.intellij.codeInsight.CodeInsightSettings
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.command.CommandProcessor
-import com.intellij.openapi.fileEditor.impl.TrailingSpacesStripper
import com.intellij.psi.codeStyle.CodeStyleSettings
import com.intellij.psi.codeStyle.CodeStyleSettingsManager
import com.intellij.psi.impl.source.PostprocessReformattingAspect
@@ -195,7 +193,6 @@ class Fooxx <caret>{
doOptimizeImports();
PostprocessReformattingAspect.getInstance(getProject()).doPostponedFormatting();
- TrailingSpacesStripper.stripIfNotCurrentLine(myFixture.getEditor().getDocument(), false);
myFixture.checkResultByFile(getTestName(false) + "_after.groovy");
}
finally {
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgLogSingleCommitAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgLogSingleCommitAction.java
index 7410b0e7703e..43ef70ed2446 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgLogSingleCommitAction.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgLogSingleCommitAction.java
@@ -16,76 +16,21 @@
package org.zmlx.hg4idea.action;
-import com.intellij.dvcs.DvcsUtil;
-import com.intellij.openapi.actionSystem.AnActionEvent;
-import com.intellij.openapi.actionSystem.CommonDataKeys;
+import com.intellij.dvcs.ui.VcsLogSingleCommitAction;
import com.intellij.openapi.components.ServiceManager;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
-import com.intellij.vcs.log.VcsFullCommitDetails;
-import com.intellij.vcs.log.VcsLog;
-import com.intellij.vcs.log.VcsLogDataKeys;
+import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
-import org.zmlx.hg4idea.HgVcs;
+import org.jetbrains.annotations.Nullable;
import org.zmlx.hg4idea.repo.HgRepository;
import org.zmlx.hg4idea.repo.HgRepositoryManager;
-import java.util.List;
-
-/**
- * @author Nadya Zabrodina
- */
-public abstract class HgLogSingleCommitAction extends DumbAwareAction {
-
- private static final Logger LOG = Logger.getInstance(HgLogSingleCommitAction.class);
-
- protected abstract void actionPerformed(@NotNull HgRepository repository, @NotNull VcsFullCommitDetails commit);
+public abstract class HgLogSingleCommitAction extends VcsLogSingleCommitAction<HgRepository> {
+ @Nullable
@Override
- public void actionPerformed(AnActionEvent e) {
- Data data = Data.collect(e);
- if (!data.isValid()) {
- return;
- }
-
- List<VcsFullCommitDetails> details = data.log.getSelectedDetails();
- if (details.size() != 1) {
- return;
- }
- VcsFullCommitDetails commit = details.get(0);
-
- HgRepositoryManager repositoryManager = ServiceManager.getService(data.project, HgRepositoryManager.class);
- final HgRepository repository = repositoryManager.getRepositoryForRoot(commit.getRoot());
- if (repository == null) {
- DvcsUtil.noVcsRepositoryForRoot(LOG, commit.getRoot(), data.project, repositoryManager, HgVcs.getInstance(data.project));
- return;
- }
-
- actionPerformed(repository, commit);
+ protected HgRepository getRepositoryForRoot(@NotNull Project project, @NotNull VirtualFile root) {
+ return ServiceManager.getService(project, HgRepositoryManager.class).getRepositoryForRoot(root);
}
- @Override
- public void update(AnActionEvent e) {
- Data data = Data.collect(e);
- boolean enabled = data.isValid() && data.log.getSelectedCommits().size() == 1;
- e.getPresentation().setVisible(data.isValid());
- e.getPresentation().setEnabled(enabled);
- }
-
- private static class Data {
- Project project;
- VcsLog log;
-
- static Data collect(AnActionEvent e) {
- Data data = new Data();
- data.project = e.getData(CommonDataKeys.PROJECT);
- data.log = e.getData(VcsLogDataKeys.VSC_LOG);
- return data;
- }
-
- boolean isValid() {
- return project != null && log != null && DvcsUtil.logHasRootForVcs(log, HgVcs.getKey());
- }
- }
}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/execution/HgCommandAuthenticator.java b/plugins/hg4idea/src/org/zmlx/hg4idea/execution/HgCommandAuthenticator.java
index 1d41cdc688f9..14f6c981777b 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/execution/HgCommandAuthenticator.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/execution/HgCommandAuthenticator.java
@@ -35,7 +35,7 @@ import org.zmlx.hg4idea.HgVcsMessages;
class HgCommandAuthenticator {
private static final Logger LOG = Logger.getInstance(HgCommandAuthenticator.class.getName());
-
+
private GetPasswordRunnable myGetPassword;
private final Project myProject;
private boolean myForceAuthorization;
@@ -71,7 +71,7 @@ class HgCommandAuthenticator {
}
public boolean promptForAuthentication(Project project, String proposedLogin, String uri, String path, @Nullable ModalityState state) {
- GetPasswordRunnable runnable = new GetPasswordRunnable(project, proposedLogin, uri, path, myForceAuthorization, state);
+ GetPasswordRunnable runnable = new GetPasswordRunnable(project, proposedLogin, uri, path, myForceAuthorization);
ApplicationManager.getApplication().invokeAndWait(runnable, state == null ? ModalityState.defaultModalityState() : state);
myGetPassword = runnable;
return runnable.isOk();
@@ -96,21 +96,14 @@ class HgCommandAuthenticator {
@Nullable private String myURL;
private boolean myRememberPassword;
private boolean myForceAuthorization;
- @Nullable private ModalityState myState;
-
- public GetPasswordRunnable(Project project,
- String proposedLogin,
- String uri,
- String path,
- boolean forceAuthorization,
- @Nullable ModalityState state) {
+
+ public GetPasswordRunnable(Project project, String proposedLogin, String uri, String path, boolean forceAuthorization) {
this.myProject = project;
this.myProposedLogin = proposedLogin;
this.myURL = uri + path;
this.myForceAuthorization = forceAuthorization;
- myState = state;
}
-
+
public void run() {
// find if we've already been here
@@ -135,9 +128,11 @@ class HgCommandAuthenticator {
final String key = keyForUrlAndLogin(myURL, login);
try {
final PasswordSafeImpl passwordSafe = (PasswordSafeImpl)PasswordSafe.getInstance();
- password = passwordSafe.getPassword(myProject, HgCommandAuthenticator.class, key, myState);
- }
- catch (PasswordSafeException e) {
+ password = passwordSafe.getMemoryProvider().getPassword(myProject, HgCommandAuthenticator.class, key);
+ if (password == null) {
+ password = passwordSafe.getPassword(myProject, HgCommandAuthenticator.class, key);
+ }
+ } catch (PasswordSafeException e) {
LOG.info("Couldn't get password for key [" + key + "]", e);
}
}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgLogProvider.java b/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgLogProvider.java
index 03c98621a8c2..4adec9dff515 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgLogProvider.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgLogProvider.java
@@ -64,10 +64,13 @@ public class HgLogProvider implements VcsLogProvider {
return HgHistoryUtil.loadMetadata(myProject, root, requirements.getCommitCount(), Collections.<String>emptyList());
}
- @NotNull
@Override
- public List<TimedVcsCommit> readAllHashes(@NotNull VirtualFile root, @NotNull Consumer<VcsUser> userRegistry) throws VcsException {
- return HgHistoryUtil.readAllHashes(myProject, root, userRegistry, Collections.<String>emptyList());
+ public void readAllHashes(@NotNull VirtualFile root, @NotNull Consumer<VcsUser> userRegistry,
+ @NotNull Consumer<TimedVcsCommit> commitConsumer) throws VcsException {
+ List<TimedVcsCommit> commits = HgHistoryUtil.readAllHashes(myProject, root, userRegistry, Collections.<String>emptyList());
+ for (TimedVcsCommit commit : commits) {
+ commitConsumer.consume(commit);
+ }
}
@NotNull
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgDiffFromHistoryHandler.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgDiffFromHistoryHandler.java
index 61d08bc94e8c..1d556a8b19cb 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgDiffFromHistoryHandler.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgDiffFromHistoryHandler.java
@@ -15,22 +15,13 @@
*/
package org.zmlx.hg4idea.provider;
-import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.progress.ProgressIndicator;
-import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.DialogBuilder;
-import com.intellij.openapi.util.Couple;
import com.intellij.openapi.vcs.FilePath;
+import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.changes.Change;
-import com.intellij.openapi.vcs.changes.ui.ChangesBrowser;
-import com.intellij.openapi.vcs.history.CurrentRevision;
-import com.intellij.openapi.vcs.history.DiffFromHistoryHandler;
-import com.intellij.openapi.vcs.history.VcsFileRevision;
-import com.intellij.openapi.vcs.history.VcsHistoryUtil;
+import com.intellij.openapi.vcs.history.BaseDiffFromHistoryHandler;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.util.Consumer;
import com.intellij.vcsUtil.VcsUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -44,111 +35,37 @@ import java.util.List;
*
* @author Nadya Zabrodina
*/
-public class HgDiffFromHistoryHandler implements DiffFromHistoryHandler {
+public class HgDiffFromHistoryHandler extends BaseDiffFromHistoryHandler<HgFileRevision> {
private static final Logger LOG = Logger.getInstance(HgDiffFromHistoryHandler.class);
- @NotNull private final Project myProject;
-
public HgDiffFromHistoryHandler(@NotNull Project project) {
- myProject = project;
+ super(project);
}
+ @NotNull
@Override
- public void showDiffForOne(@NotNull AnActionEvent e, @NotNull FilePath filePath,
- @NotNull VcsFileRevision previousRevision, @NotNull VcsFileRevision revision) {
- doShowDiff(filePath, previousRevision, revision, false);
+ protected List<Change> getChangesBetweenRevisions(@NotNull FilePath path, @NotNull HgFileRevision rev1, @Nullable HgFileRevision rev2) {
+ return executeDiff(path, rev1, rev2);
}
-
+ @NotNull
@Override
- public void showDiffForTwo(@NotNull FilePath filePath, @NotNull VcsFileRevision revision1, @NotNull VcsFileRevision revision2) {
- doShowDiff(filePath, revision1, revision2, true);
+ protected List<Change> getAffectedChanges(@NotNull FilePath path, @NotNull HgFileRevision rev) throws VcsException {
+ return executeDiff(path, null, rev);
}
- private void doShowDiff(@NotNull FilePath filePath, @NotNull VcsFileRevision revision1, @NotNull VcsFileRevision revision2,
- boolean autoSort) {
- if (!filePath.isDirectory()) {
- VcsHistoryUtil.showDifferencesInBackground(myProject, filePath, revision1, revision2, autoSort);
- }
- else if (revision2 instanceof CurrentRevision) {
- HgFileRevision left = (HgFileRevision)revision1;
- showDiffForDirectory(filePath, left, null);
- }
- else if (revision1.equals(VcsFileRevision.NULL)) {
- HgFileRevision right = (HgFileRevision)revision2;
- showDiffForDirectory(filePath, null, right);
- }
- else {
- HgFileRevision left = (HgFileRevision)revision1;
- HgFileRevision right = (HgFileRevision)revision2;
- if (autoSort) {
- Couple<VcsFileRevision> pair = VcsHistoryUtil.sortRevisions(revision1, revision2);
- left = (HgFileRevision)pair.first;
- right = (HgFileRevision)pair.second;
- }
- showDiffForDirectory(filePath, left, right);
- }
+ @NotNull
+ @Override
+ protected String getPresentableName(@NotNull HgFileRevision revision) {
+ return revision.getRevisionNumber().getChangeset();
}
- private void showDiffForDirectory(@NotNull final FilePath path,
- @Nullable final HgFileRevision rev1,
- @Nullable final HgFileRevision rev2) {
+ @NotNull
+ private List<Change> executeDiff(@NotNull FilePath path, @Nullable HgFileRevision rev1, @Nullable HgFileRevision rev2) {
VirtualFile root = VcsUtil.getVcsRootFor(myProject, path);
LOG.assertTrue(root != null, "Repository is null for " + path);
- calculateDiffInBackground(root, path, rev1, rev2, new Consumer<List<Change>>() {
- @Override
- public void consume(List<Change> changes) {
- showDirDiffDialog(path, rev1 != null ? rev1.getRevisionNumber().getChangeset() : null,
- rev2 != null ? rev2.getRevisionNumber().getChangeset() : null, changes);
- }
- });
- }
-
- // rev1 == null => rev2 is the initial commit
- // rev2 == null => comparing rev1 with local
- private void calculateDiffInBackground(@NotNull final VirtualFile root, @NotNull final FilePath path,
- @Nullable final HgFileRevision rev1, @Nullable final HgFileRevision rev2,
- final Consumer<List<Change>> successHandler) {
- new Task.Backgroundable(myProject, "Comparing revisions...") {
- private List<Change> myChanges;
- @Override
- public void run(@NotNull ProgressIndicator indicator) {
- if (myProject != null) {
- myChanges = HgUtil.getDiff(HgDiffFromHistoryHandler.this.myProject, root, path, rev1, rev2);
- }
- }
-
- @Override
- public void onSuccess() {
- successHandler.consume(myChanges);
- }
- }.queue();
- }
-
- private void showDirDiffDialog(@NotNull FilePath path, @Nullable String hash1, @Nullable String hash2, @NotNull List<Change> diff) {
- DialogBuilder dialogBuilder = new DialogBuilder(myProject);
- String title;
- if (hash2 != null) {
- if (hash1 != null) {
- title = String.format("Difference between %s and %s in %s", hash1, hash2, path.getName());
- }
- else {
- title = String.format("Initial commit %s in %s", hash2, path.getName());
- }
- }
- else {
- LOG.assertTrue(hash1 != null, "hash1 and hash2 can't both be null. Path: " + path);
- title = String.format("Difference between %s and local version in %s", hash1, path.getName());
- }
- dialogBuilder.setTitle(title);
- dialogBuilder.setActionDescriptors(new DialogBuilder.ActionDescriptor[]{new DialogBuilder.CloseDialogAction()});
- final ChangesBrowser changesBrowser = new ChangesBrowser(myProject, null, diff, null, false, true,
- null, ChangesBrowser.MyUseCase.COMMITTED_CHANGES, null);
- changesBrowser.setChangesToDisplay(diff);
- dialogBuilder.setCenterPanel(changesBrowser);
- dialogBuilder.showNotModal();
+ return HgUtil.getDiff(myProject, root, path, rev1, rev2);
}
-}
-
+} \ No newline at end of file
diff --git a/plugins/hg4idea/testSrc/hg4idea/test/HgExecutor.java b/plugins/hg4idea/testSrc/hg4idea/test/HgExecutor.java
index 2a654c4e534d..359c850362c9 100644
--- a/plugins/hg4idea/testSrc/hg4idea/test/HgExecutor.java
+++ b/plugins/hg4idea/testSrc/hg4idea/test/HgExecutor.java
@@ -65,7 +65,7 @@ public class HgExecutor extends Executor {
List<String> split = splitCommandInParameters(command);
split.add(0, HG_EXECUTABLE);
debug("hg " + command);
- return run(split, ignoreNonZeroExitCode);
+ return run(ourCurrentDir(), split, ignoreNonZeroExitCode);
}
public static void updateProject() {
diff --git a/plugins/java-i18n/src/com/intellij/codeInspection/i18n/folding/I18nMessageGotoDeclarationHandler.java b/plugins/java-i18n/src/com/intellij/codeInspection/i18n/folding/I18nMessageGotoDeclarationHandler.java
index 592bfbc6051f..155d83767f8b 100644
--- a/plugins/java-i18n/src/com/intellij/codeInspection/i18n/folding/I18nMessageGotoDeclarationHandler.java
+++ b/plugins/java-i18n/src/com/intellij/codeInspection/i18n/folding/I18nMessageGotoDeclarationHandler.java
@@ -39,7 +39,7 @@ public class I18nMessageGotoDeclarationHandler extends GotoDeclarationHandlerBas
int i = 4; //some street magic
while (element != null && i > 0) {
final ASTNode node = element.getNode();
- if (node != null && node.getUserData(KEY) != null) {
+ if (node != null && node.getUserData(KEY) instanceof PropertyFoldingBuilder) {
break;
}
else {
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFXNSDescriptor.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFXNSDescriptor.java
index 28c99b0ff067..9aa2e7250464 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFXNSDescriptor.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFXNSDescriptor.java
@@ -54,7 +54,7 @@ public class JavaFXNSDescriptor implements XmlNSDescriptor, Validator<XmlDocumen
final PsiClass paneClass = JavaPsiFacade.getInstance(project).findClass(JavaFxCommonClassNames.JAVAFX_SCENE_LAYOUT_PANE, GlobalSearchScope.allScope(project));
if (paneClass != null) {
final ArrayList<XmlElementDescriptor> result = new ArrayList<XmlElementDescriptor>();
- ClassInheritorsSearch.search(paneClass).forEach(new Processor<PsiClass>() {
+ ClassInheritorsSearch.search(paneClass, paneClass.getUseScope(), true, true, false).forEach(new Processor<PsiClass>() {
@Override
public boolean process(PsiClass psiClass) {
result.add(new JavaFxClassBackedElementDescriptor(psiClass.getName(), psiClass));
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxPropertyElementDescriptor.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxPropertyElementDescriptor.java
index b10ebcb76689..617895ff2576 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxPropertyElementDescriptor.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxPropertyElementDescriptor.java
@@ -78,7 +78,7 @@ public class JavaFxPropertyElementDescriptor implements XmlElementDescriptor {
if (collectionItemType != null) {
final PsiClass aClass = PsiUtil.resolveClassInType(collectionItemType);
if (aClass != null) {
- ClassInheritorsSearch.search(aClass).forEach(new Processor<PsiClass>() {
+ ClassInheritorsSearch.search(aClass, aClass.getUseScope(), true, true, false).forEach(new Processor<PsiClass>() {
@Override
public boolean process(PsiClass aClass) {
descriptors.add(new JavaFxClassBackedElementDescriptor(aClass.getName(), aClass));
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderEditorProvider.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderEditorProvider.java
index 6ea5c510ce4d..a0e9bd531ddc 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderEditorProvider.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderEditorProvider.java
@@ -27,7 +27,7 @@ public class SceneBuilderEditorProvider implements FileEditorProvider, DumbAware
public boolean accept(@NotNull Project project, @NotNull VirtualFile file) {
return JavaFxFileTypeFactory.FXML_EXTENSION.equalsIgnoreCase(file.getExtension()) &&
SystemInfo.isJavaVersionAtLeast("1.8") &&
- Registry.is("embed.scene.builder", true);
+ Registry.is("embed.scene.builder");
}
@NotNull
diff --git a/plugins/junit/src/com/intellij/execution/junit/TestObject.java b/plugins/junit/src/com/intellij/execution/junit/TestObject.java
index 9a7887621cb7..cc7c0ee66b74 100644
--- a/plugins/junit/src/com/intellij/execution/junit/TestObject.java
+++ b/plugins/junit/src/com/intellij/execution/junit/TestObject.java
@@ -217,7 +217,7 @@ public abstract class TestObject implements JavaCommandLine {
myJavaParameters.getClassPath().add(JavaSdkUtil.getIdeaRtJarPath());
myJavaParameters.getClassPath().add(PathUtil.getJarPathForClass(JUnitStarter.class));
- if (Registry.is("junit_sm_runner", false)) {
+ if (Registry.is("junit_sm_runner")) {
myJavaParameters.getClassPath().add(PathUtil.getJarPathForClass(ServiceMessageTypes.class));
}
myJavaParameters.getProgramParametersList().add(JUnitStarter.IDE_VERSION + JUnitStarter.VERSION);
@@ -273,7 +273,7 @@ public abstract class TestObject implements JavaCommandLine {
@Override
public ExecutionResult execute(final Executor executor, @NotNull final ProgramRunner runner) throws ExecutionException {
- final boolean smRunner = Registry.is("junit_sm_runner", false);
+ final boolean smRunner = Registry.is("junit_sm_runner");
if (smRunner) {
myJavaParameters.getVMParametersList().add("-Didea.junit.sm_runner");
}
diff --git a/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurationModel.java b/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurationModel.java
index fe5a13181ab9..9f04e6ac30bf 100644
--- a/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurationModel.java
+++ b/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurationModel.java
@@ -172,7 +172,7 @@ public class JUnitConfigurationModel {
final JUnitConfiguration.Data data = configuration.getPersistentData();
setTestType(data.TEST_OBJECT);
setJUnitTextValue(ALL_IN_PACKAGE, data.getPackageName());
- setJUnitTextValue(CLASS, data.getMainClassName().replaceAll("\\$", "\\."));
+ setJUnitTextValue(CLASS, data.getMainClassName() != null ? data.getMainClassName().replaceAll("\\$", "\\.") : "");
setJUnitTextValue(METHOD, data.getMethodName());
setJUnitTextValue(PATTERN, data.getPatternPresentation());
setJUnitTextValue(DIR, data.getDirName());
diff --git a/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/model/MavenExplicitProfiles.java b/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/model/MavenExplicitProfiles.java
new file mode 100644
index 000000000000..ed9886a7e352
--- /dev/null
+++ b/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/model/MavenExplicitProfiles.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.idea.maven.model;
+
+import gnu.trove.THashSet;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: vladimir.dubovik
+ * Date: 4/9/2014
+ * Time: 2:30 AM
+ */
+public class MavenExplicitProfiles implements Serializable {
+ public static final MavenExplicitProfiles NONE = new MavenExplicitProfiles(Collections.<String>emptySet());
+
+ private Collection<String> myEnabledProfiles;
+ private Collection<String> myDisabledProfiles;
+
+ public MavenExplicitProfiles(Collection<String> enabledProfiles, Collection<String> disabledProfiles) {
+ myEnabledProfiles = enabledProfiles;
+ myDisabledProfiles = disabledProfiles;
+ }
+
+ public MavenExplicitProfiles(Collection<String> enabledProfiles) {
+ this(enabledProfiles, Collections.<String>emptySet());
+ }
+
+ public Collection<String> getEnabledProfiles() {
+ return myEnabledProfiles;
+ }
+
+ public Collection<String> getDisabledProfiles() {
+ return myDisabledProfiles;
+ }
+
+ @Override
+ public MavenExplicitProfiles clone() {
+ return new MavenExplicitProfiles(new THashSet<String>(myEnabledProfiles), new THashSet<String>(myDisabledProfiles));
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ MavenExplicitProfiles that = (MavenExplicitProfiles)o;
+
+ if (!myEnabledProfiles.equals(that.myEnabledProfiles)) return false;
+ if (!myDisabledProfiles.equals(that.myDisabledProfiles)) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = myEnabledProfiles.hashCode();
+ result = 31 * result + myDisabledProfiles.hashCode();
+ return result;
+ }
+}
diff --git a/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/server/MavenServer.java b/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/server/MavenServer.java
index 7c945e8e0c39..827fc2816f5a 100644
--- a/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/server/MavenServer.java
+++ b/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/server/MavenServer.java
@@ -15,6 +15,7 @@
*/
package org.jetbrains.idea.maven.server;
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
import org.jetbrains.idea.maven.model.MavenModel;
import java.io.File;
@@ -35,6 +36,6 @@ public interface MavenServer extends Remote {
ProfileApplicationResult applyProfiles(MavenModel model,
File basedir,
- Collection<String> explicitProfiles,
+ MavenExplicitProfiles explicitProfiles,
Collection<String> alwaysOnProfiles) throws RemoteException;
}
diff --git a/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/server/MavenServerEmbedder.java b/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/server/MavenServerEmbedder.java
index 0c4be99814c1..6b3db15e7035 100644
--- a/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/server/MavenServerEmbedder.java
+++ b/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/server/MavenServerEmbedder.java
@@ -34,12 +34,15 @@ public interface MavenServerEmbedder extends Remote {
@NotNull
MavenServerExecutionResult resolveProject(@NotNull File file,
- @NotNull Collection<String> activeProfiles) throws RemoteException,
- MavenServerProcessCanceledException;
+ @NotNull Collection<String> activeProfiles,
+ @NotNull Collection<String> inactiveProfiles) throws RemoteException,
+ MavenServerProcessCanceledException;
@Nullable
- String evaluateEffectivePom(@NotNull File file, @NotNull List<String> activeProfiles) throws RemoteException,
- MavenServerProcessCanceledException;
+ String evaluateEffectivePom(@NotNull File file,
+ @NotNull List<String> activeProfiles,
+ @NotNull List<String> inactiveProfiles) throws RemoteException,
+ MavenServerProcessCanceledException;
@NotNull
MavenArtifact resolve(@NotNull MavenArtifactInfo info,
diff --git a/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/server/ProfileApplicationResult.java b/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/server/ProfileApplicationResult.java
index f86f74ce124f..d8283d4f8c0c 100644
--- a/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/server/ProfileApplicationResult.java
+++ b/plugins/maven/maven-server-api/src/org/jetbrains/idea/maven/server/ProfileApplicationResult.java
@@ -15,16 +15,16 @@
*/
package org.jetbrains.idea.maven.server;
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
import org.jetbrains.idea.maven.model.MavenModel;
import java.io.Serializable;
-import java.util.Collection;
public class ProfileApplicationResult implements Serializable {
private final MavenModel myModel;
- private final Collection<String> myActivatedProfiles;
+ private final MavenExplicitProfiles myActivatedProfiles;
- public ProfileApplicationResult(MavenModel model, Collection<String> activatedProfiles) {
+ public ProfileApplicationResult(MavenModel model, MavenExplicitProfiles activatedProfiles) {
myModel = model;
myActivatedProfiles = activatedProfiles;
}
@@ -33,7 +33,7 @@ public class ProfileApplicationResult implements Serializable {
return myModel;
}
- public Collection<String> getActivatedProfiles() {
+ public MavenExplicitProfiles getActivatedProfiles() {
return myActivatedProfiles;
}
}
diff --git a/plugins/maven/maven2-server-impl/src/org/jetbrains/idea/maven/server/Maven2ServerImpl.java b/plugins/maven/maven2-server-impl/src/org/jetbrains/idea/maven/server/Maven2ServerImpl.java
index 770b952e3de0..801bae42962d 100644
--- a/plugins/maven/maven2-server-impl/src/org/jetbrains/idea/maven/server/Maven2ServerImpl.java
+++ b/plugins/maven/maven2-server-impl/src/org/jetbrains/idea/maven/server/Maven2ServerImpl.java
@@ -15,6 +15,7 @@
*/
package org.jetbrains.idea.maven.server;
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
import org.jetbrains.idea.maven.model.MavenModel;
import org.jetbrains.idea.maven.server.embedder.Maven2ServerEmbedderImpl;
import org.jetbrains.idea.maven.server.embedder.Maven2ServerIndexerImpl;
@@ -76,7 +77,7 @@ public class Maven2ServerImpl extends MavenRemoteObject implements MavenServer {
public ProfileApplicationResult applyProfiles(MavenModel model,
File basedir,
- Collection<String> explicitProfiles,
+ MavenExplicitProfiles explicitProfiles,
Collection<String> alwaysOnProfiles) {
try {
return Maven2ServerEmbedderImpl.applyProfiles(model, basedir, explicitProfiles, alwaysOnProfiles);
diff --git a/plugins/maven/maven2-server-impl/src/org/jetbrains/idea/maven/server/embedder/Maven2ServerEmbedderImpl.java b/plugins/maven/maven2-server-impl/src/org/jetbrains/idea/maven/server/embedder/Maven2ServerEmbedderImpl.java
index 7ed82b0494dc..08e98de53c6c 100644
--- a/plugins/maven/maven2-server-impl/src/org/jetbrains/idea/maven/server/embedder/Maven2ServerEmbedderImpl.java
+++ b/plugins/maven/maven2-server-impl/src/org/jetbrains/idea/maven/server/embedder/Maven2ServerEmbedderImpl.java
@@ -127,13 +127,15 @@ public class Maven2ServerEmbedderImpl extends MavenRemoteObject implements Maven
@NotNull
public MavenServerExecutionResult resolveProject(@NotNull final File file,
- @NotNull final Collection<String> activeProfiles)
+ @NotNull final Collection<String> activeProfiles,
+ @NotNull final Collection<String> inactiveProfiles)
throws MavenServerProcessCanceledException, RemoteException {
return doExecute(new Executor<MavenServerExecutionResult>() {
public MavenServerExecutionResult execute() throws Exception {
DependencyTreeResolutionListener listener = new DependencyTreeResolutionListener(myConsoleWrapper);
MavenExecutionResult result = myImpl.resolveProject(file,
new ArrayList<String>(activeProfiles),
+ new ArrayList<String>(inactiveProfiles),
Arrays.<ResolutionListener>asList(listener));
return createExecutionResult(file, result, listener.getRootNode());
}
@@ -199,7 +201,7 @@ public class Maven2ServerEmbedderImpl extends MavenRemoteObject implements Maven
}
@Nullable
- public String evaluateEffectivePom(@NotNull File file, @NotNull List<String> activeProfiles) {
+ public String evaluateEffectivePom(@NotNull File file, @NotNull List<String> activeProfiles, @NotNull List<String> inactiveProfiles) {
throw new UnsupportedOperationException();
}
@@ -422,21 +424,29 @@ public class Maven2ServerEmbedderImpl extends MavenRemoteObject implements Maven
public static ProfileApplicationResult applyProfiles(MavenModel model,
File basedir,
- Collection<String> explicitProfiles,
+ MavenExplicitProfiles explicitProfiles,
Collection<String> alwaysOnProfiles) throws RemoteException {
Model nativeModel = Maven2ModelConverter.toNativeModel(model);
+ Collection<String> enabledProfiles = explicitProfiles.getEnabledProfiles();
+ Collection<String> disabledProfiles = explicitProfiles.getDisabledProfiles();
List<Profile> activatedPom = new ArrayList<Profile>();
List<Profile> activatedExternal = new ArrayList<Profile>();
List<Profile> activeByDefault = new ArrayList<Profile>();
List<Profile> rawProfiles = nativeModel.getProfiles();
List<Profile> expandedProfilesCache = null;
+ List<Profile> deactivatedProfiles = new ArrayList<Profile>();
for (int i = 0; i < rawProfiles.size(); i++) {
Profile eachRawProfile = rawProfiles.get(i);
- boolean shouldAdd = explicitProfiles.contains(eachRawProfile.getId()) || alwaysOnProfiles.contains(eachRawProfile.getId());
+ if (disabledProfiles.contains(eachRawProfile.getId())) {
+ deactivatedProfiles.add(eachRawProfile);
+ continue;
+ }
+
+ boolean shouldAdd = enabledProfiles.contains(eachRawProfile.getId()) || alwaysOnProfiles.contains(eachRawProfile.getId());
Activation activation = eachRawProfile.getActivation();
if (activation != null) {
@@ -479,7 +489,9 @@ public class Maven2ServerEmbedderImpl extends MavenRemoteObject implements Maven
}
return new ProfileApplicationResult(Maven2ModelConverter.convertModel(nativeModel, null),
- collectProfilesIds(activatedProfiles));
+ new MavenExplicitProfiles(collectProfilesIds(activatedProfiles),
+ collectProfilesIds(deactivatedProfiles))
+ );
}
private static ProfileActivator[] getProfileActivators(File basedir) throws RemoteException {
diff --git a/plugins/maven/maven2-server-impl/src/org/jetbrains/maven/embedder/MavenEmbedder.java b/plugins/maven/maven2-server-impl/src/org/jetbrains/maven/embedder/MavenEmbedder.java
index 3926a3d1f030..70a6e470926c 100644
--- a/plugins/maven/maven2-server-impl/src/org/jetbrains/maven/embedder/MavenEmbedder.java
+++ b/plugins/maven/maven2-server-impl/src/org/jetbrains/maven/embedder/MavenEmbedder.java
@@ -173,15 +173,18 @@ public class MavenEmbedder {
}
@NotNull
- public MavenExecutionResult resolveProject(@NotNull final File file, @NotNull final List<String> activeProfiles) {
- return resolveProject(file, activeProfiles, Collections.<ResolutionListener>emptyList());
+ public MavenExecutionResult resolveProject(@NotNull final File file,
+ @NotNull final List<String> activeProfiles,
+ @NotNull final List<String> inactiveProfiles) {
+ return resolveProject(file, activeProfiles, inactiveProfiles, Collections.<ResolutionListener>emptyList());
}
@NotNull
public MavenExecutionResult resolveProject(@NotNull final File file,
@NotNull final List<String> activeProfiles,
+ @NotNull final List<String> inactiveProfiles,
List<ResolutionListener> listeners) {
- MavenExecutionRequest request = createRequest(file, activeProfiles, Collections.<String>emptyList(), Collections.<String>emptyList());
+ MavenExecutionRequest request = createRequest(file, activeProfiles, inactiveProfiles, Collections.<String>emptyList());
ProjectBuilderConfiguration config = request.getProjectBuilderConfiguration();
request.getGlobalProfileManager().loadSettingsProfiles(mySettings);
diff --git a/plugins/maven/maven2-server-impl/test/org/jetbrains/idea/maven/embedder/MavenServerEmbedderTest.java b/plugins/maven/maven2-server-impl/test/org/jetbrains/idea/maven/embedder/MavenServerEmbedderTest.java
index 53a6d0fa6d72..0fc588e7127b 100644
--- a/plugins/maven/maven2-server-impl/test/org/jetbrains/idea/maven/embedder/MavenServerEmbedderTest.java
+++ b/plugins/maven/maven2-server-impl/test/org/jetbrains/idea/maven/embedder/MavenServerEmbedderTest.java
@@ -94,7 +94,8 @@ public class MavenServerEmbedderTest extends MavenImportingTestCase {
"<version>1</version>");
myEmbedder.customizeForResolve(new SoutMavenConsole(), EMPTY_MAVEN_PROCESS);
- MavenServerExecutionResult result = myEmbedder.execute(myProjectPom, Collections.<String>emptyList(), Arrays.asList("compile"));
+ MavenServerExecutionResult result =
+ myEmbedder.execute(myProjectPom, Collections.<String>emptyList(), Collections.<String>emptyList(), Arrays.asList("compile"));
assertNotNull(result.projectData);
assertNotNull(new File(getProjectPath(), "target").exists());
@@ -119,7 +120,8 @@ public class MavenServerEmbedderTest extends MavenImportingTestCase {
"</dependencies>");
myEmbedder.customizeForResolve(new SoutMavenConsole(), EMPTY_MAVEN_PROCESS);
- MavenServerExecutionResult result = myEmbedder.resolveProject(myProjectPom, Collections.<String>emptyList());
+ MavenServerExecutionResult result =
+ myEmbedder.resolveProject(myProjectPom, Collections.<String>emptyList(), Collections.<String>emptyList());
assertNotNull(result.projectData);
assertOrderedElementsAreEqual(result.unresolvedArtifacts);
@@ -135,7 +137,8 @@ public class MavenServerEmbedderTest extends MavenImportingTestCase {
"<version>1</version>");
myEmbedder.customizeForResolve(new SoutMavenConsole(), EMPTY_MAVEN_PROCESS);
- MavenServerExecutionResult result = myEmbedder.resolveProject(myProjectPom, Collections.<String>emptyList());
+ MavenServerExecutionResult result =
+ myEmbedder.resolveProject(myProjectPom, Collections.<String>emptyList(), Collections.<String>emptyList());
MavenModel project = result.projectData.mavenModel;
assertNotNull(project);
@@ -171,7 +174,8 @@ public class MavenServerEmbedderTest extends MavenImportingTestCase {
"</build>");
myEmbedder.customizeForResolve(new SoutMavenConsole(), EMPTY_MAVEN_PROCESS);
- MavenServerExecutionResult result = myEmbedder.resolveProject(myProjectPom, Collections.<String>emptyList());
+ MavenServerExecutionResult result =
+ myEmbedder.resolveProject(myProjectPom, Collections.<String>emptyList(), Collections.<String>emptyList());
assertNotNull(result.projectData);
assertOrderedElementsAreEqual(result.unresolvedArtifacts);
@@ -203,7 +207,8 @@ public class MavenServerEmbedderTest extends MavenImportingTestCase {
"</dependencies>");
myEmbedder.customizeForResolve(new SoutMavenConsole(), EMPTY_MAVEN_PROCESS);
- MavenServerExecutionResult result = myEmbedder.resolveProject(myProjectPom, Collections.<String>emptyList());
+ MavenServerExecutionResult result =
+ myEmbedder.resolveProject(myProjectPom, Collections.<String>emptyList(), Collections.<String>emptyList());
assertNotNull(result.projectData);
assertOrderedElementsAreEqual(result.unresolvedArtifacts);
@@ -264,7 +269,8 @@ public class MavenServerEmbedderTest extends MavenImportingTestCase {
"</dependencies>");
myEmbedder.customizeForResolve(new SoutMavenConsole(), EMPTY_MAVEN_PROCESS);
- MavenServerExecutionResult result = myEmbedder.resolveProject(myProjectPom, Collections.<String>emptyList());
+ MavenServerExecutionResult result =
+ myEmbedder.resolveProject(myProjectPom, Collections.<String>emptyList(), Collections.<String>emptyList());
assertNotNull(result.projectData);
assertOrderedElementsAreEqual(result.unresolvedArtifacts, new MavenId("fff", "zzz", "666"));
@@ -286,7 +292,8 @@ public class MavenServerEmbedderTest extends MavenImportingTestCase {
"</dependencies>");
myEmbedder.customizeForResolve(new SoutMavenConsole(), EMPTY_MAVEN_PROCESS);
- MavenServerExecutionResult result = myEmbedder.resolveProject(myProjectPom, Collections.<String>emptyList());
+ MavenServerExecutionResult result =
+ myEmbedder.resolveProject(myProjectPom, Collections.<String>emptyList(), Collections.<String>emptyList());
assertNotNull(result.projectData);
assertOrderedElementsAreEqual(result.unresolvedArtifacts, new MavenId("fff", "zzz", "666"));
@@ -304,7 +311,7 @@ public class MavenServerEmbedderTest extends MavenImportingTestCase {
"<version>1</version>" +
"<packaging>pom</packaging>");
myEmbedder.customizeForResolve(new SoutMavenConsole(), EMPTY_MAVEN_PROCESS);
- myEmbedder.execute(m, Collections.<String>emptyList(), Arrays.asList("install"));
+ myEmbedder.execute(m, Collections.<String>emptyList(), Collections.<String>emptyList(), Arrays.asList("install"));
myEmbedder.reset();
File fooParentFile = new File(repo, "test/foo-parent/1/foo-parent-1.pom");
assertTrue(fooParentFile.exists());
@@ -319,7 +326,7 @@ public class MavenServerEmbedderTest extends MavenImportingTestCase {
" <version>1</version>" +
"</parent>");
myEmbedder.customizeForResolve(new SoutMavenConsole(), EMPTY_MAVEN_PROCESS);
- myEmbedder.execute(m, Collections.<String>emptyList(), Arrays.asList("install"));
+ myEmbedder.execute(m, Collections.<String>emptyList(), Collections.<String>emptyList(), Arrays.asList("install"));
myEmbedder.reset();
assertTrue(new File(repo, "test/foo/1/foo-1.pom").exists());
@@ -339,7 +346,8 @@ public class MavenServerEmbedderTest extends MavenImportingTestCase {
"</dependencies>");
myEmbedder.customizeForResolve(new SoutMavenConsole(), EMPTY_MAVEN_PROCESS);
- MavenServerExecutionResult result = myEmbedder.resolveProject(myProjectPom, Collections.<String>emptyList());
+ MavenServerExecutionResult result =
+ myEmbedder.resolveProject(myProjectPom, Collections.<String>emptyList(), Collections.<String>emptyList());
assertNotNull(result.projectData);
assertOrderedElementsAreEqual(result.unresolvedArtifacts, new MavenId("test", "foo-parent", "1"));
@@ -361,7 +369,8 @@ public class MavenServerEmbedderTest extends MavenImportingTestCase {
"</dependencies>");
myEmbedder.customizeForResolve(new SoutMavenConsole(), EMPTY_MAVEN_PROCESS);
- MavenServerExecutionResult result = myEmbedder.resolveProject(myProjectPom, Collections.<String>emptyList());
+ MavenServerExecutionResult result =
+ myEmbedder.resolveProject(myProjectPom, Collections.<String>emptyList(), Collections.<String>emptyList());
assertNotNull(result);
assertOrderedElementsAreEqual(result.unresolvedArtifacts, new MavenId("fff", "zzz", "666"));
diff --git a/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerEmbedderImpl.java b/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerEmbedderImpl.java
index 66a5943211c7..854c099d25b4 100644
--- a/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerEmbedderImpl.java
+++ b/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerEmbedderImpl.java
@@ -300,20 +300,22 @@ public class Maven3ServerEmbedderImpl extends MavenRemoteObject implements Maven
@NotNull
@Override
- public MavenServerExecutionResult resolveProject(@NotNull File file, @NotNull Collection<String> activeProfiles)
+ public MavenServerExecutionResult resolveProject(@NotNull File file,
+ @NotNull Collection<String> activeProfiles,
+ @NotNull Collection<String> inactiveProfiles)
throws RemoteException, MavenServerProcessCanceledException {
DependencyTreeResolutionListener listener = new DependencyTreeResolutionListener(myConsoleWrapper);
- MavenExecutionResult result =
- doResolveProject(file, new ArrayList<String>(activeProfiles), Arrays.<ResolutionListener>asList(listener));
+ MavenExecutionResult result = doResolveProject(file, new ArrayList<String>(activeProfiles), new ArrayList<String>(inactiveProfiles),
+ Arrays.<ResolutionListener>asList(listener));
return createExecutionResult(file, result, listener.getRootNode());
}
@Nullable
@Override
- public String evaluateEffectivePom(@NotNull File file, @NotNull List<String> activeProfiles)
+ public String evaluateEffectivePom(@NotNull File file, @NotNull List<String> activeProfiles, @NotNull List<String> inactiveProfiles)
throws RemoteException, MavenServerProcessCanceledException {
- return MavenEffectivePomDumper.evaluateEffectivePom(this, file, activeProfiles);
+ return MavenEffectivePomDumper.evaluateEffectivePom(this, file, activeProfiles, inactiveProfiles);
}
public void executeWithMavenSession(MavenExecutionRequest request, Runnable runnable) {
@@ -350,9 +352,9 @@ public class Maven3ServerEmbedderImpl extends MavenRemoteObject implements Maven
@NotNull
public MavenExecutionResult doResolveProject(@NotNull final File file,
@NotNull final List<String> activeProfiles,
+ @NotNull final List<String> inactiveProfiles,
final List<ResolutionListener> listeners) throws RemoteException {
- final MavenExecutionRequest request =
- createRequest(file, activeProfiles, Collections.<String>emptyList(), Collections.<String>emptyList());
+ final MavenExecutionRequest request = createRequest(file, activeProfiles, inactiveProfiles, Collections.<String>emptyList());
request.setUpdateSnapshots(myAlwaysUpdateSnapshots);
@@ -899,21 +901,29 @@ public class Maven3ServerEmbedderImpl extends MavenRemoteObject implements Maven
public static ProfileApplicationResult applyProfiles(MavenModel model,
File basedir,
- Collection<String> explicitProfiles,
+ MavenExplicitProfiles explicitProfiles,
Collection<String> alwaysOnProfiles) throws RemoteException {
Model nativeModel = MavenModelConverter.toNativeModel(model);
+ Collection<String> enabledProfiles = explicitProfiles.getEnabledProfiles();
+ Collection<String> disabledProfiles = explicitProfiles.getDisabledProfiles();
List<Profile> activatedPom = new ArrayList<Profile>();
List<Profile> activatedExternal = new ArrayList<Profile>();
List<Profile> activeByDefault = new ArrayList<Profile>();
List<Profile> rawProfiles = nativeModel.getProfiles();
List<Profile> expandedProfilesCache = null;
+ List<Profile> deactivatedProfiles = new ArrayList<Profile>();
for (int i = 0; i < rawProfiles.size(); i++) {
Profile eachRawProfile = rawProfiles.get(i);
- boolean shouldAdd = explicitProfiles.contains(eachRawProfile.getId()) || alwaysOnProfiles.contains(eachRawProfile.getId());
+ if (disabledProfiles.contains(eachRawProfile.getId())) {
+ deactivatedProfiles.add(eachRawProfile);
+ continue;
+ }
+
+ boolean shouldAdd = enabledProfiles.contains(eachRawProfile.getId()) || alwaysOnProfiles.contains(eachRawProfile.getId());
Activation activation = eachRawProfile.getActivation();
if (activation != null) {
@@ -955,7 +965,10 @@ public class Maven3ServerEmbedderImpl extends MavenRemoteObject implements Maven
new DefaultProfileInjector().injectProfile(nativeModel, each, null, null);
}
- return new ProfileApplicationResult(MavenModelConverter.convertModel(nativeModel, null), collectProfilesIds(activatedProfiles));
+ return new ProfileApplicationResult(MavenModelConverter.convertModel(nativeModel, null),
+ new MavenExplicitProfiles(collectProfilesIds(activatedProfiles),
+ collectProfilesIds(deactivatedProfiles))
+ );
}
private static Model doInterpolate(Model result, File basedir) throws RemoteException {
diff --git a/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerImpl.java b/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerImpl.java
index 0e4d468297f3..cc33728cd46b 100644
--- a/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerImpl.java
+++ b/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerImpl.java
@@ -15,6 +15,7 @@
*/
package org.jetbrains.idea.maven.server;
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
import org.jetbrains.idea.maven.model.MavenModel;
import java.io.File;
@@ -74,7 +75,7 @@ public class Maven3ServerImpl extends MavenRemoteObject implements MavenServer {
public ProfileApplicationResult applyProfiles(MavenModel model,
File basedir,
- Collection<String> explicitProfiles,
+ MavenExplicitProfiles explicitProfiles,
Collection<String> alwaysOnProfiles) {
try {
return Maven3ServerEmbedderImpl.applyProfiles(model, basedir, explicitProfiles, alwaysOnProfiles);
diff --git a/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/MavenEffectivePomDumper.java b/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/MavenEffectivePomDumper.java
index 2d0c90dd3c0a..75d45f59fd08 100644
--- a/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/MavenEffectivePomDumper.java
+++ b/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/MavenEffectivePomDumper.java
@@ -47,14 +47,14 @@ public class MavenEffectivePomDumper {
@Nullable
public static String evaluateEffectivePom(final Maven3ServerEmbedderImpl embedder,
@NotNull final File file,
- @NotNull List<String> activeProfiles)
+ @NotNull List<String> activeProfiles,
+ @NotNull List<String> inactiveProfiles)
throws RemoteException, MavenServerProcessCanceledException {
final StringWriter w = new StringWriter();
try {
- final MavenExecutionRequest
- request = embedder.createRequest(file, activeProfiles, Collections.<String>emptyList(), Collections.<String>emptyList());
+ final MavenExecutionRequest request = embedder.createRequest(file, activeProfiles, inactiveProfiles, Collections.<String>emptyList());
embedder.executeWithMavenSession(request, new Runnable() {
@Override
diff --git a/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/MavenLeakDetector.java b/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/MavenLeakDetector.java
index 15899e7aa38f..a51ddfe0210a 100644
--- a/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/MavenLeakDetector.java
+++ b/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/MavenLeakDetector.java
@@ -18,6 +18,7 @@ package org.jetbrains.idea.maven.server;
import com.intellij.util.ReflectionUtil;
import java.rmi.RemoteException;
+import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.Map;
@@ -54,14 +55,14 @@ public class MavenLeakDetector {
}
private Map<Thread, Thread> getShutdownHooks() {
- Class clazz = null;
+ Class clazz;
try {
clazz = Class.forName("java.lang.ApplicationShutdownHooks");
}
catch (ClassNotFoundException e) {
// we can ignore this one
+ return Collections.emptyMap();
}
return ReflectionUtil.getField(clazz, null, Map.class, "hooks");
}
-
}
diff --git a/plugins/maven/pom.xml b/plugins/maven/pom.xml
index 41052264aaf0..c2f0c71115cd 100644
--- a/plugins/maven/pom.xml
+++ b/plugins/maven/pom.xml
@@ -9,7 +9,7 @@
<name>Maven Integration</name>
<description>Maven Integration plugin</description>
-
+
<repositories>
</repositories>
@@ -17,7 +17,7 @@
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-embedder</artifactId>
- <version>2.1-SNAPSHOT</version>
+ <version>3.0.5</version>
<exclusions>
<exclusion>
<groupId>aspectj</groupId>
@@ -38,9 +38,9 @@
</exclusions>
</dependency>
<dependency>
- <groupId>com.sonatype.nexus</groupId>
+ <groupId>org.sonatype.nexus</groupId>
<artifactId>nexus-indexer</artifactId>
- <version>1.0.0-SNAPSHOT</version>
+ <version>3.0.4</version>
<exclusions>
<exclusion>
<groupId>junit</groupId>
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenDomProjectProcessorUtils.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenDomProjectProcessorUtils.java
index ceebebb093e5..ba3d265b7d10 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenDomProjectProcessorUtils.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenDomProjectProcessorUtils.java
@@ -514,11 +514,12 @@ public class MavenDomProjectProcessorUtils {
MavenProject mavenProjectOrNull,
Processor<T> processor,
Function<? super MavenDomProfile, T> f) {
- Collection<String> activePropfiles = mavenProjectOrNull == null ? null : mavenProjectOrNull.getActivatedProfilesIds();
+ Collection<String> activeProfiles =
+ mavenProjectOrNull == null ? null : mavenProjectOrNull.getActivatedProfilesIds().getEnabledProfiles();
for (MavenDomProfile each : profilesDom.getProfiles()) {
XmlTag idTag = each.getId().getXmlTag();
if (idTag == null) continue;
- if (activePropfiles != null && !activePropfiles.contains(idTag.getValue().getTrimmedText())) continue;
+ if (activeProfiles != null && !activeProfiles.contains(idTag.getValue().getTrimmedText())) continue;
if (processProfile(each, processor, f)) return true;
}
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenPropertyResolver.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenPropertyResolver.java
index 66875895f278..0422898a2bbb 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenPropertyResolver.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenPropertyResolver.java
@@ -81,10 +81,10 @@ public class MavenPropertyResolver {
@Nullable Map<String, String> resolvedPropertiesParam,
Appendable out) throws IOException {
Map<String, String> resolvedProperties = resolvedPropertiesParam;
-
+
Matcher matcher = pattern.matcher(text);
int groupCount = matcher.groupCount();
-
+
int last = 0;
while (matcher.find()) {
if (escapeString != null) {
@@ -116,7 +116,7 @@ public class MavenPropertyResolver {
if (resolvedProperties == null) {
resolvedProperties = new HashMap<String, String>();
}
-
+
String propertyValue = resolvedProperties.get(propertyName);
if (propertyValue == null) {
if (resolvedProperties.containsKey(propertyName)) { // if cyclic property dependencies
@@ -146,7 +146,7 @@ public class MavenPropertyResolver {
out.append(propertyValue);
}
}
-
+
out.append(text, last, text.length());
}
@@ -177,10 +177,10 @@ public class MavenPropertyResolver {
collectPropertiesFromDOM(projectDom.getProperties(), result);
- Collection<String> activePropfiles = project.getActivatedProfilesIds();
+ Collection<String> activeProfiles = project.getActivatedProfilesIds().getEnabledProfiles();
for (MavenDomProfile each : projectDom.getProfiles().getProfiles()) {
XmlTag idTag = each.getId().getXmlTag();
- if (idTag == null || !activePropfiles.contains(idTag.getValue().getTrimmedText())) continue;
+ if (idTag == null || !activeProfiles.contains(idTag.getValue().getTrimmedText())) continue;
collectPropertiesFromDOM(each.getProperties(), result);
}
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenConfigurationProducer.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenConfigurationProducer.java
index 0bf342fcdcfa..13b58ca94b12 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenConfigurationProducer.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenConfigurationProducer.java
@@ -29,6 +29,7 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
import org.jetbrains.idea.maven.project.MavenProjectsManager;
import java.util.Collection;
@@ -76,9 +77,9 @@ public class MavenConfigurationProducer extends RuntimeConfigurationProducer {
VirtualFile f = ((PsiFile)l.getPsiElement()).getVirtualFile();
List<String> goals = ((MavenGoalLocation)l).getGoals();
- Collection<String> profiles = MavenProjectsManager.getInstance(l.getProject()).getExplicitProfiles();
+ MavenExplicitProfiles profiles = MavenProjectsManager.getInstance(l.getProject()).getExplicitProfiles();
- return new MavenRunnerParameters(true, f.getParent().getPath(), goals, profiles);
+ return new MavenRunnerParameters(true, f.getParent().getPath(), goals, profiles.getEnabledProfiles(), profiles.getDisabledProfiles());
}
public int compareTo(Object o) {
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunnerParameters.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunnerParameters.java
index c04f2d344e51..bca71b2c0d8f 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunnerParameters.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunnerParameters.java
@@ -23,6 +23,7 @@ import com.intellij.util.xmlb.annotations.Transient;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.maven.model.MavenConstants;
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
import org.jetbrains.idea.maven.utils.Path;
import java.io.File;
@@ -53,6 +54,13 @@ public class MavenRunnerParameters implements Cloneable {
public MavenRunnerParameters(boolean isPomExecution,
@NotNull String workingDirPath,
@Nullable List<String> goals,
+ @NotNull MavenExplicitProfiles explicitProfiles) {
+ this(isPomExecution, workingDirPath, goals, explicitProfiles.getEnabledProfiles(), explicitProfiles.getDisabledProfiles());
+ }
+
+ public MavenRunnerParameters(boolean isPomExecution,
+ @NotNull String workingDirPath,
+ @Nullable List<String> goals,
@Nullable Collection<String> explicitEnabledProfiles,
@Nullable Collection<String> explicitDisabledProfiles) {
this.isPomExecution = isPomExecution;
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenRootModelAdapter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenRootModelAdapter.java
index 65e1b5ed2dce..e2a313ef30a9 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenRootModelAdapter.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenRootModelAdapter.java
@@ -19,12 +19,15 @@ import com.intellij.openapi.application.AccessToken;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.module.ModifiableModuleModel;
import com.intellij.openapi.module.Module;
+import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.*;
import com.intellij.openapi.roots.impl.ModuleOrderEntryImpl;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.registry.Registry;
+import com.intellij.openapi.vcs.changes.ChangeListManager;
import com.intellij.openapi.vfs.JarFileSystem;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFileManager;
@@ -45,6 +48,7 @@ import org.jetbrains.jps.model.java.JpsJavaExtensionService;
import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
import java.io.File;
+import java.util.Arrays;
import java.util.Set;
public class MavenRootModelAdapter {
@@ -176,10 +180,7 @@ public class MavenRootModelAdapter {
public boolean isAlreadyExcluded(File f) {
String url = toUrl(f.getPath()).getUrl();
- for (String excludedUrl : myRootModel.getExcludeRootUrls()) {
- if (VfsUtilCore.isEqualOrAncestor(excludedUrl, url)) return true;
- }
- return false;
+ return VfsUtilCore.isUnder(url, Arrays.asList(myRootModel.getExcludeRootUrls()));
}
private boolean exists(String path) {
@@ -193,6 +194,10 @@ public class MavenRootModelAdapter {
if (e == null) return;
if (e.getUrl().equals(url.getUrl())) return;
e.addExcludeFolder(url.getUrl());
+ if (!Registry.is("ide.hide.excluded.files")) {
+ Project project = myRootModel.getProject();
+ ChangeListManager.getInstance(project).addDirectoryToIgnoreImplicitly(toPath(path).getPath());
+ }
}
public void unregisterAll(String path, boolean under, boolean unregisterSources) {
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/MavenProjectsNavigatorPanel.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/MavenProjectsNavigatorPanel.java
index 86761532f6a0..04e93ac9e0e2 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/MavenProjectsNavigatorPanel.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/MavenProjectsNavigatorPanel.java
@@ -39,6 +39,7 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.maven.execution.MavenGoalLocation;
import org.jetbrains.idea.maven.model.MavenArtifact;
import org.jetbrains.idea.maven.model.MavenConstants;
+import org.jetbrains.idea.maven.model.MavenProfileKind;
import org.jetbrains.idea.maven.project.MavenProject;
import org.jetbrains.idea.maven.project.MavenProjectsManager;
import org.jetbrains.idea.maven.utils.MavenDataKeys;
@@ -226,9 +227,9 @@ public class MavenProjectsNavigatorPanel extends SimpleToolWindowPanel implement
private Object extractProfiles() {
final List<MavenProjectsStructure.ProfileNode> nodes = getSelectedNodes(MavenProjectsStructure.ProfileNode.class);
- final List<String> profiles = new ArrayList<String>();
+ final Map<String, MavenProfileKind> profiles = new THashMap<String, MavenProfileKind>();
for (MavenProjectsStructure.ProfileNode node : nodes) {
- profiles.add(node.getProfileName());
+ profiles.put(node.getProfileName(), node.getState());
}
return profiles;
}
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/actions/MavenExecuteGoalAction.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/actions/MavenExecuteGoalAction.java
index e591bb61d11b..8c02946b5b72 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/actions/MavenExecuteGoalAction.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/actions/MavenExecuteGoalAction.java
@@ -37,6 +37,7 @@ import org.jetbrains.idea.maven.utils.MavenUtil;
import javax.swing.event.HyperlinkEvent;
import java.io.File;
import java.util.Arrays;
+import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
@@ -105,7 +106,7 @@ public class MavenExecuteGoalAction extends DumbAwareAction {
return;
}
- MavenRunnerParameters parameters = new MavenRunnerParameters(true, workDirectory, Arrays.asList(ParametersList.parse(goals)), null);
+ MavenRunnerParameters parameters = new MavenRunnerParameters(true, workDirectory, Arrays.asList(ParametersList.parse(goals)), Collections.<String>emptyList());
MavenGeneralSettings generalSettings = new MavenGeneralSettings();
generalSettings.setMavenHome(mavenHome.getPath());
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProject.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProject.java
index 70a8aa8cfd81..01fc83800372 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProject.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProject.java
@@ -19,7 +19,6 @@ import com.intellij.execution.configurations.ParametersList;
import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.module.StdModuleTypes;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.roots.ui.LightFilePointer;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Key;
@@ -29,13 +28,11 @@ import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.openapi.vfs.pointers.VirtualFilePointer;
import com.intellij.util.containers.ContainerUtil;
import gnu.trove.THashSet;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import org.jetbrains.idea.maven.dom.MavenDomUtil;
import org.jetbrains.idea.maven.importing.MavenExtraArtifactType;
import org.jetbrains.idea.maven.importing.MavenImporter;
import org.jetbrains.idea.maven.model.*;
@@ -607,7 +604,7 @@ public class MavenProject {
@NotNull
public MavenProjectChanges read(@NotNull MavenGeneralSettings generalSettings,
- @NotNull Collection<String> profiles,
+ @NotNull MavenExplicitProfiles profiles,
@NotNull MavenProjectReader reader,
@NotNull MavenProjectReaderProjectLocator locator) {
return set(reader.readProject(generalSettings, myFile, profiles, locator), generalSettings, true, false, true);
@@ -805,7 +802,7 @@ public class MavenProject {
}
@NotNull
- public Collection<String> getActivatedProfilesIds() {
+ public MavenExplicitProfiles getActivatedProfilesIds() {
return myState.myActivatedProfilesIds;
}
@@ -1089,7 +1086,7 @@ public class MavenProject {
Map<String, String> myModelMap;
Collection<String> myProfilesIds;
- Collection<String> myActivatedProfilesIds;
+ MavenExplicitProfiles myActivatedProfilesIds;
Collection<MavenProjectProblem> myReadingProblems;
Set<MavenId> myUnresolvedArtifactIds;
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectReader.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectReader.java
index bb465f5e5fc1..31f245ccfdc6 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectReader.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectReader.java
@@ -47,9 +47,9 @@ public class MavenProjectReader {
public MavenProjectReaderResult readProject(MavenGeneralSettings generalSettings,
VirtualFile file,
- Collection<String> explicitProfiles,
+ MavenExplicitProfiles explicitProfiles,
MavenProjectReaderProjectLocator locator) {
- Pair<RawModelReadResult, Collection<String>> readResult =
+ Pair<RawModelReadResult, MavenExplicitProfiles> readResult =
doReadProjectModel(generalSettings, file, explicitProfiles, new THashSet<VirtualFile>(), locator);
File basedir = getBaseDir(file);
@@ -76,11 +76,11 @@ public class MavenProjectReader {
return new File(file.getParent().getPath());
}
- private Pair<RawModelReadResult, Collection<String>> doReadProjectModel(MavenGeneralSettings generalSettings,
- VirtualFile file,
- Collection<String> explicitProfiles,
- Set<VirtualFile> recursionGuard,
- MavenProjectReaderProjectLocator locator) {
+ private Pair<RawModelReadResult, MavenExplicitProfiles> doReadProjectModel(MavenGeneralSettings generalSettings,
+ VirtualFile file,
+ MavenExplicitProfiles explicitProfiles,
+ Set<VirtualFile> recursionGuard,
+ MavenProjectReaderProjectLocator locator) {
RawModelReadResult cachedModel = myRawModelsCache.get(file);
if (cachedModel == null) {
cachedModel = doReadProjectModel(file, false);
@@ -364,7 +364,7 @@ public class MavenProjectReader {
private static ProfileApplicationResult applyProfiles(MavenModel model,
File basedir,
- Collection<String> explicitProfiles,
+ MavenExplicitProfiles explicitProfiles,
Collection<String> alwaysOnProfiles) {
return MavenServerManager.getInstance().applyProfiles(model, basedir, explicitProfiles, alwaysOnProfiles);
}
@@ -372,7 +372,7 @@ public class MavenProjectReader {
private MavenModel resolveInheritance(final MavenGeneralSettings generalSettings,
MavenModel model,
final VirtualFile file,
- final Collection<String> explicitProfiles,
+ final MavenExplicitProfiles explicitProfiles,
final Set<VirtualFile> recursionGuard,
final MavenProjectReaderProjectLocator locator,
Collection<MavenProjectProblem> problems) {
@@ -456,21 +456,23 @@ public class MavenProjectReader {
public MavenProjectReaderResult resolveProject(MavenGeneralSettings generalSettings,
MavenEmbedderWrapper embedder,
VirtualFile file,
- Collection<String> explicitProfiles,
+ MavenExplicitProfiles explicitProfiles,
MavenProjectReaderProjectLocator locator) throws MavenProcessCanceledException {
try {
- MavenServerExecutionResult result = embedder.resolveProject(file, explicitProfiles);
- if (result.projectData == null) {
+ MavenServerExecutionResult result =
+ embedder.resolveProject(file, explicitProfiles.getEnabledProfiles(), explicitProfiles.getDisabledProfiles());
+ MavenServerExecutionResult.ProjectData projectData = result.projectData;
+ if (projectData == null) {
MavenProjectReaderResult temp = readProject(generalSettings, file, explicitProfiles, locator);
temp.readingProblems.addAll(result.problems);
temp.unresolvedArtifactIds.addAll(result.unresolvedArtifacts);
return temp;
}
- return new MavenProjectReaderResult(result.projectData.mavenModel,
- result.projectData.mavenModelMap,
- result.projectData.activatedProfiles,
- result.projectData.nativeMavenProject,
+ return new MavenProjectReaderResult(projectData.mavenModel,
+ projectData.mavenModelMap,
+ new MavenExplicitProfiles(projectData.activatedProfiles, explicitProfiles.getDisabledProfiles()),
+ projectData.nativeMavenProject,
result.problems,
result.unresolvedArtifacts);
}
@@ -497,17 +499,18 @@ public class MavenProjectReader {
public static MavenProjectReaderResult generateSources(MavenEmbedderWrapper embedder,
MavenImportingSettings importingSettings,
VirtualFile file,
- Collection<String> profiles,
+ MavenExplicitProfiles profiles,
MavenConsole console) throws MavenProcessCanceledException {
try {
List<String> goals = Collections.singletonList(importingSettings.getUpdateFoldersOnImportPhase());
- MavenServerExecutionResult result = embedder.execute(file, profiles, goals);
- if (result.projectData == null) return null;
-
- return new MavenProjectReaderResult(result.projectData.mavenModel,
- result.projectData.mavenModelMap,
- result.projectData.activatedProfiles,
- result.projectData.nativeMavenProject,
+ MavenServerExecutionResult result = embedder.execute(file, profiles.getEnabledProfiles(), profiles.getDisabledProfiles(), goals);
+ MavenServerExecutionResult.ProjectData projectData = result.projectData;
+ if (projectData == null) return null;
+
+ return new MavenProjectReaderResult(projectData.mavenModel,
+ projectData.mavenModelMap,
+ new MavenExplicitProfiles(projectData.activatedProfiles, profiles.getDisabledProfiles()),
+ projectData.nativeMavenProject,
result.problems,
result.unresolvedArtifacts);
}
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectReaderResult.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectReaderResult.java
index 29ac462b115a..cbec80162fd0 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectReaderResult.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectReaderResult.java
@@ -16,6 +16,7 @@
package org.jetbrains.idea.maven.project;
import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
import org.jetbrains.idea.maven.model.MavenId;
import org.jetbrains.idea.maven.model.MavenModel;
import org.jetbrains.idea.maven.model.MavenProjectProblem;
@@ -28,14 +29,14 @@ import java.util.Set;
public class MavenProjectReaderResult {
public final MavenModel mavenModel;
public final Map<String, String> nativeModelMap;
- public final Collection<String> activatedProfiles;
+ public final MavenExplicitProfiles activatedProfiles;
@Nullable public final NativeMavenProjectHolder nativeMavenProject;
public final Collection<MavenProjectProblem> readingProblems;
public final Set<MavenId> unresolvedArtifactIds;
public MavenProjectReaderResult(MavenModel mavenModel,
Map<String, String> nativeModelMap,
- Collection<String> activatedProfiles,
+ MavenExplicitProfiles activatedProfiles,
@Nullable NativeMavenProjectHolder nativeMavenProject,
Collection<MavenProjectProblem> readingProblems,
Set<MavenId> unresolvedArtifactIds) {
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectSettings.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectSettings.java
index 4671a261b590..6ff6c851c67b 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectSettings.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectSettings.java
@@ -25,8 +25,11 @@ import org.jetbrains.annotations.Nullable;
*/
@State(
name = "MavenProjectSettings",
- storages = {@Storage(
- file = StoragePathMacros.PROJECT_CONFIG_DIR + "/mavenProjectSettings.xml")})
+ storages = {
+ @Storage(file = StoragePathMacros.PROJECT_FILE),
+ @Storage(file = StoragePathMacros.PROJECT_CONFIG_DIR + "/mavenProjectSettings.xml", scheme = StorageScheme.DIRECTORY_BASED)
+ }
+)
public class MavenProjectSettings implements PersistentStateComponent<MavenProjectSettings> {
private final Project myProject;
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManager.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManager.java
index 37a1a47cde6a..88b92ae679a6 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManager.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManager.java
@@ -183,9 +183,10 @@ public class MavenProjectsManager extends MavenSimpleProjectComponent
doInit(false);
}
- private void initNew(List<VirtualFile> files, List<String> explicitProfiles) {
+ private void initNew(List<VirtualFile> files, MavenExplicitProfiles explicitProfiles) {
myState.originalFiles = MavenUtil.collectPaths(files);
- getWorkspaceSettings().setEnabledProfiles(explicitProfiles);
+ getWorkspaceSettings().setEnabledProfiles(explicitProfiles.getEnabledProfiles());
+ getWorkspaceSettings().setDisabledProfiles(explicitProfiles.getDisabledProfiles());
doInit(true);
}
@@ -241,7 +242,9 @@ public class MavenProjectsManager extends MavenSimpleProjectComponent
}
private void applyStateToTree() {
- myProjectsTree.resetManagedFilesPathsAndProfiles(myState.originalFiles, getWorkspaceSettings().enabledProfiles);
+ MavenWorkspaceSettings settings = getWorkspaceSettings();
+ MavenExplicitProfiles explicitProfiles = new MavenExplicitProfiles(settings.enabledProfiles, settings.disabledProfiles);
+ myProjectsTree.resetManagedFilesPathsAndProfiles(myState.originalFiles, explicitProfiles);
myProjectsTree.setIgnoredFilesPaths(new ArrayList<String>(myState.ignoredFiles));
myProjectsTree.setIgnoredFilesPatterns(myState.ignoredPathMasks);
}
@@ -474,11 +477,11 @@ public class MavenProjectsManager extends MavenSimpleProjectComponent
}
@TestOnly
- public void resetManagedFilesAndProfilesInTests(List<VirtualFile> files, List<String> profiles) {
+ public void resetManagedFilesAndProfilesInTests(List<VirtualFile> files, MavenExplicitProfiles profiles) {
myWatcher.resetManagedFilesAndProfilesInTests(files, profiles);
}
- public void addManagedFilesWithProfiles(List<VirtualFile> files, List<String> profiles) {
+ public void addManagedFilesWithProfiles(List<VirtualFile> files, MavenExplicitProfiles profiles) {
if (!isInitialized()) {
initNew(files, profiles);
}
@@ -488,7 +491,7 @@ public class MavenProjectsManager extends MavenSimpleProjectComponent
}
public void addManagedFiles(@NotNull List<VirtualFile> files) {
- addManagedFilesWithProfiles(files, Collections.<String>emptyList());
+ addManagedFilesWithProfiles(files, MavenExplicitProfiles.NONE);
}
public void addManagedFilesOrUnignore(@NotNull List<VirtualFile> files) {
@@ -506,12 +509,12 @@ public class MavenProjectsManager extends MavenSimpleProjectComponent
}
@NotNull
- public Collection<String> getExplicitProfiles() {
- if (!isInitialized()) return Collections.emptyList();
+ public MavenExplicitProfiles getExplicitProfiles() {
+ if (!isInitialized()) return MavenExplicitProfiles.NONE;
return myProjectsTree.getExplicitProfiles();
}
- public void setExplicitProfiles(@NotNull Collection<String> profiles) {
+ public void setExplicitProfiles(@NotNull MavenExplicitProfiles profiles) {
myWatcher.setExplicitProfiles(profiles);
}
@@ -776,8 +779,10 @@ public class MavenProjectsManager extends MavenSimpleProjectComponent
@Override
public void run(MavenEmbedderWrapper embedder) throws MavenProcessCanceledException {
try {
+ MavenExplicitProfiles profiles = mavenProject.getActivatedProfilesIds();
String res =
- embedder.evaluateEffectivePom(mavenProject.getFile(), mavenProject.getActivatedProfilesIds());
+ embedder.evaluateEffectivePom(mavenProject.getFile(), profiles.getEnabledProfiles(),
+ profiles.getDisabledProfiles());
consumer.consume(res);
}
catch (UnsupportedOperationException e) {
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManagerWatcher.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManagerWatcher.java
index 81eb778b2466..b8644991eaff 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManagerWatcher.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManagerWatcher.java
@@ -51,6 +51,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import org.jetbrains.idea.maven.model.MavenConstants;
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
import org.jetbrains.idea.maven.utils.MavenMergingUpdateQueue;
import org.jetbrains.idea.maven.utils.MavenUtil;
@@ -247,13 +248,13 @@ public class MavenProjectsManagerWatcher {
Disposer.dispose(myChangedDocumentsQueue);
}
- public synchronized void addManagedFilesWithProfiles(List<VirtualFile> files, List<String> explicitProfiles) {
+ public synchronized void addManagedFilesWithProfiles(List<VirtualFile> files, MavenExplicitProfiles explicitProfiles) {
myProjectsTree.addManagedFilesWithProfiles(files, explicitProfiles);
scheduleUpdateAll(false, true);
}
@TestOnly
- public synchronized void resetManagedFilesAndProfilesInTests(List<VirtualFile> files, List<String> explicitProfiles) {
+ public synchronized void resetManagedFilesAndProfilesInTests(List<VirtualFile> files, MavenExplicitProfiles explicitProfiles) {
myProjectsTree.resetManagedFilesAndProfiles(files, explicitProfiles);
scheduleUpdateAll(false, true);
}
@@ -263,7 +264,7 @@ public class MavenProjectsManagerWatcher {
scheduleUpdateAll(false, true);
}
- public synchronized void setExplicitProfiles(Collection<String> profiles) {
+ public synchronized void setExplicitProfiles(MavenExplicitProfiles profiles) {
myProjectsTree.setExplicitProfiles(profiles);
scheduleUpdateAll(false, false);
}
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsTree.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsTree.java
index 89bf69711114..c7adefebf207 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsTree.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsTree.java
@@ -68,8 +68,9 @@ public class MavenProjectsTree {
private volatile List<String> myIgnoredFilesPatterns = new ArrayList<String>();
private volatile Pattern myIgnoredFilesPatternsCache;
- private Set<String> myExplicitProfiles = new HashSet<String>();
- private final Set<String> myTemporarilyRemovedExplicitProfiles = new HashSet<String>();
+ private MavenExplicitProfiles myExplicitProfiles = MavenExplicitProfiles.NONE;
+ private final MavenExplicitProfiles myTemporarilyRemovedExplicitProfiles =
+ new MavenExplicitProfiles(new HashSet<String>(), new HashSet<String>());
private final List<MavenProject> myRootProjects = new ArrayList<MavenProject>();
@@ -100,7 +101,8 @@ public class MavenProjectsTree {
result.myManagedFilesPaths = readCollection(in, new LinkedHashSet<String>());
result.myIgnoredFilesPaths = readCollection(in, new ArrayList<String>());
result.myIgnoredFilesPatterns = readCollection(in, new ArrayList<String>());
- result.myExplicitProfiles = readCollection(in, new THashSet<String>());
+ result.myExplicitProfiles = new MavenExplicitProfiles(readCollection(in, new THashSet<String>()),
+ readCollection(in, new THashSet<String>()));
result.myRootProjects.addAll(readProjectsRecursively(in, result));
}
catch (IOException e) {
@@ -166,7 +168,8 @@ public class MavenProjectsTree {
writeCollection(out, myManagedFilesPaths);
writeCollection(out, myIgnoredFilesPaths);
writeCollection(out, myIgnoredFilesPatterns);
- writeCollection(out, myExplicitProfiles);
+ writeCollection(out, myExplicitProfiles.getEnabledProfiles());
+ writeCollection(out, myExplicitProfiles.getDisabledProfiles());
writeProjectsRecursively(out, myRootProjects);
}
finally {
@@ -194,7 +197,7 @@ public class MavenProjectsTree {
}
}
- public void resetManagedFilesPathsAndProfiles(List<String> paths, Collection<String> profiles) {
+ public void resetManagedFilesPathsAndProfiles(List<String> paths, MavenExplicitProfiles profiles) {
synchronized (myStateLock) {
myManagedFilesPaths = new LinkedHashSet<String>(paths);
}
@@ -202,19 +205,20 @@ public class MavenProjectsTree {
}
@TestOnly
- public void resetManagedFilesAndProfiles(List<VirtualFile> files, Collection<String> profiles) {
+ public void resetManagedFilesAndProfiles(List<VirtualFile> files, MavenExplicitProfiles profiles) {
resetManagedFilesPathsAndProfiles(MavenUtil.collectPaths(files), profiles);
}
- public void addManagedFilesWithProfiles(List<VirtualFile> files, Collection<String> profiles) {
+ public void addManagedFilesWithProfiles(List<VirtualFile> files, MavenExplicitProfiles profiles) {
List<String> newFiles;
- Set<String> newProfiles;
+ MavenExplicitProfiles newProfiles;
synchronized (myStateLock) {
newFiles = new ArrayList<String>(myManagedFilesPaths);
newFiles.addAll(MavenUtil.collectPaths(files));
- newProfiles = new THashSet<String>(myExplicitProfiles);
- newProfiles.addAll(profiles);
+ newProfiles = myExplicitProfiles.clone();
+ newProfiles.getEnabledProfiles().addAll(profiles.getEnabledProfiles());
+ newProfiles.getDisabledProfiles().addAll(profiles.getDisabledProfiles());
}
resetManagedFilesPathsAndProfiles(newFiles, newProfiles);
@@ -349,15 +353,15 @@ public class MavenProjectsTree {
}
}
- public Collection<String> getExplicitProfiles() {
+ public MavenExplicitProfiles getExplicitProfiles() {
synchronized (myStateLock) {
- return new THashSet<String>(myExplicitProfiles);
+ return myExplicitProfiles.clone();
}
}
- public void setExplicitProfiles(Collection<String> explicitProfiles) {
+ public void setExplicitProfiles(MavenExplicitProfiles explicitProfiles) {
synchronized (myStateLock) {
- myExplicitProfiles = new THashSet<String>(explicitProfiles);
+ myExplicitProfiles = explicitProfiles.clone();
}
fireProfilesChanged();
}
@@ -366,17 +370,25 @@ public class MavenProjectsTree {
Collection<String> available = getAvailableProfiles();
synchronized (myStateLock) {
- Collection<String> removedProfiles = new THashSet<String>(myExplicitProfiles);
- removedProfiles.removeAll(available);
- myTemporarilyRemovedExplicitProfiles.addAll(removedProfiles);
+ updateExplicitProfiles(myExplicitProfiles.getEnabledProfiles(), myTemporarilyRemovedExplicitProfiles.getEnabledProfiles(),
+ available);
+ updateExplicitProfiles(myExplicitProfiles.getDisabledProfiles(), myTemporarilyRemovedExplicitProfiles.getDisabledProfiles(),
+ available);
+ }
+ }
- Collection<String> restoredProfiles = new THashSet<String>(myTemporarilyRemovedExplicitProfiles);
- restoredProfiles.retainAll(available);
- myTemporarilyRemovedExplicitProfiles.removeAll(restoredProfiles);
+ private void updateExplicitProfiles(Collection<String> explicitProfiles, Collection<String> temporarilyRemovedExplicitProfiles,
+ Collection<String> available) {
+ Collection<String> removedProfiles = new THashSet<String>(explicitProfiles);
+ removedProfiles.removeAll(available);
+ temporarilyRemovedExplicitProfiles.addAll(removedProfiles);
- myExplicitProfiles.removeAll(removedProfiles);
- myExplicitProfiles.addAll(restoredProfiles);
- }
+ Collection<String> restoredProfiles = new THashSet<String>(temporarilyRemovedExplicitProfiles);
+ restoredProfiles.retainAll(available);
+ temporarilyRemovedExplicitProfiles.removeAll(restoredProfiles);
+
+ explicitProfiles.removeAll(removedProfiles);
+ explicitProfiles.addAll(restoredProfiles);
}
public Collection<String> getAvailableProfiles() {
@@ -396,17 +408,26 @@ public class MavenProjectsTree {
Collection<String> active = new THashSet<String>();
for (MavenProject each : getProjects()) {
available.addAll(each.getProfilesIds());
- active.addAll(each.getActivatedProfilesIds());
+ active.addAll(each.getActivatedProfilesIds().getEnabledProfiles());
}
- Collection<String> explicitProfiles = getExplicitProfiles();
+ Collection<String> enabledProfiles = getExplicitProfiles().getEnabledProfiles();
+ Collection<String> disabledProfiles = getExplicitProfiles().getDisabledProfiles();
for (String each : available) {
- MavenProfileKind state = MavenProfileKind.NONE;
- if (explicitProfiles.contains(each)) {
+ MavenProfileKind state;
+ if (disabledProfiles.contains(each)) {
+ state = MavenProfileKind.NONE;
+ }
+ else if (enabledProfiles.contains(each)) {
state = MavenProfileKind.EXPLICIT;
}
- else if (active.contains(each)) state = MavenProfileKind.IMPLICIT;
+ else if (active.contains(each)) {
+ state = MavenProfileKind.IMPLICIT;
+ }
+ else {
+ state = MavenProfileKind.NONE;
+ }
result.add(Pair.create(each, state));
}
return result;
@@ -414,7 +435,7 @@ public class MavenProjectsTree {
public void updateAll(boolean force, MavenGeneralSettings generalSettings, MavenProgressIndicator process) {
List<VirtualFile> managedFiles = getExistingManagedFiles();
- Collection<String> explicitProfiles = getExplicitProfiles();
+ MavenExplicitProfiles explicitProfiles = getExplicitProfiles();
MavenProjectReader projectReader = new MavenProjectReader();
update(managedFiles, true, force, explicitProfiles, projectReader, generalSettings, process);
@@ -434,7 +455,7 @@ public class MavenProjectsTree {
private void update(Collection<VirtualFile> files,
boolean recursive,
boolean force,
- Collection<String> explicitProfiles,
+ MavenExplicitProfiles explicitProfiles,
MavenProjectReader projectReader,
MavenGeneralSettings generalSettings,
MavenProgressIndicator process) {
@@ -469,7 +490,7 @@ public class MavenProjectsTree {
private void doAdd(final VirtualFile f,
boolean recursuve,
- Collection<String> explicitProfiles,
+ MavenExplicitProfiles explicitProfiles,
UpdateContext updateContext,
Stack<MavenProject> updateStack,
MavenProjectReader reader,
@@ -503,7 +524,7 @@ public class MavenProjectsTree {
boolean isNew,
boolean recursive,
boolean force,
- Collection<String> explicitProfiles,
+ MavenExplicitProfiles explicitProfiles,
UpdateContext updateContext,
Stack<MavenProject> updateStack,
MavenProjectReader reader,
@@ -649,7 +670,7 @@ public class MavenProjectsTree {
}
private MavenProjectTimestamp calculateTimestamp(final MavenProject mavenProject,
- final Collection<String> explicitProfiles,
+ final MavenExplicitProfiles explicitProfiles,
final MavenGeneralSettings generalSettings) {
AccessToken accessToken = ApplicationManager.getApplication().acquireReadActionLock();
try {
@@ -712,7 +733,7 @@ public class MavenProjectsTree {
private void delete(MavenProjectReader projectReader,
List<VirtualFile> files,
- Collection<String> explicitProfiles,
+ MavenExplicitProfiles explicitProfiles,
MavenGeneralSettings generalSettings,
MavenProgressIndicator process) {
if (files.isEmpty()) return;
@@ -892,7 +913,7 @@ public class MavenProjectsTree {
try {
final CRC32 crc = new CRC32();
- Set<String> profiles = myExplicitProfiles;
+ MavenExplicitProfiles profiles = myExplicitProfiles;
if (profiles != null) {
updateCrc(crc, profiles.hashCode());
}
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenWorkspaceSettings.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenWorkspaceSettings.java
index 3451f0c33f2e..4b0ef285a76d 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenWorkspaceSettings.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenWorkspaceSettings.java
@@ -24,10 +24,16 @@ public class MavenWorkspaceSettings {
public MavenImportingSettings importingSettings = new MavenImportingSettings();
public List<String> enabledProfiles = new ArrayList<String>();
+ public List<String> disabledProfiles = new ArrayList<String>();
public void setEnabledProfiles(Collection<String> profiles) {
enabledProfiles.clear();
enabledProfiles.addAll(profiles);
}
+ public void setDisabledProfiles(Collection<String> profiles) {
+ disabledProfiles.clear();
+ disabledProfiles.addAll(profiles);
+ }
+
}
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenWorkspaceSettingsComponent.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenWorkspaceSettingsComponent.java
index dc1bbdb79a8e..d5e9e2d92815 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenWorkspaceSettingsComponent.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenWorkspaceSettingsComponent.java
@@ -18,6 +18,7 @@ package org.jetbrains.idea.maven.project;
import com.intellij.openapi.components.*;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
@State(name = "MavenImportPreferences", storages = {@Storage( file = StoragePathMacros.WORKSPACE_FILE)})
public class MavenWorkspaceSettingsComponent implements PersistentStateComponent<MavenWorkspaceSettings> {
@@ -35,7 +36,9 @@ public class MavenWorkspaceSettingsComponent implements PersistentStateComponent
@NotNull
public MavenWorkspaceSettings getState() {
- mySettings.setEnabledProfiles(MavenProjectsManager.getInstance(myProject).getExplicitProfiles());
+ MavenExplicitProfiles profiles = MavenProjectsManager.getInstance(myProject).getExplicitProfiles();
+ mySettings.setEnabledProfiles(profiles.getEnabledProfiles());
+ mySettings.setDisabledProfiles(profiles.getDisabledProfiles());
return mySettings;
}
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/actions/RunBuildAction.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/actions/RunBuildAction.java
index e52453070a0e..497f29b6a7a8 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/actions/RunBuildAction.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/actions/RunBuildAction.java
@@ -19,6 +19,7 @@ import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DataContext;
import org.jetbrains.idea.maven.execution.MavenRunConfigurationType;
import org.jetbrains.idea.maven.execution.MavenRunnerParameters;
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
import org.jetbrains.idea.maven.project.MavenProject;
import org.jetbrains.idea.maven.utils.MavenDataKeys;
import org.jetbrains.idea.maven.utils.actions.MavenAction;
@@ -46,10 +47,12 @@ public class RunBuildAction extends MavenAction {
if (!perform) return true;
+ MavenExplicitProfiles explicitProfiles = MavenActionUtil.getProjectsManager(context).getExplicitProfiles();
final MavenRunnerParameters params = new MavenRunnerParameters(true,
project.getDirectory(),
goals,
- MavenActionUtil.getProjectsManager(context).getExplicitProfiles());
+ explicitProfiles.getEnabledProfiles(),
+ explicitProfiles.getDisabledProfiles());
MavenRunConfigurationType.runConfiguration(MavenActionUtil.getProject(context), params, null);
return true;
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/actions/ToggleProfileAction.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/actions/ToggleProfileAction.java
index 3e9bf7f92ddd..af0fbd091aad 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/actions/ToggleProfileAction.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/actions/ToggleProfileAction.java
@@ -16,15 +16,15 @@
package org.jetbrains.idea.maven.project.actions;
import com.intellij.openapi.actionSystem.AnActionEvent;
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
+import org.jetbrains.idea.maven.model.MavenProfileKind;
import org.jetbrains.idea.maven.project.MavenProjectsManager;
import org.jetbrains.idea.maven.project.ProjectBundle;
import org.jetbrains.idea.maven.utils.MavenDataKeys;
import org.jetbrains.idea.maven.utils.actions.MavenAction;
import org.jetbrains.idea.maven.utils.actions.MavenActionUtil;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
+import java.util.Map;
import java.util.Set;
public class ToggleProfileAction extends MavenAction {
@@ -32,47 +32,105 @@ public class ToggleProfileAction extends MavenAction {
super.update(e);
if (!isAvailable(e)) return;
- MavenProjectsManager projectsManager = MavenActionUtil.getProjectsManager(e.getDataContext());
- List<String> profiles = e.getData(MavenDataKeys.MAVEN_PROFILES);
-
- e.getPresentation().setText(isActive(projectsManager, profiles)
- ? ProjectBundle.message("maven.profile.deactivate")
- : ProjectBundle.message("maven.profile.activate"));
+ MavenProfileKind targetState = getTargetState(e);
+ String text;
+ switch (targetState) {
+ case NONE:
+ text = ProjectBundle.message("maven.profile.deactivate");
+ break;
+ case EXPLICIT:
+ text = ProjectBundle.message("maven.profile.activate");
+ break;
+ case IMPLICIT:
+ default:
+ text = ProjectBundle.message("maven.profile.default");
+ break;
+ }
+ e.getPresentation().setText(text);
}
@Override
protected boolean isAvailable(AnActionEvent e) {
if (!super.isAvailable(e)) return false;
- List<String> selectedProfiles = e.getData(MavenDataKeys.MAVEN_PROFILES);
- if (selectedProfiles == null || selectedProfiles.isEmpty()) return false;
+ return getTargetState(e) != null;
+ }
+
+ private static MavenProfileKind getTargetState(AnActionEvent e) {
+ Map<String, MavenProfileKind> selectedProfiles = e.getData(MavenDataKeys.MAVEN_PROFILES);
+ if (selectedProfiles == null || selectedProfiles.isEmpty()) return null;
- Collection<String> activeProfiles = MavenActionUtil.getProjectsManager(e.getDataContext()).getExplicitProfiles();
- int activeCount = 0;
- for (String profile : selectedProfiles) {
- if (activeProfiles.contains(profile)) {
- activeCount++;
+ MavenProjectsManager projectsManager = MavenActionUtil.getProjectsManager(e.getDataContext());
+ return getTargetState(projectsManager, selectedProfiles);
+ }
+
+ private static MavenProfileKind getTargetState(MavenProjectsManager projectsManager, Map<String, MavenProfileKind> profiles) {
+ MavenExplicitProfiles explicitProfiles = projectsManager.getExplicitProfiles();
+ MavenProfileKind targetState = null;
+ // all profiles should target to the same state
+ for (Map.Entry<String, MavenProfileKind> profile : profiles.entrySet()) {
+ MavenProfileKind profileTargetState = getTargetState(profile, explicitProfiles);
+ if (targetState == null) {
+ targetState = profileTargetState;
+ }
+ else if (!targetState.equals(profileTargetState)) {
+ targetState = null;
+ break;
}
}
- return activeCount == 0 || activeCount == selectedProfiles.size();
+ return targetState;
}
- private static boolean isActive(MavenProjectsManager projectsManager, List<String> profiles) {
- return projectsManager.getExplicitProfiles().contains(profiles.get(0));
+ private static MavenProfileKind getTargetState(Map.Entry<String, MavenProfileKind> profile, MavenExplicitProfiles explicitProfiles) {
+ MavenProfileKind targetState;
+ if (explicitProfiles.getDisabledProfiles().contains(profile.getKey())) {
+ // explicitly disabled -> explicitly enabled
+ targetState = MavenProfileKind.EXPLICIT;
+ }
+ else if (explicitProfiles.getEnabledProfiles().contains(profile.getKey())) {
+ // explicitly enabled -> default
+ targetState = MavenProfileKind.IMPLICIT;
+ }
+ else {
+ // default
+ if (MavenProfileKind.NONE.equals(profile.getValue())) {
+ // default inactive -> explicitly enabled
+ targetState = MavenProfileKind.EXPLICIT;
+ }
+ else {
+ // default active -> explicitly disabled
+ targetState = MavenProfileKind.NONE;
+ }
+ }
+ return targetState;
}
@Override
public void actionPerformed(AnActionEvent e) {
MavenProjectsManager manager = MavenActionUtil.getProjectsManager(e.getDataContext());
- List<String> selectedProfiles = e.getData(MavenDataKeys.MAVEN_PROFILES);
+ Map<String, MavenProfileKind> selectedProfiles = e.getData(MavenDataKeys.MAVEN_PROFILES);
+ Set<String> selectedProfileIds = selectedProfiles.keySet();
- Set<String> activeProfiles = new HashSet<String>(manager.getExplicitProfiles());
- if (isActive(manager, selectedProfiles)) {
- activeProfiles.removeAll(selectedProfiles);
- }
- else {
- activeProfiles.addAll(selectedProfiles);
+ MavenProfileKind targetState = getTargetState(manager, selectedProfiles);
+ MavenExplicitProfiles newExplicitProfiles = manager.getExplicitProfiles().clone();
+ switch (targetState) {
+ case NONE:
+ // disable explicitly
+ newExplicitProfiles.getEnabledProfiles().removeAll(selectedProfileIds);
+ newExplicitProfiles.getDisabledProfiles().addAll(selectedProfileIds);
+ break;
+ case EXPLICIT:
+ // enable explicitly
+ newExplicitProfiles.getDisabledProfiles().removeAll(selectedProfileIds);
+ newExplicitProfiles.getEnabledProfiles().addAll(selectedProfileIds);
+ break;
+ case IMPLICIT:
+ default:
+ // reset to default state
+ newExplicitProfiles.getEnabledProfiles().removeAll(selectedProfileIds);
+ newExplicitProfiles.getDisabledProfiles().removeAll(selectedProfileIds);
+ break;
}
- manager.setExplicitProfiles(activeProfiles);
+ manager.setExplicitProfiles(newExplicitProfiles);
}
}
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenEmbedderWrapper.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenEmbedderWrapper.java
index a0882e7c87fd..006f4caeac3a 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenEmbedderWrapper.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenEmbedderWrapper.java
@@ -93,22 +93,26 @@ public abstract class MavenEmbedderWrapper extends RemoteObjectWrapper<MavenServ
@NotNull
public MavenServerExecutionResult resolveProject(@NotNull final VirtualFile file,
- @NotNull final Collection<String> activeProfiles) throws MavenProcessCanceledException {
+ @NotNull final Collection<String> activeProfiles,
+ @NotNull final Collection<String> inactiveProfiles)
+ throws MavenProcessCanceledException {
return perform(new RetriableCancelable<MavenServerExecutionResult>() {
@Override
public MavenServerExecutionResult execute() throws RemoteException, MavenServerProcessCanceledException {
- return getOrCreateWrappee().resolveProject(new File(file.getPath()), activeProfiles);
+ return getOrCreateWrappee().resolveProject(new File(file.getPath()), activeProfiles, inactiveProfiles);
}
});
}
@Nullable
- public String evaluateEffectivePom(@NotNull final VirtualFile file, @NotNull final Collection<String> activeProfiles)
- throws MavenProcessCanceledException {
+ public String evaluateEffectivePom(@NotNull final VirtualFile file,
+ @NotNull final Collection<String> activeProfiles,
+ @NotNull final Collection<String> inactiveProfiles) throws MavenProcessCanceledException {
return perform(new RetriableCancelable<String>() {
@Override
public String execute() throws RemoteException, MavenServerProcessCanceledException {
- return getOrCreateWrappee().evaluateEffectivePom(new File(file.getPath()), new ArrayList<String>(activeProfiles));
+ return getOrCreateWrappee()
+ .evaluateEffectivePom(new File(file.getPath()), new ArrayList<String>(activeProfiles), new ArrayList<String>(inactiveProfiles));
}
});
}
@@ -165,14 +169,14 @@ public abstract class MavenEmbedderWrapper extends RemoteObjectWrapper<MavenServ
@NotNull
public MavenServerExecutionResult execute(@NotNull final VirtualFile file,
- @NotNull final Collection<String> activeProfiles,
- @NotNull final List<String> goals) throws MavenProcessCanceledException {
+ @NotNull final Collection<String> activeProfiles,
+ @NotNull final Collection<String> inactiveProfiles,
+ @NotNull final List<String> goals) throws MavenProcessCanceledException {
return perform(new RetriableCancelable<MavenServerExecutionResult>() {
@Override
public MavenServerExecutionResult execute() throws RemoteException, MavenServerProcessCanceledException {
return getOrCreateWrappee()
- .execute(new File(file.getPath()), activeProfiles, Collections.<String>emptyList(), goals, Collections.<String>emptyList(), false,
- false);
+ .execute(new File(file.getPath()), activeProfiles, inactiveProfiles, goals, Collections.<String>emptyList(), false, false);
}
});
}
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenServerManager.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenServerManager.java
index 5777e246f858..7ef16bdcfc4e 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenServerManager.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenServerManager.java
@@ -45,6 +45,7 @@ import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.maven.execution.MavenRunnerSettings;
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
import org.jetbrains.idea.maven.model.MavenId;
import org.jetbrains.idea.maven.model.MavenModel;
import org.jetbrains.idea.maven.project.MavenConsole;
@@ -409,7 +410,7 @@ public class MavenServerManager extends RemoteObjectWrapper<MavenServer> impleme
public ProfileApplicationResult applyProfiles(final MavenModel model,
final File basedir,
- final Collection<String> explicitProfiles,
+ final MavenExplicitProfiles explicitProfiles,
final Collection<String> alwaysOnProfiles) {
return perform(new Retriable<ProfileApplicationResult>() {
@Override
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/tasks/MavenBeforeRunTasksProvider.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/tasks/MavenBeforeRunTasksProvider.java
index b98fff5cd5d7..d128dac01b80 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/tasks/MavenBeforeRunTasksProvider.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/tasks/MavenBeforeRunTasksProvider.java
@@ -39,6 +39,7 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.maven.execution.MavenEditGoalDialog;
import org.jetbrains.idea.maven.execution.MavenRunner;
import org.jetbrains.idea.maven.execution.MavenRunnerParameters;
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
import org.jetbrains.idea.maven.project.MavenProject;
import org.jetbrains.idea.maven.project.MavenProjectsManager;
import org.jetbrains.idea.maven.utils.MavenLog;
@@ -162,7 +163,7 @@ public class MavenBeforeRunTasksProvider extends BeforeRunTaskProvider<MavenBefo
FileDocumentManager.getInstance().saveAllDocuments();
- final Collection<String> explicitProfiles = MavenProjectsManager.getInstance(project).getExplicitProfiles();
+ final MavenExplicitProfiles explicitProfiles = MavenProjectsManager.getInstance(project).getExplicitProfiles();
final MavenRunner mavenRunner = MavenRunner.getInstance(project);
targetDone.down();
@@ -173,7 +174,8 @@ public class MavenBeforeRunTasksProvider extends BeforeRunTaskProvider<MavenBefo
true,
mavenProject.getDirectory(),
ParametersListUtil.parse(task.getGoal()),
- explicitProfiles);
+ explicitProfiles.getEnabledProfiles(),
+ explicitProfiles.getDisabledProfiles());
result[0] = mavenRunner.runBatch(Collections.singletonList(params),
null,
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/tasks/MavenKeymapExtension.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/tasks/MavenKeymapExtension.java
index 7bde42d519e1..25db4aa482be 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/tasks/MavenKeymapExtension.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/tasks/MavenKeymapExtension.java
@@ -27,6 +27,7 @@ import org.jetbrains.annotations.TestOnly;
import org.jetbrains.idea.maven.execution.MavenRunConfigurationType;
import org.jetbrains.idea.maven.execution.MavenRunnerParameters;
import org.jetbrains.idea.maven.model.MavenConstants;
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
import org.jetbrains.idea.maven.model.MavenPlugin;
import org.jetbrains.idea.maven.project.MavenProject;
import org.jetbrains.idea.maven.utils.MavenArtifactUtil;
@@ -176,10 +177,12 @@ public class MavenKeymapExtension implements KeymapExtension {
public void actionPerformed(AnActionEvent e) {
final DataContext context = e.getDataContext();
+ MavenExplicitProfiles explicitProfiles = MavenActionUtil.getProjectsManager(context).getExplicitProfiles();
MavenRunnerParameters params = new MavenRunnerParameters(true,
myMavenProject.getDirectory(),
Arrays.asList(myGoal),
- MavenActionUtil.getProjectsManager(context).getExplicitProfiles());
+ explicitProfiles.getEnabledProfiles(),
+ explicitProfiles.getDisabledProfiles());
MavenRunConfigurationType.runConfiguration(MavenActionUtil.getProject(context), params, null);
}
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/tasks/MavenTasksManager.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/tasks/MavenTasksManager.java
index 3dabc5a32f25..c085e1867d10 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/tasks/MavenTasksManager.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/tasks/MavenTasksManager.java
@@ -33,6 +33,7 @@ import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.maven.execution.MavenRunner;
import org.jetbrains.idea.maven.execution.MavenRunnerParameters;
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
import org.jetbrains.idea.maven.project.MavenProject;
import org.jetbrains.idea.maven.project.MavenProjectsManager;
import org.jetbrains.idea.maven.utils.MavenSimpleProjectComponent;
@@ -133,10 +134,12 @@ public class MavenTasksManager extends MavenSimpleProjectComponent implements Pe
for (MavenCompilerTask each : tasks) {
VirtualFile file = LocalFileSystem.getInstance().findFileByPath(each.getProjectPath());
if (file == null) continue;
+ MavenExplicitProfiles explicitProfiles = myProjectsManager.getExplicitProfiles();
parametersList.add(new MavenRunnerParameters(true,
file.getParent().getPath(),
Arrays.asList(each.getGoal()),
- myProjectsManager.getExplicitProfiles()));
+ explicitProfiles.getEnabledProfiles(),
+ explicitProfiles.getDisabledProfiles()));
}
}
return myRunner.runBatch(parametersList, null, null, TasksBundle.message("maven.tasks.executing"), context.getProgressIndicator());
@@ -194,4 +197,4 @@ public class MavenTasksManager extends MavenSimpleProjectComponent implements Pe
public interface Listener {
void compileTasksChanged();
}
-} \ No newline at end of file
+}
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenDataKeys.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenDataKeys.java
index 397447c44393..aff34a18217a 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenDataKeys.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenDataKeys.java
@@ -18,16 +18,18 @@ package org.jetbrains.idea.maven.utils;
import com.intellij.execution.RunnerAndConfigurationSettings;
import com.intellij.openapi.actionSystem.DataKey;
import org.jetbrains.idea.maven.model.MavenArtifact;
+import org.jetbrains.idea.maven.model.MavenProfileKind;
import javax.swing.*;
import java.util.Collection;
import java.util.List;
+import java.util.Map;
public class MavenDataKeys {
public static final DataKey<List<String>> MAVEN_GOALS = DataKey.create("MAVEN_GOALS");
public static final DataKey<RunnerAndConfigurationSettings> RUN_CONFIGURATION = DataKey.create("MAVEN_RUN_CONFIGURATION");
- public static final DataKey<List<String>> MAVEN_PROFILES = DataKey.create("MAVEN_PROFILES");
+ public static final DataKey<Map<String, MavenProfileKind>> MAVEN_PROFILES = DataKey.create("MAVEN_PROFILES");
public static final DataKey<Collection<MavenArtifact>> MAVEN_DEPENDENCIES = DataKey.create("MAVEN_DEPENDENCIES");
public static final DataKey<JTree> MAVEN_PROJECTS_TREE = DataKey.create("MAVEN_PROJECTS_TREE");
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenModuleBuilderHelper.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenModuleBuilderHelper.java
index 30755ff733d8..1f0190aaff48 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenModuleBuilderHelper.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenModuleBuilderHelper.java
@@ -194,7 +194,9 @@ public class MavenModuleBuilderHelper {
}
MavenRunnerParameters params = new MavenRunnerParameters(
- false, workingDir.getPath(), Collections.singletonList("org.apache.maven.plugins:maven-archetype-plugin:RELEASE:generate"), null);
+ false, workingDir.getPath(),
+ Collections.singletonList("org.apache.maven.plugins:maven-archetype-plugin:RELEASE:generate"),
+ Collections.<String>emptyList());
MavenRunner runner = MavenRunner.getInstance(project);
MavenRunnerSettings settings = runner.getState().clone();
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenProjectBuilder.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenProjectBuilder.java
index 53a486fb47ba..730284863e32 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenProjectBuilder.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenProjectBuilder.java
@@ -36,6 +36,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.maven.importing.MavenDefaultModifiableModelsProvider;
import org.jetbrains.idea.maven.importing.MavenUIModifiableModelsProvider;
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
import org.jetbrains.idea.maven.model.MavenId;
import org.jetbrains.idea.maven.project.*;
import org.jetbrains.idea.maven.utils.*;
@@ -53,7 +54,8 @@ public class MavenProjectBuilder extends ProjectImportBuilder<MavenProject> {
private VirtualFile myImportRoot;
private List<VirtualFile> myFiles;
private List<String> myProfiles = new ArrayList<String>();
- private List<String> mySelectedProfiles = new ArrayList<String>();
+ private List<String> myActivatedProfiles = new ArrayList<String>();
+ private MavenExplicitProfiles mySelectedProfiles = MavenExplicitProfiles.NONE;
private MavenProjectsTree myMavenProjectTree;
private List<MavenProject> mySelectedProjects;
@@ -109,20 +111,14 @@ public class MavenProjectBuilder extends ProjectImportBuilder<MavenProject> {
settings.generalSettings.setUserSettingsFile(settingsFile.trim());
}
- List<String> selectedProfiles = getSelectedProfiles();
+ MavenExplicitProfiles selectedProfiles = getSelectedProfiles();
- String profilesList = System.getProperty("idea.maven.import.enabled.profiles");
- if (profilesList != null) {
- Set<String> selectedProfilesSet = new LinkedHashSet<String>(selectedProfiles);
-
- for (String profile : StringUtil.split(profilesList, ",")) {
- String trimmedProfileName = profile.trim();
- if (!trimmedProfileName.isEmpty()) {
- selectedProfilesSet.add(trimmedProfileName);
- }
- }
-
- selectedProfiles = new ArrayList<String>(selectedProfilesSet);
+ String enabledProfilesList = System.getProperty("idea.maven.import.enabled.profiles");
+ String disabledProfilesList = System.getProperty("idea.maven.import.disabled.profiles");
+ if (enabledProfilesList != null || disabledProfilesList != null) {
+ selectedProfiles = selectedProfiles.clone();
+ appendProfilesFromString(selectedProfiles.getEnabledProfiles(), enabledProfilesList);
+ appendProfilesFromString(selectedProfiles.getDisabledProfiles(), disabledProfilesList);
}
MavenProjectsManager manager = MavenProjectsManager.getInstance(project);
@@ -138,9 +134,21 @@ public class MavenProjectBuilder extends ProjectImportBuilder<MavenProject> {
: new MavenDefaultModifiableModelsProvider(project));
}
+ private void appendProfilesFromString(Collection<String> selectedProfiles, String profilesList) {
+ if (profilesList == null) return;
+
+ for (String profile : StringUtil.split(profilesList, ",")) {
+ String trimmedProfileName = profile.trim();
+ if (!trimmedProfileName.isEmpty()) {
+ selectedProfiles.add(trimmedProfileName);
+ }
+ }
+ }
+
public boolean setRootDirectory(@Nullable Project projectToUpdate, final String root) throws ConfigurationException {
getParameters().myFiles = null;
getParameters().myProfiles.clear();
+ getParameters().myActivatedProfiles.clear();
getParameters().myMavenProjectTree = null;
getParameters().myProjectToUpdate = projectToUpdate; // We cannot determinate project in non-EDT thread.
@@ -174,7 +182,8 @@ public class MavenProjectBuilder extends ProjectImportBuilder<MavenProject> {
private void collectProfiles(MavenProgressIndicator process) {
process.setText(ProjectBundle.message("maven.searching.profiles"));
- Set<String> uniqueProfiles = new LinkedHashSet<String>();
+ Set<String> availableProfiles = new LinkedHashSet<String>();
+ Set<String> activatedProfiles = new LinkedHashSet<String>();
MavenProjectReader reader = new MavenProjectReader();
MavenGeneralSettings generalSettings = getGeneralSettings();
MavenProjectReaderProjectLocator locator = new MavenProjectReaderProjectLocator() {
@@ -185,21 +194,27 @@ public class MavenProjectBuilder extends ProjectImportBuilder<MavenProject> {
for (VirtualFile f : getParameters().myFiles) {
MavenProject project = new MavenProject(f);
process.setText2(ProjectBundle.message("maven.reading.pom", f.getPath()));
- project.read(generalSettings, Collections.<String>emptyList(), reader, locator);
- uniqueProfiles.addAll(project.getProfilesIds());
+ project.read(generalSettings, MavenExplicitProfiles.NONE, reader, locator);
+ availableProfiles.addAll(project.getProfilesIds());
+ activatedProfiles.addAll(project.getActivatedProfilesIds().getEnabledProfiles());
}
- getParameters().myProfiles = new ArrayList<String>(uniqueProfiles);
+ getParameters().myProfiles = new ArrayList<String>(availableProfiles);
+ getParameters().myActivatedProfiles = new ArrayList<String>(activatedProfiles);
}
public List<String> getProfiles() {
return getParameters().myProfiles;
}
- public List<String> getSelectedProfiles() {
+ public List<String> getActivatedProfiles() {
+ return getParameters().myActivatedProfiles;
+ }
+
+ public MavenExplicitProfiles getSelectedProfiles() {
return getParameters().mySelectedProfiles;
}
- public boolean setSelectedProfiles(List<String> profiles) {
+ public boolean setSelectedProfiles(MavenExplicitProfiles profiles) {
getParameters().myMavenProjectTree = null;
getParameters().mySelectedProfiles = profiles;
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenProjectOpenProcessor.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenProjectOpenProcessor.java
index 0ba88d7330a1..db9b5562e073 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenProjectOpenProcessor.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenProjectOpenProcessor.java
@@ -26,9 +26,9 @@ import com.intellij.projectImport.ProjectOpenProcessorBase;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.maven.model.MavenConstants;
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
import org.jetbrains.idea.maven.project.MavenProject;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -45,7 +45,7 @@ public class MavenProjectOpenProcessor extends ProjectOpenProcessorBase<MavenPro
public boolean doQuickImport(VirtualFile file, WizardContext wizardContext) {
getBuilder().setFiles(Arrays.asList(file));
- if (!getBuilder().setSelectedProfiles(new ArrayList<String>())) return false;
+ if (!getBuilder().setSelectedProfiles(MavenExplicitProfiles.NONE)) return false;
List<MavenProject> projects = getBuilder().getList();
if (projects.size() != 1) return false;
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/SelectProfilesStep.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/SelectProfilesStep.java
index 4f0238c2694b..3fc7fb47b202 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/SelectProfilesStep.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/SelectProfilesStep.java
@@ -15,14 +15,21 @@
*/
package org.jetbrains.idea.maven.wizards;
-import com.intellij.ide.util.ElementsChooser;
+import com.intellij.ide.util.MultiStateElementsChooser;
import com.intellij.ide.util.projectWizard.WizardContext;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.projectImport.ProjectImportWizardStep;
+import gnu.trove.THashSet;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
+import org.jetbrains.idea.maven.model.MavenProfileKind;
import javax.swing.*;
-import java.util.ArrayList;
+import javax.swing.table.TableCellRenderer;
+import java.awt.*;
+import java.util.*;
import java.util.List;
/**
@@ -30,7 +37,8 @@ import java.util.List;
*/
public class SelectProfilesStep extends ProjectImportWizardStep {
private JPanel panel;
- private ElementsChooser<String> profileChooser;
+ private MultiStateElementsChooser<String, MavenProfileKind> profileChooser;
+ private MavenProfileKindMarkStateDescriptor myMarkStateDescriptor;
public SelectProfilesStep(final WizardContext context) {
super(context);
@@ -52,7 +60,8 @@ public class SelectProfilesStep extends ProjectImportWizardStep {
}
public void createUIComponents() {
- profileChooser = new ElementsChooser<String>(true);
+ myMarkStateDescriptor = new MavenProfileKindMarkStateDescriptor();
+ profileChooser = new MultiStateElementsChooser<String, MavenProfileKind>(true, myMarkStateDescriptor);
}
public JComponent getComponent() {
@@ -61,15 +70,39 @@ public class SelectProfilesStep extends ProjectImportWizardStep {
public void updateStep() {
List<String> allProfiles = getBuilder().getProfiles();
- List<String> markedProfiles = new ArrayList<String>(getBuilder().getSelectedProfiles());
- markedProfiles.retainAll(allProfiles); // mark only existing profiles
+ List<String> activatedProfiles = getBuilder().getActivatedProfiles();
+ MavenExplicitProfiles selectedProfiles = getBuilder().getSelectedProfiles();
+ List<String> enabledProfiles = new ArrayList<String>(selectedProfiles.getEnabledProfiles());
+ List<String> disabledProfiles = new ArrayList<String>(selectedProfiles.getDisabledProfiles());
+ enabledProfiles.retainAll(allProfiles); // mark only existing profiles
+ disabledProfiles.retainAll(allProfiles); // mark only existing profiles
- profileChooser.setElements(allProfiles, false);
- profileChooser.markElements(markedProfiles);
+ myMarkStateDescriptor.setActivatedProfiles(activatedProfiles);
+ profileChooser.setElements(allProfiles, null);
+ profileChooser.markElements(enabledProfiles, MavenProfileKind.EXPLICIT);
+ profileChooser.markElements(disabledProfiles, MavenProfileKind.NONE);
}
public boolean validate() throws ConfigurationException {
- return getBuilder().setSelectedProfiles(profileChooser.getMarkedElements());
+ Collection<String> activatedProfiles = myMarkStateDescriptor.getActivatedProfiles();
+ MavenExplicitProfiles newSelectedProfiles = MavenExplicitProfiles.NONE.clone();
+ for (Map.Entry<String, MavenProfileKind> entry : profileChooser.getElementMarkStates().entrySet()) {
+ String profile = entry.getKey();
+ MavenProfileKind profileKind = entry.getValue();
+ switch (profileKind) {
+ case NONE:
+ if (activatedProfiles.contains(profile)) {
+ newSelectedProfiles.getDisabledProfiles().add(profile);
+ }
+ break;
+ case EXPLICIT:
+ newSelectedProfiles.getEnabledProfiles().add(profile);
+ break;
+ case IMPLICIT:
+ break;
+ }
+ }
+ return getBuilder().setSelectedProfiles(newSelectedProfiles);
}
public void updateDataModel() {
@@ -79,4 +112,100 @@ public class SelectProfilesStep extends ProjectImportWizardStep {
public String getHelpId() {
return "reference.dialogs.new.project.import.maven.page2";
}
+
+ private static class MavenProfileKindMarkStateDescriptor
+ implements MultiStateElementsChooser.MarkStateDescriptor<String, MavenProfileKind> {
+ private Collection<String> myActivatedProfiles = Collections.emptySet();
+
+ public Collection<String> getActivatedProfiles() {
+ return myActivatedProfiles;
+ }
+
+ public void setActivatedProfiles(Collection<String> activatedProfiles) {
+ myActivatedProfiles = new THashSet<String>(activatedProfiles);
+ }
+
+ @NotNull
+ @Override
+ public MavenProfileKind getDefaultState(@NotNull String element) {
+ return myActivatedProfiles.contains(element) ? MavenProfileKind.IMPLICIT : MavenProfileKind.NONE;
+ }
+
+ @NotNull
+ @Override
+ public MavenProfileKind getNextState(@NotNull String element, @NotNull MavenProfileKind state) {
+ MavenProfileKind nextState;
+ switch (state) {
+ case NONE:
+ nextState = MavenProfileKind.EXPLICIT;
+ break;
+ case EXPLICIT:
+ nextState = getDefaultState(element);
+ break;
+ case IMPLICIT:
+ default:
+ nextState = MavenProfileKind.NONE;
+ break;
+ }
+ return nextState;
+ }
+
+ @Nullable
+ @Override
+ public MavenProfileKind getNextState(@NotNull Map<String, MavenProfileKind> elementsWithStates) {
+ MavenProfileKind nextState = null;
+ for (Map.Entry<String, MavenProfileKind> entry : elementsWithStates.entrySet()) {
+ MavenProfileKind nextElementState = getNextState(entry.getKey(), entry.getValue());
+ if (nextState == null) {
+ nextState = nextElementState;
+ }
+ else if (!nextState.equals(nextElementState)) {
+ nextState = null;
+ break;
+ }
+ }
+ return nextState;
+ }
+
+ @Override
+ public boolean isMarked(@NotNull MavenProfileKind state) {
+ return state != MavenProfileKind.NONE;
+ }
+
+ @Nullable
+ @Override
+ public MavenProfileKind getMarkState(@Nullable Object value) {
+ return value instanceof MavenProfileKind ? (MavenProfileKind)value : null;
+ }
+
+ @Nullable
+ @Override
+ public TableCellRenderer getMarkRenderer() {
+ return new CheckboxTableCellRenderer();
+ }
+ }
+
+ private static class CheckboxTableCellRenderer extends JCheckBox implements TableCellRenderer {
+ public CheckboxTableCellRenderer() {
+ setHorizontalAlignment(SwingConstants.CENTER);
+ setBorder(null);
+ }
+
+ public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
+ if (isSelected) {
+ setForeground(table.getSelectionForeground());
+ super.setBackground(table.getSelectionBackground());
+ }
+ else {
+ setForeground(table.getForeground());
+ setBackground(table.getBackground());
+ }
+
+ MavenProfileKind state = (MavenProfileKind)value;
+ setSelected(state != MavenProfileKind.NONE);
+ setEnabled(state != MavenProfileKind.IMPLICIT);
+
+ return this;
+ }
+ }
}
diff --git a/plugins/maven/src/main/resources/ProjectBundle.properties b/plugins/maven/src/main/resources/ProjectBundle.properties
index 926720c4d82e..6ceac4f4fcee 100644
--- a/plugins/maven/src/main/resources/ProjectBundle.properties
+++ b/plugins/maven/src/main/resources/ProjectBundle.properties
@@ -66,6 +66,7 @@ maven.ingored.no.file=No Maven files
maven.ignore.edit=Edit Ignored Files...
maven.profile.activate=Activate
maven.profile.deactivate=Deactivate
+maven.profile.default=Use default
maven.project.problem.recursiveInheritance=Recursive inheritance found
maven.project.problem.selfInheritance=Self-inheritance found
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenImportingTestCase.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenImportingTestCase.java
index 6cc0966180b0..79639e96c8b8 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenImportingTestCase.java
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenImportingTestCase.java
@@ -42,6 +42,7 @@ import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.maven.execution.*;
import org.jetbrains.idea.maven.model.MavenArtifact;
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
import org.jetbrains.idea.maven.project.MavenArtifactDownloader;
import org.jetbrains.idea.maven.project.MavenProject;
import org.jetbrains.idea.maven.project.MavenProjectsManager;
@@ -402,7 +403,7 @@ public abstract class MavenImportingTestCase extends MavenTestCase {
}
protected void readProjects(List<VirtualFile> files, String... profiles) {
- myProjectsManager.resetManagedFilesAndProfilesInTests(files, Arrays.asList(profiles));
+ myProjectsManager.resetManagedFilesAndProfilesInTests(files, new MavenExplicitProfiles(Arrays.asList(profiles)));
waitForReadingCompletion();
}
@@ -502,7 +503,7 @@ public abstract class MavenImportingTestCase extends MavenTestCase {
protected void executeGoal(String relativePath, String goal) {
VirtualFile dir = myProjectRoot.findFileByRelativePath(relativePath);
- MavenRunnerParameters rp = new MavenRunnerParameters(true, dir.getPath(), Arrays.asList(goal), null);
+ MavenRunnerParameters rp = new MavenRunnerParameters(true, dir.getPath(), Arrays.asList(goal), Collections.<String>emptyList());
MavenRunnerSettings rs = new MavenRunnerSettings();
MavenExecutor e = new MavenExternalExecutor(myProject, rp, getMavenGeneralSettings(), rs, new SoutMavenConsole());
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/compiler/ResourceFilteringTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/compiler/ResourceFilteringTest.java
index 24b6e5f4e39c..38fc7e27d99a 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/compiler/ResourceFilteringTest.java
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/compiler/ResourceFilteringTest.java
@@ -19,6 +19,7 @@ import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.fileTypes.FileTypes;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
import java.util.Arrays;
@@ -658,7 +659,7 @@ public class ResourceFilteringTest extends MavenCompilingTestCase {
compileModules("project");
assertResult("target/classes/file.properties", "value=val1");
- myProjectsManager.setExplicitProfiles(Arrays.asList("two"));
+ myProjectsManager.setExplicitProfiles(new MavenExplicitProfiles(Arrays.asList("two")));
scheduleResolveAll();
resolveDependenciesAndImport();
compileModules("project");
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenPropertyCompletionAndResolutionTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenPropertyCompletionAndResolutionTest.java
index dc3fb091287b..f9c648cacd5b 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenPropertyCompletionAndResolutionTest.java
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenPropertyCompletionAndResolutionTest.java
@@ -27,6 +27,7 @@ import com.intellij.psi.xml.XmlTag;
import org.jetbrains.idea.maven.dom.model.MavenDomProfiles;
import org.jetbrains.idea.maven.dom.model.MavenDomProfilesModel;
import org.jetbrains.idea.maven.dom.model.MavenDomSettingsModel;
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
import org.jetbrains.idea.maven.vfs.MavenPropertiesVirtualFileSystem;
import java.util.Arrays;
@@ -933,7 +934,7 @@ public class MavenPropertyCompletionAndResolutionTest extends MavenDomTestCase {
assertContain(variants, "project.groupId");
assertDoNotContain(variants, "groupId");
}
-
+
public void testCompletingAfterOpenBraceAndSomeTextWithDot() throws Exception {
createProjectPom("<groupId>test</groupId>" +
"<artifactId>project</artifactId>" +
@@ -955,7 +956,7 @@ public class MavenPropertyCompletionAndResolutionTest extends MavenDomTestCase {
}
private void readWithProfiles(String... profiles) {
- myProjectsManager.setExplicitProfiles(Arrays.asList(profiles));
+ myProjectsManager.setExplicitProfiles(new MavenExplicitProfiles(Arrays.asList(profiles)));
waitForReadingCompletion();
}
}
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/execution/MavenExecutionTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/execution/MavenExecutionTest.java
index 4a0f5e22cc45..f8c019c5b6be 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/execution/MavenExecutionTest.java
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/execution/MavenExecutionTest.java
@@ -30,6 +30,7 @@ import org.jetbrains.idea.maven.MavenImportingTestCase;
import javax.swing.*;
import java.io.File;
import java.util.Arrays;
+import java.util.Collections;
@SuppressWarnings({"ConstantConditions"})
public class MavenExecutionTest extends MavenImportingTestCase {
@@ -59,7 +60,7 @@ public class MavenExecutionTest extends MavenImportingTestCase {
assertFalse(new File(getProjectPath(), "target").exists());
- execute(new MavenRunnerParameters(true, getProjectPath(), Arrays.asList("compile"), null));
+ execute(new MavenRunnerParameters(true, getProjectPath(), Arrays.asList("compile"), Collections.<String>emptyList()));
assertTrue(new File(getProjectPath(), "target").exists());
}
@@ -84,7 +85,7 @@ public class MavenExecutionTest extends MavenImportingTestCase {
assertModules("project");
assertExcludes("project", "target");
- MavenRunnerParameters params = new MavenRunnerParameters(true, getProjectPath(), Arrays.asList("compile"), null);
+ MavenRunnerParameters params = new MavenRunnerParameters(true, getProjectPath(), Arrays.asList("compile"), Collections.<String>emptyList());
execute(params);
SwingUtilities.invokeAndWait(new Runnable() {
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/MavenPerformanceTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/MavenPerformanceTest.java
index e98fe82ec4b8..008fc9c88076 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/MavenPerformanceTest.java
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/MavenPerformanceTest.java
@@ -19,6 +19,7 @@ import com.intellij.idea.Bombed;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.idea.maven.MavenImportingTestCase;
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
import org.jetbrains.idea.maven.project.MavenProject;
import java.util.Calendar;
@@ -34,7 +35,7 @@ public abstract class MavenPerformanceTest extends MavenImportingTestCase {
super.setUp();
VirtualFile file = LocalFileSystem.getInstance().findFileByPath("C:\\projects\\mvn\\_projects\\geronimo\\pom.xml");
initProjectsManager(false);
- myProjectsManager.resetManagedFilesAndProfilesInTests(Collections.singletonList(file), Collections.<String>emptyList());
+ myProjectsManager.resetManagedFilesAndProfilesInTests(Collections.singletonList(file), MavenExplicitProfiles.NONE);
}
public void testReading() throws Exception {
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/navigator/MavenProjectsNavigatorTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/navigator/MavenProjectsNavigatorTest.java
index 86a80e0b98e6..a04fe5bd94d5 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/navigator/MavenProjectsNavigatorTest.java
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/navigator/MavenProjectsNavigatorTest.java
@@ -17,6 +17,7 @@ package org.jetbrains.idea.maven.navigator;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.idea.maven.MavenImportingTestCase;
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
import java.util.Arrays;
import java.util.Collections;
@@ -50,7 +51,7 @@ public class MavenProjectsNavigatorTest extends MavenImportingTestCase {
createModulePom("m", "<groupId>test</groupId>" +
"<artifactId>m</artifactId>" +
"<version>1</version>");
- myProjectsManager.resetManagedFilesAndProfilesInTests(Collections.singletonList(myProjectPom), Collections.<String>emptyList());
+ myProjectsManager.resetManagedFilesAndProfilesInTests(Collections.singletonList(myProjectPom), MavenExplicitProfiles.NONE);
waitForReadingCompletion();
myProjectsManager.fireActivatedInTests();
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenFoldersImporterTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenFoldersImporterTest.java
index e6e946e71c15..cea4ea2232e9 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenFoldersImporterTest.java
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenFoldersImporterTest.java
@@ -18,6 +18,8 @@ package org.jetbrains.idea.maven.project;
import com.intellij.ProjectTopics;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.roots.*;
+import com.intellij.openapi.util.registry.Registry;
+import com.intellij.openapi.vcs.changes.ChangeListManager;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Consumer;
import org.jetbrains.idea.maven.MavenImportingTestCase;
@@ -49,6 +51,23 @@ public class MavenFoldersImporterTest extends MavenImportingTestCase {
assertNull(myProjectRoot.findChild("target"));
}
+ public void testIgnoreTargetFolder() throws Exception {
+ importProject("<groupId>test</groupId>" +
+ "<artifactId>project</artifactId>" +
+ "<version>1</version>");
+
+ new File(myProjectRoot.getPath(), "target/classes").mkdirs();
+ updateProjectFolders();
+
+ assertExcludes("project", "target");
+ myProjectRoot.refresh(false, true);
+ VirtualFile target = myProjectRoot.findChild("target");
+ assertNotNull(target);
+ if (!Registry.is("ide.hide.excluded.files")) {
+ assertTrue(ChangeListManager.getInstance(myProject).isIgnoredFile(target));
+ }
+ }
+
public void testUpdatingFoldersForAllTheProjects() throws Exception {
createProjectPom("<groupId>test</groupId>" +
"<artifactId>project</artifactId>" +
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectReaderTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectReaderTest.java
index 770196b390b9..8fc251ac3791 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectReaderTest.java
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectReaderTest.java
@@ -1586,7 +1586,7 @@ public class MavenProjectReaderTest extends MavenTestCase {
String... profiles) {
MavenProjectReaderResult result = new MavenProjectReader().readProject(getMavenGeneralSettings(),
file,
- Arrays.asList(profiles),
+ new MavenExplicitProfiles(Arrays.asList(profiles)),
locator);
return result;
}
@@ -1629,7 +1629,7 @@ public class MavenProjectReaderTest extends MavenTestCase {
private void assertActiveProfiles(List<String> explicitProfiles, String... expected) {
MavenProjectReaderResult result =
readProject(myProjectPom, new NullProjectLocator(), ArrayUtil.toStringArray(explicitProfiles));
- assertUnorderedElementsAreEqual(result.activatedProfiles, expected);
+ assertUnorderedElementsAreEqual(result.activatedProfiles.getEnabledProfiles(), expected);
}
private static class NullProjectLocator implements MavenProjectReaderProjectLocator {
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectsManagerTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectsManagerTest.java
index 6c9bc1c4d08f..dc7f5490f272 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectsManagerTest.java
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectsManagerTest.java
@@ -29,6 +29,7 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.FileContentUtil;
import org.jetbrains.idea.maven.MavenImportingTestCase;
import org.jetbrains.idea.maven.importing.MavenRootModelAdapter;
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
import org.jetbrains.idea.maven.server.NativeMavenProjectHolder;
import java.io.File;
@@ -686,7 +687,7 @@ public class MavenProjectsManagerTest extends MavenImportingTestCase {
"<version>1</version>");
importProjects(p1, p2);
- myProjectsManager.setExplicitProfiles(Arrays.asList("one", "two"));
+ myProjectsManager.setExplicitProfiles(new MavenExplicitProfiles(Arrays.asList("one", "two")));
myProjectsManager.setIgnoredFilesPaths(Arrays.asList(p1.getPath()));
myProjectsManager.setIgnoredFilesPatterns(Arrays.asList("*.xxx"));
@@ -707,7 +708,7 @@ public class MavenProjectsManagerTest extends MavenImportingTestCase {
assertUnorderedPathsAreEqual(myProjectsManager.getProjectsTreeForTests().getManagedFilesPaths(),
Arrays.asList(p1.getPath(), p3.getPath()));
- assertUnorderedElementsAreEqual(myProjectsManager.getExplicitProfiles(), "three");
+ assertUnorderedElementsAreEqual(myProjectsManager.getExplicitProfiles().getEnabledProfiles(), "three");
assertUnorderedPathsAreEqual(myProjectsManager.getIgnoredFilesPaths(), Arrays.asList(p1.getPath()));
assertUnorderedElementsAreEqual(myProjectsManager.getIgnoredFilesPatterns(), "*.zzz");
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectsTreeReadingTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectsTreeReadingTest.java
index 842b6099b721..c3a322c49c0a 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectsTreeReadingTest.java
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectsTreeReadingTest.java
@@ -22,6 +22,7 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.testFramework.PlatformTestUtil;
import com.intellij.util.Function;
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
import org.jetbrains.idea.maven.server.NativeMavenProjectHolder;
import org.jetbrains.idea.maven.utils.MavenUtil;
@@ -1539,7 +1540,7 @@ public class MavenProjectsTreeReadingTest extends MavenProjectsTreeTestCase {
MyLoggingListener l = new MyLoggingListener();
myTree.addListener(l);
- myTree.addManagedFilesWithProfiles(Collections.singletonList(myProjectPom), Collections.<String>emptyList());
+ myTree.addManagedFilesWithProfiles(Collections.singletonList(myProjectPom), MavenExplicitProfiles.NONE);
myTree.updateAll(false, getMavenGeneralSettings(), EMPTY_MAVEN_PROCESS);
assertEquals("updated: parent m1 m2 deleted: <none> ", l.log);
@@ -2022,7 +2023,7 @@ public class MavenProjectsTreeReadingTest extends MavenProjectsTreeTestCase {
myProjectPom);
MavenProject project = myTree.findProject(myProjectPom);
- assertUnorderedElementsAreEqual(project.getActivatedProfilesIds(),
+ assertUnorderedElementsAreEqual(project.getActivatedProfilesIds().getEnabledProfiles(),
"projectProfileXml",
"projectProfile",
"parent1Profile",
@@ -2044,7 +2045,7 @@ public class MavenProjectsTreeReadingTest extends MavenProjectsTreeTestCase {
embeddersManager.releaseInTests();
}
- assertUnorderedElementsAreEqual(project.getActivatedProfilesIds(),
+ assertUnorderedElementsAreEqual(project.getActivatedProfilesIds().getEnabledProfiles(),
"projectProfileXml",
"projectProfile",
"parent1Profile",
@@ -2069,24 +2070,24 @@ public class MavenProjectsTreeReadingTest extends MavenProjectsTreeTestCase {
"</profile>");
updateAll(Arrays.asList("one", "two"), myProjectPom);
- assertUnorderedElementsAreEqual(myTree.getExplicitProfiles(), "one", "two");
+ assertUnorderedElementsAreEqual(myTree.getExplicitProfiles().getEnabledProfiles(), "one", "two");
deleteProfilesXml();
update(myProjectPom);
- assertUnorderedElementsAreEqual(myTree.getExplicitProfiles(), "one");
+ assertUnorderedElementsAreEqual(myTree.getExplicitProfiles().getEnabledProfiles(), "one");
createProjectPom("<groupId>test</groupId>" +
"<artifactId>project</artifactId>" +
"<version>1</version>");
update(myProjectPom);
- assertUnorderedElementsAreEqual(myTree.getExplicitProfiles());
+ assertUnorderedElementsAreEqual(myTree.getExplicitProfiles().getEnabledProfiles());
createProfilesXml("<profile>" +
" <id>two</id>" +
"</profile>");
update(myProjectPom);
- assertUnorderedElementsAreEqual(myTree.getExplicitProfiles(), "two");
+ assertUnorderedElementsAreEqual(myTree.getExplicitProfiles().getEnabledProfiles(), "two");
createProjectPom("<groupId>test</groupId>" +
"<artifactId>project</artifactId>" +
@@ -2097,7 +2098,7 @@ public class MavenProjectsTreeReadingTest extends MavenProjectsTreeTestCase {
" </profile>" +
"</profiles>");
update(myProjectPom);
- assertUnorderedElementsAreEqual(myTree.getExplicitProfiles(), "one", "two");
+ assertUnorderedElementsAreEqual(myTree.getExplicitProfiles().getEnabledProfiles(), "one", "two");
}
public void testDeletingAndRestoringActiveProfilesWhenProjectDeletes() throws Exception {
@@ -2128,7 +2129,7 @@ public class MavenProjectsTreeReadingTest extends MavenProjectsTreeTestCase {
"</profiles>");
updateAll(Arrays.asList("one", "two"), myProjectPom);
- assertUnorderedElementsAreEqual(myTree.getExplicitProfiles(), "one", "two");
+ assertUnorderedElementsAreEqual(myTree.getExplicitProfiles().getEnabledProfiles(), "one", "two");
final VirtualFile finalM = m;
new WriteCommandAction.Simple(myProject) {
@@ -2139,7 +2140,7 @@ public class MavenProjectsTreeReadingTest extends MavenProjectsTreeTestCase {
}
}.execute().throwException();
- assertUnorderedElementsAreEqual(myTree.getExplicitProfiles(), "one");
+ assertUnorderedElementsAreEqual(myTree.getExplicitProfiles().getEnabledProfiles(), "one");
m = createModulePom("m",
"<groupId>test</groupId>" +
@@ -2152,7 +2153,7 @@ public class MavenProjectsTreeReadingTest extends MavenProjectsTreeTestCase {
" </profile>" +
"</profiles>");
update(m);
- assertUnorderedElementsAreEqual(myTree.getExplicitProfiles(), "one", "two");
+ assertUnorderedElementsAreEqual(myTree.getExplicitProfiles().getEnabledProfiles(), "one", "two");
}
public void testFindRootWithMultiLevelAggregator() throws Exception {
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectsTreeTestCase.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectsTreeTestCase.java
index 3688a2df46dd..8d73c5f53bb1 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectsTreeTestCase.java
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectsTreeTestCase.java
@@ -17,6 +17,7 @@ package org.jetbrains.idea.maven.project;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.idea.maven.MavenImportingTestCase;
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
import org.jetbrains.idea.maven.utils.MavenProcessCanceledException;
import java.io.IOException;
@@ -33,7 +34,7 @@ public abstract class MavenProjectsTreeTestCase extends MavenImportingTestCase {
}
protected void updateAll(List<String> profiles, VirtualFile... files) throws MavenProcessCanceledException {
- myTree.resetManagedFilesAndProfiles(asList(files), profiles);
+ myTree.resetManagedFilesAndProfiles(asList(files), new MavenExplicitProfiles(profiles));
myTree.updateAll(false, getMavenGeneralSettings(), EMPTY_MAVEN_PROCESS);
}
@@ -50,4 +51,4 @@ public abstract class MavenProjectsTreeTestCase extends MavenImportingTestCase {
each.setBinaryContent(each.contentsToByteArray());
}
}
-} \ No newline at end of file
+}
diff --git a/plugins/properties/resources/icons/xmlProperties.png b/plugins/properties/properties-psi-api/resources/icons/xmlProperties.png
index a9958c7311ad..a9958c7311ad 100644
--- a/plugins/properties/resources/icons/xmlProperties.png
+++ b/plugins/properties/properties-psi-api/resources/icons/xmlProperties.png
Binary files differ
diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/PropertiesImplUtil.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/PropertiesImplUtil.java
index b29fc4f78141..8f5084b87391 100644
--- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/PropertiesImplUtil.java
+++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/PropertiesImplUtil.java
@@ -115,21 +115,18 @@ public class PropertiesImplUtil extends PropertiesUtil {
@Nullable
public static ResourceBundle createByUrl(final @NotNull String url, final @NotNull Project project) {
- if (!url.startsWith(ResourceBundleImpl.RESOURCE_BUNDLE_PREFIX)) return null;
-
- final String defaultPropertiesUrl = url.substring(ResourceBundleImpl.RESOURCE_BUNDLE_PREFIX.length());
- final int idx = defaultPropertiesUrl.lastIndexOf('/');
+ final int idx = url.lastIndexOf('/');
if (idx == -1) return null;
- final String baseDirectoryName = defaultPropertiesUrl.substring(0, idx);
- final String baseName = defaultPropertiesUrl.substring(idx + 1);
+ final String baseDirectoryName = url.substring(0, idx);
+ final String baseName = url.substring(idx + 1);
final VirtualFile baseDirectoryVirtualFile = VirtualFileManager.getInstance().findFileByUrl(baseDirectoryName);
if (baseDirectoryVirtualFile == null) {
return null;
}
- final PsiFile baseDirectory = PsiManager.getInstance(project).findFile(baseDirectoryVirtualFile);
- if (baseDirectory == null || !(baseDirectory instanceof PsiDirectory)) {
+ final PsiDirectory baseDirectory = PsiManager.getInstance(project).findDirectory(baseDirectoryVirtualFile);
+ if (baseDirectory == null) {
return null;
}
- return getResourceBundle(baseName, (PsiDirectory)baseDirectory);
+ return getResourceBundle(baseName, baseDirectory);
}
}
diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleImpl.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleImpl.java
index d257824166e9..ca5c8aa39a36 100644
--- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleImpl.java
+++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleImpl.java
@@ -23,16 +23,13 @@ import com.intellij.lang.properties.psi.PropertiesFile;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiFile;
import com.intellij.util.SmartList;
-import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public class ResourceBundleImpl extends ResourceBundle {
- @NonNls public static final String RESOURCE_BUNDLE_PREFIX = "resourceBundle:";
@NotNull private final PropertiesFile myDefaultPropertiesFile;
public ResourceBundleImpl(@NotNull final PropertiesFile defaultPropertiesFile) {
@@ -106,6 +103,6 @@ public class ResourceBundleImpl extends ResourceBundle {
}
public String getUrl() {
- return RESOURCE_BUNDLE_PREFIX + getBaseDirectory() + "/" + getBaseName();
+ return getBaseDirectory() + "/" + getBaseName();
}
} \ No newline at end of file
diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/structureView/PropertiesSeparatorManager.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/structureView/PropertiesSeparatorManager.java
index cb60de04bc4f..398b9ae1f8e4 100644
--- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/structureView/PropertiesSeparatorManager.java
+++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/structureView/PropertiesSeparatorManager.java
@@ -23,11 +23,13 @@ import com.intellij.lang.properties.*;
import com.intellij.lang.properties.psi.PropertiesFile;
import com.intellij.openapi.components.*;
import com.intellij.openapi.project.Project;
-import gnu.trove.THashMap;
+import com.intellij.util.containers.HashMap;
+import com.intellij.util.containers.SoftFactoryMap;
+import com.intellij.util.xmlb.annotations.MapAnnotation;
+import com.intellij.util.xmlb.annotations.Property;
+import com.intellij.util.xmlb.annotations.Transient;
import gnu.trove.TIntLongHashMap;
import gnu.trove.TIntProcedure;
-import org.jdom.Element;
-import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -41,17 +43,22 @@ import java.util.Map;
file = StoragePathMacros.PROJECT_FILE
)}
)
-public class PropertiesSeparatorManager implements PersistentStateComponent<Element> {
- @NonNls private static final String FILE_ELEMENT = "file";
- @NonNls private static final String URL_ELEMENT = "url";
- @NonNls private static final String SEPARATOR_ATTR = "separator";
+public class PropertiesSeparatorManager implements PersistentStateComponent<PropertiesSeparatorManager.PropertiesSeparatorManagerState> {
private final Project myProject;
public static PropertiesSeparatorManager getInstance(final Project project) {
return ServiceManager.getService(project, PropertiesSeparatorManager.class);
}
- private final Map<String, String> mySeparators = new THashMap<String, String>();
+ private PropertiesSeparatorManagerState myUserDefinedSeparators = new PropertiesSeparatorManagerState();
+ @SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
+ private final SoftFactoryMap<ResourceBundleImpl, String> myGuessedSeparators = new SoftFactoryMap<ResourceBundleImpl, String>() {
+ @Nullable
+ @Override
+ protected String create(ResourceBundleImpl resourceBundle) {
+ return guessSeparator(resourceBundle);
+ }
+ };
public PropertiesSeparatorManager(final Project project) {
myProject = project;
@@ -62,12 +69,9 @@ public class PropertiesSeparatorManager implements PersistentStateComponent<Elem
if (!(resourceBundle instanceof ResourceBundleImpl)) {
return ".";
}
- String separator = mySeparators.get(((ResourceBundleImpl)resourceBundle).getUrl());
- if (separator == null) {
- separator = guessSeparator((ResourceBundleImpl)resourceBundle);
- setSeparator(resourceBundle, separator);
- }
- return separator;
+ final ResourceBundleImpl resourceBundleImpl = (ResourceBundleImpl)resourceBundle;
+ String separator = myUserDefinedSeparators.getSeparators().get(resourceBundleImpl.getUrl());
+ return separator == null ? myGuessedSeparators.get(resourceBundleImpl) : separator;
}
//returns most probable separator in properties files
@@ -108,23 +112,68 @@ public class PropertiesSeparatorManager implements PersistentStateComponent<Elem
public void setSeparator(ResourceBundle resourceBundle, String separator) {
if (resourceBundle instanceof ResourceBundleImpl) {
- mySeparators.put(((ResourceBundleImpl)resourceBundle).getUrl(), separator);
+ myUserDefinedSeparators.getSeparators().put(((ResourceBundleImpl)resourceBundle).getUrl(), separator);
}
}
- public void loadState(final Element element) {
- List<Element> files = element.getChildren(FILE_ELEMENT);
- for (Element fileElement : files) {
- String url = fileElement.getAttributeValue(URL_ELEMENT, "");
- String separator = fileElement.getAttributeValue(SEPARATOR_ATTR,"");
- separator = decodeSeparator(separator);
- if (separator == null) {
- continue;
+ public void loadState(final PropertiesSeparatorManagerState state) {
+ myUserDefinedSeparators = state.decode(myProject);
+ }
+
+ @Nullable
+ @Override
+ public PropertiesSeparatorManagerState getState() {
+ return myUserDefinedSeparators.isEmpty() ? null : myUserDefinedSeparators.encode();
+ }
+
+ public static class PropertiesSeparatorManagerState {
+ @Property(surroundWithTag = false)
+ @MapAnnotation(surroundWithTag = false,
+ surroundKeyWithTag = false,
+ surroundValueWithTag = false,
+ keyAttributeName = "url",
+ valueAttributeName = "separator",
+ entryTagName = "file")
+ public Map<String, String> mySeparators = new HashMap<String, String>();
+
+ public Map<String, String> getSeparators() {
+ return mySeparators;
+ }
+
+ public boolean isEmpty() {
+ return mySeparators.isEmpty();
+ }
+
+ public PropertiesSeparatorManagerState encode() {
+ PropertiesSeparatorManagerState encodedState = new PropertiesSeparatorManagerState();
+ for (final Map.Entry<String, String> entry : mySeparators.entrySet()) {
+ String separator = entry.getValue();
+ StringBuilder encoded = new StringBuilder(separator.length());
+ for (int i=0;i<separator.length();i++) {
+ char c = separator.charAt(i);
+ encoded.append("\\u");
+ encoded.append(String.format("%04x", (int) c));
+ }
+ encodedState.getSeparators().put(entry.getKey(), encoded.toString());
}
- ResourceBundle resourceBundle = PropertiesImplUtil.createByUrl(url, myProject);
- if (resourceBundle != null) {
- mySeparators.put(url, separator);
+ return encodedState;
+ }
+
+ public PropertiesSeparatorManagerState decode(final Project project) {
+ PropertiesSeparatorManagerState decoded = new PropertiesSeparatorManagerState();
+ for (final Map.Entry<String, String> entry : mySeparators.entrySet()) {
+ String separator = entry.getValue();
+ separator = decodeSeparator(separator);
+ if (separator == null) {
+ continue;
+ }
+ final String url = entry.getKey();
+ ResourceBundle resourceBundle = PropertiesImplUtil.createByUrl(url, project);
+ if (resourceBundle != null) {
+ decoded.getSeparators().put(url, separator);
+ }
}
+ return decoded;
}
}
@@ -140,42 +189,10 @@ public class PropertiesSeparatorManager implements PersistentStateComponent<Elem
if (!encodedCharacter.startsWith("\\u")) {
return null;
}
- int d1 = Character.digit(encodedCharacter.charAt(2), 16);
- int d2 = Character.digit(encodedCharacter.charAt(3), 16);
- int d3 = Character.digit(encodedCharacter.charAt(4), 16);
- int d4 = Character.digit(encodedCharacter.charAt(5), 16);
- if (d1 == -1 || d2 == -1 || d3 == -1 || d4 == -1) {
- return null;
- }
- int b1 = (d1 << 12) & 0xF000;
- int b2 = (d2 << 8) & 0x0F00;
- int b3 = (d3 << 4) & 0x00F0;
- int b4 = (d4 << 0) & 0x000F;
- char code = (char) (b1 | b2 | b3 | b4);
+ char code = (char) Integer.parseInt(encodedCharacter.substring(2), 16);
result.append(code);
pos += 6;
}
return result.toString();
}
-
- public Element getState() {
- Element element = new Element("PropertiesSeparatorManager");
- for (final String url: mySeparators.keySet()) {
- String separator = mySeparators.get(url);
- StringBuilder encoded = new StringBuilder(separator.length());
- for (int i=0;i<separator.length();i++) {
- char c = separator.charAt(i);
- encoded.append("\\u");
- encoded.append(Character.forDigit(c >> 12, 16));
- encoded.append(Character.forDigit((c >> 8) & 0xf, 16));
- encoded.append(Character.forDigit((c >> 4) & 0xf, 16));
- encoded.append(Character.forDigit(c & 0xf, 16));
- }
- Element fileElement = new Element(FILE_ELEMENT);
- fileElement.setAttribute(URL_ELEMENT, url);
- fileElement.setAttribute(SEPARATOR_ATTR, encoded.toString());
- element.addContent(fileElement);
- }
- return element;
- }
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/NestedCopiesBuilder.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/NestedCopiesBuilder.java
index d0eafb77bc4b..062666fbd402 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/NestedCopiesBuilder.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/NestedCopiesBuilder.java
@@ -86,6 +86,10 @@ public class NestedCopiesBuilder implements StatusReceiver {
}
}
+ @Override
+ public void finish() {
+ }
+
public Set<NestedCopyInfo> getCopies() {
return mySet;
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/StatusReceiver.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/StatusReceiver.java
index ac165c48f5c3..f6515de0ebf1 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/StatusReceiver.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/StatusReceiver.java
@@ -29,4 +29,5 @@ public interface StatusReceiver extends EventListener {
void processUnversioned(final VirtualFile vFile);
void processCopyRoot(VirtualFile file, SVNURL url, WorkingCopyFormat format, SVNURL rootURL);
void bewareRoot(VirtualFile vf, SVNURL url);
+ void finish();
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/StatusWalkerPartner.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/StatusWalkerPartner.java
index 367ae1bc4619..690eb1e76ee3 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/StatusWalkerPartner.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/StatusWalkerPartner.java
@@ -15,12 +15,11 @@
*/
package org.jetbrains.idea.svn;
-import com.intellij.lifecycle.PeriodicalTasksCloser;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressIndicator;
-import com.intellij.openapi.roots.FileIndexFacade;
import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.vcs.ProjectLevelVcsManager;
import com.intellij.openapi.vcs.changes.ChangeListManager;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
@@ -34,14 +33,14 @@ import org.tmatesoft.svn.core.wc.ISVNStatusFileProvider;
public class StatusWalkerPartner {
private final SvnVcs myVcs;
private final ChangeListManager myClManager;
- private final FileIndexFacade myExcludedFileIndex;
+ private final ProjectLevelVcsManager myVcsManager;
private final ProgressIndicator myIndicator;
private ISVNStatusFileProvider myFileProvider;
public StatusWalkerPartner(final SvnVcs vcs, final ProgressIndicator pi) {
myVcs = vcs;
myClManager = ChangeListManager.getInstance(myVcs.getProject());
- myExcludedFileIndex = PeriodicalTasksCloser.getInstance().safeGetService(myVcs.getProject(), FileIndexFacade.class);
+ myVcsManager = ProjectLevelVcsManager.getInstance(myVcs.getProject());
myIndicator = pi;
}
@@ -75,12 +74,12 @@ public class StatusWalkerPartner {
}
}
- public boolean isExcluded(final VirtualFile vFile) {
+ public boolean isIgnoredByVcs(final VirtualFile vFile) {
return ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
@Override
public Boolean compute() {
if (myVcs.getProject().isDisposed()) throw new ProcessCanceledException();
- return myExcludedFileIndex.isExcludedFile(vFile);
+ return myVcsManager.isIgnored(vFile);
}
});
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProvider.java
index 073826f6b035..41461ed623c6 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProvider.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProvider.java
@@ -95,6 +95,8 @@ public class SvnChangeProvider implements ChangeProvider {
walker.go(item.getDir(), Depth.IMMEDIATES);
}
+ statusReceiver.getMulticaster().finish();
+
processCopiedAndDeleted(context, dirtyScope);
processUnsaved(dirtyScope, addGate, context);
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProviderContext.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProviderContext.java
index 716abbe1b20b..9ae90c722cb3 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProviderContext.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProviderContext.java
@@ -23,6 +23,7 @@ import com.intellij.openapi.vcs.*;
import com.intellij.openapi.vcs.changes.*;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.actions.AbstractShowPropertiesDiffAction;
@@ -48,6 +49,7 @@ class SvnChangeProviderContext implements StatusReceiver {
private Map<FilePath, String> myCopyFromURLs = null;
private final SvnVcs myVcs;
private final SvnBranchConfigurationManager myBranchConfigurationManager;
+ private final List<File> filesToRefresh = ContainerUtil.newArrayList();
private final ProgressIndicator myProgress;
@@ -79,6 +81,11 @@ class SvnChangeProviderContext implements StatusReceiver {
public void bewareRoot(VirtualFile vf, SVNURL url) {
}
+ @Override
+ public void finish() {
+ LocalFileSystem.getInstance().refreshIoFiles(filesToRefresh, true, false, null);
+ }
+
public ChangelistBuilder getBuilder() {
return myChangelistBuilder;
}
@@ -302,7 +309,7 @@ class SvnChangeProviderContext implements StatusReceiver {
*
* @param filePath the path of a changed file.
*/
- private static void loadEntriesFile(final FilePath filePath) {
+ private void loadEntriesFile(final FilePath filePath) {
final FilePath parentPath = filePath.getParentPath();
if (parentPath == null) {
return;
@@ -313,9 +320,11 @@ class SvnChangeProviderContext implements StatusReceiver {
}
}
- private static void refreshDotSvnAndEntries(FilePath filePath) {
+ private void refreshDotSvnAndEntries(FilePath filePath) {
final File svn = new File(filePath.getPath(), SvnUtil.SVN_ADMIN_DIR_NAME);
- LocalFileSystem.getInstance().refreshIoFiles(Arrays.asList(svn, new File(svn, SvnUtil.ENTRIES_FILE_NAME)), true, false, null);
+
+ filesToRefresh.add(svn);
+ filesToRefresh.add(new File(svn, SvnUtil.ENTRIES_FILE_NAME));
}
// seems here we can only have a tree conflict; which can be marked on either path (?)
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnDiffProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnDiffProvider.java
index 49ea87d44f6e..5f5edd12eea7 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnDiffProvider.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnDiffProvider.java
@@ -34,14 +34,14 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.commandLine.SvnBindException;
import org.jetbrains.idea.svn.history.LatestExistentSearcher;
-import org.jetbrains.idea.svn.info.InfoConsumer;
import org.jetbrains.idea.svn.info.Info;
+import org.jetbrains.idea.svn.info.InfoConsumer;
+import org.jetbrains.idea.svn.properties.PropertyValue;
import org.jetbrains.idea.svn.status.Status;
import org.jetbrains.idea.svn.status.StatusType;
import org.tmatesoft.svn.core.SVNException;
-import org.tmatesoft.svn.core.SVNPropertyValue;
import org.tmatesoft.svn.core.SVNURL;
-import org.tmatesoft.svn.core.wc.*;
+import org.tmatesoft.svn.core.wc.SVNRevision;
import org.tmatesoft.svn.core.wc2.SvnTarget;
import java.io.File;
@@ -162,11 +162,12 @@ public class SvnDiffProvider extends DiffProviderEx implements DiffProvider, Dif
}
}
+ @Nullable
private String getCommitMessage(File path) throws VcsException {
- SVNPropertyData property =
+ PropertyValue property =
myVcs.getFactory(path).createPropertyClient().getProperty(SvnTarget.fromFile(path), COMMIT_MESSAGE, true, SVNRevision.BASE);
- return property != null ? SVNPropertyValue.getPropertyAsString(property.getValue()) : null;
+ return PropertyValue.toString(property);
}
private static ItemLatestState defaultResult() {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnEditFileProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnEditFileProvider.java
index 64248892614a..c8b47aa0928e 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnEditFileProvider.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnEditFileProvider.java
@@ -19,7 +19,7 @@ import com.intellij.openapi.vcs.EditFileProvider;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.idea.svn.properties.PropertyClient;
-import org.tmatesoft.svn.core.wc.SVNPropertyData;
+import org.jetbrains.idea.svn.properties.PropertyValue;
import org.tmatesoft.svn.core.wc.SVNRevision;
import org.tmatesoft.svn.core.wc2.SvnTarget;
@@ -42,10 +42,10 @@ public class SvnEditFileProvider implements EditFileProvider {
ioFiles[i] = new File(files[i].getPath());
PropertyClient client = myVCS.getFactory(ioFiles[i]).createPropertyClient();
- SVNPropertyData property = client.getProperty(SvnTarget.fromFile(ioFiles[i], SVNRevision.WORKING), SvnPropertyKeys.SVN_NEEDS_LOCK,
+ PropertyValue property = client.getProperty(SvnTarget.fromFile(ioFiles[i], SVNRevision.WORKING), SvnPropertyKeys.SVN_NEEDS_LOCK,
false, SVNRevision.WORKING);
- if (property == null || property.getValue() == null) {
+ if (property == null) {
throw new VcsException(SvnBundle.message("exception.text.file.miss.svn", ioFiles[i].getName()));
}
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFormatSelector.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFormatSelector.java
index 1719f781a34a..977c6add0c1f 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFormatSelector.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFormatSelector.java
@@ -15,122 +15,15 @@
*/
package org.jetbrains.idea.svn;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.diagnostic.Logger;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import org.tmatesoft.svn.core.SVNErrorCode;
-import org.tmatesoft.svn.core.SVNErrorMessage;
import org.tmatesoft.svn.core.SVNException;
-import org.tmatesoft.svn.core.internal.wc.admin.ISVNAdminAreaFactorySelector;
import org.tmatesoft.svn.core.internal.wc.admin.SVNAdminAreaFactory;
import org.tmatesoft.svn.core.internal.wc2.SvnWcGeneration;
import org.tmatesoft.svn.core.wc2.SvnOperationFactory;
import java.io.File;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Iterator;
-public class SvnFormatSelector implements ISVNAdminAreaFactorySelector {
-
- private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.SvnFormatSelector");
-
- public Collection getEnabledFactories(File path, Collection factories, boolean writeAccess) throws SVNException {
- if (ApplicationManager.getApplication().isUnitTestMode()) {
- return factories;
- }
-
- if (! writeAccess) {
- return factories;
- }
-
- Collection result = null;
- final WorkingCopyFormat presetFormat = SvnWorkingCopyFormatHolder.getPresetFormat();
- if (presetFormat != null) {
- result = format2Factories(presetFormat, factories);
- }
-
- if (result == null) {
- final WorkingCopyFormat format = getWorkingCopyFormat(path);
- result = format2Factories(format, factories);
- }
-
- if (result == null) {
- throw new SVNException(SVNErrorMessage.create(SVNErrorCode.WC_NOT_DIRECTORY));
- }
- return result;
- }
-
- @Nullable
- static Collection format2Factories(final WorkingCopyFormat format, final Collection factories) {
- if (WorkingCopyFormat.ONE_DOT_SEVEN.equals(format)) {
- return factories;
- } else if (WorkingCopyFormat.ONE_DOT_SIX.equals(format)) {
- return factoriesFor16(factories);
- } else if (WorkingCopyFormat.ONE_DOT_FIVE.equals(format)) {
- return factoriesFor15(factories);
- } else if (WorkingCopyFormat.ONE_DOT_FOUR.equals(format)) {
- return factoriesFor14(factories);
- } else if (WorkingCopyFormat.ONE_DOT_THREE.equals(format)) {
- return factoriesFor13(factories);
- }
- return null;
- }
-
- private static Collection<SVNAdminAreaFactory> factoriesFor13(final Collection factories) {
- for (Iterator iterator = factories.iterator(); iterator.hasNext();) {
- final SVNAdminAreaFactory factory = (SVNAdminAreaFactory) iterator.next();
- final int supportedVersion = factory.getSupportedVersion();
- if (WorkingCopyFormat.ONE_DOT_THREE.getFormat() == supportedVersion) {
- return Collections.singletonList(factory);
- }
- }
- return Collections.emptyList();
- }
-
- private static Collection<SVNAdminAreaFactory> factoriesFor14(final Collection factories) {
- final Collection<SVNAdminAreaFactory> result = new ArrayList<SVNAdminAreaFactory>(2);
- for (Iterator iterator = factories.iterator(); iterator.hasNext();) {
- final SVNAdminAreaFactory factory = (SVNAdminAreaFactory) iterator.next();
- final int supportedVersion = factory.getSupportedVersion();
- if ((WorkingCopyFormat.ONE_DOT_FOUR.getFormat() == supportedVersion) ||
- (WorkingCopyFormat.ONE_DOT_THREE.getFormat() == supportedVersion)) {
- result.add(factory);
- }
- }
- return result;
- }
-
- private static Collection<SVNAdminAreaFactory> factoriesFor15(final Collection factories) {
- final Collection<SVNAdminAreaFactory> result = new ArrayList<SVNAdminAreaFactory>(2);
- for (Iterator iterator = factories.iterator(); iterator.hasNext();) {
- final SVNAdminAreaFactory factory = (SVNAdminAreaFactory) iterator.next();
- final int supportedVersion = factory.getSupportedVersion();
- if ((WorkingCopyFormat.ONE_DOT_FOUR.getFormat() == supportedVersion) ||
- (WorkingCopyFormat.ONE_DOT_THREE.getFormat() == supportedVersion) ||
- (WorkingCopyFormat.ONE_DOT_FIVE.getFormat() == supportedVersion)) {
- result.add(factory);
- }
- }
- return result;
- }
-
- private static Collection<SVNAdminAreaFactory> factoriesFor16(final Collection factories) {
- final Collection<SVNAdminAreaFactory> result = new ArrayList<SVNAdminAreaFactory>(2);
- for (Iterator iterator = factories.iterator(); iterator.hasNext();) {
- final SVNAdminAreaFactory factory = (SVNAdminAreaFactory) iterator.next();
- final int supportedVersion = factory.getSupportedVersion();
- if ((WorkingCopyFormat.ONE_DOT_FOUR.getFormat() == supportedVersion) ||
- (WorkingCopyFormat.ONE_DOT_THREE.getFormat() == supportedVersion) ||
- (WorkingCopyFormat.ONE_DOT_FIVE.getFormat() == supportedVersion) ||
- (WorkingCopyFormat.ONE_DOT_SIX.getFormat() == supportedVersion)) {
- result.add(factory);
- }
- }
- return result;
- }
+public class SvnFormatSelector {
@NotNull
public static WorkingCopyFormat findRootAndGetFormat(final File path) {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java
index 1b1cd00589d0..13c15b23efa8 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java
@@ -103,7 +103,7 @@ public class SvnRecursiveStatusWalker {
if (e.contains(SVNErrorCode.WC_NOT_DIRECTORY) || e.contains(SVNErrorCode.WC_NOT_FILE)) {
final VirtualFile virtualFile = path.getVirtualFile();
if (virtualFile != null) {
- if (! myPartner.isExcluded(virtualFile)) {
+ if (! myPartner.isIgnoredByVcs(virtualFile)) {
// self is unversioned
myReceiver.processUnversioned(virtualFile);
@@ -184,15 +184,20 @@ public class SvnRecursiveStatusWalker {
}
};
if (Depth.EMPTY.equals(newDepth)) {
- directoryFilter = Processor.TRUE;
+ // just process immediate children - so only root directory itself should satisfy filter
+ directoryFilter = new Processor<File>() {
+ @Override
+ public boolean process(File file) {
+ return FileUtil.filesEqual(ioFile, file);
+ }
+ };
processor = new Processor<File>() {
@Override
public boolean process(File file) {
- // here we deal only with immediate children - so ignored on IDEA level for children is not important - we nevertheless do not go into
- // other levels
- if (! FileUtil.filesEqual(ioFile, file)) return true;
- if (! FileUtil.filesEqual(ioFile, file.getParentFile())) return false;
- return checkDirProcessor.process(file);
+ // TODO: check if we should still call checkDirProcessor() here - or we really could not check ignore settings but just call
+ // TODO: myReceiver.processUnversioned() for all immediate children
+ // here we deal only with immediate children - so ignored on IDEA level for children is not important
+ return FileUtil.filesEqual(ioFile, file) || checkDirProcessor.process(file);
}
};
} else {
@@ -278,7 +283,7 @@ public class SvnRecursiveStatusWalker {
@Override
public Boolean compute() {
if (myProject.isDisposed()) return null;
- return myPartner.isExcluded(vFile);
+ return myPartner.isIgnoredByVcs(vFile);
}
});
if (Boolean.TRUE.equals(excluded)) return;
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java
index 5010ac580750..b44fd16f979f 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java
@@ -81,6 +81,8 @@ import org.jetbrains.idea.svn.history.SvnHistoryProvider;
import org.jetbrains.idea.svn.info.Info;
import org.jetbrains.idea.svn.info.InfoConsumer;
import org.jetbrains.idea.svn.properties.PropertyClient;
+import org.jetbrains.idea.svn.properties.PropertyData;
+import org.jetbrains.idea.svn.properties.PropertyValue;
import org.jetbrains.idea.svn.rollback.SvnRollbackEnvironment;
import org.jetbrains.idea.svn.status.Status;
import org.jetbrains.idea.svn.status.StatusType;
@@ -89,7 +91,6 @@ import org.jetbrains.idea.svn.update.SvnIntegrateEnvironment;
import org.jetbrains.idea.svn.update.SvnUpdateEnvironment;
import org.tmatesoft.svn.core.*;
import org.tmatesoft.svn.core.internal.wc.SVNAdminUtil;
-import org.tmatesoft.svn.core.wc.SVNPropertyData;
import org.tmatesoft.svn.core.wc.SVNRevision;
import org.tmatesoft.svn.core.wc2.SvnTarget;
@@ -108,8 +109,8 @@ public class SvnVcs extends AbstractVcs<CommittedChangeList> {
private static final VcsKey ourKey = createKey(VCS_NAME);
public static final Topic<Runnable> WC_CONVERTED = new Topic<Runnable>("WC_CONVERTED", Runnable.class);
- private final Map<String, Map<String, Pair<SVNPropertyValue, Trinity<Long, Long, Long>>>> myPropertyCache =
- new SoftHashMap<String, Map<String, Pair<SVNPropertyValue, Trinity<Long, Long, Long>>>>();
+ private final Map<String, Map<String, Pair<PropertyValue, Trinity<Long, Long, Long>>>> myPropertyCache =
+ new SoftHashMap<String, Map<String, Pair<PropertyValue, Trinity<Long, Long, Long>>>>();
private final SvnConfiguration myConfiguration;
private final SvnEntriesFileListener myEntriesFileListener;
@@ -567,9 +568,9 @@ public class SvnVcs extends AbstractVcs<CommittedChangeList> {
}
@Nullable
- public SVNPropertyValue getPropertyWithCaching(final VirtualFile file, final String propName) throws VcsException {
- Map<String, Pair<SVNPropertyValue, Trinity<Long, Long, Long>>> cachedMap = myPropertyCache.get(keyForVf(file));
- final Pair<SVNPropertyValue, Trinity<Long, Long, Long>> cachedValue = cachedMap == null ? null : cachedMap.get(propName);
+ public PropertyValue getPropertyWithCaching(final VirtualFile file, final String propName) throws VcsException {
+ Map<String, Pair<PropertyValue, Trinity<Long, Long, Long>>> cachedMap = myPropertyCache.get(keyForVf(file));
+ final Pair<PropertyValue, Trinity<Long, Long, Long>> cachedValue = cachedMap == null ? null : cachedMap.get(propName);
final File ioFile = new File(file.getPath());
final Trinity<Long, Long, Long> tsTrinity = getTimestampForPropertiesChange(ioFile, file.isDirectory());
@@ -582,17 +583,16 @@ public class SvnVcs extends AbstractVcs<CommittedChangeList> {
}
PropertyClient client = getFactory(ioFile).createPropertyClient();
- final SVNPropertyData value = client.getProperty(SvnTarget.fromFile(ioFile, SVNRevision.WORKING), propName, false, SVNRevision.WORKING);
- final SVNPropertyValue propValue = value == null ? null : value.getValue();
+ final PropertyValue value = client.getProperty(SvnTarget.fromFile(ioFile, SVNRevision.WORKING), propName, false, SVNRevision.WORKING);
if (cachedMap == null) {
- cachedMap = new HashMap<String, Pair<SVNPropertyValue, Trinity<Long, Long, Long>>>();
+ cachedMap = new HashMap<String, Pair<PropertyValue, Trinity<Long, Long, Long>>>();
myPropertyCache.put(keyForVf(file), cachedMap);
}
- cachedMap.put(propName, Pair.create(propValue, tsTrinity));
+ cachedMap.put(propName, Pair.create(value, tsTrinity));
- return propValue;
+ return value;
}
@Override
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/AbstractShowPropertiesDiffAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/AbstractShowPropertiesDiffAction.java
index 97e6a618ba7c..395dc36b7371 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/AbstractShowPropertiesDiffAction.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/AbstractShowPropertiesDiffAction.java
@@ -19,12 +19,15 @@ import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.diff.DiffManager;
import com.intellij.openapi.diff.SimpleContent;
import com.intellij.openapi.diff.SimpleDiffRequest;
+import com.intellij.openapi.progress.PerformInBackgroundOption;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.AbstractVcs;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.VcsDataKeys;
@@ -34,17 +37,20 @@ import com.intellij.openapi.vcs.changes.ChangesUtil;
import com.intellij.openapi.vcs.changes.ContentRevision;
import com.intellij.openapi.vcs.changes.MarkerVcsContentRevision;
import com.intellij.openapi.vfs.VirtualFile;
-import org.jetbrains.annotations.NonNls;
+import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.SvnBundle;
-import org.jetbrains.idea.svn.SvnRevisionNumber;
import org.jetbrains.idea.svn.SvnVcs;
import org.jetbrains.idea.svn.api.Depth;
import org.jetbrains.idea.svn.history.SvnRepositoryContentRevision;
-import org.tmatesoft.svn.core.*;
-import org.tmatesoft.svn.core.wc.ISVNPropertyHandler;
-import org.tmatesoft.svn.core.wc.SVNPropertyData;
+import org.jetbrains.idea.svn.properties.PropertyConsumer;
+import org.jetbrains.idea.svn.properties.PropertyData;
+import org.jetbrains.idea.svn.properties.PropertyValue;
+import org.tmatesoft.svn.core.SVNErrorCode;
+import org.tmatesoft.svn.core.SVNErrorMessage;
+import org.tmatesoft.svn.core.SVNException;
+import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.wc.SVNRevision;
import org.tmatesoft.svn.core.wc2.SvnTarget;
@@ -69,8 +75,6 @@ public abstract class AbstractShowPropertiesDiffAction extends AnAction implemen
@Override
public void update(final AnActionEvent e) {
final DataContext dataContext = e.getDataContext();
- final Project project = CommonDataKeys.PROJECT.getData(dataContext);
-
final Presentation presentation = e.getPresentation();
final Change[] data = VcsDataKeys.CHANGES.getData(dataContext);
boolean showAction = checkThatChangesAreUnderSvn(data);
@@ -78,38 +82,23 @@ public abstract class AbstractShowPropertiesDiffAction extends AnAction implemen
presentation.setEnabled(showAction);
}
- private boolean checkThatChangesAreUnderSvn(Change[] data) {
- boolean showAction = false;
- if (data != null) {
- for (Change change : data) {
- final ContentRevision before = change.getBeforeRevision();
- if (before != null) {
- showAction = showAction || before instanceof MarkerVcsContentRevision && SvnVcs.getKey().equals(((MarkerVcsContentRevision)before).getVcsKey());
- }
- final ContentRevision after = change.getAfterRevision();
- if (after != null) {
- showAction = showAction || after instanceof MarkerVcsContentRevision && SvnVcs.getKey().equals(((MarkerVcsContentRevision)after).getVcsKey());
+ private static boolean checkThatChangesAreUnderSvn(@Nullable Change[] changes) {
+ boolean result = false;
+
+ if (changes != null) {
+ result = ContainerUtil.or(changes, new Condition<Change>() {
+ @Override
+ public boolean value(Change change) {
+ return isUnderSvn(change.getBeforeRevision()) || isUnderSvn(change.getAfterRevision());
}
- if (showAction) break;
- }
+ });
}
- return showAction;
- }
- private boolean enabled(final Project project, final Change[] changes) {
- final boolean noChange = (project == null) || (changes == null) || (changes.length != 1);
- if (noChange) {
- return false;
- } else {
- final Change change = changes[0];
-
- final ContentRevision revision = (change.getBeforeRevision() != null) ? change.getBeforeRevision() : change.getAfterRevision();
- if ((revision == null) || (! (revision.getRevisionNumber() instanceof SvnRevisionNumber))) {
- return false;
- }
+ return result;
+ }
- return checkVcs(project, change);
- }
+ private static boolean isUnderSvn(@Nullable ContentRevision revision) {
+ return revision instanceof MarkerVcsContentRevision && SvnVcs.getKey().equals(((MarkerVcsContentRevision)revision).getVcsKey());
}
protected boolean checkVcs(final Project project, final Change change) {
@@ -146,7 +135,7 @@ public abstract class AbstractShowPropertiesDiffAction extends AnAction implemen
private final String myErrorTitle;
private CalculateAndShow(@Nullable final Project project, final Change change, final String errorTitle) {
- super(project, SvnBundle.message("fetching.properties.contents.progress.title"), true, Backgroundable.DEAF);
+ super(project, SvnBundle.message("fetching.properties.contents.progress.title"), true, PerformInBackgroundOption.DEAF);
myChange = change;
myErrorTitle = errorTitle;
}
@@ -179,7 +168,7 @@ public abstract class AbstractShowPropertiesDiffAction extends AnAction implemen
}
if (myBeforeContent != null && myAfterContent != null && myBeforeRevisionValue != null && myAfterRevision != null) {
final SimpleDiffRequest diffRequest = new SimpleDiffRequest(myProject, getDiffWindowTitle(myChange));
- if (compareRevisions(myBeforeRevisionValue, myAfterRevision) >= 0) {
+ if (compareRevisions(myBeforeRevisionValue, myAfterRevision) > 0) {
// before ahead
diffRequest.setContents(new SimpleContent(myAfterContent), new SimpleContent(myBeforeContent));
diffRequest.setContentTitles(revisionToString(myAfterRevision), revisionToString(myBeforeRevisionValue));
@@ -194,7 +183,8 @@ public abstract class AbstractShowPropertiesDiffAction extends AnAction implemen
}
}
- private String getDiffWindowTitle(final Change change) {
+ @NotNull
+ private static String getDiffWindowTitle(@NotNull Change change) {
if (change.isMoved() || change.isRenamed()) {
final FilePath beforeFilePath = ChangesUtil.getBeforePath(change);
final FilePath afterFilePath = ChangesUtil.getAfterPath(change);
@@ -207,7 +197,7 @@ public abstract class AbstractShowPropertiesDiffAction extends AnAction implemen
}
}
- private int compareRevisions(@NonNls final SVNRevision revision1, @NonNls final SVNRevision revision2) {
+ private static int compareRevisions(@NotNull SVNRevision revision1, @NotNull SVNRevision revision2) {
if (revision1.equals(revision2)) {
return 0;
}
@@ -227,11 +217,9 @@ public abstract class AbstractShowPropertiesDiffAction extends AnAction implemen
return revision1.getNumber() > revision2.getNumber() ? 1 : -1;
}
- private String revisionToString(final SVNRevision revision) {
- if (revision == null) {
- return "not exists";
- }
- return revision.toString();
+ @NotNull
+ private static String revisionToString(@Nullable SVNRevision revision) {
+ return revision == null ? "not exists" : revision.toString();
}
private final static String ourPropertiesDelimiter = "\n";
@@ -273,35 +261,35 @@ public abstract class AbstractShowPropertiesDiffAction extends AnAction implemen
private static String getPropertyList(@NotNull SvnVcs vcs, @NotNull SvnTarget target, @Nullable SVNRevision revision)
throws VcsException {
- final List<SVNPropertyData> lines = new ArrayList<SVNPropertyData>();
- final ISVNPropertyHandler propertyHandler = createHandler(revision, lines);
+ final List<PropertyData> lines = new ArrayList<PropertyData>();
+ final PropertyConsumer propertyHandler = createHandler(revision, lines);
vcs.getFactory(target).createPropertyClient().list(target, revision, Depth.EMPTY, propertyHandler);
return toSortedStringPresentation(lines);
}
- private static ISVNPropertyHandler createHandler(SVNRevision revision, final List<SVNPropertyData> lines) {
+ private static PropertyConsumer createHandler(SVNRevision revision, final List<PropertyData> lines) {
final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
if (indicator != null) {
indicator.checkCanceled();
indicator.setText(SvnBundle.message("show.properties.diff.progress.text.revision.information", revision.toString()));
}
- return new ISVNPropertyHandler() {
- public void handleProperty(final File path, final SVNPropertyData property) throws SVNException {
+ return new PropertyConsumer() {
+ public void handleProperty(final File path, final PropertyData property) throws SVNException {
registerProperty(property);
}
- public void handleProperty(final SVNURL url, final SVNPropertyData property) throws SVNException {
+ public void handleProperty(final SVNURL url, final PropertyData property) throws SVNException {
registerProperty(property);
}
- public void handleProperty(final long revision, final SVNPropertyData property) throws SVNException {
+ public void handleProperty(final long revision, final PropertyData property) throws SVNException {
// revision properties here
}
- private void registerProperty(@NotNull SVNPropertyData property) {
+ private void registerProperty(@NotNull PropertyData property) {
if (indicator != null) {
indicator.checkCanceled();
indicator.setText2(SvnBundle.message("show.properties.diff.progress.text2.property.information", property.getName()));
@@ -311,26 +299,26 @@ public abstract class AbstractShowPropertiesDiffAction extends AnAction implemen
};
}
- private static String toSortedStringPresentation(List<SVNPropertyData> lines) {
+ private static String toSortedStringPresentation(List<PropertyData> lines) {
StringBuilder sb = new StringBuilder();
- Collections.sort(lines, new Comparator<SVNPropertyData>() {
- public int compare(final SVNPropertyData o1, final SVNPropertyData o2) {
+ Collections.sort(lines, new Comparator<PropertyData>() {
+ public int compare(final PropertyData o1, final PropertyData o2) {
return o1.getName().compareTo(o2.getName());
}
});
- for (SVNPropertyData line : lines) {
+ for (PropertyData line : lines) {
addPropertyPresentation(line, sb);
}
return sb.toString();
}
- private static void addPropertyPresentation(final SVNPropertyData property, final StringBuilder sb) {
+ private static void addPropertyPresentation(final PropertyData property, final StringBuilder sb) {
if (sb.length() != 0) {
sb.append(ourPropertiesDelimiter);
}
- sb.append(property.getName()).append("=").append((property.getValue() == null) ? "" : SVNPropertyValue.getPropertyAsString(property.getValue()));
+ sb.append(property.getName()).append("=").append(StringUtil.notNullize(PropertyValue.toString(property.getValue())));
}
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CreateExternalAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CreateExternalAction.java
index 31206eec045c..d6d9c3152dde 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CreateExternalAction.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CreateExternalAction.java
@@ -24,7 +24,6 @@ import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
-import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.*;
import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager;
@@ -42,15 +41,16 @@ import org.jetbrains.idea.svn.api.ProgressEvent;
import org.jetbrains.idea.svn.api.ProgressTracker;
import org.jetbrains.idea.svn.commandLine.CommandUtil;
import org.jetbrains.idea.svn.dialogs.SelectCreateExternalTargetDialog;
+import org.jetbrains.idea.svn.properties.ExternalsDefinitionParser;
+import org.jetbrains.idea.svn.properties.PropertyValue;
import org.jetbrains.idea.svn.update.UpdateClient;
import org.tmatesoft.svn.core.SVNCancelException;
import org.tmatesoft.svn.core.SVNException;
-import org.tmatesoft.svn.core.SVNPropertyValue;
-import org.tmatesoft.svn.core.internal.wc.SVNExternal;
-import org.tmatesoft.svn.core.wc.*;
+import org.tmatesoft.svn.core.wc.SVNRevision;
import org.tmatesoft.svn.core.wc2.SvnTarget;
import java.io.File;
+import java.util.Map;
/**
* Created with IntelliJ IDEA.
@@ -132,25 +132,24 @@ public class CreateExternalAction extends DumbAwareAction {
public static boolean addToExternalProperty(@NotNull SvnVcs vcs, @NotNull File ioFile, String target, String url)
throws SVNException, VcsException {
ClientFactory factory = vcs.getFactory(ioFile);
- SVNPropertyData propertyData = factory.createPropertyClient().getProperty(SvnTarget.fromFile(ioFile), SvnPropertyKeys.SVN_EXTERNALS,
+ PropertyValue propertyValue = factory.createPropertyClient().getProperty(SvnTarget.fromFile(ioFile), SvnPropertyKeys.SVN_EXTERNALS,
false, SVNRevision.UNDEFINED);
String newValue;
- if (propertyData != null && propertyData.getValue() != null && ! StringUtil.isEmptyOrSpaces(propertyData.getValue().getString())) {
- final SVNExternal[] externals = SVNExternal.parseExternals("Create External", propertyData.getValue().getString());
- for (SVNExternal external : externals) {
- if (Comparing.equal(external.getPath(), target)) {
- AbstractVcsHelper
- .getInstance(vcs.getProject()).showError(new VcsException("Selected destination conflicts with existing: " + external.toString()), "Create External");
- return true;
- }
+ if (propertyValue != null && !StringUtil.isEmptyOrSpaces(propertyValue.toString())) {
+ Map<String, String> externalsMap = ExternalsDefinitionParser.parseExternalsProperty(propertyValue.toString());
+ String externalsForTarget = externalsMap.get(target);
+
+ if (externalsForTarget != null) {
+ AbstractVcsHelper.getInstance(vcs.getProject()).showError(
+ new VcsException("Selected destination conflicts with existing: " + externalsForTarget), "Create External");
+ return true;
}
final String string = createExternalDefinitionString(url, target);
- newValue = propertyData.getValue().getString().trim() + "\n" + string;
+ newValue = propertyValue.toString().trim() + "\n" + string;
} else {
newValue = createExternalDefinitionString(url, target);
}
- factory.createPropertyClient().setProperty(ioFile, SvnPropertyKeys.SVN_EXTERNALS, SVNPropertyValue.create(newValue), Depth.EMPTY,
- false);
+ factory.createPropertyClient().setProperty(ioFile, SvnPropertyKeys.SVN_EXTERNALS, PropertyValue.create(newValue), Depth.EMPTY, false);
return false;
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SetPropertyAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SetPropertyAction.java
index cdc738cf2d40..5e53cc956e92 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SetPropertyAction.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SetPropertyAction.java
@@ -30,7 +30,7 @@ import org.jetbrains.idea.svn.SvnVcs;
import org.jetbrains.idea.svn.api.Depth;
import org.jetbrains.idea.svn.dialogs.SetPropertyDialog;
import org.jetbrains.idea.svn.properties.PropertyClient;
-import org.tmatesoft.svn.core.SVNPropertyValue;
+import org.jetbrains.idea.svn.properties.PropertyValue;
import java.io.File;
@@ -79,7 +79,7 @@ public class SetPropertyAction extends BasicAction {
// TODO: most likely SVNDepth.getInfinityOrEmptyDepth should be used instead of SVNDepth.fromRecursive - to have either "infinity"
// TODO: or "empty" depth, and not "infinity" or "files" depth. But previous logic used SVNDepth.fromRecursive implicitly
- client.setProperty(ioFile, name, SVNPropertyValue.create(value), Depth.allOrFiles(recursive), false);
+ client.setProperty(ioFile, name, PropertyValue.create(value), Depth.allOrFiles(recursive), false);
}
for(int i = 0; i < file.length; i++) {
if (recursive && file[i].isDirectory()) {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SvnExcludingIgnoredOperation.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SvnExcludingIgnoredOperation.java
index c206cd3451d8..94fc2e11c96e 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SvnExcludingIgnoredOperation.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SvnExcludingIgnoredOperation.java
@@ -15,11 +15,10 @@
*/
package org.jetbrains.idea.svn.actions;
-import com.intellij.lifecycle.PeriodicalTasksCloser;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.roots.FileIndexFacade;
import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.vcs.ProjectLevelVcsManager;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.changes.ChangeListManager;
import com.intellij.openapi.vfs.VfsUtilCore;
@@ -42,39 +41,36 @@ public class SvnExcludingIgnoredOperation {
public static class Filter {
private final Project myProject;
- private final FileIndexFacade myIndex;
+ private final ProjectLevelVcsManager myVcsManager;
private final ChangeListManager myClManager;
public Filter(final Project project) {
myProject = project;
if (!project.isDefault()) {
- myIndex = PeriodicalTasksCloser.getInstance().safeGetService(project, FileIndexFacade.class);
+ myVcsManager = ProjectLevelVcsManager.getInstance(project);
myClManager = ChangeListManager.getInstance(project);
}
else {
- myIndex = null;
+ myVcsManager = null;
myClManager = null;
}
}
public boolean accept(final VirtualFile file) {
if (!myProject.isDefault()) {
- if (isExcluded(file)) {
- return false;
- }
- if (myClManager.isIgnoredFile(file)) {
+ if (isIgnoredByVcs(file) || myClManager.isIgnoredFile(file)) {
return false;
}
}
return true;
}
- private boolean isExcluded(final VirtualFile file) {
+ private boolean isIgnoredByVcs(final VirtualFile file) {
return ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
@Override
public Boolean compute() {
- return myIndex.isExcludedFile(file);
+ return myVcsManager.isIgnored(file);
}
});
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SvnMergeProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SvnMergeProvider.java
index 912bd970f7b0..ddd9bd572f0e 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SvnMergeProvider.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SvnMergeProvider.java
@@ -32,9 +32,9 @@ import org.jetbrains.idea.svn.SvnVcs;
import org.jetbrains.idea.svn.api.Depth;
import org.jetbrains.idea.svn.info.Info;
import org.jetbrains.idea.svn.properties.PropertyClient;
+import org.jetbrains.idea.svn.properties.PropertyValue;
import org.tmatesoft.svn.core.SVNProperty;
-import org.tmatesoft.svn.core.SVNPropertyValue;
-import org.tmatesoft.svn.core.wc.*;
+import org.tmatesoft.svn.core.wc.SVNRevision;
import org.tmatesoft.svn.core.wc2.SvnTarget;
import java.io.ByteArrayOutputStream;
@@ -162,8 +162,8 @@ public class SvnMergeProvider implements MergeProvider {
File ioFile = new File(file.getPath());
PropertyClient client = vcs.getFactory(ioFile).createPropertyClient();
- SVNPropertyData svnPropertyData = client.getProperty(SvnTarget.fromFile(ioFile), SVNProperty.MIME_TYPE, false, SVNRevision.WORKING);
- if (svnPropertyData != null && SVNProperty.isBinaryMimeType(SVNPropertyValue.getPropertyAsString(svnPropertyData.getValue()))) {
+ PropertyValue value = client.getProperty(SvnTarget.fromFile(ioFile), SVNProperty.MIME_TYPE, false, SVNRevision.WORKING);
+ if (value != null && SVNProperty.isBinaryMimeType(value.toString())) {
return true;
}
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandExecutor.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandExecutor.java
index 33e06739ad0b..0b484e41d1c5 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandExecutor.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandExecutor.java
@@ -23,6 +23,7 @@ import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.util.EventDispatcher;
@@ -36,6 +37,7 @@ import java.io.File;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.List;
+import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
@@ -152,9 +154,20 @@ public class CommandExecutor {
protected void beforeCreateProcess() throws SvnBindException {
EncodingEnvironmentUtil.fixDefaultEncodingIfMac(myCommandLine, null);
+ setupLocale();
ensureMessageFile();
}
+ private void setupLocale() {
+ String locale = Registry.stringValue("svn.executable.locale");
+ Map<String, String> environment = myCommandLine.getEnvironment();
+
+ // TODO: check if we need to set LC_ALL to configured locale or just clear it
+ environment.put("LC_ALL", "");
+ environment.put("LC_MESSAGES", locale);
+ environment.put("LANG", locale);
+ }
+
private void ensureMessageFile() throws SvnBindException {
if (myMessage != null) {
myMessageFile = createTempFile("commit-message", ".txt");
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandUtil.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandUtil.java
index eee798737846..eb2e6cf976cb 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandUtil.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandUtil.java
@@ -58,8 +58,7 @@ public class CommandUtil {
boolean hasPegRevision = pegRevision != null &&
!SVNRevision.UNDEFINED.equals(pegRevision) &&
!SVNRevision.WORKING.equals(pegRevision) &&
- pegRevision.isValid() &&
- pegRevision.getNumber() != 0;
+ pegRevision.isValid();
if (hasPegRevision || hasAtSymbol) {
// add '@' to correctly handle paths that contain '@' symbol
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/config/SvnConfigureProxiesDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/config/SvnConfigureProxiesDialog.java
index a70a4f28d0fd..40e3c80d1fc6 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/config/SvnConfigureProxiesDialog.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/config/SvnConfigureProxiesDialog.java
@@ -63,16 +63,10 @@ public class SvnConfigureProxiesDialog extends DialogWrapper implements Validati
public void onError(final String text, final JComponent component, final boolean forbidSave) {
myTabbedPane.setSelectedComponent(component);
- String prefixString = "";
- for (int i = 0; i < myTabbedPane.getComponentCount(); i++) {
- final Component currentComponent = myTabbedPane.getComponentAt(i);
- // compare referencies - same objects
- if (currentComponent == component) {
- prefixString = myTabbedPane.getTitleAt(i) + ": ";
- }
- }
+ String errorPrefix = myTabbedPane.getTitleAt(myTabbedPane.indexOfComponent(component)) + ": ";
+
setOKActionEnabled(! forbidSave);
- setInvalid(prefixString + text);
+ setInvalid(errorPrefix + text);
}
public void onSuccess() {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/BranchConfigurationDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/BranchConfigurationDialog.java
index 6bd08c1089cb..50ddd9615d41 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/BranchConfigurationDialog.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/BranchConfigurationDialog.java
@@ -22,10 +22,12 @@ import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.MultiLineLabelUI;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
+import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.*;
import com.intellij.ui.components.JBList;
+import com.intellij.util.ObjectUtils;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -100,16 +102,23 @@ public class BranchConfigurationDialog extends DialogWrapper {
myListPanel.add(
ToolbarDecorator.createDecorator(myLocationList)
.setAddAction(new AnActionButtonRunnable() {
+
+ @Nullable private SVNURL usedRootUrl;
+
@Override
public void run(AnActionButton button) {
- final String selectedUrl = SelectLocationDialog.selectLocation(project, rootUrl.toDecodedString());
- if (selectedUrl != null) {
- if (!configuration.getBranchUrls().contains(selectedUrl)) {
- configuration
- .addBranches(selectedUrl, new InfoStorage<List<SvnBranchItem>>(new ArrayList<SvnBranchItem>(), InfoReliability.empty));
- mySvnBranchConfigManager.reloadBranches(myRoot, selectedUrl, null);
- listModel.fireItemAdded();
- myLocationList.setSelectedIndex(listModel.getSize() - 1);
+ Pair<String, SVNURL> result = SelectLocationDialog.selectLocation(project, ObjectUtils.notNull(usedRootUrl, rootUrl));
+ if (result != null) {
+ String selectedUrl = result.getFirst();
+ usedRootUrl = result.getSecond();
+ if (selectedUrl != null) {
+ if (!configuration.getBranchUrls().contains(selectedUrl)) {
+ configuration
+ .addBranches(selectedUrl, new InfoStorage<List<SvnBranchItem>>(new ArrayList<SvnBranchItem>(), InfoReliability.empty));
+ mySvnBranchConfigManager.reloadBranches(myRoot, selectedUrl, null);
+ listModel.fireItemAdded();
+ myLocationList.setSelectedIndex(listModel.getSize() - 1);
+ }
}
}
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/PropertiesComponent.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/PropertiesComponent.java
index 860c524ed591..cd504be56077 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/PropertiesComponent.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/PropertiesComponent.java
@@ -37,9 +37,12 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.SvnPropertyKeys;
import org.jetbrains.idea.svn.SvnVcs;
import org.jetbrains.idea.svn.api.Depth;
-import org.tmatesoft.svn.core.*;
-import org.tmatesoft.svn.core.wc.ISVNPropertyHandler;
-import org.tmatesoft.svn.core.wc.SVNPropertyData;
+import org.jetbrains.idea.svn.properties.PropertyConsumer;
+import org.jetbrains.idea.svn.properties.PropertyData;
+import org.jetbrains.idea.svn.properties.PropertyValue;
+import org.tmatesoft.svn.core.SVNException;
+import org.tmatesoft.svn.core.SVNProperty;
+import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.wc.SVNRevision;
import org.tmatesoft.svn.core.wc2.SvnTarget;
@@ -151,20 +154,20 @@ public class PropertiesComponent extends JPanel {
}
}
- private void collectProperties(@NotNull SvnVcs vcs, @NotNull File file, @NotNull final Map<String, String> props) {
+ private static void collectProperties(@NotNull SvnVcs vcs, @NotNull File file, @NotNull final Map<String, String> props) {
try {
- ISVNPropertyHandler handler = new ISVNPropertyHandler() {
- public void handleProperty(File path, SVNPropertyData property) throws SVNException {
- final SVNPropertyValue value = property.getValue();
+ PropertyConsumer handler = new PropertyConsumer() {
+ public void handleProperty(File path, PropertyData property) throws SVNException {
+ final PropertyValue value = property.getValue();
if (value != null) {
- props.put(property.getName(), SVNPropertyValue.getPropertyAsString(property.getValue()));
+ props.put(property.getName(), PropertyValue.toString(property.getValue()));
}
}
- public void handleProperty(SVNURL url, SVNPropertyData property) throws SVNException {
+ public void handleProperty(SVNURL url, PropertyData property) throws SVNException {
}
- public void handleProperty(long revision, SVNPropertyData property) throws SVNException {
+ public void handleProperty(long revision, PropertyData property) throws SVNException {
}
};
vcs.getFactory(file).createPropertyClient().list(SvnTarget.fromFile(file, SVNRevision.UNDEFINED), SVNRevision.WORKING, Depth.EMPTY,
@@ -229,10 +232,12 @@ public class PropertiesComponent extends JPanel {
String url = "file://" + myFile.getPath().replace(File.separatorChar, '/');
VirtualFile file = VirtualFileManager.getInstance().findFileByUrl(url);
if (file != null) {
+ VcsDirtyScopeManager dirtyScopeManager = VcsDirtyScopeManager.getInstance(myVcs.getProject());
+
if (recursive && file.isDirectory()) {
- VcsDirtyScopeManager.getInstance(myVcs.getProject()).dirDirtyRecursively(file, true);
+ dirtyScopeManager.dirDirtyRecursively(file);
} else {
- VcsDirtyScopeManager.getInstance(myVcs.getProject()).fileDirty(file);
+ dirtyScopeManager.fileDirty(file);
}
}
}
@@ -272,8 +277,7 @@ public class PropertiesComponent extends JPanel {
if (!StringUtil.isEmpty(property)) {
try {
myVcs.getFactory(myFile).createPropertyClient()
- .setProperty(myFile, property, value != null ? SVNPropertyValue.create(value) : null,
- Depth.allOrEmpty(recursive), force);
+ .setProperty(myFile, property, PropertyValue.create(value), Depth.allOrEmpty(recursive), force);
}
catch (VcsException error) {
VcsBalloonProblemNotifier
@@ -302,7 +306,7 @@ public class PropertiesComponent extends JPanel {
public void actionPerformed(AnActionEvent e) {
Project project = CommonDataKeys.PROJECT.getData(e.getDataContext());
- SVNPropertyData propValue = null;
+ PropertyValue propValue = null;
try {
propValue = myVcs.getFactory(myFile).createPropertyClient()
.getProperty(SvnTarget.fromFile(myFile), SVNProperty.KEYWORDS, false, SVNRevision.WORKING);
@@ -311,8 +315,7 @@ public class PropertiesComponent extends JPanel {
// show erorr message
}
- SetKeywordsDialog dialog = new SetKeywordsDialog(project,
- propValue != null ? SVNPropertyValue.getPropertyAsString(propValue.getValue()) : null);
+ SetKeywordsDialog dialog = new SetKeywordsDialog(project, PropertyValue.toString(propValue));
dialog.show();
if (dialog.isOK()) {
setProperty(SvnPropertyKeys.SVN_KEYWORDS, dialog.getKeywords(), false, false);
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserComponent.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserComponent.java
index 0fd1f06bf7cb..163be4922224 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserComponent.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserComponent.java
@@ -76,10 +76,26 @@ public class RepositoryBrowserComponent extends JPanel implements Disposable, Da
}
public void setRepositoryURLs(SVNURL[] urls, final boolean showFiles) {
+ setRepositoryURLs(urls, showFiles, null, false);
+ }
+
+ public void setRepositoryURLs(SVNURL[] urls,
+ final boolean showFiles,
+ @Nullable NotNullFunction<RepositoryBrowserComponent, Expander> defaultExpanderFactory,
+ boolean expandFirst) {
RepositoryTreeModel model = new RepositoryTreeModel(myVCS, showFiles, this);
+
+ if (defaultExpanderFactory != null) {
+ model.setDefaultExpanderFactory(defaultExpanderFactory);
+ }
+
model.setRoots(urls);
Disposer.register(this, model);
myRepositoryTree.setModel(model);
+
+ if (expandFirst) {
+ myRepositoryTree.expandRow(0);
+ }
}
public void setRepositoryURL(SVNURL url, boolean showFiles, final NotNullFunction<RepositoryBrowserComponent, Expander> defaultExpanderFactory) {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserDialog.java
index 191acf387b86..83d895b93ffc 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserDialog.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserDialog.java
@@ -93,7 +93,7 @@ public class RepositoryBrowserDialog extends DialogWrapper {
private final boolean myShowFiles;
- @NonNls private static final String PLACE_TOOLBAR = "RepositoryBrowser.Toolbar";
+ @NonNls public static final String PLACE_TOOLBAR = "RepositoryBrowser.Toolbar";
@NonNls private static final String PLACE_MENU = "RepositoryBrowser.Menu";
private final String myRepositoriesLabelText;
protected JLabel myRepositoriesLabel;
@@ -138,7 +138,7 @@ public class RepositoryBrowserDialog extends DialogWrapper {
DefaultActionGroup group = new DefaultActionGroup();
final RepositoryBrowserComponent browser = getRepositoryBrowser();
group.add(new AddLocationAction(browser));
- group.add(new EditLocationAction());
+ group.add(new EditLocationAction(browser));
group.add(new DiscardLocationAction(browser));
group.add(new DetailsAction());
group.addSeparator();
@@ -216,7 +216,7 @@ public class RepositoryBrowserDialog extends DialogWrapper {
group.add(copyUrlAction);
group.addSeparator();
group.add(new RefreshAction(browser));
- group.add(new EditLocationAction());
+ group.add(new EditLocationAction(browser));
group.add(new DiscardLocationAction(browser));
ActionPopupMenu menu = ActionManager.getInstance().createActionPopupMenu(PLACE_MENU, group);
return menu.getComponent();
@@ -413,13 +413,17 @@ public class RepositoryBrowserDialog extends DialogWrapper {
}
}
- protected class EditLocationAction extends AnAction {
- public EditLocationAction() {
+ protected static class EditLocationAction extends AnAction {
+
+ @NotNull private final RepositoryBrowserComponent myBrowserComponent;
+
+ public EditLocationAction(@NotNull RepositoryBrowserComponent browserComponent) {
super(SvnBundle.message("repository.browser.edit.location.menu.item"));
+ myBrowserComponent = browserComponent;
}
public void update(AnActionEvent e) {
- RepositoryTreeNode node = getRepositoryBrowser().getSelectedNode();
+ RepositoryTreeNode node = myBrowserComponent.getSelectedNode();
if (e.getPlace().equals(PLACE_TOOLBAR)) {
e.getPresentation().setDescription(SvnBundle.message("repository.browser.edit.location.menu.item"));
e.getPresentation().setText(SvnBundle.message("repository.browser.edit.location.menu.item"));
@@ -429,13 +433,14 @@ public class RepositoryBrowserDialog extends DialogWrapper {
}
public void actionPerformed(AnActionEvent e) {
- RepositoryTreeNode node = getRepositoryBrowser().getSelectedNode();
+ RepositoryTreeNode node = myBrowserComponent.getSelectedNode();
if (node == null || (! (node.getParent() instanceof RepositoryTreeRootNode))) {
return;
}
final String oldUrl = node.getURL().toString();
final SvnApplicationSettings settings = SvnApplicationSettings.getInstance();
- final AddRepositoryLocationDialog dialog = new AddRepositoryLocationDialog(myProject, settings.getTypedUrlsListCopy()) {
+ final AddRepositoryLocationDialog dialog =
+ new AddRepositoryLocationDialog(myBrowserComponent.getProject(), settings.getTypedUrlsListCopy()) {
@Override
protected String initText() {
return oldUrl;
@@ -453,9 +458,9 @@ public class RepositoryBrowserDialog extends DialogWrapper {
settings.addTypedUrl(url);
settings.removeCheckoutURL(oldUrl);
settings.addCheckoutURL(url);
- final RepositoryBrowserComponent browser = getRepositoryBrowser();
- browser.removeURL(oldUrl);
- browser.addURL(url);
+
+ myBrowserComponent.removeURL(oldUrl);
+ myBrowserComponent.addURL(url);
}
}
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SelectLocationDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SelectLocationDialog.java
index a6ca6ad54f11..bcbbe79c1b45 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SelectLocationDialog.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SelectLocationDialog.java
@@ -15,12 +15,15 @@
*/
package org.jetbrains.idea.svn.dialogs;
+import com.intellij.openapi.actionSystem.ActionManager;
+import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.help.HelpManager;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Disposer;
+import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.Ref;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -52,21 +55,30 @@ public class SelectLocationDialog extends DialogWrapper {
private final String myDstLabel;
private JTextField myDstText;
private final boolean myIsShowFiles;
+ private final boolean myAllowActions;
@NonNls private static final String HELP_ID = "vcs.subversion.common";
// todo check that works when authenticated
@Nullable
public static String selectLocation(Project project, String url) {
- SelectLocationDialog dialog = openDialog(project, url, null, null, true, null);
+ SelectLocationDialog dialog = openDialog(project, url, null, null, true, false, null);
return dialog == null || !dialog.isOK() ? null : dialog.getSelectedURL();
}
@Nullable
+ public static Pair<String, SVNURL> selectLocation(Project project, @NotNull SVNURL url) {
+ SelectLocationDialog dialog = new SelectLocationDialog(project, url, null, null, true, true);
+ dialog.show();
+
+ return dialog.isOK() ? Pair.create(dialog.getSelectedURL(), dialog.getRootUrl()) : null;
+ }
+
+ @Nullable
public static String selectCopyDestination(Project project, String url, String dstLabel, String dstName, boolean showFiles) {
SelectLocationDialog dialog =
- openDialog(project, url, dstLabel, dstName, showFiles, SvnBundle.message("select.location.invalid.url.message", url));
+ openDialog(project, url, dstLabel, dstName, showFiles, false, SvnBundle.message("select.location.invalid.url.message", url));
return dialog == null || !dialog.isOK() ? null : SVNPathUtil.append(dialog.getSelectedURL(), dialog.getDestinationName());
}
@@ -77,6 +89,7 @@ public class SelectLocationDialog extends DialogWrapper {
String dstLabel,
String dstName,
boolean showFiles,
+ boolean allowActions,
String errorMessage) {
try {
SVNURL svnUrl = SvnUtil.createUrl(url);
@@ -86,8 +99,7 @@ public class SelectLocationDialog extends DialogWrapper {
SvnBundle.message("dialog.title.select.repository.location"));
return null;
}
-
- SelectLocationDialog dialog = new SelectLocationDialog(project, repositoryUrl, dstLabel, dstName, showFiles);
+ SelectLocationDialog dialog = new SelectLocationDialog(project, repositoryUrl, dstLabel, dstName, showFiles, allowActions);
dialog.show();
return dialog;
}
@@ -98,13 +110,14 @@ public class SelectLocationDialog extends DialogWrapper {
}
}
- private SelectLocationDialog(Project project, SVNURL url, String dstLabel, String dstName, boolean showFiles) {
+ private SelectLocationDialog(Project project, SVNURL url, String dstLabel, String dstName, boolean showFiles, boolean allowActions) {
super(project, true);
myProject = project;
myDstLabel = dstLabel;
myDstName = dstName;
myURL = url;
myIsShowFiles = showFiles;
+ myAllowActions = allowActions;
setTitle(SvnBundle.message("dialog.title.select.repository.location"));
getHelpAction().setEnabled(true);
init();
@@ -146,7 +159,13 @@ public class SelectLocationDialog extends DialogWrapper {
protected void init() {
super.init();
final String urlString = myURL.toString();
- myRepositoryBrowser.setRepositoryURL(myURL, myIsShowFiles, new UrlOpeningExpander.Factory(urlString, urlString));
+ if (myAllowActions) {
+ // initialize repo browser this way - to make actions work correctly
+ myRepositoryBrowser.setRepositoryURLs(new SVNURL[]{myURL}, myIsShowFiles, new UrlOpeningExpander.Factory(urlString, urlString), true);
+ }
+ else {
+ myRepositoryBrowser.setRepositoryURL(myURL, myIsShowFiles, new UrlOpeningExpander.Factory(urlString, urlString));
+ }
myRepositoryBrowser.addChangeListener(new TreeSelectionListener() {
public void valueChanged(TreeSelectionEvent e) {
getOKAction().setEnabled(isOKActionEnabled());
@@ -162,7 +181,10 @@ public class SelectLocationDialog extends DialogWrapper {
protected JComponent createCenterPanel() {
JPanel panel = new JPanel();
- panel.setLayout(new GridBagLayout());
+ panel.setLayout(new BorderLayout());
+
+ JPanel browserPanel = new JPanel();
+ browserPanel.setLayout(new GridBagLayout());
GridBagConstraints gc = new GridBagConstraints();
gc.insets = new Insets(2, 2, 2, 2);
@@ -177,7 +199,7 @@ public class SelectLocationDialog extends DialogWrapper {
myRepositoryBrowser = new RepositoryBrowserComponent(SvnVcs.getInstance(myProject));
- panel.add(myRepositoryBrowser, gc);
+ browserPanel.add(myRepositoryBrowser, gc);
if (myDstName != null) {
gc.gridy += 1;
gc.gridwidth = 1;
@@ -187,7 +209,7 @@ public class SelectLocationDialog extends DialogWrapper {
gc.weighty = 0;
JLabel dstLabel = new JLabel(myDstLabel);
- panel.add(dstLabel, gc);
+ browserPanel.add(dstLabel, gc);
gc.gridx += 1;
gc.weightx = 1;
@@ -196,7 +218,7 @@ public class SelectLocationDialog extends DialogWrapper {
myDstText = new JTextField();
myDstText.setText(myDstName);
myDstText.selectAll();
- panel.add(myDstText, gc);
+ browserPanel.add(myDstText, gc);
myDstText.getDocument().addDocumentListener(new DocumentListener() {
public void insertUpdate(DocumentEvent e) {
@@ -217,12 +239,25 @@ public class SelectLocationDialog extends DialogWrapper {
gc.gridy += 1;
gc.gridwidth = 2;
- panel.add(new JSeparator(), gc);
+ browserPanel.add(new JSeparator(), gc);
+ }
+
+ if (myAllowActions) {
+ panel.add(createToolbar(), BorderLayout.NORTH);
}
+ panel.add(browserPanel, BorderLayout.CENTER);
return panel;
}
+ @NotNull
+ private JComponent createToolbar() {
+ DefaultActionGroup group = new DefaultActionGroup();
+ group.add(new RepositoryBrowserDialog.EditLocationAction(myRepositoryBrowser));
+
+ return ActionManager.getInstance().createActionToolbar(RepositoryBrowserDialog.PLACE_TOOLBAR, group, true).getComponent();
+ }
+
public JComponent getPreferredFocusedComponent() {
return (JComponent)myRepositoryBrowser.getPreferredFocusedComponent();
}
@@ -246,4 +281,16 @@ public class SelectLocationDialog extends DialogWrapper {
public String getSelectedURL() {
return myRepositoryBrowser.getSelectedURL();
}
+
+ @Nullable
+ public SVNURL getRootUrl() {
+ RepositoryTreeNode node = myRepositoryBrowser.getSelectedNode();
+
+ // find the most top parent of type RepositoryTreeNode
+ while (node != null && node.getParent() instanceof RepositoryTreeNode) {
+ node = (RepositoryTreeNode)node.getParent();
+ }
+
+ return node != null ? node.getURL() : null;
+ }
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SetPropertyDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SetPropertyDialog.java
index 28375d28b7ba..f2a58a0bd2da 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SetPropertyDialog.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SetPropertyDialog.java
@@ -24,15 +24,16 @@ import com.intellij.openapi.vcs.VcsException;
import com.intellij.ui.DocumentAdapter;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.SvnBundle;
import org.jetbrains.idea.svn.SvnPropertyKeys;
import org.jetbrains.idea.svn.SvnVcs;
import org.jetbrains.idea.svn.api.Depth;
import org.jetbrains.idea.svn.properties.PropertyClient;
-import org.tmatesoft.svn.core.SVNPropertyValue;
+import org.jetbrains.idea.svn.properties.PropertyConsumer;
+import org.jetbrains.idea.svn.properties.PropertyData;
+import org.jetbrains.idea.svn.properties.PropertyValue;
import org.tmatesoft.svn.core.SVNURL;
-import org.tmatesoft.svn.core.wc.ISVNPropertyHandler;
-import org.tmatesoft.svn.core.wc.SVNPropertyData;
import org.tmatesoft.svn.core.wc.SVNRevision;
import org.tmatesoft.svn.core.wc2.SvnTarget;
@@ -154,10 +155,10 @@ public class SetPropertyDialog extends DialogWrapper {
return;
}
File file = myFiles[0];
- SVNPropertyData property = !StringUtil.isEmpty(name) ? getProperty(file, name) : null;
+ PropertyValue property = !StringUtil.isEmpty(name) ? getProperty(file, name) : null;
if (property != null) {
- myValueText.setText(SVNPropertyValue.getPropertyAsString(property.getValue()));
+ myValueText.setText(property.toString());
myValueText.selectAll();
}
else {
@@ -165,19 +166,20 @@ public class SetPropertyDialog extends DialogWrapper {
}
}
- private SVNPropertyData getProperty(@NotNull File file, @NotNull String name) {
- SVNPropertyData property;
+ @Nullable
+ private PropertyValue getProperty(@NotNull File file, @NotNull String name) {
+ PropertyValue result;
try {
PropertyClient client = myVCS.getFactory(file).createPropertyClient();
- property = client.getProperty(SvnTarget.fromFile(file, SVNRevision.WORKING), name, false, SVNRevision.WORKING);
+ result = client.getProperty(SvnTarget.fromFile(file, SVNRevision.WORKING), name, false, SVNRevision.WORKING);
}
catch (VcsException e) {
LOG.info(e);
- property = null;
+ result = null;
}
- return property;
+ return result;
}
protected JComponent createCenterPanel() {
@@ -205,18 +207,18 @@ public class SetPropertyDialog extends DialogWrapper {
if (files.length == 1) {
File file = files[0];
try {
- ISVNPropertyHandler handler = new ISVNPropertyHandler() {
- public void handleProperty(File path, SVNPropertyData property) {
+ PropertyConsumer handler = new PropertyConsumer() {
+ public void handleProperty(File path, PropertyData property) {
String name = property.getName();
if (name != null) {
names.add(name);
}
}
- public void handleProperty(SVNURL url, SVNPropertyData property) {
+ public void handleProperty(SVNURL url, PropertyData property) {
}
- public void handleProperty(long revision, SVNPropertyData property) {
+ public void handleProperty(long revision, PropertyData property) {
}
};
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CmdDiffClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CmdDiffClient.java
index 497134727ee4..be084b0986d0 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CmdDiffClient.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CmdDiffClient.java
@@ -52,13 +52,14 @@ import java.util.List;
*/
public class CmdDiffClient extends BaseSvnClient implements DiffClient {
+ @NotNull
@Override
public List<Change> compare(@NotNull SvnTarget target1, @NotNull SvnTarget target2) throws VcsException {
- assertUrl(target2);
- if (target1.isFile()) {
+ assertUrl(target1);
+ if (target2.isFile()) {
// Such combination (file and url) with "--summarize" option is supported only in svn 1.8.
// For svn 1.7 "--summarize" is only supported when both targets are repository urls.
- assertDirectory(target1);
+ assertDirectory(target2);
WorkingCopyFormat format = WorkingCopyFormat.from(myFactory.createVersionClient().getVersion());
if (format.less(WorkingCopyFormat.ONE_DOT_EIGHT)) {
@@ -95,6 +96,7 @@ public class CmdDiffClient extends BaseSvnClient implements DiffClient {
}
}
+ @NotNull
private List<Change> parseOutput(@NotNull SvnTarget target1, @NotNull SvnTarget target2, @NotNull CommandExecutor executor)
throws SvnBindException {
try {
@@ -114,16 +116,30 @@ public class CmdDiffClient extends BaseSvnClient implements DiffClient {
}
}
- private ContentRevision createRemoteRevision(@NotNull FilePath remotePath, @NotNull FilePath localPath, @NotNull FileStatus status) {
+ @NotNull
+ private ContentRevision createRevision(@NotNull FilePath path,
+ @NotNull FilePath localPath,
+ @NotNull SVNRevision revision,
+ @NotNull FileStatus status) {
+ ContentRevision result;
+
+ if (path.isNonLocal()) {
// explicitly use local path for deleted items - so these items will be correctly displayed as deleted under local working copy node
// and not as deleted under remote branch node (in ChangesBrowser)
// NOTE, that content is still retrieved using remotePath.
- return SvnRepositoryContentRevision
- .create(myVcs, remotePath, status == FileStatus.DELETED ? localPath : null, SVNRevision.HEAD.getNumber());
+ result = SvnRepositoryContentRevision.create(myVcs, path, status == FileStatus.DELETED ? localPath : null, revision.getNumber());
+ }
+ else {
+ result = CurrentContentRevision.create(path);
}
- private static ContentRevision createLocalRevision(@NotNull FilePath path) {
- return CurrentContentRevision.create(path);
+ return result;
+ }
+
+ private static FilePath createFilePath(@NotNull SvnTarget target, boolean isDirectory) {
+ return target.isFile()
+ ? VcsUtil.getFilePath(target.getFile(), isDirectory)
+ : VcsUtil.getFilePathOnNonLocal(SvnUtil.toDecodedString(target), isDirectory);
}
@NotNull
@@ -134,9 +150,7 @@ public class CmdDiffClient extends BaseSvnClient implements DiffClient {
// TODO: 3) Properties change is currently not added as part of result change like in SvnChangeProviderContext.patchWithPropertyChange
SvnTarget subTarget1 = SvnUtil.append(target1, diffPath.path, true);
- String relativePath = target1.isFile()
- ? FileUtil.getRelativePath(target1.getFile(), subTarget1.getFile())
- : SvnUtil.getRelativeUrl(SvnUtil.toDecodedString(target1), SvnUtil.toDecodedString(subTarget1));
+ String relativePath = SvnUtil.getRelativeUrl(SvnUtil.toDecodedString(target1), SvnUtil.toDecodedString(subTarget1));
if (relativePath == null) {
throw new SvnBindException("Could not get relative path for " + target1 + " and " + subTarget1);
@@ -144,27 +158,19 @@ public class CmdDiffClient extends BaseSvnClient implements DiffClient {
SvnTarget subTarget2 = SvnUtil.append(target2, FileUtil.toSystemIndependentName(relativePath));
- FilePath target1Path = target1.isFile()
- ? VcsUtil.getFilePath(subTarget1.getFile(), diffPath.isDirectory())
- : VcsUtil.getFilePathOnNonLocal(SvnUtil.toDecodedString(subTarget1), diffPath.isDirectory());
- FilePath target2Path = VcsUtil.getFilePathOnNonLocal(SvnUtil.toDecodedString(subTarget2), diffPath.isDirectory());
+ FilePath target1Path = createFilePath(subTarget1, diffPath.isDirectory());
+ FilePath target2Path = createFilePath(subTarget2, diffPath.isDirectory());
FileStatus status = SvnStatusConvertor
.convertStatus(SvnStatusHandler.getStatus(diffPath.itemStatus), SvnStatusHandler.getStatus(diffPath.propertiesStatus));
- // for "file + url" pair - statuses determine changes needs to be done to "url" to get "file" state
- // for "url1 + url2" pair - statuses determine changes needs to be done to "url1" to get "url2" state
+ // statuses determine changes needs to be done to "target1" to get "target2" state
ContentRevision beforeRevision = status == FileStatus.ADDED
? null
- : target1.isFile()
- ? createRemoteRevision(target2Path, target1Path, status)
- : createRemoteRevision(target1Path, target2Path, status);
+ : createRevision(target1Path, target2Path, target1.getPegRevision(), status);
ContentRevision afterRevision = status == FileStatus.DELETED
? null
- : target1.isFile()
- ? createLocalRevision(target1Path)
- : createRemoteRevision(target2Path, target1Path, status);
-
+ : createRevision(target2Path, target1Path, target2.getPegRevision(), status);
return createChange(status, beforeRevision, afterRevision);
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/DiffClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/DiffClient.java
index 35c35e9313f1..dfa43ddcb4bd 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/DiffClient.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/DiffClient.java
@@ -29,6 +29,11 @@ import java.util.List;
*/
public interface DiffClient extends SvnClient {
+ /**
+ * @param target1 Should always be url.
+ * @param target2 Could be either url or file. And should be directory if file.
+ */
+ @NotNull
List<Change> compare(@NotNull SvnTarget target1, @NotNull SvnTarget target2) throws VcsException;
void unifiedDiff(@NotNull SvnTarget target1, @NotNull SvnTarget target2, @NotNull OutputStream output) throws VcsException;
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/DirectoryWithBranchComparer.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/DirectoryWithBranchComparer.java
index 0f0e6a714037..784548d9e661 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/DirectoryWithBranchComparer.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/DirectoryWithBranchComparer.java
@@ -24,6 +24,7 @@ import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.svn.SvnBundle;
+import org.jetbrains.idea.svn.SvnVcs;
import org.jetbrains.idea.svn.WorkingCopyFormat;
import org.jetbrains.idea.svn.api.ClientFactory;
import org.tmatesoft.svn.core.SVNException;
@@ -53,19 +54,24 @@ public class DirectoryWithBranchComparer extends ElementWithBranchComparer {
titleBuilder.append(SvnBundle.message("repository.browser.compare.title", myElementUrl,
FileUtil.toSystemDependentName(myVirtualFile.getPresentableUrl())));
- SvnTarget target1 = SvnTarget.fromFile(new File(myVirtualFile.getPath()));
- SvnTarget target2 = SvnTarget.fromURL(myElementUrl);
+ SvnTarget target1 = SvnTarget.fromURL(myElementUrl);
+ SvnTarget target2 = SvnTarget.fromFile(new File(myVirtualFile.getPath()));
changes.addAll(getClientFactory().createDiffClient().compare(target1, target2));
}
@NotNull
private ClientFactory getClientFactory() {
- WorkingCopyFormat format = myVcs.getWorkingCopyFormat(VfsUtilCore.virtualToIoFile(myVirtualFile));
+ return getClientFactory(myVcs, VfsUtilCore.virtualToIoFile(myVirtualFile));
+ }
+
+ @NotNull
+ public static ClientFactory getClientFactory(@NotNull SvnVcs vcs, @NotNull File file) {
+ WorkingCopyFormat format = vcs.getWorkingCopyFormat(file);
// svn 1.7 command line "--summarize" option for "diff" command does not support comparing working copy directories with repository
// directories - that is why command line is only used explicitly for svn 1.8
- return format.isOrGreater(WorkingCopyFormat.ONE_DOT_EIGHT) ? myVcs.getCommandLineFactory() : myVcs.getSvnKitFactory();
+ return format.isOrGreater(WorkingCopyFormat.ONE_DOT_EIGHT) ? vcs.getCommandLineFactory() : vcs.getSvnKitFactory();
}
@Override
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/SvnKitDiffClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/SvnKitDiffClient.java
index 0a1b14837b7e..ec4c51288cc2 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/SvnKitDiffClient.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/SvnKitDiffClient.java
@@ -54,6 +54,7 @@ import java.util.List;
*/
public class SvnKitDiffClient extends BaseSvnClient implements DiffClient {
+ @NotNull
@Override
public List<Change> compare(@NotNull SvnTarget target1, @NotNull SvnTarget target2) throws VcsException {
DiffExecutor executor = new DiffExecutor(target1, target2);
@@ -99,12 +100,12 @@ public class SvnKitDiffClient extends BaseSvnClient implements DiffClient {
}
public void run() throws SVNException {
- assertUrl(myTarget2);
+ assertUrl(myTarget1);
- if (myTarget1.isFile()) {
- assertDirectory(myTarget1);
+ if (myTarget2.isFile()) {
+ assertDirectory(myTarget2);
- WorkingCopyFormat format = myVcs.getWorkingCopyFormat(myTarget1.getFile());
+ WorkingCopyFormat format = myVcs.getWorkingCopyFormat(myTarget2.getFile());
myChanges.addAll(WorkingCopyFormat.ONE_DOT_SIX.equals(format) ? run16Diff() : run17Diff());
}
else {
@@ -142,20 +143,20 @@ public class SvnKitDiffClient extends BaseSvnClient implements DiffClient {
}
private Collection<Change> run17Diff() throws SVNException {
- final Info info1 = myVcs.getInfo(myTarget1.getFile(), SVNRevision.HEAD);
+ final Info info1 = myVcs.getInfo(myTarget2.getFile(), SVNRevision.HEAD);
if (info1 == null) {
SVNErrorMessage err =
- SVNErrorMessage.create(SVNErrorCode.ENTRY_NOT_FOUND, "''{0}'' is not under version control", myTarget1);
+ SVNErrorMessage.create(SVNErrorCode.ENTRY_NOT_FOUND, "''{0}'' is not under version control", myTarget2);
SVNErrorManager.error(err, SVNLogType.WC);
}
else if (info1.getURL() == null) {
- SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.ENTRY_MISSING_URL, "''{0}'' has no URL", myTarget1);
+ SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.ENTRY_MISSING_URL, "''{0}'' has no URL", myTarget2);
SVNErrorManager.error(err, SVNLogType.WC);
}
final SVNReporter17 reporter17 =
- new SVNReporter17(myTarget1.getFile(), new SVNWCContext(myVcs.getSvnKitManager().getSvnOptions(), new ISVNEventHandler() {
+ new SVNReporter17(myTarget2.getFile(), new SVNWCContext(myVcs.getSvnKitManager().getSvnOptions(), new ISVNEventHandler() {
@Override
public void handleEvent(SVNEvent event, double progress) throws SVNException {
}
@@ -169,9 +170,9 @@ public class SvnKitDiffClient extends BaseSvnClient implements DiffClient {
try {
repository = myVcs.getSvnKitManager().createRepository(info1.getURL());
long rev = repository.getLatestRevision();
- repository2 = myVcs.getSvnKitManager().createRepository(myTarget2.getURL());
- SvnDiffEditor diffEditor = new SvnDiffEditor(myTarget1.getFile(), repository2, rev, true);
- repository.diff(myTarget2.getURL(), rev, rev, null, true, SVNDepth.INFINITY, false, reporter17,
+ repository2 = myVcs.getSvnKitManager().createRepository(myTarget1.getURL());
+ SvnDiffEditor diffEditor = new SvnDiffEditor(myTarget2.getFile(), repository2, rev, true);
+ repository.diff(myTarget1.getURL(), rev, rev, null, true, SVNDepth.INFINITY, false, reporter17,
SVNCancellableEditor.newInstance(diffEditor, new SvnKitProgressCanceller(), null));
return diffEditor.getChangesMap().values();
@@ -193,7 +194,7 @@ public class SvnKitDiffClient extends BaseSvnClient implements DiffClient {
SVNRepository repository = null;
SVNRepository repository2 = null;
try {
- SVNAdminAreaInfo info = wcAccess.openAnchor(myTarget1.getFile(), false, SVNWCAccess.INFINITE_DEPTH);
+ SVNAdminAreaInfo info = wcAccess.openAnchor(myTarget2.getFile(), false, SVNWCAccess.INFINITE_DEPTH);
File anchorPath = info.getAnchor().getRoot();
String target = "".equals(info.getTargetName()) ? null : info.getTargetName();
@@ -215,10 +216,10 @@ public class SvnKitDiffClient extends BaseSvnClient implements DiffClient {
repository = myVcs.getSvnKitManager().createRepository(anchorURL.toString());
long rev = repository.getLatestRevision();
repository2 =
- myVcs.getSvnKitManager().createRepository((target == null) ? myTarget2.getURL() : myTarget2.getURL().removePathTail());
+ myVcs.getSvnKitManager().createRepository((target == null) ? myTarget1.getURL() : myTarget1.getURL().removePathTail());
SvnDiffEditor diffEditor =
- new SvnDiffEditor(target == null ? myTarget1.getFile() : myTarget1.getFile().getParentFile(), repository2, rev, true);
- repository.diff(myTarget2.getURL(), rev, rev, target, true, true, false, reporter,
+ new SvnDiffEditor(target == null ? myTarget2.getFile() : myTarget2.getFile().getParentFile(), repository2, rev, true);
+ repository.diff(myTarget1.getURL(), rev, rev, target, true, true, false, reporter,
SVNCancellableEditor.newInstance(diffEditor, new SvnKitProgressCanceller(), null));
return diffEditor.getChangesMap().values();
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnDiffFromHistoryHandler.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnDiffFromHistoryHandler.java
new file mode 100644
index 000000000000..be112127ecc9
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnDiffFromHistoryHandler.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.idea.svn.history;
+
+import com.intellij.openapi.vcs.FilePath;
+import com.intellij.openapi.vcs.VcsException;
+import com.intellij.openapi.vcs.changes.Change;
+import com.intellij.openapi.vcs.history.BaseDiffFromHistoryHandler;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.svn.SvnUtil;
+import org.jetbrains.idea.svn.SvnVcs;
+import org.jetbrains.idea.svn.api.ClientFactory;
+import org.jetbrains.idea.svn.diff.DirectoryWithBranchComparer;
+import org.tmatesoft.svn.core.wc.SVNRevision;
+import org.tmatesoft.svn.core.wc2.SvnTarget;
+
+import java.io.File;
+import java.util.List;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public class SvnDiffFromHistoryHandler extends BaseDiffFromHistoryHandler<SvnFileRevision> {
+
+ @NotNull private final SvnVcs myVcs;
+
+ public SvnDiffFromHistoryHandler(@NotNull SvnVcs vcs) {
+ super(vcs.getProject());
+ myVcs = vcs;
+ }
+
+ @NotNull
+ @Override
+ protected List<Change> getChangesBetweenRevisions(@NotNull FilePath path, @NotNull SvnFileRevision rev1, @Nullable SvnFileRevision rev2)
+ throws VcsException {
+ File file = path.getIOFile();
+ SvnTarget target1 = SvnTarget.fromURL(SvnUtil.createUrl(rev1.getURL()), rev1.getRevision());
+ SvnTarget target2 = rev2 != null ? SvnTarget.fromURL(SvnUtil.createUrl(rev2.getURL()), rev2.getRevision()) : SvnTarget.fromFile(file);
+
+ return executeDiff(path, target1, target2);
+ }
+
+ @NotNull
+ @Override
+ protected List<Change> getAffectedChanges(@NotNull FilePath path, @NotNull SvnFileRevision rev) throws VcsException {
+ // Diff with zero revision is used here to get just affected changes under the path, and not all affected changes of the revision.
+ SvnTarget target1 = SvnTarget.fromURL(SvnUtil.createUrl(rev.getURL()), SVNRevision.create(0));
+ SvnTarget target2 = SvnTarget.fromURL(SvnUtil.createUrl(rev.getURL()), rev.getRevision());
+
+ return executeDiff(path, target1, target2);
+ }
+
+ @NotNull
+ @Override
+ protected String getPresentableName(@NotNull SvnFileRevision revision) {
+ return revision.getRevisionNumber().asString();
+ }
+
+ @NotNull
+ private List<Change> executeDiff(@NotNull FilePath path, @NotNull SvnTarget target1, @NotNull SvnTarget target2) throws VcsException {
+ File file = path.getIOFile();
+ ClientFactory factory = target2.isURL() ? myVcs.getFactory(file) : DirectoryWithBranchComparer.getClientFactory(myVcs, file);
+
+ return factory.createDiffClient().compare(target1, target2);
+ }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnEditCommitMessageAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnEditCommitMessageAction.java
index d2b820607ff4..8d1830763fc6 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnEditCommitMessageAction.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnEditCommitMessageAction.java
@@ -40,8 +40,8 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.SvnPropertyKeys;
import org.jetbrains.idea.svn.SvnUtil;
import org.jetbrains.idea.svn.SvnVcs;
+import org.jetbrains.idea.svn.properties.PropertyValue;
import org.tmatesoft.svn.core.SVNException;
-import org.tmatesoft.svn.core.SVNPropertyValue;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.wc.SVNRevision;
import org.tmatesoft.svn.core.wc2.SvnTarget;
@@ -145,7 +145,7 @@ public class SvnEditCommitMessageAction extends AnAction {
}
SvnTarget target = SvnTarget.fromURL(root);
myVcs.getFactory(target).createPropertyClient()
- .setRevisionProperty(target, SvnPropertyKeys.LOG, SVNRevision.create(myNumber), SVNPropertyValue.create(myNewMessage), false);
+ .setRevisionProperty(target, SvnPropertyKeys.LOG, SVNRevision.create(myNumber), PropertyValue.create(myNewMessage), false);
}
catch (SVNException e) {
myException = new VcsException(e);
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java
index 9e9dd7e1befc..b23b57772535 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java
@@ -73,7 +73,7 @@ public class SvnHistoryProvider
@Override
public DiffFromHistoryHandler getHistoryDiffHandler() {
- return null;
+ return new SvnDiffFromHistoryHandler(myVcs);
}
@Override
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistorySession.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistorySession.java
index f2f91bceec14..8ae2da7cf8b3 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistorySession.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistorySession.java
@@ -77,11 +77,6 @@ public class SvnHistorySession extends VcsAbstractHistorySession {
return myCommittedPath;
}
- @Override
- public boolean isContentAvailable(final VcsFileRevision revision) {
- return !myCommittedPath.isDirectory();
- }
-
public boolean isHaveMergeSources() {
return myHaveMergeSources;
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/ignore/SvnPropertyService.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/ignore/SvnPropertyService.java
index 8a9dbf760922..e0bdc15f78b1 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/ignore/SvnPropertyService.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/ignore/SvnPropertyService.java
@@ -24,8 +24,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.svn.SvnPropertyKeys;
import org.jetbrains.idea.svn.SvnVcs;
import org.jetbrains.idea.svn.api.Depth;
-import org.tmatesoft.svn.core.SVNPropertyValue;
-import org.tmatesoft.svn.core.wc.SVNPropertyData;
+import org.jetbrains.idea.svn.properties.PropertyValue;
import org.tmatesoft.svn.core.wc.SVNRevision;
import org.tmatesoft.svn.core.wc2.SvnTarget;
@@ -68,7 +67,7 @@ public class SvnPropertyService {
protected final boolean myCanUseCachedProperty;
protected abstract void processFolder(final VirtualFile folder, final File folderDir, final Set<String> data,
- final SVNPropertyValue propertyValue) throws VcsException;
+ final PropertyValue propertyValue) throws VcsException;
protected abstract void onAfterProcessing(final VirtualFile[] file) throws VcsException;
@@ -92,14 +91,12 @@ public class SvnPropertyService {
}
final File dir = new File(entry.getKey().getPath());
try {
- final SVNPropertyValue value;
+ final PropertyValue value;
if (myCanUseCachedProperty) {
value = myVcs.getPropertyWithCaching(entry.getKey(), SvnPropertyKeys.SVN_IGNORE);
} else {
- final SVNPropertyData data =
- myVcs.getFactory(dir).createPropertyClient()
- .getProperty(SvnTarget.fromFile(dir), SvnPropertyKeys.SVN_IGNORE, false, SVNRevision.WORKING);
- value = data == null ? null : data.getValue();
+ value = myVcs.getFactory(dir).createPropertyClient()
+ .getProperty(SvnTarget.fromFile(dir), SvnPropertyKeys.SVN_IGNORE, false, SVNRevision.WORKING);
}
processFolder(entry.getKey(), dir, entry.getValue(), value);
}
@@ -127,7 +124,7 @@ public class SvnPropertyService {
return (! myFilesOk) && (! myExtensionOk);
}
- protected void processFolder(final VirtualFile folder, final File folderDir, final Set<String> data, final SVNPropertyValue propertyValue)
+ protected void processFolder(final VirtualFile folder, final File folderDir, final Set<String> data, final PropertyValue propertyValue)
throws VcsException {
if (propertyValue == null) {
myFilesOk = false;
@@ -135,7 +132,7 @@ public class SvnPropertyService {
return;
}
final Set<String> ignorePatterns = new HashSet<String>();
- final StringTokenizer st = new StringTokenizer(SVNPropertyValue.getPropertyAsString(propertyValue), "\r\n ");
+ final StringTokenizer st = new StringTokenizer(PropertyValue.toString(propertyValue), "\r\n ");
while (st.hasMoreElements()) {
final String ignorePattern = (String)st.nextElement();
ignorePatterns.add(ignorePattern);
@@ -180,14 +177,14 @@ public class SvnPropertyService {
return false;
}
- protected abstract String getNewPropertyValue(final Set<String> data, final SVNPropertyValue propertyValue);
+ protected abstract String getNewPropertyValue(final Set<String> data, final PropertyValue propertyValue);
- protected void processFolder(final VirtualFile folder, final File folderDir, final Set<String> data, final SVNPropertyValue propertyValue)
+ protected void processFolder(final VirtualFile folder, final File folderDir, final Set<String> data, final PropertyValue propertyValue)
throws VcsException {
String newValue = getNewPropertyValue(data, propertyValue);
newValue = (newValue.trim().isEmpty()) ? null : newValue;
myVcs.getFactory(folderDir).createPropertyClient()
- .setProperty(folderDir, SvnPropertyKeys.SVN_IGNORE, SVNPropertyValue.create(newValue), Depth.EMPTY, false);
+ .setProperty(folderDir, SvnPropertyKeys.SVN_IGNORE, PropertyValue.create(newValue), Depth.EMPTY, false);
if (myUseCommonExtension) {
dirtyScopeManager.dirDirtyRecursively(folder);
@@ -216,9 +213,9 @@ public class SvnPropertyService {
super(activeVcs, project, useCommonExtension);
}
- protected String getNewPropertyValue(final Set<String> data, final SVNPropertyValue propertyValue) {
+ protected String getNewPropertyValue(final Set<String> data, final PropertyValue propertyValue) {
if (propertyValue != null) {
- return getNewPropertyValueForRemove(data, SVNPropertyValue.getPropertyAsString(propertyValue));
+ return getNewPropertyValueForRemove(data, PropertyValue.toString(propertyValue));
}
return "";
}
@@ -241,7 +238,7 @@ public class SvnPropertyService {
super(activeVcs, project, useCommonExtension);
}
- protected String getNewPropertyValue(final Set<String> data, final SVNPropertyValue propertyValue) {
+ protected String getNewPropertyValue(final Set<String> data, final PropertyValue propertyValue) {
final String ignoreString;
if (data.size() == 1) {
ignoreString = data.iterator().next();
@@ -252,7 +249,7 @@ public class SvnPropertyService {
}
ignoreString = sb.toString();
}
- return (propertyValue == null) ? ignoreString : (SVNPropertyValue.getPropertyAsString(propertyValue) + '\n' + ignoreString);
+ return (propertyValue == null) ? ignoreString : (PropertyValue.toString(propertyValue) + '\n' + ignoreString);
}
}
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/GatheringChangelistBuilder.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/GatheringChangelistBuilder.java
index b6228fca921d..1e031e20d408 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/GatheringChangelistBuilder.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/GatheringChangelistBuilder.java
@@ -20,7 +20,10 @@ import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.VcsKey;
-import com.intellij.openapi.vcs.changes.*;
+import com.intellij.openapi.vcs.changes.Change;
+import com.intellij.openapi.vcs.changes.ChangeList;
+import com.intellij.openapi.vcs.changes.ChangesUtil;
+import com.intellij.openapi.vcs.changes.EmptyChangelistBuilder;
import com.intellij.openapi.vcs.update.UpdatedFilesReverseSide;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.ContainerUtil;
@@ -28,12 +31,14 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.SvnPropertyKeys;
import org.jetbrains.idea.svn.SvnVcs;
-import org.tmatesoft.svn.core.wc.SVNPropertyData;
+import org.jetbrains.idea.svn.properties.PropertyValue;
import org.tmatesoft.svn.core.wc.SVNRevision;
import org.tmatesoft.svn.core.wc2.SvnTarget;
import java.io.File;
-import java.util.*;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
public class GatheringChangelistBuilder extends EmptyChangelistBuilder {
@@ -92,13 +97,13 @@ public class GatheringChangelistBuilder extends EmptyChangelistBuilder {
SvnTarget target = SvnTarget.fromFile(file);
try {
- SVNPropertyData current =
+ PropertyValue current =
myVcs.getFactory(target).createPropertyClient().getProperty(target, SvnPropertyKeys.MERGE_INFO, false, SVNRevision.WORKING);
- SVNPropertyData base =
+ PropertyValue base =
myVcs.getFactory(target).createPropertyClient().getProperty(target, SvnPropertyKeys.MERGE_INFO, false, SVNRevision.BASE);
if (current != null) {
- return base == null || !Comparing.equal(current.getValue(), base.getValue());
+ return base == null || !Comparing.equal(current, base);
}
}
catch (VcsException e) {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/BranchInfo.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/BranchInfo.java
index 62638291b485..701bb2575001 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/BranchInfo.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/BranchInfo.java
@@ -22,10 +22,10 @@ import com.intellij.util.containers.MultiMap;
import org.jetbrains.idea.svn.SvnVcs;
import org.jetbrains.idea.svn.history.SvnChangeList;
import org.jetbrains.idea.svn.info.Info;
+import org.jetbrains.idea.svn.properties.PropertyValue;
import org.tmatesoft.svn.core.*;
import org.tmatesoft.svn.core.internal.util.SVNMergeInfoUtil;
import org.tmatesoft.svn.core.internal.util.SVNPathUtil;
-import org.tmatesoft.svn.core.wc.SVNPropertyData;
import org.tmatesoft.svn.core.wc.SVNRevision;
import org.tmatesoft.svn.core.wc2.SvnTarget;
@@ -205,7 +205,7 @@ public class BranchInfo {
return SvnMergeInfoCache.MergeCheckResult.getInstance(mergeInfo.contains(revisionAsked));
}
- final SVNPropertyData mergeinfoProperty;
+ final PropertyValue mergeinfoProperty;
SvnTarget target = SvnTarget.fromURL(branchUrl);
try {
@@ -235,7 +235,7 @@ public class BranchInfo {
return goUpInRepo(revisionAsked, targetRevision, newBranchUrl, newTrunkUrl);
}
// process
- return processMergeinfoProperty(keyString, revisionAsked, mergeinfoProperty.getValue(), trunkUrl, false);
+ return processMergeinfoProperty(keyString, revisionAsked, mergeinfoProperty, trunkUrl, false);
}
private Info getInfo(final File pathFile) {
@@ -277,7 +277,7 @@ public class BranchInfo {
return SvnMergeInfoCache.MergeCheckResult.getInstance(merged);
}
- final SVNPropertyData mergeinfoProperty;
+ final PropertyValue mergeinfoProperty;
try {
if (actualRevision == targetRevisionCorrected) {
// look in WC
@@ -302,11 +302,11 @@ public class BranchInfo {
return goUp(revisionAsked, targetRevisionCorrected, branchRootPath, path, trunkUrl);
}
// process
- return processMergeinfoProperty(keyString, revisionAsked, mergeinfoProperty.getValue(), trunkUrl, self);
+ return processMergeinfoProperty(keyString, revisionAsked, mergeinfoProperty, trunkUrl, self);
}
private SvnMergeInfoCache.MergeCheckResult processMergeinfoProperty(final String pathWithRevisionNumber, final long revisionAsked,
- final SVNPropertyValue value, final String trunkRelativeUrl,
+ final PropertyValue value, final String trunkRelativeUrl,
final boolean self) {
final String valueAsString = value.toString().trim();
@@ -318,7 +318,7 @@ public class BranchInfo {
final Map<String, SVNMergeRangeList> map;
try {
- map = SVNMergeInfoUtil.parseMergeInfo(new StringBuffer(replaceSeparators(value.getString())), null);
+ map = SVNMergeInfoUtil.parseMergeInfo(new StringBuffer(replaceSeparators(value.toString())), null);
}
catch (SVNException e) {
LOG.info(e);
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneRecursiveShotMergeInfoWorker.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneRecursiveShotMergeInfoWorker.java
index 0ea95c99c4d4..225bc6ad0396 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneRecursiveShotMergeInfoWorker.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneRecursiveShotMergeInfoWorker.java
@@ -23,11 +23,12 @@ import com.intellij.util.PairProcessor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.svn.api.Depth;
import org.jetbrains.idea.svn.dialogs.MergeContext;
+import org.jetbrains.idea.svn.properties.PropertyConsumer;
+import org.jetbrains.idea.svn.properties.PropertyData;
+import org.jetbrains.idea.svn.properties.PropertyValue;
import org.tmatesoft.svn.core.*;
import org.tmatesoft.svn.core.internal.util.SVNMergeInfoUtil;
import org.tmatesoft.svn.core.internal.util.SVNPathUtil;
-import org.tmatesoft.svn.core.wc.ISVNPropertyHandler;
-import org.tmatesoft.svn.core.wc.SVNPropertyData;
import org.tmatesoft.svn.core.wc.SVNRevision;
import org.tmatesoft.svn.core.wc2.SvnTarget;
@@ -63,19 +64,19 @@ public class OneRecursiveShotMergeInfoWorker implements MergeInfoWorker {
public void prepare() throws VcsException {
final Depth depth = Depth.allOrEmpty(myMergeContext.getVcs().getSvnConfiguration().isCheckNestedForQuickMerge());
- ISVNPropertyHandler handler = new ISVNPropertyHandler() {
- public void handleProperty(File path, SVNPropertyData property) throws SVNException {
+ PropertyConsumer handler = new PropertyConsumer() {
+ public void handleProperty(File path, PropertyData property) throws SVNException {
final String key = keyFromFile(path);
synchronized (myLock) {
myDataMap.put(key, SVNMergeInfoUtil
- .parseMergeInfo(new StringBuffer(replaceSeparators(SVNPropertyValue.getPropertyAsString(property.getValue()))), null));
+ .parseMergeInfo(new StringBuffer(replaceSeparators(PropertyValue.toString(property.getValue()))), null));
}
}
- public void handleProperty(SVNURL url, SVNPropertyData property) throws SVNException {
+ public void handleProperty(SVNURL url, PropertyData property) throws SVNException {
}
- public void handleProperty(long revision, SVNPropertyData property) throws SVNException {
+ public void handleProperty(long revision, PropertyData property) throws SVNException {
}
};
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/CmdPropertyClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/CmdPropertyClient.java
index e855abe1ec2e..e053776d14ce 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/CmdPropertyClient.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/CmdPropertyClient.java
@@ -10,9 +10,8 @@ import org.jetbrains.idea.svn.commandLine.CommandExecutor;
import org.jetbrains.idea.svn.commandLine.CommandUtil;
import org.jetbrains.idea.svn.commandLine.SvnCommandName;
import org.jetbrains.idea.svn.info.Info;
-import org.tmatesoft.svn.core.*;
-import org.tmatesoft.svn.core.wc.ISVNPropertyHandler;
-import org.tmatesoft.svn.core.wc.SVNPropertyData;
+import org.tmatesoft.svn.core.SVNException;
+import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.wc.SVNRevision;
import org.tmatesoft.svn.core.wc2.SvnTarget;
@@ -24,6 +23,7 @@ import javax.xml.bind.annotation.XmlValue;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
/**
* @author Konstantin Kolosovsky.
@@ -32,10 +32,10 @@ public class CmdPropertyClient extends BaseSvnClient implements PropertyClient {
@Nullable
@Override
- public SVNPropertyData getProperty(@NotNull SvnTarget target,
- @NotNull String property,
- boolean revisionProperty,
- @Nullable SVNRevision revision)
+ public PropertyValue getProperty(@NotNull SvnTarget target,
+ @NotNull String property,
+ boolean revisionProperty,
+ @Nullable SVNRevision revision)
throws VcsException {
List<String> parameters = new ArrayList<String>();
@@ -57,7 +57,9 @@ public class CmdPropertyClient extends BaseSvnClient implements PropertyClient {
parameters.add("--xml");
CommandExecutor command = execute(myVcs, target, SvnCommandName.propget, parameters, null);
- return parseSingleProperty(target, command.getOutput());
+ PropertyData data = parseSingleProperty(target, command.getOutput());
+
+ return data != null ? data.getValue() : null;
}
@Override
@@ -65,7 +67,7 @@ public class CmdPropertyClient extends BaseSvnClient implements PropertyClient {
@NotNull String property,
@Nullable SVNRevision revision,
@Nullable Depth depth,
- @Nullable ISVNPropertyHandler handler) throws VcsException {
+ @Nullable PropertyConsumer handler) throws VcsException {
List<String> parameters = new ArrayList<String>();
parameters.add(property);
@@ -79,7 +81,7 @@ public class CmdPropertyClient extends BaseSvnClient implements PropertyClient {
public void list(@NotNull SvnTarget target,
@Nullable SVNRevision revision,
@Nullable Depth depth,
- @Nullable ISVNPropertyHandler handler) throws VcsException {
+ @Nullable PropertyConsumer handler) throws VcsException {
List<String> parameters = new ArrayList<String>();
fillListParameters(target, revision, depth, parameters, true);
@@ -90,39 +92,39 @@ public class CmdPropertyClient extends BaseSvnClient implements PropertyClient {
@Override
public void setProperty(@NotNull File file,
@NotNull String property,
- @Nullable SVNPropertyValue value,
+ @Nullable PropertyValue value,
@Nullable Depth depth,
boolean force) throws VcsException {
runSetProperty(SvnTarget.fromFile(file), property, null, depth, value, force);
}
@Override
- public void setProperties(@NotNull File file, @NotNull SVNProperties properties) throws VcsException {
- SVNProperties currentProperties = collectPropertiesToDelete(file);
+ public void setProperties(@NotNull File file, @NotNull PropertiesMap properties) throws VcsException {
+ PropertiesMap currentProperties = collectPropertiesToDelete(file);
currentProperties.putAll(properties);
- for (String propertyName : currentProperties.nameSet()) {
- setProperty(file, propertyName, currentProperties.getSVNPropertyValue(propertyName), Depth.EMPTY, true);
+ for (Map.Entry<String, PropertyValue> entry : currentProperties.entrySet()) {
+ setProperty(file, entry.getKey(), entry.getValue(), Depth.EMPTY, true);
}
}
@NotNull
- private SVNProperties collectPropertiesToDelete(@NotNull File file) throws VcsException {
- final SVNProperties result = new SVNProperties();
+ private PropertiesMap collectPropertiesToDelete(@NotNull File file) throws VcsException {
+ final PropertiesMap result = new PropertiesMap();
- list(SvnTarget.fromFile(file), null, Depth.EMPTY, new ISVNPropertyHandler() {
+ list(SvnTarget.fromFile(file), null, Depth.EMPTY, new PropertyConsumer() {
@Override
- public void handleProperty(File path, SVNPropertyData property) throws SVNException {
+ public void handleProperty(File path, PropertyData property) throws SVNException {
// null indicates property will be deleted
- result.put(property.getName(), (SVNPropertyValue)null);
+ result.put(property.getName(), null);
}
@Override
- public void handleProperty(SVNURL url, SVNPropertyData property) throws SVNException {
+ public void handleProperty(SVNURL url, PropertyData property) throws SVNException {
}
@Override
- public void handleProperty(long revision, SVNPropertyData property) throws SVNException {
+ public void handleProperty(long revision, PropertyData property) throws SVNException {
}
});
@@ -133,7 +135,7 @@ public class CmdPropertyClient extends BaseSvnClient implements PropertyClient {
public void setRevisionProperty(@NotNull SvnTarget target,
@NotNull String property,
@NotNull SVNRevision revision,
- @Nullable SVNPropertyValue value,
+ @Nullable PropertyValue value,
boolean force) throws VcsException {
runSetProperty(target, property, revision, null, value, force);
}
@@ -142,7 +144,7 @@ public class CmdPropertyClient extends BaseSvnClient implements PropertyClient {
@NotNull String property,
@Nullable SVNRevision revision,
@Nullable Depth depth,
- @Nullable SVNPropertyValue value,
+ @Nullable PropertyValue value,
boolean force) throws VcsException {
List<String> parameters = new ArrayList<String>();
boolean isDelete = value == null;
@@ -153,7 +155,7 @@ public class CmdPropertyClient extends BaseSvnClient implements PropertyClient {
CommandUtil.put(parameters, revision);
}
if (!isDelete) {
- parameters.add(SVNPropertyValue.getPropertyAsString(value));
+ parameters.add(PropertyValue.toString(value));
// --force could only be used in "propset" command, but not in "propdel" command
CommandUtil.put(parameters, force, "--force");
}
@@ -180,21 +182,22 @@ public class CmdPropertyClient extends BaseSvnClient implements PropertyClient {
CommandUtil.put(parameters, verbose, "--verbose");
}
- private SVNPropertyData parseSingleProperty(SvnTarget target, String output) throws VcsException {
- final SVNPropertyData[] data = new SVNPropertyData[1];
- ISVNPropertyHandler handler = new ISVNPropertyHandler() {
+ @Nullable
+ private PropertyData parseSingleProperty(SvnTarget target, String output) throws VcsException {
+ final PropertyData[] data = new PropertyData[1];
+ PropertyConsumer handler = new PropertyConsumer() {
@Override
- public void handleProperty(File path, SVNPropertyData property) throws SVNException {
+ public void handleProperty(File path, PropertyData property) throws SVNException {
data[0] = property;
}
@Override
- public void handleProperty(SVNURL url, SVNPropertyData property) throws SVNException {
+ public void handleProperty(SVNURL url, PropertyData property) throws SVNException {
data[0] = property;
}
@Override
- public void handleProperty(long revision, SVNPropertyData property) throws SVNException {
+ public void handleProperty(long revision, PropertyData property) throws SVNException {
data[0] = property;
}
};
@@ -204,7 +207,7 @@ public class CmdPropertyClient extends BaseSvnClient implements PropertyClient {
return data[0];
}
- private static void parseOutput(SvnTarget target, String output, ISVNPropertyHandler handler) throws VcsException {
+ private static void parseOutput(SvnTarget target, String output, PropertyConsumer handler) throws VcsException {
try {
Properties properties = CommandUtil.parse(output, Properties.class);
@@ -231,7 +234,7 @@ public class CmdPropertyClient extends BaseSvnClient implements PropertyClient {
}
}
- private static void invokeHandler(@NotNull SvnTarget target, @Nullable SVNPropertyData data, @Nullable ISVNPropertyHandler handler)
+ private static void invokeHandler(@NotNull SvnTarget target, @Nullable PropertyData data, @Nullable PropertyConsumer handler)
throws SVNException {
if (handler != null && data != null) {
if (target.isFile()) {
@@ -242,7 +245,7 @@ public class CmdPropertyClient extends BaseSvnClient implements PropertyClient {
}
}
- private static void invokeHandler(long revision, @Nullable SVNPropertyData data, @Nullable ISVNPropertyHandler handler)
+ private static void invokeHandler(long revision, @Nullable PropertyData data, @Nullable PropertyConsumer handler)
throws SVNException {
if (handler != null && data != null) {
handler.handleProperty(revision, data);
@@ -250,13 +253,13 @@ public class CmdPropertyClient extends BaseSvnClient implements PropertyClient {
}
@Nullable
- private static SVNPropertyData create(@NotNull String property, @Nullable String value) {
- SVNPropertyData result = null;
+ private static PropertyData create(@NotNull String property, @Nullable String value) {
+ PropertyData result = null;
// such behavior is required to compatibility with SVNKit as some logic in merge depends on
// whether null property data or property data with empty string value is returned
if (value != null) {
- result = new SVNPropertyData(property, SVNPropertyValue.create(value.trim()), LF_SEPARATOR_OPTIONS);
+ result = new PropertyData(property, PropertyValue.create(value.trim()));
}
return result;
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/ExternalsDefinitionParser.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/ExternalsDefinitionParser.java
new file mode 100644
index 000000000000..b3ec74e397cb
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/ExternalsDefinitionParser.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.idea.svn.properties;
+
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.idea.svn.commandLine.SvnBindException;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public class ExternalsDefinitionParser {
+
+ /**
+ * Parses "svn:externals" property in format starting from svn 1.5.
+ *
+ * @return map of externals definitions: key - relative directory, value - corresponding complete externals definition.
+ */
+ @NotNull
+ public static Map<String, String> parseExternalsProperty(@NotNull String externals) throws SvnBindException {
+ HashMap<String, String> map = ContainerUtil.newHashMap();
+
+ for (String external : StringUtil.splitByLines(externals, true)) {
+ map.put(parseRelativeDirectory(external), external);
+ }
+
+ return map;
+ }
+
+ /**
+ * Parses relative directory from externals definition (in format starting from svn 1.5). Restrictions for relative directory:
+ * - is at the end of externals definition separated from other parameters by ' ' char
+ * - could be quoted with '"' char
+ * - certain chars could be escaped with '\' char
+ */
+ @NotNull
+ public static String parseRelativeDirectory(@NotNull String s) throws SvnBindException {
+ s = s.trim();
+
+ int length = s.length();
+ String result;
+
+ if (isUnescapedQuote(s, length - 1)) {
+ int index = lastUnescapedIndexOf(s, length - 1, '"');
+ assertIndex(s, index, "Could not find start quote");
+ result = s.substring(index + 1, length - 1);
+ }
+ else {
+ int index = lastUnescapedIndexOf(s, length, ' ');
+ assertIndex(s, index, "Could not find separating space");
+ result = s.substring(index + 1);
+ }
+
+ return unescape(result);
+ }
+
+ private static void assertIndex(@NotNull String s, int index, @NotNull String message) throws SvnBindException {
+ if (index < 0) {
+ throw new SvnBindException(message + " - " + s);
+ }
+ }
+
+ @NotNull
+ private static String unescape(@NotNull String s) {
+ return s.replace("\\", "");
+ }
+
+ /**
+ * "from" index is excluded.
+ */
+ private static int lastUnescapedIndexOf(@NotNull String s, int from, char c) {
+ int result = from;
+
+ do {
+ result = s.lastIndexOf(c, result - 1);
+ }
+ while (result != -1 && !isUnescaped(s, result, c));
+
+ return result;
+ }
+
+ private static boolean isUnescapedQuote(@NotNull String s, int index) {
+ return isUnescaped(s, index, '"');
+ }
+
+ private static boolean isUnescaped(@NotNull String s, int index, char c) {
+ return StringUtil.isChar(s, index, c) && !StringUtil.isChar(s, index - 1, '\\');
+ }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertiesMap.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertiesMap.java
new file mode 100644
index 000000000000..c5857aa4b345
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertiesMap.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.idea.svn.properties;
+
+import com.intellij.util.containers.HashMap;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public class PropertiesMap extends HashMap<String, PropertyValue> {
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertyClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertyClient.java
index 1b61d59c0e20..42acfc8109d7 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertyClient.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertyClient.java
@@ -1,18 +1,10 @@
package org.jetbrains.idea.svn.properties;
import com.intellij.openapi.vcs.VcsException;
-import com.intellij.openapi.vfs.CharsetToolkit;
-import com.intellij.util.LineSeparator;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.api.Depth;
import org.jetbrains.idea.svn.api.SvnClient;
-import org.tmatesoft.svn.core.SVNProperties;
-import org.tmatesoft.svn.core.SVNPropertyValue;
-import org.tmatesoft.svn.core.internal.wc.DefaultSVNOptions;
-import org.tmatesoft.svn.core.wc.ISVNOptions;
-import org.tmatesoft.svn.core.wc.ISVNPropertyHandler;
-import org.tmatesoft.svn.core.wc.SVNPropertyData;
import org.tmatesoft.svn.core.wc.SVNRevision;
import org.tmatesoft.svn.core.wc2.SvnTarget;
@@ -23,40 +15,33 @@ import java.io.File;
*/
public interface PropertyClient extends SvnClient {
- ISVNOptions LF_SEPARATOR_OPTIONS = new DefaultSVNOptions() {
- @Override
- public byte[] getNativeEOL() {
- return CharsetToolkit.getUtf8Bytes(LineSeparator.LF.getSeparatorString());
- }
- };
-
@Nullable
- SVNPropertyData getProperty(@NotNull final SvnTarget target,
- @NotNull final String property,
- boolean revisionProperty,
- @Nullable SVNRevision revision) throws VcsException;
+ PropertyValue getProperty(@NotNull final SvnTarget target,
+ @NotNull final String property,
+ boolean revisionProperty,
+ @Nullable SVNRevision revision) throws VcsException;
void getProperty(@NotNull SvnTarget target, @NotNull String property,
@Nullable SVNRevision revision,
@Nullable Depth depth,
- @Nullable ISVNPropertyHandler handler) throws VcsException;
+ @Nullable PropertyConsumer handler) throws VcsException;
void list(@NotNull SvnTarget target,
@Nullable SVNRevision revision,
@Nullable Depth depth,
- @Nullable ISVNPropertyHandler handler) throws VcsException;
+ @Nullable PropertyConsumer handler) throws VcsException;
void setProperty(@NotNull File file,
@NotNull String property,
- @Nullable SVNPropertyValue value,
+ @Nullable PropertyValue value,
@Nullable Depth depth,
boolean force) throws VcsException;
- void setProperties(@NotNull File file, @NotNull SVNProperties properties) throws VcsException;
+ void setProperties(@NotNull File file, @NotNull PropertiesMap properties) throws VcsException;
void setRevisionProperty(@NotNull SvnTarget target,
@NotNull String property,
@NotNull SVNRevision revision,
- @Nullable SVNPropertyValue value,
+ @Nullable PropertyValue value,
boolean force) throws VcsException;
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertyConsumer.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertyConsumer.java
new file mode 100644
index 000000000000..f45e09df39d5
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertyConsumer.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.idea.svn.properties;
+
+import org.tmatesoft.svn.core.SVNException;
+import org.tmatesoft.svn.core.SVNURL;
+
+import java.io.File;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public interface PropertyConsumer {
+
+ void handleProperty(File path, PropertyData property) throws SVNException;
+
+ void handleProperty(SVNURL url, PropertyData property) throws SVNException;
+
+ void handleProperty(long revision, PropertyData property) throws SVNException;
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertyData.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertyData.java
new file mode 100644
index 000000000000..3953636d870c
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertyData.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.idea.svn.properties;
+
+import org.jetbrains.annotations.Nullable;
+import org.tmatesoft.svn.core.wc.SVNPropertyData;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public class PropertyData {
+
+ private final PropertyValue myValue;
+
+ private final String myName;
+
+ public PropertyData(String name, PropertyValue value) {
+ myName = name;
+ myValue = value;
+ }
+
+ public String getName() {
+ return myName;
+ }
+
+ public PropertyValue getValue() {
+ return myValue;
+ }
+
+ @Nullable
+ public static PropertyData create(@Nullable SVNPropertyData data) {
+ PropertyData result = null;
+
+ if (data != null) {
+ result = new PropertyData(data.getName(), PropertyValue.create(data.getValue()));
+ }
+
+ return result;
+ }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertyValue.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertyValue.java
new file mode 100644
index 000000000000..62cb7cbd0340
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertyValue.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.idea.svn.properties;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.tmatesoft.svn.core.SVNPropertyValue;
+
+/**
+ * TODO: Add correct support of binary properties - support in api, diff, etc.
+ *
+ * @author Konstantin Kolosovsky.
+ */
+public class PropertyValue {
+
+ @NotNull private final String myValue;
+
+ @Nullable
+ public static PropertyValue create(@Nullable SVNPropertyValue value) {
+ return create(SVNPropertyValue.getPropertyAsString(value));
+ }
+
+ private PropertyValue(@NotNull String propertyValue) {
+ myValue = propertyValue;
+ }
+
+ @Nullable
+ public static PropertyValue create(@Nullable String propertyValue) {
+ return propertyValue == null ? null : new PropertyValue(propertyValue);
+ }
+
+ @Nullable
+ public static String toString(@Nullable PropertyValue value) {
+ return value == null ? null : value.myValue;
+ }
+
+ public String toString() {
+ return myValue;
+ }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/SvnKitPropertyClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/SvnKitPropertyClient.java
index 4ad3f10afccc..23fedd3c7ac8 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/SvnKitPropertyClient.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/SvnKitPropertyClient.java
@@ -1,42 +1,57 @@
package org.jetbrains.idea.svn.properties;
import com.intellij.openapi.vcs.VcsException;
+import com.intellij.openapi.vfs.CharsetToolkit;
+import com.intellij.util.LineSeparator;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.api.BaseSvnClient;
import org.jetbrains.idea.svn.api.Depth;
import org.jetbrains.idea.svn.commandLine.SvnBindException;
import org.tmatesoft.svn.core.*;
+import org.tmatesoft.svn.core.internal.wc.DefaultSVNOptions;
import org.tmatesoft.svn.core.wc.*;
import org.tmatesoft.svn.core.wc2.SvnTarget;
import java.io.File;
+import java.util.Map;
/**
* @author Konstantin Kolosovsky.
*/
public class SvnKitPropertyClient extends BaseSvnClient implements PropertyClient {
+ public static final ISVNOptions LF_SEPARATOR_OPTIONS = new DefaultSVNOptions() {
+ @Override
+ public byte[] getNativeEOL() {
+ return CharsetToolkit.getUtf8Bytes(LineSeparator.LF.getSeparatorString());
+ }
+ };
+
@Nullable
@Override
- public SVNPropertyData getProperty(@NotNull SvnTarget target,
- @NotNull String property,
- boolean revisionProperty,
- @Nullable SVNRevision revision) throws VcsException {
+ public PropertyValue getProperty(@NotNull SvnTarget target,
+ @NotNull String property,
+ boolean revisionProperty,
+ @Nullable SVNRevision revision) throws VcsException {
+ PropertyData resultData;
+
try {
if (!revisionProperty) {
if (target.isFile()) {
- return createClient().doGetProperty(target.getFile(), property, target.getPegRevision(), revision);
+ resultData = PropertyData.create(createClient().doGetProperty(target.getFile(), property, target.getPegRevision(), revision));
} else {
- return createClient().doGetProperty(target.getURL(), property, target.getPegRevision(), revision);
+ resultData = PropertyData.create(createClient().doGetProperty(target.getURL(), property, target.getPegRevision(), revision));
}
} else {
- return getRevisionProperty(target, property, revision);
+ resultData = getRevisionProperty(target, property, revision);
}
}
catch (SVNException e) {
throw new VcsException(e);
}
+
+ return resultData != null ? resultData.getValue() : null;
}
@NotNull
@@ -52,7 +67,7 @@ public class SvnKitPropertyClient extends BaseSvnClient implements PropertyClien
@NotNull String property,
@Nullable SVNRevision revision,
@Nullable Depth depth,
- @Nullable ISVNPropertyHandler handler) throws VcsException {
+ @Nullable PropertyConsumer handler) throws VcsException {
runGetProperty(target, property, revision, depth, handler);
}
@@ -60,18 +75,18 @@ public class SvnKitPropertyClient extends BaseSvnClient implements PropertyClien
public void list(@NotNull SvnTarget target,
@Nullable SVNRevision revision,
@Nullable Depth depth,
- @Nullable ISVNPropertyHandler handler) throws VcsException {
+ @Nullable PropertyConsumer handler) throws VcsException {
runGetProperty(target, null, revision, depth, handler);
}
@Override
public void setProperty(@NotNull File file,
@NotNull String property,
- @Nullable SVNPropertyValue value,
+ @Nullable PropertyValue value,
@Nullable Depth depth,
boolean force) throws VcsException {
try {
- createClient().doSetProperty(file, property, value, force, toDepth(depth), null, null);
+ createClient().doSetProperty(file, property, toPropertyValue(value), force, toDepth(depth), null, null);
}
catch (SVNException e) {
throw new SvnBindException(e);
@@ -79,12 +94,13 @@ public class SvnKitPropertyClient extends BaseSvnClient implements PropertyClien
}
@Override
- public void setProperties(@NotNull File file, @NotNull SVNProperties properties) throws VcsException {
+ public void setProperties(@NotNull File file, @NotNull PropertiesMap properties) throws VcsException {
+ final SVNProperties propertiesToSet = toSvnProperties(properties);
try {
createClient().doSetProperty(file, new ISVNPropertyValueProvider() {
@Override
public SVNProperties providePropertyValues(File path, SVNProperties properties) throws SVNException {
- return properties;
+ return propertiesToSet;
}
}, true, SVNDepth.EMPTY, null, null);
}
@@ -97,14 +113,14 @@ public class SvnKitPropertyClient extends BaseSvnClient implements PropertyClien
public void setRevisionProperty(@NotNull SvnTarget target,
@NotNull String property,
@NotNull SVNRevision revision,
- @Nullable SVNPropertyValue value,
+ @Nullable PropertyValue value,
boolean force) throws VcsException {
try {
if (target.isFile()) {
- createClient().doSetRevisionProperty(target.getFile(), revision, property, value, force, null);
+ createClient().doSetRevisionProperty(target.getFile(), revision, property, toPropertyValue(value), force, null);
}
else {
- createClient().doSetRevisionProperty(target.getURL(), revision, property, value, force, null);
+ createClient().doSetRevisionProperty(target.getURL(), revision, property, toPropertyValue(value), force, null);
}
}
catch (SVNException e) {
@@ -112,27 +128,39 @@ public class SvnKitPropertyClient extends BaseSvnClient implements PropertyClien
}
}
+ @NotNull
+ private static SVNProperties toSvnProperties(@NotNull PropertiesMap properties) {
+ SVNProperties result = new SVNProperties();
+
+ for (Map.Entry<String, PropertyValue> entry : properties.entrySet()) {
+ result.put(entry.getKey(), toPropertyValue(entry.getValue()));
+ }
+
+ return result;
+ }
+
private void runGetProperty(@NotNull SvnTarget target,
@Nullable String property,
@Nullable SVNRevision revision,
@Nullable Depth depth,
- @Nullable ISVNPropertyHandler handler) throws VcsException {
+ @Nullable PropertyConsumer handler) throws VcsException {
SVNWCClient client = createClient();
try {
if (target.isURL()) {
- client.doGetProperty(target.getURL(), property, target.getPegRevision(), revision, toDepth(depth), handler);
+ client.doGetProperty(target.getURL(), property, target.getPegRevision(), revision, toDepth(depth), toHandler(handler));
} else {
- client.doGetProperty(target.getFile(), property, target.getPegRevision(), revision, toDepth(depth), handler, null);
+ client.doGetProperty(target.getFile(), property, target.getPegRevision(), revision, toDepth(depth), toHandler(handler), null);
}
} catch (SVNException e) {
throw new VcsException(e);
}
}
- private SVNPropertyData getRevisionProperty(@NotNull SvnTarget target, @NotNull final String property, @Nullable SVNRevision revision) throws SVNException{
+ private PropertyData getRevisionProperty(@NotNull SvnTarget target, @NotNull final String property, @Nullable SVNRevision revision)
+ throws SVNException {
final SVNWCClient client = createClient();
- final SVNPropertyData[] result = new SVNPropertyData[1];
+ final PropertyData[] result = new PropertyData[1];
ISVNPropertyHandler handler = new ISVNPropertyHandler() {
@Override
public void handleProperty(File path, SVNPropertyData property) throws SVNException {
@@ -151,7 +179,7 @@ public class SvnKitPropertyClient extends BaseSvnClient implements PropertyClien
private void handle(@NotNull SVNPropertyData data) {
if (property.equals(data.getName())) {
- result[0] = data;
+ result[0] = PropertyData.create(data);
}
}
};
@@ -164,4 +192,41 @@ public class SvnKitPropertyClient extends BaseSvnClient implements PropertyClien
return result[0];
}
+
+ @Nullable
+ private static ISVNPropertyHandler toHandler(@Nullable final PropertyConsumer consumer) {
+ ISVNPropertyHandler result = null;
+
+ if (consumer != null) {
+ result = new ISVNPropertyHandler() {
+ @Override
+ public void handleProperty(File path, SVNPropertyData property) throws SVNException {
+ consumer.handleProperty(path, PropertyData.create(property));
+ }
+
+ @Override
+ public void handleProperty(SVNURL url, SVNPropertyData property) throws SVNException {
+ consumer.handleProperty(url, PropertyData.create(property));
+ }
+
+ @Override
+ public void handleProperty(long revision, SVNPropertyData property) throws SVNException {
+ consumer.handleProperty(revision, PropertyData.create(property));
+ }
+ };
+ }
+
+ return result;
+ }
+
+ @Nullable
+ private static SVNPropertyValue toPropertyValue(@Nullable PropertyValue value) {
+ SVNPropertyValue result = null;
+
+ if (value != null) {
+ result = SVNPropertyValue.create(value.toString());
+ }
+
+ return result;
+ }
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/rollback/SvnRollbackEnvironment.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/rollback/SvnRollbackEnvironment.java
index 237d05bd5f7a..7b09461b3766 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/rollback/SvnRollbackEnvironment.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/rollback/SvnRollbackEnvironment.java
@@ -34,6 +34,9 @@ import org.jetbrains.idea.svn.api.ProgressEvent;
import org.jetbrains.idea.svn.api.ProgressTracker;
import org.jetbrains.idea.svn.commandLine.SvnBindException;
import org.jetbrains.idea.svn.info.Info;
+import org.jetbrains.idea.svn.properties.PropertiesMap;
+import org.jetbrains.idea.svn.properties.PropertyConsumer;
+import org.jetbrains.idea.svn.properties.PropertyData;
import org.tmatesoft.svn.core.*;
import org.tmatesoft.svn.core.wc.*;
import org.tmatesoft.svn.core.wc2.SvnTarget;
@@ -100,7 +103,7 @@ public class SvnRollbackEnvironment extends DefaultRollbackEnvironment {
};
final List<CopiedAsideInfo> fromToModified = new ArrayList<CopiedAsideInfo>();
- final Map<File, SVNProperties> properties = ContainerUtil.newHashMap();
+ final Map<File, PropertiesMap> properties = ContainerUtil.newHashMap();
moveRenamesToTmp(exceptions, fromToModified, properties, collector);
// adds (deletes)
// deletes (adds)
@@ -123,29 +126,29 @@ public class SvnRollbackEnvironment extends DefaultRollbackEnvironment {
private void moveRenamesToTmp(List<VcsException> exceptions,
List<CopiedAsideInfo> fromToModified,
- final Map<File, SVNProperties> properties,
+ final Map<File, PropertiesMap> properties,
final UnversionedAndNotTouchedFilesGroupCollector collector) {
final Map<File, ThroughRenameInfo> fromTo = collector.getFromTo();
try {
final File tmp = FileUtil.createTempDirectory("forRename", "");
- final ISVNPropertyHandler handler = new ISVNPropertyHandler() {
+ final PropertyConsumer handler = new PropertyConsumer() {
@Override
- public void handleProperty(File path, SVNPropertyData property) throws SVNException {
+ public void handleProperty(File path, PropertyData property) throws SVNException {
final ThroughRenameInfo info = collector.findToFile(new FilePathImpl(path, path.isDirectory()), null);
if (info != null) {
if (!properties.containsKey(info.getTo())) {
- properties.put(info.getTo(), new SVNProperties());
+ properties.put(info.getTo(), new PropertiesMap());
}
properties.get(info.getTo()).put(property.getName(), property.getValue());
}
}
@Override
- public void handleProperty(SVNURL url, SVNPropertyData property) throws SVNException {
+ public void handleProperty(SVNURL url, PropertyData property) throws SVNException {
}
@Override
- public void handleProperty(long revision, SVNPropertyData property) throws SVNException {
+ public void handleProperty(long revision, PropertyData property) throws SVNException {
}
};
@@ -181,7 +184,7 @@ public class SvnRollbackEnvironment extends DefaultRollbackEnvironment {
private void moveGroup(final List<VcsException> exceptions,
List<CopiedAsideInfo> fromTo,
- Map<File, SVNProperties> properties) {
+ Map<File, PropertiesMap> properties) {
Collections.sort(fromTo, new Comparator<CopiedAsideInfo>() {
@Override
public int compare(CopiedAsideInfo o1, CopiedAsideInfo o2) {
@@ -240,8 +243,8 @@ public class SvnRollbackEnvironment extends DefaultRollbackEnvironment {
applyProperties(properties, exceptions);
}
- private void applyProperties(Map<File, SVNProperties> propertiesMap, final List<VcsException> exceptions) {
- for (Map.Entry<File, SVNProperties> entry : propertiesMap.entrySet()) {
+ private void applyProperties(Map<File, PropertiesMap> propertiesMap, final List<VcsException> exceptions) {
+ for (Map.Entry<File, PropertiesMap> entry : propertiesMap.entrySet()) {
File file = entry.getKey();
try {
mySvnVcs.getFactory(file).createPropertyClient().setProperties(file, entry.getValue());
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/svnkit/SvnKitAdminAreaFactorySelector.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/svnkit/SvnKitAdminAreaFactorySelector.java
new file mode 100644
index 000000000000..0d1a4c0106e0
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/svnkit/SvnKitAdminAreaFactorySelector.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.idea.svn.svnkit;
+
+import com.intellij.openapi.application.ApplicationManager;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.svn.SvnFormatSelector;
+import org.jetbrains.idea.svn.SvnWorkingCopyFormatHolder;
+import org.jetbrains.idea.svn.WorkingCopyFormat;
+import org.tmatesoft.svn.core.SVNErrorCode;
+import org.tmatesoft.svn.core.SVNErrorMessage;
+import org.tmatesoft.svn.core.SVNException;
+import org.tmatesoft.svn.core.internal.wc.admin.ISVNAdminAreaFactorySelector;
+import org.tmatesoft.svn.core.internal.wc.admin.SVNAdminAreaFactory;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public class SvnKitAdminAreaFactorySelector implements ISVNAdminAreaFactorySelector {
+
+ public Collection getEnabledFactories(File path, Collection factories, boolean writeAccess) throws SVNException {
+ if (ApplicationManager.getApplication().isUnitTestMode()) {
+ return factories;
+ }
+
+ if (!writeAccess) {
+ return factories;
+ }
+
+ Collection result = null;
+ final WorkingCopyFormat presetFormat = SvnWorkingCopyFormatHolder.getPresetFormat();
+ if (presetFormat != null) {
+ result = format2Factories(presetFormat, factories);
+ }
+
+ if (result == null) {
+ final WorkingCopyFormat format = SvnFormatSelector.getWorkingCopyFormat(path);
+ result = format2Factories(format, factories);
+ }
+
+ if (result == null) {
+ throw new SVNException(SVNErrorMessage.create(SVNErrorCode.WC_NOT_DIRECTORY));
+ }
+ return result;
+ }
+
+ @Nullable
+ static Collection format2Factories(final WorkingCopyFormat format, final Collection factories) {
+ if (WorkingCopyFormat.ONE_DOT_SEVEN.equals(format)) {
+ return factories;
+ }
+ else if (WorkingCopyFormat.ONE_DOT_SIX.equals(format)) {
+ return factoriesFor16(factories);
+ }
+ else if (WorkingCopyFormat.ONE_DOT_FIVE.equals(format)) {
+ return factoriesFor15(factories);
+ }
+ else if (WorkingCopyFormat.ONE_DOT_FOUR.equals(format)) {
+ return factoriesFor14(factories);
+ }
+ else if (WorkingCopyFormat.ONE_DOT_THREE.equals(format)) {
+ return factoriesFor13(factories);
+ }
+ return null;
+ }
+
+ private static Collection<SVNAdminAreaFactory> factoriesFor13(final Collection factories) {
+ for (Object item : factories) {
+ final SVNAdminAreaFactory factory = (SVNAdminAreaFactory)item;
+ final int supportedVersion = factory.getSupportedVersion();
+ if (WorkingCopyFormat.ONE_DOT_THREE.getFormat() == supportedVersion) {
+ return Collections.singletonList(factory);
+ }
+ }
+ return Collections.emptyList();
+ }
+
+ private static Collection<SVNAdminAreaFactory> factoriesFor14(final Collection factories) {
+ final Collection<SVNAdminAreaFactory> result = new ArrayList<SVNAdminAreaFactory>(2);
+ for (Object item : factories) {
+ final SVNAdminAreaFactory factory = (SVNAdminAreaFactory)item;
+ final int supportedVersion = factory.getSupportedVersion();
+ if ((WorkingCopyFormat.ONE_DOT_FOUR.getFormat() == supportedVersion) ||
+ (WorkingCopyFormat.ONE_DOT_THREE.getFormat() == supportedVersion)) {
+ result.add(factory);
+ }
+ }
+ return result;
+ }
+
+ private static Collection<SVNAdminAreaFactory> factoriesFor15(final Collection factories) {
+ final Collection<SVNAdminAreaFactory> result = new ArrayList<SVNAdminAreaFactory>(2);
+ for (Object item : factories) {
+ final SVNAdminAreaFactory factory = (SVNAdminAreaFactory)item;
+ final int supportedVersion = factory.getSupportedVersion();
+ if ((WorkingCopyFormat.ONE_DOT_FOUR.getFormat() == supportedVersion) ||
+ (WorkingCopyFormat.ONE_DOT_THREE.getFormat() == supportedVersion) ||
+ (WorkingCopyFormat.ONE_DOT_FIVE.getFormat() == supportedVersion)) {
+ result.add(factory);
+ }
+ }
+ return result;
+ }
+
+ private static Collection<SVNAdminAreaFactory> factoriesFor16(final Collection factories) {
+ final Collection<SVNAdminAreaFactory> result = new ArrayList<SVNAdminAreaFactory>(2);
+ for (Object item : factories) {
+ final SVNAdminAreaFactory factory = (SVNAdminAreaFactory)item;
+ final int supportedVersion = factory.getSupportedVersion();
+ if ((WorkingCopyFormat.ONE_DOT_FOUR.getFormat() == supportedVersion) ||
+ (WorkingCopyFormat.ONE_DOT_THREE.getFormat() == supportedVersion) ||
+ (WorkingCopyFormat.ONE_DOT_FIVE.getFormat() == supportedVersion) ||
+ (WorkingCopyFormat.ONE_DOT_SIX.getFormat() == supportedVersion)) {
+ result.add(factory);
+ }
+ }
+ return result;
+ }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/svnkit/SvnKitManager.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/svnkit/SvnKitManager.java
index a446b58bb1cb..757100026797 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/svnkit/SvnKitManager.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/svnkit/SvnKitManager.java
@@ -26,7 +26,6 @@ import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.SvnConfiguration;
-import org.jetbrains.idea.svn.SvnFormatSelector;
import org.jetbrains.idea.svn.SvnHttpAuthMethodsDefaultChecker;
import org.jetbrains.idea.svn.SvnVcs;
import org.jetbrains.idea.svn.auth.SvnAuthenticationManager;
@@ -72,7 +71,7 @@ public class SvnKitManager {
SVNJNAUtil.setJNAEnabled(true);
SvnHttpAuthMethodsDefaultChecker.check();
- SVNAdminAreaFactory.setSelector(new SvnFormatSelector());
+ SVNAdminAreaFactory.setSelector(new SvnKitAdminAreaFactorySelector());
DAVRepositoryFactory.setup();
SVNRepositoryFactoryImpl.setup();
diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/ExternalsDefinitionParserTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/ExternalsDefinitionParserTest.java
new file mode 100644
index 000000000000..ff24c79a6b4c
--- /dev/null
+++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/ExternalsDefinitionParserTest.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.idea.svn;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.idea.svn.properties.ExternalsDefinitionParser;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public class ExternalsDefinitionParserTest {
+
+ @Test
+ public void test_no_space_directory_with_revision() throws Exception {
+ assertRelativeDirectory("third-party/skins", "-r148 http://svn.example.com/skinproj third-party/skins");
+ }
+
+ @Test
+ public void test_no_space_directory_with_peg_revision() throws Exception {
+ assertRelativeDirectory("third-party/skins", "http://svn.example.com/skinproj@148 third-party/skins");
+ }
+
+ @Test
+ public void test_no_space_directory_without_revision() throws Exception {
+ assertRelativeDirectory("third-party/sounds", " http://svn.example.com/repos/sounds third-party/sounds");
+ }
+
+ @Test
+ public void test_quoted_no_space_directory() throws Exception {
+ assertRelativeDirectory("third-party/skins", "-r148 http://svn.example.com/skinproj \"third-party/skins\"");
+ }
+
+ @Test
+ public void test_quoted_with_space_directory() throws Exception {
+ assertRelativeDirectory("My Project", "http://svn.thirdparty.com/repos/My%20Project \"My Project\"");
+ }
+
+ @Test
+ public void test_escaped_with_space_and_quotes_directory() throws Exception {
+ assertRelativeDirectory("\"Quotes Too\"", "http://svn.thirdparty.com/repos/%22Quotes%20Too%22 \\\"Quotes\\ Too\\\"");
+ }
+
+ private static void assertRelativeDirectory(@NotNull String expected, @NotNull String external) throws Exception {
+ assertEquals(expected, ExternalsDefinitionParser.parseRelativeDirectory(external));
+ }
+}
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/config/TaskConfigurable.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/config/TaskConfigurable.java
index 2e2da7228dda..06f2685fceb1 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/config/TaskConfigurable.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/config/TaskConfigurable.java
@@ -2,7 +2,6 @@ package com.intellij.tasks.config;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.options.ConfigurationException;
-import com.intellij.openapi.options.NonDefaultProjectConfigurable;
import com.intellij.openapi.options.SearchableConfigurable;
import com.intellij.openapi.options.binding.BindControl;
import com.intellij.openapi.options.binding.BindableConfigurable;
@@ -24,8 +23,7 @@ import java.awt.event.ActionListener;
* @author Dmitry Avdeev
*/
@SuppressWarnings({"UnusedDeclaration"})
-public class TaskConfigurable extends BindableConfigurable implements SearchableConfigurable.Parent,
- NonDefaultProjectConfigurable, Configurable.NoScroll {
+public class TaskConfigurable extends BindableConfigurable implements SearchableConfigurable.Parent, Configurable.NoScroll {
private JPanel myPanel;
diff --git a/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/live/TrelloIntegrationTest.java b/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/live/TrelloIntegrationTest.java
index 3da6ad3d82d7..2f93b83bef09 100644
--- a/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/live/TrelloIntegrationTest.java
+++ b/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/live/TrelloIntegrationTest.java
@@ -29,16 +29,20 @@ public class TrelloIntegrationTest extends LiveIntegrationTestCase<TrelloReposit
@Override
protected TrelloRepository createRepository() throws Exception {
- TrelloRepository repository = new TrelloRepository(new TrelloRepositoryType());
- String token = System.getProperty("tasks.tests.trello.token");
- if (StringUtil.isEmpty(token)) {
- throw new AssertionError("Authorization token is not set");
+ try {
+ TrelloRepository repository = new TrelloRepository(new TrelloRepositoryType());
+ String token = System.getProperty("tasks.tests.trello.token");
+ assertTrue("Authorization token is not set", !StringUtil.isEmpty(token));
+ repository.setPassword(token);
+ TrelloUser user = repository.fetchUserByToken();
+ assertNotNull(user);
+ repository.setCurrentUser(user);
+ return repository;
+ }
+ catch (AssertionError ae){
+ tearDown();
+ throw ae;
}
- repository.setPassword(token);
- TrelloUser user = repository.fetchUserByToken();
- assertNotNull(user);
- repository.setCurrentUser(user);
- return repository;
}
// TODO Check closed tasks exclusion
diff --git a/plugins/terminal/lib/jediterm-pty-2.0.jar b/plugins/terminal/lib/jediterm-pty-2.0.jar
index 794d97412396..e8eaa9bd7a9b 100644
--- a/plugins/terminal/lib/jediterm-pty-2.0.jar
+++ b/plugins/terminal/lib/jediterm-pty-2.0.jar
Binary files differ
diff --git a/plugins/terminal/resources/META-INF/terminal.xml b/plugins/terminal/resources/META-INF/terminal.xml
index 11a18e18d81f..e85297f2b715 100644
--- a/plugins/terminal/resources/META-INF/terminal.xml
+++ b/plugins/terminal/resources/META-INF/terminal.xml
@@ -1,12 +1,4 @@
<idea-plugin version="2">
- <actions>
- <action id="org.jetbrains.plugins.terminal.OpenLocalTerminalAction"
- class="org.jetbrains.plugins.terminal.OpenLocalTerminalAction"
- text="Open Terminal..." description="Open terminal locally">
- <add-to-group group-id="ToolsMenu" anchor="last"/>
- </action>
- </actions>
-
<extensions defaultExtensionNs="com.intellij">
<toolWindow id="Terminal" anchor="bottom" icon="TerminalIcons.OpenTerminal_13x13"
factoryClass="org.jetbrains.plugins.terminal.TerminalToolWindowFactory" secondary="false"/>
diff --git a/plugins/terminal/src/org/jetbrains/plugins/terminal/LocalTerminalDirectRunner.java b/plugins/terminal/src/org/jetbrains/plugins/terminal/LocalTerminalDirectRunner.java
index caaa54166e7d..f67f84412a02 100644
--- a/plugins/terminal/src/org/jetbrains/plugins/terminal/LocalTerminalDirectRunner.java
+++ b/plugins/terminal/src/org/jetbrains/plugins/terminal/LocalTerminalDirectRunner.java
@@ -16,6 +16,7 @@ import com.jediterm.pty.PtyProcessTtyConnector;
import com.jediterm.terminal.TtyConnector;
import com.pty4j.PtyProcess;
import com.pty4j.util.PtyUtil;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
@@ -63,6 +64,11 @@ public class LocalTerminalDirectRunner extends AbstractTerminalRunner<PtyProcess
return null;
}
+ @NotNull
+ public static LocalTerminalDirectRunner createTerminalRunner(Project project) {
+ return new LocalTerminalDirectRunner(project);
+ }
+
@Override
protected PtyProcess createProcess(@Nullable String directory) throws ExecutionException {
Map<String, String> envs = new HashMap<String, String>(System.getenv());
@@ -77,10 +83,14 @@ public class LocalTerminalDirectRunner extends AbstractTerminalRunner<PtyProcess
}
private String currentProjectFolder() {
- for (VirtualFile vf : ProjectRootManager.getInstance(myProject).getContentRoots()) {
- return vf.getCanonicalPath();
+ final ProjectRootManager projectRootManager = ProjectRootManager.getInstance(myProject);
+
+ final VirtualFile[] roots = projectRootManager.getContentRoots();
+ if (roots.length == 1) {
+ roots[0].getCanonicalPath();
}
- return null;
+ final VirtualFile baseDir = myProject.getBaseDir();
+ return baseDir == null ? null : baseDir.getCanonicalPath();
}
@Override
diff --git a/plugins/terminal/src/org/jetbrains/plugins/terminal/OpenLocalTerminalAction.java b/plugins/terminal/src/org/jetbrains/plugins/terminal/OpenLocalTerminalAction.java
deleted file mode 100644
index 4d93dd9fc46e..000000000000
--- a/plugins/terminal/src/org/jetbrains/plugins/terminal/OpenLocalTerminalAction.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package org.jetbrains.plugins.terminal;
-
-import com.intellij.openapi.actionSystem.AnAction;
-import com.intellij.openapi.actionSystem.AnActionEvent;
-import com.intellij.openapi.actionSystem.CommonDataKeys;
-import com.intellij.openapi.project.DumbAware;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.wm.ToolWindow;
-import com.intellij.openapi.wm.ToolWindowManager;
-import icons.TerminalIcons;
-import org.jetbrains.annotations.NotNull;
-
-/**
- * @author traff
- */
-public class OpenLocalTerminalAction extends AnAction implements DumbAware {
- public OpenLocalTerminalAction() {
- super("Open Terminal...", null, TerminalIcons.OpenTerminal);
- }
-
- @Override
- public void update(final AnActionEvent e) {
- e.getPresentation().setVisible(true);
- e.getPresentation().setEnabled(true);
- }
-
- public void actionPerformed(final AnActionEvent e) {
- runLocalTerminal(e);
- }
-
- public void runLocalTerminal(AnActionEvent event) {
- final Project project = event.getData(CommonDataKeys.PROJECT);
- runLocalTerminal(project);
- }
-
- public static void runLocalTerminal(final Project project) {
- ToolWindow terminal = ToolWindowManager.getInstance(project).getToolWindow("Terminal");
- if (terminal.isActive()) {
- TerminalView.getInstance(project).openLocalSession(project, terminal);
- }
- terminal.activate(new Runnable() {
- @Override
- public void run() {
-
- }
- }, true);
- }
-
- @NotNull
- public static LocalTerminalDirectRunner createTerminalRunner(Project project) {
- return new LocalTerminalDirectRunner(project);
- }
-}
diff --git a/plugins/terminal/src/org/jetbrains/plugins/terminal/TerminalView.java b/plugins/terminal/src/org/jetbrains/plugins/terminal/TerminalView.java
index 14b992a7c143..32b7c9b13c06 100644
--- a/plugins/terminal/src/org/jetbrains/plugins/terminal/TerminalView.java
+++ b/plugins/terminal/src/org/jetbrains/plugins/terminal/TerminalView.java
@@ -1,7 +1,6 @@
package org.jetbrains.plugins.terminal;
import com.intellij.icons.AllIcons;
-import com.intellij.notification.EventLog;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.project.DumbAwareAction;
@@ -23,7 +22,6 @@ import com.intellij.util.ui.UIUtil;
import com.jediterm.terminal.ui.JediTermWidget;
import com.jediterm.terminal.ui.TabbedTerminalWidget;
import com.jediterm.terminal.ui.TerminalWidget;
-import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.terminal.vfs.TerminalSessionVirtualFileImpl;
@@ -54,7 +52,7 @@ public class TerminalView {
public void initTerminal(final ToolWindow toolWindow) {
- LocalTerminalDirectRunner terminalRunner = OpenLocalTerminalAction.createTerminalRunner(myProject);
+ LocalTerminalDirectRunner terminalRunner = LocalTerminalDirectRunner.createTerminalRunner(myProject);
toolWindow.setToHideOnEmptyContent(true);
@@ -99,14 +97,9 @@ public class TerminalView {
}
}
- private Content createTerminalInContentPanel(@Nullable LocalTerminalDirectRunner terminalRunner,
+ private Content createTerminalInContentPanel(@NotNull AbstractTerminalRunner terminalRunner,
final @NotNull ToolWindow toolWindow) {
- SimpleToolWindowPanel panel = new SimpleToolWindowPanel(false, true) {
- @Override
- public Object getData(@NonNls String dataId) {
- return PlatformDataKeys.HELP_ID.is(dataId) ? EventLog.HELP_ID : super.getData(dataId);
- }
- };
+ SimpleToolWindowPanel panel = new SimpleToolWindowPanel(false, true);
final Content content = ContentFactory.SERVICE.getInstance().createContent(panel, "", false);
content.setCloseable(true);
@@ -162,14 +155,14 @@ public class TerminalView {
}
public void openLocalSession(Project project, ToolWindow terminal) {
- LocalTerminalDirectRunner terminalRunner = OpenLocalTerminalAction.createTerminalRunner(project);
+ LocalTerminalDirectRunner terminalRunner = LocalTerminalDirectRunner.createTerminalRunner(project);
openSession(terminal, terminalRunner);
}
private void openSession(@NotNull ToolWindow toolWindow, @NotNull AbstractTerminalRunner terminalRunner) {
if (myTerminalWidget == null) {
toolWindow.getContentManager().removeAllContents(true);
- final Content content = createTerminalInContentPanel(null, toolWindow);
+ final Content content = createTerminalInContentPanel(terminalRunner, toolWindow);
toolWindow.getContentManager().addContent(content);
}
else {
@@ -184,7 +177,7 @@ public class TerminalView {
}, true);
}
- private ActionToolbar createToolbar(@Nullable final LocalTerminalDirectRunner terminalRunner,
+ private ActionToolbar createToolbar(@Nullable final AbstractTerminalRunner terminalRunner,
@NotNull final JBTabbedTerminalWidget terminal, @NotNull ToolWindow toolWindow) {
DefaultActionGroup group = new DefaultActionGroup();
@@ -215,10 +208,10 @@ public class TerminalView {
private static class NewSession extends DumbAwareAction {
- private final LocalTerminalDirectRunner myTerminalRunner;
+ private final AbstractTerminalRunner myTerminalRunner;
private final TerminalWidget myTerminal;
- public NewSession(@NotNull LocalTerminalDirectRunner terminalRunner, @NotNull TerminalWidget terminal) {
+ public NewSession(@NotNull AbstractTerminalRunner terminalRunner, @NotNull TerminalWidget terminal) {
super("New Session", "Create New Terminal Session", AllIcons.General.Add);
myTerminalRunner = terminalRunner;
myTerminal = terminal;
diff --git a/plugins/testng/src/com/theoryinpractice/testng/configuration/SearchingForTestsTask.java b/plugins/testng/src/com/theoryinpractice/testng/configuration/SearchingForTestsTask.java
index 639236152acb..413aceebf8d4 100644
--- a/plugins/testng/src/com/theoryinpractice/testng/configuration/SearchingForTestsTask.java
+++ b/plugins/testng/src/com/theoryinpractice/testng/configuration/SearchingForTestsTask.java
@@ -122,7 +122,7 @@ public class SearchingForTestsTask extends Task.Backgroundable {
writeTempFile();
finish();
- if (!Registry.is("testng_sm_runner", false)) myClient.startListening(myConfig);
+ if (!Registry.is("testng_sm_runner")) myClient.startListening(myConfig);
}
@Override
diff --git a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGRunnableState.java b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGRunnableState.java
index be953950ccb8..21afb568e912 100644
--- a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGRunnableState.java
+++ b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGRunnableState.java
@@ -122,7 +122,7 @@ public class TestNGRunnableState extends JavaCommandLineState {
@Override
public ExecutionResult execute(@NotNull final Executor executor, @NotNull final ProgramRunner runner) throws ExecutionException {
- final boolean smRunner = Registry.is("testng_sm_runner", false);
+ final boolean smRunner = Registry.is("testng_sm_runner");
if (smRunner) {
return startSMRunner(executor);
}
diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/PsiPropertiesProvider.java b/plugins/ui-designer/src/com/intellij/uiDesigner/PsiPropertiesProvider.java
index 5b8518f0d70b..91b75c91b619 100644
--- a/plugins/ui-designer/src/com/intellij/uiDesigner/PsiPropertiesProvider.java
+++ b/plugins/ui-designer/src/com/intellij/uiDesigner/PsiPropertiesProvider.java
@@ -16,6 +16,7 @@
package com.intellij.uiDesigner;
import com.intellij.openapi.module.Module;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.ClassUtil;
@@ -74,7 +75,8 @@ public final class PsiPropertiesProvider implements PropertiesProvider {
}
final PsiType type = getter.getReturnType();
- final String propertyClassName = type.getCanonicalText();
+ String propertyClassName =
+ StringUtil.defaultIfEmpty(StringUtil.substringBefore(type.getCanonicalText(), "<"), type.getCanonicalText());
LwIntrospectedProperty property = CompiledClassPropertiesProvider.propertyFromClassName(propertyClassName, name);
if (property == null) {
diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/editors/ColorEditor.java b/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/editors/ColorEditor.java
index 7e6b94dc4784..96ddb74494d1 100644
--- a/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/editors/ColorEditor.java
+++ b/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/editors/ColorEditor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,33 +15,19 @@
*/
package com.intellij.uiDesigner.propertyInspector.editors;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
-import com.intellij.ui.ListSpeedSearch;
-import com.intellij.ui.ScrollPaneFactory;
-import com.intellij.ui.components.JBList;
+import com.intellij.ui.ColorChooser;
+import com.intellij.ui.JBColor;
import com.intellij.uiDesigner.UIDesignerBundle;
import com.intellij.uiDesigner.lw.ColorDescriptor;
import com.intellij.uiDesigner.propertyInspector.InplaceContext;
import com.intellij.uiDesigner.propertyInspector.PropertyEditor;
-import com.intellij.uiDesigner.propertyInspector.renderers.ColorRenderer;
import com.intellij.uiDesigner.radComponents.RadComponent;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
import javax.swing.*;
-import javax.swing.colorchooser.AbstractColorChooserPanel;
-import javax.swing.event.ListSelectionEvent;
-import javax.swing.event.ListSelectionListener;
-import javax.swing.plaf.ColorChooserUI;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
-import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
-import java.util.*;
-import java.util.List;
/**
* @author yole
@@ -50,7 +36,6 @@ public class ColorEditor extends PropertyEditor<ColorDescriptor> {
private final String myPropertyName;
private final TextFieldWithBrowseButton myTextField = new TextFieldWithBrowseButton();
private ColorDescriptor myValue;
- private Project myProject;
public ColorEditor(String propertyName) {
myPropertyName = propertyName;
@@ -58,11 +43,10 @@ public class ColorEditor extends PropertyEditor<ColorDescriptor> {
myTextField.getTextField().setEditable(false);
myTextField.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
- MyColorChooserDialog dialog = new MyColorChooserDialog(myProject);
- dialog.setSelectedValue(myValue);
- dialog.show();
- if (dialog.getExitCode() == DialogWrapper.OK_EXIT_CODE) {
- myValue = dialog.getSelectedValue();
+ String title = UIDesignerBundle.message("color.chooser.title", myPropertyName);
+ Color color = ColorChooser.chooseColor(myTextField, title , myValue.getColor());
+ if (color != null) {
+ myValue = new ColorDescriptor(color);
updateTextField();
}
}
@@ -74,8 +58,7 @@ public class ColorEditor extends PropertyEditor<ColorDescriptor> {
}
public JComponent getComponent(RadComponent component, ColorDescriptor value, InplaceContext inplaceContext) {
- myValue = value != null ? value : new ColorDescriptor(new Color(0));
- myProject = component.getProject();
+ myValue = value != null ? value : new ColorDescriptor(JBColor.BLACK);
updateTextField();
return myTextField;
}
@@ -87,174 +70,4 @@ public class ColorEditor extends PropertyEditor<ColorDescriptor> {
public void updateUI() {
SwingUtilities.updateComponentTreeUI(myTextField);
}
-
- private static class ColorDescriptorWrapper extends Color {
- private final ColorDescriptor myDescriptor;
-
- public ColorDescriptorWrapper(ColorDescriptor descriptor) {
- super(descriptor.getResolvedColor() == null ? 0 : descriptor.getResolvedColor().getRGB());
- myDescriptor = descriptor;
- }
-
- public ColorDescriptor getDescriptor() {
- return myDescriptor;
- }
- }
-
- private class MyColorChooserDialog extends DialogWrapper {
- private JColorChooser myColorChooser;
- private MyDescriptorChooserPanel mySwingChooserPanel;
- private MyDescriptorChooserPanel mySystemChooserPanel;
- private MyDescriptorChooserPanel myAWTChooserPanel;
-
- public MyColorChooserDialog(Project project) {
- super(project, false);
- setTitle(UIDesignerBundle.message("color.chooser.title", myPropertyName));
- init();
- }
-
- protected JComponent createCenterPanel() {
- myColorChooser = new JColorChooser();
- mySwingChooserPanel = new MyDescriptorChooserPanel(UIDesignerBundle.message("color.chooser.swing.palette"), collectSwingColorDescriptors());
- myColorChooser.addChooserPanel(mySwingChooserPanel);
- mySystemChooserPanel = new MyDescriptorChooserPanel(UIDesignerBundle.message("color.chooser.system.palette"),
- collectColorFields(SystemColor.class, true));
- myColorChooser.addChooserPanel(mySystemChooserPanel);
- myAWTChooserPanel = new MyDescriptorChooserPanel(UIDesignerBundle.message("color.chooser.awt.palette"),
- collectColorFields(Color.class, false));
- myColorChooser.addChooserPanel(myAWTChooserPanel);
- return myColorChooser;
- }
-
- private void selectTabForColor(@Nullable final ColorDescriptor value) {
- String tabName;
-
- if (value == null || value.getSwingColor() != null) {
- tabName = mySwingChooserPanel.getDisplayName();
- }
- else if (value.getSystemColor() != null) {
- tabName = mySystemChooserPanel.getDisplayName();
- }
- else if (value.getAWTColor() != null) {
- tabName = myAWTChooserPanel.getDisplayName();
- }
- else {
- return;
- }
-
- final ColorChooserUI ui = myColorChooser.getUI();
- try {
- final Field field = ui.getClass().getDeclaredField("tabbedPane");
- field.setAccessible(true);
- JTabbedPane tabbedPane = (JTabbedPane) field.get(ui);
- for(int i=0; i<tabbedPane.getTabCount(); i++) {
- if (tabbedPane.getTitleAt(i).equals(tabName)) {
- tabbedPane.setSelectedIndex(i);
- break;
- }
- }
- }
- catch (NoSuchFieldException e) {
- // ignore
- }
- catch (IllegalAccessException e) {
- // ignore
- }
- }
-
- private List<ColorDescriptor> collectSwingColorDescriptors() {
- ArrayList<ColorDescriptor> result = new ArrayList<ColorDescriptor>();
- UIDefaults defaults = UIManager.getDefaults();
- Enumeration e = defaults.keys ();
- while(e.hasMoreElements()) {
- Object key = e.nextElement();
- Object value = defaults.get(key);
- if (key instanceof String && value instanceof Color) {
- result.add(ColorDescriptor.fromSwingColor((String) key));
- }
- }
- return result;
- }
-
- private List<ColorDescriptor> collectColorFields(final Class aClass, final boolean isSystem) {
- ArrayList<ColorDescriptor> result = new ArrayList<ColorDescriptor>();
- Field[] colorFields = aClass.getDeclaredFields();
- for(Field field: colorFields) {
- if ((field.getModifiers() & Modifier.STATIC) != 0 &&
- Color.class.isAssignableFrom(field.getType()) &&
- Character.isLowerCase(field.getName().charAt(0))) {
- final ColorDescriptor color = isSystem
- ? ColorDescriptor.fromSystemColor(field.getName())
- : ColorDescriptor.fromAWTColor(field.getName());
- result.add(color);
- }
- }
- return result;
- }
-
- public void setSelectedValue(@NotNull final ColorDescriptor value) {
- myColorChooser.setColor(new ColorDescriptorWrapper(value));
- selectTabForColor(value);
- }
-
- public ColorDescriptor getSelectedValue() {
- final Color color = myColorChooser.getColor();
- if (color instanceof ColorDescriptorWrapper) {
- return ((ColorDescriptorWrapper) color).getDescriptor();
- }
- return new ColorDescriptor(color);
- }
- }
-
- private static class MyDescriptorChooserPanel extends AbstractColorChooserPanel {
- private final String myDisplayName;
- private final ColorDescriptor[] myColorDescriptors;
- private JList myDescriptorList;
-
- public MyDescriptorChooserPanel(final String displayName, List<ColorDescriptor> colorDescriptorList) {
- myDisplayName = displayName;
-
- Collections.sort(colorDescriptorList, new Comparator<ColorDescriptor>() {
- public int compare(final ColorDescriptor o1, final ColorDescriptor o2) {
- return o1.toString().compareTo(o2.toString());
- }
- });
-
- myColorDescriptors = colorDescriptorList.toArray(new ColorDescriptor[colorDescriptorList.size()]);
- }
-
- public void updateChooser() {
- myDescriptorList.setSelectedValue(getColorFromModel(), true);
- }
-
- protected void buildChooser() {
- setLayout(new BorderLayout());
- myDescriptorList = new JBList(myColorDescriptors);
- myDescriptorList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
- myDescriptorList.setVisibleRowCount(15);
- myDescriptorList.setCellRenderer(new ColorRenderer());
- myDescriptorList.addListSelectionListener(new ListSelectionListener() {
- public void valueChanged(ListSelectionEvent e) {
- ColorDescriptor descriptor = (ColorDescriptor)myDescriptorList.getSelectedValue();
- getColorSelectionModel().setSelectedColor(new ColorDescriptorWrapper(descriptor));
- }
- });
- new ListSpeedSearch(myDescriptorList);
- add(ScrollPaneFactory.createScrollPane(myDescriptorList), BorderLayout.CENTER);
- }
-
- public String getDisplayName() {
- return myDisplayName;
- }
-
- @Nullable
- public Icon getSmallDisplayIcon() {
- return null;
- }
-
- @Nullable
- public Icon getLargeDisplayIcon() {
- return null;
- }
- }
}
diff --git a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/associations/impl/FileAssociationsConfigurable.java b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/associations/impl/FileAssociationsConfigurable.java
index 0313fb41ded6..dc8c73771a46 100644
--- a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/associations/impl/FileAssociationsConfigurable.java
+++ b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/associations/impl/FileAssociationsConfigurable.java
@@ -20,14 +20,17 @@ import com.intellij.ide.util.treeView.TreeState;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.components.*;
-import com.intellij.openapi.options.*;
+import com.intellij.openapi.options.Configurable;
+import com.intellij.openapi.options.ConfigurationException;
+import com.intellij.openapi.options.SearchableConfigurable;
+import com.intellij.openapi.options.ShowSettingsUtil;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
-public class FileAssociationsConfigurable implements SearchableConfigurable, NonDefaultProjectConfigurable, Configurable.NoScroll {
+public class FileAssociationsConfigurable implements SearchableConfigurable, Configurable.NoScroll {
private final Project myProject;
private final UIState myState;
private AssociationsEditor myEditor;
@@ -37,17 +40,21 @@ public class FileAssociationsConfigurable implements SearchableConfigurable, Non
myState = ServiceManager.getService(project, UIState.class);
}
+ @Override
public String getDisplayName() {
return "XSLT File Associations";
}
+ @Override
@NotNull
public String getHelpTopic() {
return "xslt.associations";
}
+ @Override
public JComponent createComponent() {
myEditor = new ReadAction<AssociationsEditor>() {
+ @Override
protected void run(Result<AssociationsEditor> result) throws Throwable {
result.setResult(new AssociationsEditor(myProject, myState.state));
}
@@ -55,19 +62,23 @@ public class FileAssociationsConfigurable implements SearchableConfigurable, Non
return myEditor.getComponent();
}
+ @Override
public synchronized boolean isModified() {
return myEditor != null && myEditor.isModified();
}
+ @Override
public void apply() throws ConfigurationException {
myEditor.apply();
DaemonCodeAnalyzer.getInstance(myProject).restart();
}
+ @Override
public void reset() {
myEditor.reset();
}
+ @Override
public synchronized void disposeUIResources() {
if (myEditor != null) {
myState.state = myEditor.getState();
@@ -84,6 +95,7 @@ public class FileAssociationsConfigurable implements SearchableConfigurable, Non
final FileAssociationsConfigurable instance = new FileAssociationsConfigurable(project);
ShowSettingsUtil.getInstance().editConfigurable(project, instance, new Runnable() {
+ @Override
public void run() {
final AssociationsEditor editor = instance.getEditor();
if (file != null) {
@@ -99,20 +111,24 @@ public class FileAssociationsConfigurable implements SearchableConfigurable, Non
public static class UIState implements PersistentStateComponent<TreeState> {
private TreeState state;
+ @Override
public TreeState getState() {
return state != null ? state : new TreeState();
}
+ @Override
public void loadState(TreeState state) {
this.state = state;
}
}
+ @Override
@NotNull
public String getId() {
return getHelpTopic();
}
+ @Override
public Runnable enableSearch(final String option) {
return null;
}
diff --git a/python/IntelliLang-python/IntelliLang-python.iml b/python/IntelliLang-python/IntelliLang-python.iml
index a877c73afd91..49ab883c711d 100644
--- a/python/IntelliLang-python/IntelliLang-python.iml
+++ b/python/IntelliLang-python/IntelliLang-python.iml
@@ -4,6 +4,7 @@
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/resources" type="java-resource" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
diff --git a/python/IntelliLang-python/src/META-INF/intellilang-python-support.xml b/python/IntelliLang-python/resources/META-INF/intellilang-python-support.xml
index 44bab2c91b05..c96f0b7f2b3a 100644
--- a/python/IntelliLang-python/src/META-INF/intellilang-python-support.xml
+++ b/python/IntelliLang-python/resources/META-INF/intellilang-python-support.xml
@@ -3,7 +3,7 @@
<idea-plugin version="2">
<extensions defaultExtensionNs="org.intellij.intelliLang">
<languageSupport implementation="com.jetbrains.python.intelliLang.PyLanguageInjectionSupport"/>
- <injectionConfig config="pyInjections.xml"/>
+ <injectionConfig config="resources/pyInjections.xml"/>
</extensions>
<extensions defaultExtensionNs="com.intellij">
<patterns.patternClass className="com.jetbrains.python.patterns.PythonPatterns" alias="py"/>
diff --git a/python/IntelliLang-python/resources/META-INF/plugin.xml b/python/IntelliLang-python/resources/META-INF/plugin.xml
new file mode 100644
index 000000000000..6b2717a6e7b1
--- /dev/null
+++ b/python/IntelliLang-python/resources/META-INF/plugin.xml
@@ -0,0 +1,16 @@
+<idea-plugin version="2" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <name>Python IntelliLang</name>
+ <id>org.jetbrains.plugins.python-intelliLang</id>
+ <version>VERSION</version>
+ <description>This plugin enables language injections</description>
+ <vendor>JetBrains</vendor>
+
+ <depends>com.intellij.modules.python</depends>
+ <depends>org.intellij.intelliLang</depends>
+
+ <xi:include href="/META-INF/intellilang-python-support.xml" xpointer="xpointer(/idea-plugin/*)"/>
+
+ <extensions defaultExtensionNs="com.intellij">
+ <errorHandler implementation="com.intellij.diagnostic.ITNReporter"/>
+ </extensions>
+</idea-plugin>
diff --git a/python/IntelliLang-python/src/com/jetbrains/python/intelliLang/PyLanguageInjectionSupport.java b/python/IntelliLang-python/src/com/jetbrains/python/intelliLang/PyLanguageInjectionSupport.java
index dee16d27646f..70768781ee38 100644
--- a/python/IntelliLang-python/src/com/jetbrains/python/intelliLang/PyLanguageInjectionSupport.java
+++ b/python/IntelliLang-python/src/com/jetbrains/python/intelliLang/PyLanguageInjectionSupport.java
@@ -58,6 +58,6 @@ public class PyLanguageInjectionSupport extends AbstractLanguageInjectionSupport
@Nullable
@Override
public BaseInjection findCommentInjection(@NotNull PsiElement host, @Nullable Ref<PsiElement> commentRef) {
- return null;
+ return super.findCommentInjection(host, commentRef);
}
}
diff --git a/python/IntelliLang-python/src/pyInjections.xml b/python/IntelliLang-python/src/resources/pyInjections.xml
index fc9207aeb8f9..fc9207aeb8f9 100644
--- a/python/IntelliLang-python/src/pyInjections.xml
+++ b/python/IntelliLang-python/src/resources/pyInjections.xml
diff --git a/python/build/paths.nsi b/python/build/paths.nsi
index cf4f769c5f9f..6baf09644c8b 100644
--- a/python/build/paths.nsi
+++ b/python/build/paths.nsi
@@ -2,5 +2,5 @@
!define IMAGES_LOCATION ${COMMUNITY_DIR}\python\build\resources
;!define LICENSE_FILE ${BASE_DIR}\python\license\PyCharm_Preview_License
!define PRODUCT_PROPERTIES_FILE ${BASE_DIR}\out\pycharmCE\layout\bin\idea.properties
-!define PRODUCT_VM_OPTIONS_NAME pycharm.exe.vmoptions
+!define PRODUCT_VM_OPTIONS_NAME pycharm*.exe.vmoptions
!define PRODUCT_VM_OPTIONS_FILE ${BASE_DIR}\out\pycharmCE\win\bin\${PRODUCT_VM_OPTIONS_NAME}
diff --git a/python/build/pycharm64_community_launcher.properties b/python/build/pycharm64_community_launcher.properties
new file mode 100644
index 000000000000..ff7b0ffa11c3
--- /dev/null
+++ b/python/build/pycharm64_community_launcher.properties
@@ -0,0 +1,3 @@
+IDS_JDK_ENV_VAR=PYCHARM_JDK_64
+IDS_JDK_ONLY=true
+IDS_VM_OPTIONS=-Didea.platform.prefix=PyCharmCore -Didea.no.jre.check=true -Didea.paths.selector=__PRODUCT_PATHS_SELECTOR__
diff --git a/python/build/pycharm_community_build.gant b/python/build/pycharm_community_build.gant
index 3b793ec4498f..cfaaf33f3bd0 100644
--- a/python/build/pycharm_community_build.gant
+++ b/python/build/pycharm_community_build.gant
@@ -162,11 +162,14 @@ public layoutCommunity(String classesPath, Set usedJars) {
ant.echo(message: "PC-${buildNumber}", file: "${paths.distAll}/build.txt")
def launcher = "${paths.distWin}/bin/pycharm.exe"
+ def launcher64 = "${paths.distWin}/bin/pycharm64.exe"
List resourcePaths = ["$ch/community-resources/src",
"$ch/platform/icons/src",
"$pythonCommunityHome/resources"]
buildWinLauncher("$ch", "$ch/bin/WinLauncher/WinLauncher.exe", launcher,
appInfo, "$pythonCommunityHome/build/pycharm_community_launcher.properties", system_selector, resourcePaths)
+ buildWinLauncher("$ch", "$ch/bin/WinLauncher/WinLauncher64.exe", launcher64,
+ appInfo, "$pythonCommunityHome/build/pycharm64_community_launcher.properties", system_selector, resourcePaths)
buildWinZip("${paths.artifacts}/pycharmPC-${buildNumber}.zip", [paths.distAll, paths.distWin])
@@ -328,8 +331,7 @@ private layoutWin(Map args, String target) {
}
winScripts(target, ch, "pycharm.bat", args)
- winVMOptions(target, null, "pycharm.exe")
-
+ winVMOptions(target, null, "pycharm.exe", "pycharm64.exe")
ant.copy(file: "$home/python/help/pycharmhelp.jar", todir: "$target/help", failonerror: false)
}
diff --git a/python/edu/build/DMG_background.png b/python/edu/build/DMG_background.png
new file mode 100644
index 000000000000..3b5a4b2c1b26
--- /dev/null
+++ b/python/edu/build/DMG_background.png
Binary files differ
diff --git a/python/edu/build/build.xml b/python/edu/build/build.xml
new file mode 100644
index 000000000000..913237c81f27
--- /dev/null
+++ b/python/edu/build/build.xml
@@ -0,0 +1,46 @@
+<project name="PyCharm Educational Edition" default="all">
+ <property name="project.home" value="${basedir}/../../.."/>
+ <property name="python.home" value="${basedir}"/>
+ <property name="out.dir" value="${project.home}/out"/>
+ <property name="tmp.dir" value="${project.home}/out/tmp"/>
+
+ <target name="cleanup">
+ <delete dir="${out.dir}" failonerror="false"/>
+ </target>
+
+ <target name="init">
+ <mkdir dir="${out.dir}"/>
+ <mkdir dir="${tmp.dir}"/>
+ </target>
+
+ <macrodef name="call_gant">
+ <attribute name="script" />
+ <sequential>
+ <java failonerror="true" jar="${project.home}/lib/ant/lib/ant-launcher.jar" fork="true">
+ <jvmarg line="-Xmx612m -XX:MaxPermSize=152m -Didea.build.number=${idea.build.number} &quot;-DideaPath=${idea.path}&quot;"/>
+ <sysproperty key="java.awt.headless" value="true"/>
+ <arg line="&quot;-Dgant.script=@{script}&quot;"/>
+ <arg line="&quot;-Dteamcity.build.tempDir=${tmp.dir}&quot;"/>
+ <arg line="&quot;-Didea.build.number=${idea.build.number}&quot;"/>
+ <arg line="&quot;-Didea.test.group=ALL_EXCLUDE_DEFINED&quot;"/>
+ <arg value="-f"/>
+ <arg value="${project.home}/build/gant.xml"/>
+ </java>
+ </sequential>
+ </macrodef>
+
+ <target name="build" depends="init">
+ <call_gant script="${python.home}/pycharm_edu_build.gant"/>
+ </target>
+
+ <!--<target name="plugin" depends="init">-->
+ <!--<call_gant script="${python.home}/build/python_plugin_build.gant"/>-->
+ <!--</target>-->
+ <!--
+ <target name="test" depends="init">
+ <call_gant script="${project.home}/build/scripts/tests.gant"/>
+ </target>
+ -->
+
+ <target name="all" depends="cleanup,build"/>
+</project>
diff --git a/python/edu/build/paths.nsi b/python/edu/build/paths.nsi
new file mode 100644
index 000000000000..910f2b3555b7
--- /dev/null
+++ b/python/edu/build/paths.nsi
@@ -0,0 +1,6 @@
+; Installer images
+!define IMAGES_LOCATION ${COMMUNITY_DIR}\python\build\resources
+;!define LICENSE_FILE ${BASE_DIR}\python\license\PyCharm_Preview_License
+!define PRODUCT_PROPERTIES_FILE ${BASE_DIR}\out\pycharmEDU\layout\bin\idea.properties
+!define PRODUCT_VM_OPTIONS_NAME pycharm.exe.vmoptions
+!define PRODUCT_VM_OPTIONS_FILE ${BASE_DIR}\out\pycharmEDU\win\bin\${PRODUCT_VM_OPTIONS_NAME}
diff --git a/python/edu/build/plugin-list.txt b/python/edu/build/plugin-list.txt
new file mode 100644
index 000000000000..ceaa60895918
--- /dev/null
+++ b/python/edu/build/plugin-list.txt
@@ -0,0 +1,11 @@
+svn4idea
+git4idea
+remote-servers-git
+github
+terminal
+IntelliLang
+IntelliLang-xml
+IntelliLang-js
+IntelliLang-python
+rest
+python-rest
diff --git a/python/edu/build/pycharm_edu_build.gant b/python/edu/build/pycharm_edu_build.gant
new file mode 100644
index 000000000000..8c857c159874
--- /dev/null
+++ b/python/edu/build/pycharm_edu_build.gant
@@ -0,0 +1,393 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import org.jetbrains.jps.LayoutInfo
+
+import static org.jetbrains.jps.idea.IdeaProjectLoader.guessHome
+
+setProperty("home", guessHome(this as Script))
+
+includeTargets << new File("${guessHome(this as Script)}/build/scripts/utils.gant")
+// signMacZip locates in ultimate_utils.gant
+ includeTargets << new File("${guessHome(this)}/ultimate/build/scripts/ultimate_utils.gant")
+includeTargets << new File("${guessHome(this)}/build/scripts/libLicenses.gant")
+
+requireProperty("buildNumber", requireProperty("build.number", snapshot))
+
+setProperty("ch", "$home")
+setProperty("pythonCommunityHome", "$ch/python")
+setProperty("pythonEduHome", "$ch/python/edu")
+
+// load ApplicationInfo.xml properties
+ant.xmlproperty(file: "$pythonEduHome/resources/idea/PyCharmEduApplicationInfo.xml", collapseAttributes: "true")
+
+setProperty("system_selector", "PyCharm${p("component.version.major")}0")
+setProperty("dryRun", false)
+setProperty("jdk16", guessJdk())
+
+//modules to compile
+setProperty("pluginFilter", new File("$pythonEduHome/build/plugin-list.txt").readLines())
+
+private List<String> pycharmPlatformApiModules() {
+ return [platformApiModules, "dom-openapi"].flatten()
+}
+
+
+private List pycharmImplementationModules() { //modules to put into pycharm.jar
+ return [platformImplementationModules, "dom-impl", "python-community", "python-ide-community", "python-educational", "python-openapi", "python-psi-api",
+ "platform-main"].flatten()
+}
+
+private List modules() {
+ return [
+ "python-pydev", "colorSchemes", pycharmPlatformApiModules(), pycharmImplementationModules(), pluginFilter
+ ].flatten()
+}
+
+private List approvedJars() {
+ def normalizedHome = ch.replace('\\', '/')
+ def normalizedPythonHome = pythonCommunityHome.replace('\\', '/')
+ return ["$normalizedHome/lib/", "$normalizedPythonHome/lib/", "$normalizedHome/xml/relaxng/lib/"]
+}
+
+class Paths {
+ final sandbox
+ final distAll
+ final distWin
+ final distMac
+ final distUnix
+ final artifacts
+ final ideaSystem
+ final ideaConfig
+
+ def Paths(String home) {
+ sandbox = "$home/out/pycharmEDU"
+
+ distAll = "$sandbox/layout"
+ distWin = "$sandbox/win"
+ distMac = "$sandbox/mac"
+ distUnix = "$sandbox/unix"
+ artifacts = "$sandbox/artifacts"
+
+ ideaSystem = "$sandbox/system"
+ ideaConfig = "$sandbox/config"
+ }
+}
+
+setProperty("paths", new Paths(home))
+setProperty("buildName", "PE-$buildNumber")
+
+target('default': "Build artifacts") {
+
+ loadProject()
+
+ projectBuilder.stage("Cleaning up sandbox folder")
+
+ projectBuilder.targetFolder = "${paths.sandbox}/classes"
+ projectBuilder.dryRun = dryRun
+
+ if (!dryRun) {
+ forceDelete(paths.sandbox)
+ ant.mkdir(dir: paths.sandbox)
+ }
+
+ ant.tstamp() {
+ format(property: "todayYear", pattern: "yyyy")
+ }
+
+ ant.patternset(id: "resources.included") {
+ include(name: "**/*.properties")
+ include(name: "fileTemplates/**/*")
+ include(name: "inspectionDescriptions/**/*")
+ include(name: "intentionDescriptions/**/*")
+ include(name: "tips/**/*")
+ include(name: "search/**/*")
+ }
+
+ ant.patternset(id: "resources.excluded") {
+ exclude(name: "**/*.properties")
+ exclude(name: "fileTemplates/**/*")
+ exclude(name: "fileTemplates")
+ exclude(name: "inspectionDescriptions/**/*")
+ exclude(name: "inspectionDescriptions")
+ exclude(name: "intentionDescriptions/**/*")
+ exclude(name: "intentionDescriptions")
+ exclude(name: "tips/**/*")
+ exclude(name: "tips")
+ }
+
+ zipSources(home, paths.artifacts)
+
+ def usedJars = buildModulesAndCollectUsedJars(modules(), approvedJars(), ["/ant/"])
+
+ layoutEducational("${paths.sandbox}/classes/production", usedJars)
+
+
+ //buildNSIS([paths.distAll, paths.distWin],
+ // "${pythonEduHome}/build/strings.nsi", "${pythonEduHome}/build/paths.nsi",
+ // "pycharm", false, true, ".py", system_selector)
+
+ def extraArgs = ["build.code": "pycharmEDU-${buildNumber}", "build.number": "PE-$buildNumber", "artifacts.path": "${paths.artifacts}"]
+ signMacZip("pycharm", extraArgs)
+ buildDmg("pycharm", "${pythonEduHome}/build/DMG_background.png", extraArgs)
+
+}
+
+public layoutEducational(String classesPath, Set usedJars) {
+ setProperty("pluginFilter", new File("$pythonEduHome/build/plugin-list.txt").readLines())
+
+ if (usedJars == null) {
+ usedJars = collectUsedJars(modules(), approvedJars(), ["/ant/"], null)
+ }
+
+ def appInfo = appInfoFile(classesPath)
+ def paths = new Paths(home)
+ buildSearchableOptions("${projectBuilder.moduleOutput(findModule("platform-resources"))}/search", [], {
+ projectBuilder.moduleRuntimeClasspath(findModule("main_pycharm_edu"), false).each {
+ ant.pathelement(location: it)
+ }
+ }, "-Didea.platform.prefix=PyCharmEdu -Didea.no.jre.check=true")
+
+ if (!dryRun) {
+ wireBuildDate("PE-${buildNumber}", appInfo)
+ }
+
+ Map args = [
+ buildNumber: "PE-${buildNumber}",
+ system_selector: system_selector,
+ ide_jvm_args: "-Didea.platform.prefix=PyCharmEdu -Didea.no.jre.check=true"]
+
+ LayoutInfo layoutInfo = layoutFull(args, paths.distAll, usedJars)
+ generateLicensesTable("$paths.artifacts/third-party-libraries.txt", layoutInfo.usedModules);
+
+ layoutWin(args, paths.distWin)
+ layoutUnix(args, paths.distUnix)
+ layoutMac(args, paths.distMac)
+
+ ant.echo(message: "PE-${buildNumber}", file: "${paths.distAll}/build.txt")
+
+ def launcher = "${paths.distWin}/bin/pycharm.exe"
+ List resourcePaths = ["$ch/community-resources/src",
+ "$ch/platform/icons/src",
+ "$pythonEduHome/resources"]
+ buildWinLauncher("$ch", "$ch/bin/WinLauncher/WinLauncher.exe", launcher,
+ appInfo, "$pythonEduHome/build/pycharm_edu_launcher.properties", system_selector, resourcePaths)
+
+ buildWinZip("${paths.artifacts}/pycharmPE-${buildNumber}.zip", [paths.distAll, paths.distWin])
+
+ String tarRoot = isEap() ? "pycharm-edu-$buildNumber" : "pycharm-edu-${p("component.version.major")}.${p("component.version.minor")}"
+ buildTarGz(tarRoot, "$paths.artifacts/pycharmPE-${buildNumber}.tar", [paths.distAll, paths.distUnix])
+
+ String macAppRoot = isEap() ? "PyCharm EDU ${p("component.version.major")}.${p("component.version.minor")} EAP.app/Contents" : "PyCharm EDU.app/Contents"
+ buildMacZip(macAppRoot, "${paths.artifacts}/pycharmEDU-${buildNumber}.sit", [paths.distAll], paths.distMac)
+}
+
+private layoutPlugins(layouts) {
+ dir("plugins") {
+ layouts.layoutPlugin("rest")
+ layouts.layoutPlugin("python-rest")
+ }
+
+ layouts.layoutCommunityPlugins(ch)
+}
+
+private String appInfoFile(String classesPath) {
+ return "$classesPath/python-educational/idea/PyCharmEduApplicationInfo.xml"
+}
+
+private layoutFull(Map args, String target, Set usedJars) {
+ def openapiModules = pycharmPlatformApiModules()
+ def superLayouts = includeFile("$ch/build/scripts/layouts.gant")
+
+ reassignAltClickToMultipleCarets("$ch")
+
+ def result = layout(target) {
+ dir("lib") {
+ jar("util.jar") {
+ module("util")
+ module("util-rt")
+ }
+
+ jar("openapi.jar") {
+ openapiModules.each { module it }
+ }
+
+ jar("annotations.jar") { module("annotations") }
+ jar("extensions.jar") { module("extensions") }
+
+ jar("pycharm.jar") {
+ pycharmImplementationModules().each {
+ module(it) {
+ exclude(name: "**/tips/**")
+ }
+ }
+ }
+
+ jar("pycharm-pydev.jar") {
+ module("python-pydev")
+ }
+
+ jar("bootstrap.jar") { module("bootstrap") }
+ jar("resources.jar") {
+ module("platform-resources")
+ module("colorSchemes")
+ }
+
+ jar("forms_rt.jar") {
+ module("forms_rt")
+ }
+
+ //noinspection GroovyAssignabilityCheck
+ jar([name: "resources_en.jar", duplicate: "preserve"]) {
+ // custom resources should go first
+ fileset(dir: "$pythonCommunityHome/resources") {
+ include(name: "**/tips/**")
+ }
+ module("platform-resources-en") {
+ ant.patternset {
+ exclude(name: "tips/images/switcher.png")
+ exclude(name: "tips/images/navigateToFilePath.gif")
+ }
+ }
+ }
+
+ jar("icons.jar") { module("icons") }
+ jar("boot.jar") { module("boot") }
+
+ usedJars.each {
+ fileset(file: it)
+ }
+
+ dir("libpty") {
+ fileset(dir: "$ch/lib/libpty") {
+ exclude(name: "*.txt")
+ }
+ }
+
+ dir("ext") {
+ fileset(dir: "$ch/lib") {
+ include(name: "cglib*.jar")
+ }
+ }
+
+ dir("src") {
+ fileset(dir: "$ch/lib/src") {
+ include(name: "trove4j_changes.txt")
+ include(name: "trove4j_src.jar")
+ }
+
+ jar("pycharm-pydev-src.zip") {
+ fileset(dir: "$pythonCommunityHome/pydevSrc")
+ }
+ jar("pycharm-openapi-src.zip") {
+ fileset(dir: "$pythonCommunityHome/openapi/src")
+ fileset(dir: "$pythonCommunityHome/psi-api/src")
+ }
+ }
+ }
+
+ dir("help") {
+ fileset(dir: "$home/python/help") {
+ include(name: "*.pdf")
+ }
+ }
+
+ dir("helpers") {
+ fileset(dir: "$pythonCommunityHome/helpers")
+ }
+
+ dir("license") {
+ fileset(dir: "$ch/license")
+ fileset(dir: "$ch") {
+ include(name: "LICENSE.txt")
+ include(name: "NOTICE.txt")
+ }
+ }
+
+ layoutPlugins(superLayouts)
+
+ dir("bin") {
+ fileset(dir: "$ch/bin") {
+ exclude(name: "appletviewer.policy")
+ include(name: "*.*")
+ }
+ }
+ }
+ patchPropertiesFile(target, args + [appendices: ["$home/build/conf/ideaJNC.properties"]])
+ return result
+}
+
+private layoutWin(Map args, String target) {
+ layout(target) {
+ dir("bin") {
+ fileset(dir: "$ch/bin/win") {
+ exclude(name: "breakgen*")
+ }
+ }
+
+ dir("skeletons") {
+ fileset(dir: "$pythonCommunityHome/skeletons") {
+ include(name: "skeletons-win*.zip")
+ }
+ }
+ }
+
+ winScripts(target, ch, "pycharm.bat", args)
+ winVMOptions(target, null, "pycharm.exe")
+
+ ant.copy(file: "$home/python/help/pycharmhelp.jar", todir: "$target/help", failonerror: false)
+}
+
+private layoutUnix(Map args, String target) {
+ layout(target) {
+ dir("bin") {
+ fileset(dir: "$ch/bin/linux") {
+ exclude(name: "libbreakgen*")
+ }
+ }
+ }
+
+ ant.copy(file: "$pythonCommunityHome/resources/PyCharmCore128.png", tofile: "$target/bin/pycharm.png")
+
+ unixScripts(target, ch, "pycharm.sh", args)
+ unixVMOptions(target, "pycharm")
+
+ ant.copy(file: "$home/python/help/pycharmhelp.jar", todir: "$target/help", failonerror: false)
+}
+
+private layoutMac(Map _args, String target) {
+ layout(target) {
+ dir("bin") {
+ fileset(dir: "$home/bin") {
+ include(name: "*.jnilib")
+ }
+ }
+
+ dir("skeletons") {
+ fileset(dir: "$pythonCommunityHome/skeletons") {
+ include(name: "skeletons-mac*.zip")
+ }
+ }
+ }
+
+ Map args = new HashMap(_args)
+ args.icns = "$pythonCommunityHome/resources/PyCharmCore.icns"
+ args.bundleIdentifier = "com.jetbrains.pycharm"
+ args.platform_prefix = "PyCharmEdu"
+ args.help_id = "PY"
+ args."idea.properties.path" = "${paths.distAll}/bin/idea.properties"
+ args."idea.properties" = ["idea.no.jre.check": true, "ide.mac.useNativeClipboard": "false"];
+ layoutMacApp(target, ch, args)
+}
diff --git a/python/edu/build/pycharm_edu_launcher.properties b/python/edu/build/pycharm_edu_launcher.properties
new file mode 100644
index 000000000000..d3554685ce3b
--- /dev/null
+++ b/python/edu/build/pycharm_edu_launcher.properties
@@ -0,0 +1,3 @@
+IDS_JDK_ENV_VAR=PYCHARM_JDK
+IDS_JDK_ONLY=false
+IDS_VM_OPTIONS=-Didea.platform.prefix=PyCharmEdu -Didea.no.jre.check=true -Didea.paths.selector=__PRODUCT_PATHS_SELECTOR__
diff --git a/python/edu/build/python-edu-build.iml b/python/edu/build/python-edu-build.iml
new file mode 100644
index 000000000000..bda177851580
--- /dev/null
+++ b/python/edu/build/python-edu-build.iml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$" isTestSource="false" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="library" name="Groovy" level="project" />
+ <orderEntry type="module" module-name="jps-standalone-builder" />
+ </component>
+</module>
+
diff --git a/python/edu/build/resources/PC_instCom.ico b/python/edu/build/resources/PC_instCom.ico
new file mode 100644
index 000000000000..44ecec9c8755
--- /dev/null
+++ b/python/edu/build/resources/PC_instCom.ico
Binary files differ
diff --git a/python/edu/build/resources/PC_uninstCom.ico b/python/edu/build/resources/PC_uninstCom.ico
new file mode 100644
index 000000000000..13e9f96f9987
--- /dev/null
+++ b/python/edu/build/resources/PC_uninstCom.ico
Binary files differ
diff --git a/python/edu/build/resources/headerlogo.bmp b/python/edu/build/resources/headerlogo.bmp
new file mode 100644
index 000000000000..c06099264961
--- /dev/null
+++ b/python/edu/build/resources/headerlogo.bmp
Binary files differ
diff --git a/python/edu/build/resources/logo.bmp b/python/edu/build/resources/logo.bmp
new file mode 100644
index 000000000000..0f0f82da7b1e
--- /dev/null
+++ b/python/edu/build/resources/logo.bmp
Binary files differ
diff --git a/python/edu/build/resources/pycharm_inst.ico b/python/edu/build/resources/pycharm_inst.ico
new file mode 100644
index 000000000000..6c75bcdbc441
--- /dev/null
+++ b/python/edu/build/resources/pycharm_inst.ico
Binary files differ
diff --git a/python/edu/build/resources/pycharm_uninst.ico b/python/edu/build/resources/pycharm_uninst.ico
new file mode 100644
index 000000000000..a5b9ad86ae94
--- /dev/null
+++ b/python/edu/build/resources/pycharm_uninst.ico
Binary files differ
diff --git a/python/edu/build/strings.nsi b/python/edu/build/strings.nsi
new file mode 100644
index 000000000000..fa10d421024c
--- /dev/null
+++ b/python/edu/build/strings.nsi
@@ -0,0 +1,13 @@
+!define MANUFACTURER "JetBrains"
+!define MUI_PRODUCT "PyCharm Educational Edition"
+!define PRODUCT_FULL_NAME "JetBrains PyCharm Educational Edition"
+!define PRODUCT_EXE_FILE "pycharm.exe"
+!define PRODUCT_ICON_FILE "PC_instCom.ico"
+!define PRODUCT_UNINST_ICON_FILE "PC_uninstCom.ico"
+!define PRODUCT_LOGO_FILE "logo.bmp"
+!define PRODUCT_HEADER_FILE "headerlogo.bmp"
+
+; if SHOULD_SET_DEFAULT_INSTDIR != 0 then default installation directory will be directory where highest-numbered PyCharm build has been installed
+; set to 1 for release build
+!define SHOULD_SET_DEFAULT_INSTDIR "0"
+
diff --git a/python/edu/main_pycharm_edu.iml b/python/edu/main_pycharm_edu.iml
new file mode 100644
index 000000000000..2acdd8733873
--- /dev/null
+++ b/python/edu/main_pycharm_edu.iml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
+ <exclude-output />
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="module" module-name="bootstrap" />
+ <orderEntry type="module" module-name="colorSchemes" />
+ <orderEntry type="module" module-name="svn4idea" />
+ <orderEntry type="module" module-name="git4idea" />
+ <orderEntry type="module" module-name="relaxng" />
+ <orderEntry type="module" module-name="rest" />
+ <orderEntry type="module" module-name="python-helpers" />
+ <orderEntry type="module" module-name="terminal" />
+ <orderEntry type="module" module-name="python-ide-community" />
+ <orderEntry type="module" module-name="platform-main" />
+ <orderEntry type="module" module-name="ShortcutPromoter" />
+ <orderEntry type="module" module-name="python-educational" />
+ </component>
+</module>
+
diff --git a/python/edu/python-educational.iml b/python/edu/python-educational.iml
new file mode 100644
index 000000000000..92439c421c2d
--- /dev/null
+++ b/python/edu/python-educational.iml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/resources" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/gen" isTestSource="false" generated="true" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="module" module-name="python-openapi" exported="" />
+ <orderEntry type="module" module-name="platform-impl" />
+ <orderEntry type="module" module-name="lang-impl" />
+ <orderEntry type="library" name="Guava" level="project" />
+ <orderEntry type="module" module-name="python-pydev" />
+ <orderEntry type="library" exported="" name="XmlRPC" level="project" />
+ <orderEntry type="module" module-name="xdebugger-api" />
+ <orderEntry type="library" name="http-client-3.1" level="project" />
+ <orderEntry type="module" module-name="RegExpSupport" exported="" />
+ <orderEntry type="module" module-name="testRunner" />
+ <orderEntry type="module" module-name="smRunner" />
+ <orderEntry type="module" module-name="spellchecker" />
+ <orderEntry type="module" module-name="xdebugger-impl" />
+ <orderEntry type="module" module-name="xml-psi-impl" />
+ <orderEntry type="module" module-name="python-community" />
+ </component>
+</module>
+
diff --git a/python/edu/resources/idea/PyCharmEduApplicationInfo.xml b/python/edu/resources/idea/PyCharmEduApplicationInfo.xml
new file mode 100644
index 000000000000..46695ef29ed4
--- /dev/null
+++ b/python/edu/resources/idea/PyCharmEduApplicationInfo.xml
@@ -0,0 +1,23 @@
+<component>
+ <company name="JetBrains s.r.o." url="http://www.jetbrains.com/?fromIDE"/>
+ <version major="3" minor="0" eap="true"/>
+ <build number="__BUILD_NUMBER__" date="__BUILD_DATE__"/>
+ <logo url="/pycharm_core_logo.png" textcolor="ffffff" progressColor="ffaa16" progressY="230" progressTailIcon="/community_progress_tail.png"/>
+ <about url="/pycharm_core_about.png" logoX="300" logoY="265" logoW="75" logoH="30" foreground="ffffff" linkColor="fca11a"/>
+ <icon size32="/PyCharmCore32.png" size16="/PyCharmCore16.png" size32opaque="/PyCharmCore32.png" size12="/PyCharmCore13.png" ico="PyCharmCore.ico"/>
+ <package code="__PACKAGE_CODE__"/>
+ <names product="PyCharm" fullname="PyCharm Educational Edition" script="charm"/>
+ <install-over minbuild="0" maxbuild="0" version="1.x"/>
+
+ <welcome-screen logo-url="/PyCharmCoreWelcomeScreen.png" caption-url="PyCharmCoreWelcomeCaption.png" slogan-url="/developSlogan.png"/>
+
+ <third-party url="http://confluence.jetbrains.com/display/PYH/Third-Party+Software+Used+by+PyCharm"/>
+
+ <update-urls logo-url="/Logo_welcomeScreen.png"
+ check="http://www.jetbrains.com/updates/updates.xml"
+ patches="http://download.jetbrains.com/python/"/>
+
+ <feedback eap-url="http://www.jetbrains.com/feedback/feedback.jsp?product=PyCharm&amp;build=$BUILD&amp;timezone=$TIMEZONE&amp;eval=$EVAL"
+ release-url="http://www.jetbrains.com/feedback/feedback.jsp?product=PyCharm&amp;build=$BUILD&amp;timezone=$TIMEZONE&amp;eval=$EVAL"/>
+ <help file="pycharmhelp.jar" root="pycharm"/>
+</component>
diff --git a/python/edu/src/META-INF/PyCharmEduPlugin.xml b/python/edu/src/META-INF/PyCharmEduPlugin.xml
new file mode 100644
index 000000000000..9adf03dfd9c8
--- /dev/null
+++ b/python/edu/src/META-INF/PyCharmEduPlugin.xml
@@ -0,0 +1,36 @@
+<idea-plugin version="2" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <!-- Components and extensions declared in this file work ONLY in Pycharm Educational Edition -->
+
+ <application-components>
+ <component>
+ <implementation-class>com.jetbrains.python.edu.PyCharmEduInitialConfigurator$First</implementation-class>
+ <headless-implementation-class/>
+ </component>
+ </application-components>
+
+ <xi:include href="/META-INF/pycharm-core.xml" xpointer="xpointer(/idea-plugin/*)"/>
+
+ <xi:include href="/META-INF/python-core.xml" xpointer="xpointer(/idea-plugin/*)"/>
+
+
+ <actions>
+ <group overrides="true" class="com.intellij.openapi.actionSystem.EmptyActionGroup" id="ToolsMenu"/>
+
+ <group overrides="true" class="com.intellij.openapi.actionSystem.EmptyActionGroup" id="PrintExportGroup"/>
+ <group overrides="true" id="FileMainSettingsGroup">
+ <reference id="ShowSettings"/>
+ <separator/>
+ <reference id="ExportImportGroup"/>
+ </group>
+
+ <group overrides="true" class="com.intellij.openapi.actionSystem.EmptyActionGroup" id="EditBookmarksGroup"/>
+ <group overrides="true" class="com.intellij.openapi.actionSystem.EmptyActionGroup" id="AddToFavorites"/>
+ <group overrides="true" class="com.intellij.openapi.actionSystem.EmptyActionGroup" id="AddAllToFavorites"/>
+ <action overrides="true" class="com.intellij.openapi.actionSystem.EmptyAction" id="AddToFavoritesPopup"/>
+ <action overrides="true" class="com.intellij.openapi.actionSystem.EmptyAction" id="RemoveFromFavorites"/>
+
+ <action overrides="true" class="com.intellij.openapi.actionSystem.EmptyAction" id="NewHtmlFile"/>
+
+
+ </actions>
+</idea-plugin>
diff --git a/python/edu/src/com/jetbrains/python/edu/PyCharmEduInitialConfigurator.java b/python/edu/src/com/jetbrains/python/edu/PyCharmEduInitialConfigurator.java
new file mode 100644
index 000000000000..451c5193645e
--- /dev/null
+++ b/python/edu/src/com/jetbrains/python/edu/PyCharmEduInitialConfigurator.java
@@ -0,0 +1,247 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.jetbrains.python.edu;
+
+import com.intellij.application.options.InitialConfigurationDialog;
+import com.intellij.codeInsight.CodeInsightSettings;
+import com.intellij.codeInsight.intention.IntentionActionBean;
+import com.intellij.codeInsight.intention.IntentionManager;
+import com.intellij.ide.AppLifecycleListener;
+import com.intellij.ide.GeneralSettings;
+import com.intellij.ide.RecentProjectsManagerBase;
+import com.intellij.ide.SelectInTarget;
+import com.intellij.ide.ui.UISettings;
+import com.intellij.ide.util.PropertiesComponent;
+import com.intellij.ide.util.TipDialog;
+import com.intellij.notification.EventLog;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.ModalityState;
+import com.intellij.openapi.editor.ex.EditorSettingsExternalizable;
+import com.intellij.openapi.extensions.Extensions;
+import com.intellij.openapi.extensions.ExtensionsArea;
+import com.intellij.openapi.fileChooser.impl.FileChooserUtil;
+import com.intellij.openapi.fileTypes.FileTypeManager;
+import com.intellij.openapi.keymap.Keymap;
+import com.intellij.openapi.keymap.ex.KeymapManagerEx;
+import com.intellij.openapi.keymap.impl.KeymapImpl;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.project.ProjectManager;
+import com.intellij.openapi.project.ProjectManagerAdapter;
+import com.intellij.openapi.project.ex.ProjectManagerEx;
+import com.intellij.openapi.util.Disposer;
+import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.vfs.VfsUtil;
+import com.intellij.openapi.wm.ToolWindowEP;
+import com.intellij.openapi.wm.ToolWindowId;
+import com.intellij.openapi.wm.WindowManager;
+import com.intellij.platform.DirectoryProjectConfigurator;
+import com.intellij.platform.PlatformProjectViewOpener;
+import com.intellij.psi.codeStyle.CodeStyleSettings;
+import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
+import com.intellij.util.Alarm;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.messages.MessageBus;
+import com.jetbrains.python.PythonLanguage;
+import com.jetbrains.python.codeInsight.PyCodeInsightSettings;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import java.util.Set;
+
+/**
+ * @author traff
+ */
+@SuppressWarnings({"UtilityClassWithoutPrivateConstructor", "UtilityClassWithPublicConstructor"})
+public class PyCharmEduInitialConfigurator {
+ @NonNls private static final String DISPLAYED_PROPERTY = "PyCharm.initialConfigurationShown";
+
+ @NonNls private static final String CONFIGURED = "PyCharm.InitialConfiguration";
+
+
+ public static class First {
+
+ public First() {
+ patchRootAreaExtensions();
+ }
+ }
+
+ /**
+ * @noinspection UnusedParameters
+ */
+ public PyCharmEduInitialConfigurator(MessageBus bus,
+ UISettings uiSettings,
+ CodeInsightSettings codeInsightSettings,
+ final PropertiesComponent propertiesComponent,
+ FileTypeManager fileTypeManager,
+ final ProjectManagerEx projectManager,
+ RecentProjectsManagerBase recentProjectsManager) {
+ if (!propertiesComponent.getBoolean(CONFIGURED, false)) {
+ propertiesComponent.setValue(CONFIGURED, "true");
+ recentProjectsManager.loadState(new RecentProjectsManagerBase.State());
+ propertiesComponent.setValue("toolwindow.stripes.buttons.info.shown", "true");
+ UISettings.getInstance().HIDE_TOOL_STRIPES = false;
+ uiSettings.SHOW_MEMORY_INDICATOR = false;
+ uiSettings.SHOW_DIRECTORY_FOR_NON_UNIQUE_FILENAMES = true;
+ codeInsightSettings.REFORMAT_ON_PASTE = CodeInsightSettings.NO_REFORMAT;
+
+ EditorSettingsExternalizable.getInstance().setVirtualSpace(false);
+ final CodeStyleSettings settings = CodeStyleSettingsManager.getInstance().getCurrentSettings();
+ settings.ALIGN_MULTILINE_PARAMETERS_IN_CALLS = true;
+ settings.getCommonSettings(PythonLanguage.getInstance()).ALIGN_MULTILINE_PARAMETERS_IN_CALLS = true;
+ UISettings.getInstance().SHOW_DIRECTORY_FOR_NON_UNIQUE_FILENAMES = true;
+ UISettings.getInstance().SHOW_MEMORY_INDICATOR = false;
+ final String ignoredFilesList = fileTypeManager.getIgnoredFilesList();
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ @Override
+ public void run() {
+ FileTypeManager.getInstance().setIgnoredFilesList(ignoredFilesList + ";*$py.class");
+ }
+ });
+ }
+ });
+ PyCodeInsightSettings.getInstance().SHOW_IMPORT_POPUP = false;
+ }
+ bus.connect().subscribe(AppLifecycleListener.TOPIC, new AppLifecycleListener.Adapter() {
+ @Override
+ public void appFrameCreated(String[] commandLineArgs, @NotNull Ref<Boolean> willOpenProject) {
+ if (!propertiesComponent.isValueSet(DISPLAYED_PROPERTY)) {
+ GeneralSettings.getInstance().setShowTipsOnStartup(false);
+ showInitialConfigurationDialog();
+ propertiesComponent.setValue(DISPLAYED_PROPERTY, "true");
+ }
+ }
+
+ @Override
+ public void appStarting(Project projectFromCommandLine) {
+ patchKeymap();
+ }
+ });
+ bus.connect().subscribe(ProjectManager.TOPIC, new ProjectManagerAdapter() {
+ @Override
+ public void projectOpened(final Project project) {
+ if (project.isDefault()) return;
+ if (FileChooserUtil.getLastOpenedFile(project) == null) {
+ FileChooserUtil.setLastOpenedFile(project, VfsUtil.getUserHomeDir());
+ }
+
+ patchProjectAreaExtensions(project);
+
+ //StartupManager.getInstance(project).runWhenProjectIsInitialized(new DumbAwareRunnable() {
+ // @Override
+ // public void run() {
+ // if (project.isDisposed()) return;
+ //
+ // ToolWindowManager.getInstance(project).invokeLater(new Runnable() {
+ // int count = 0;
+ // public void run() {
+ // if (project.isDisposed()) return;
+ // if (count ++ < 3) {
+ // ToolWindowManager.getInstance(project).invokeLater(this);
+ // return;
+ // }
+ // if (!propertiesComponent.isValueSet(INIT_DB_DIALOG_DISPLAYED)) {
+ // ToolWindow toolWindow = DatabaseView.getDatabaseToolWindow(project);
+ // if (toolWindow.getType() != ToolWindowType.SLIDING) {
+ // toolWindow.activate(null);
+ // }
+ // propertiesComponent.setValue(INIT_DB_DIALOG_DISPLAYED, "true");
+ // onFirstProjectOpened(project);
+ // }
+ // }
+ // });
+ // }
+ //});
+ }
+ });
+ }
+
+ private static void onFirstProjectOpened(@NotNull final Project project) {
+ // show python console
+
+
+ GeneralSettings.getInstance().setShowTipsOnStartup(true);
+
+ // show tips once
+ final Alarm alarm = new Alarm(project);
+ alarm.addRequest(new Runnable() {
+ @Override
+ public void run() {
+ Disposer.dispose(alarm);
+ TipDialog.createForProject(project).show();
+ }
+ }, 2000, ModalityState.NON_MODAL);
+ }
+
+ private static void patchRootAreaExtensions() {
+ ExtensionsArea rootArea = Extensions.getArea(null);
+
+ for (ToolWindowEP ep : Extensions.getExtensions(ToolWindowEP.EP_NAME)) {
+ if (ToolWindowId.FAVORITES_VIEW.equals(ep.id) || ToolWindowId.TODO_VIEW.equals(ep.id) || EventLog.LOG_TOOL_WINDOW_ID.equals(ep.id)) {
+ rootArea.getExtensionPoint(ToolWindowEP.EP_NAME).unregisterExtension(ep);
+ }
+ }
+
+ for (DirectoryProjectConfigurator ep : Extensions.getExtensions(DirectoryProjectConfigurator.EP_NAME)) {
+ if (ep instanceof PlatformProjectViewOpener) {
+ rootArea.getExtensionPoint(DirectoryProjectConfigurator.EP_NAME).unregisterExtension(ep);
+ }
+ }
+
+ for (IntentionActionBean ep : Extensions.getExtensions(IntentionManager.EP_INTENTION_ACTIONS)) {
+ if ("org.intellij.lang.regexp.intention.CheckRegExpIntentionAction".equals(ep.className)) {
+ rootArea.getExtensionPoint(IntentionManager.EP_INTENTION_ACTIONS).unregisterExtension(ep);
+ }
+ }
+ }
+
+ private static void patchProjectAreaExtensions(@NotNull final Project project) {
+ for (SelectInTarget target : Extensions.getExtensions(SelectInTarget.EP_NAME, project)) {
+ if (ToolWindowId.FAVORITES_VIEW.equals(target.getToolWindowId())) {
+ Extensions.getArea(project).getExtensionPoint(SelectInTarget.EP_NAME).unregisterExtension(target);
+ }
+ }
+ }
+
+ private static void patchKeymap() {
+ Set<String> droppedActions = ContainerUtil.newHashSet(
+ "AddToFavoritesPopup", "RemoveFromFavorites",
+ "DatabaseView.ImportDataSources",
+ "CompileDirty", "Compile",
+ // hidden
+ "AddNewFavoritesList", "EditFavorites", "RemoveFromFavorites", "RenameFavoritesList", "RemoveFavoritesList");
+ KeymapManagerEx keymapManager = KeymapManagerEx.getInstanceEx();
+
+
+ for (Keymap keymap : keymapManager.getAllKeymaps()) {
+ if (keymap.canModify()) continue;
+
+ KeymapImpl keymapImpl = (KeymapImpl)keymap;
+
+ for (String id : keymapImpl.getOwnActionIds()) {
+ if (droppedActions.contains(id)) keymapImpl.clearOwnActionsId(id);
+ }
+ }
+ }
+
+ private static void showInitialConfigurationDialog() {
+ final JFrame frame = WindowManager.getInstance().findVisibleFrame();
+ new InitialConfigurationDialog(frame, "Python").show();
+ }
+}
diff --git a/python/helpers/pycharm/_bdd_utils.py b/python/helpers/pycharm/_bdd_utils.py
new file mode 100644
index 000000000000..0c92532b516c
--- /dev/null
+++ b/python/helpers/pycharm/_bdd_utils.py
@@ -0,0 +1,201 @@
+# coding=utf-8
+"""
+Tools for running BDD frameworks in python.
+You probably need to extend BddRunner (see its doc).
+
+You may also need "get_path_by_args" that gets folder (current or passed as first argument)
+"""
+import os
+import time
+import abc
+
+import tcmessages
+
+
+__author__ = 'Ilya.Kazakevich'
+
+
+def get_path_by_args(arguments):
+ """
+ :type arguments list
+ :param arguments: arguments (sys.argv)
+ :return: tuple (base_dir, what_to_run) where dir is current or first argument from argv, checking it exists
+ :rtype tuple of str
+ """
+ what_to_run = arguments[1] if len(arguments) > 1 else "."
+ base_dir = what_to_run
+ assert os.path.exists(what_to_run), "{} does not exist".format(what_to_run)
+
+ if os.path.isfile(what_to_run):
+ base_dir = os.path.dirname(what_to_run) # User may point to the file directly
+ return base_dir, what_to_run
+
+
+class BddRunner(object):
+ """
+ Extends this class, implement abstract methods and use its API to implement new BDD frameworks.
+ Call "run()" to launch it.
+ This class does the following:
+ * Gets features to run (using "_get_features_to_run()") and calculates steps in it
+ * Reports steps to Intellij or TC
+ * Calls "_run_tests()" where *you* should install all hooks you need into your BDD and use "self._" functions
+ to report tests and features. It actually wraps tcmessages but adds some stuff like duration count etc
+ :param base_dir:
+ """
+ __metaclass__ = abc.ABCMeta
+
+ def __init__(self, base_dir):
+ """
+ :type base_dir str
+ :param base_dir base directory of your project
+ """
+ super(BddRunner, self).__init__()
+ self.tc_messages = tcmessages.TeamcityServiceMessages()
+ """
+ tcmessages TeamCity/Intellij test API. See TeamcityServiceMessages
+ """
+ self.__base_dir = base_dir
+ self.__last_test_start_time = None # TODO: Doc when use
+ self.__last_test_name = None
+
+ def run(self):
+ """"
+ Runs runner. To be called right after constructor.
+ """
+ self.tc_messages.testCount(self._get_number_of_tests())
+ self.tc_messages.testMatrixEntered()
+ self._run_tests()
+
+ def __gen_location(self, location):
+ """
+ Generates location in format, supported by tcmessages
+ :param location object with "file" (relative to base_dir) and "line" fields.
+ :return: location in format file:line (as supported in tcmessages)
+ """
+ my_file = str(location.file).lstrip("/\\")
+ return "file:///{}:{}".format(os.path.normpath(os.path.join(self.__base_dir, my_file)), location.line)
+
+ def _test_undefined(self, test_name, location):
+ """
+ Mark test as undefined
+ :param test_name: name of test
+ :type test_name str
+ :param location its location
+
+ """
+ if test_name != self.__last_test_name:
+ self._test_started(test_name, location)
+ self._test_failed(test_name, message="Test undefined", details="Please define test")
+
+ def _test_skipped(self, test_name, reason, location):
+ """
+ Mark test as skipped
+ :param test_name: name of test
+ :param reason: why test was skipped
+ :type reason str
+ :type test_name str
+ :param location its location
+
+ """
+ if test_name != self.__last_test_name:
+ self._test_started(test_name, location)
+ self.tc_messages.testIgnored(test_name, "Skipped: {}".format(reason))
+ self.__last_test_name = None
+ pass
+
+ def _test_failed(self, name, message, details):
+ """
+ Report test failure
+ :param name: test name
+ :type name str
+ :param message: failure message
+ :type message str
+ :param details: failure details (probably stacktrace)
+ :type details str
+ """
+ self.tc_messages.testFailed(name, message=message, details=details)
+ self.__last_test_name = None
+
+ def _test_passed(self, name, duration=None):
+ """
+ Reports test passed
+ :param name: test name
+ :type name str
+ :param duration: time (in seconds) test took. Pass None if you do not know (we'll try to calculate it)
+ :type duration int
+ :return:
+ """
+ duration_to_report = duration
+ if self.__last_test_start_time and not duration: # And not provided
+ duration_to_report = int(time.time() - self.__last_test_start_time)
+ self.tc_messages.testFinished(name, duration=int(duration_to_report))
+ self.__last_test_start_time = None
+ self.__last_test_name = None
+
+ def _test_started(self, name, location):
+ """
+ Reports test launched
+ :param name: test name
+ :param location object with "file" (relative to base_dir) and "line" fields.
+ :type name str
+ """
+ self.__last_test_start_time = time.time()
+ self.__last_test_name = name
+ self.tc_messages.testStarted(name, self.__gen_location(location))
+
+ def _feature_or_scenario(self, is_started, name, location):
+ """
+ Reports feature or scenario launched or stopped
+ :param is_started: started or finished?
+ :type is_started bool
+ :param name: scenario or feature name
+ :param location object with "file" (relative to base_dir) and "line" fields.
+ """
+ if is_started:
+ self.tc_messages.testSuiteStarted(name, self.__gen_location(location))
+ else:
+ self.tc_messages.testSuiteFinished(name)
+
+ def _background(self, is_started, location):
+ """
+ Reports background or stopped
+ :param is_started: started or finished?
+ :type is_started bool
+ :param location object with "file" (relative to base_dir) and "line" fields.
+ """
+ self._feature_or_scenario(is_started, "Background", location)
+
+ def _get_number_of_tests(self):
+ """"
+ Gets number of tests using "_get_features_to_run()" to obtain number of features to calculate.
+ Supports backgrounds as well.
+ :return number of steps
+ :rtype int
+ """
+ num_of_steps = 0
+ for feature in self._get_features_to_run():
+ if feature.background:
+ num_of_steps += len(feature.background.steps) * len(feature.scenarios)
+ for scenario in feature.scenarios:
+ num_of_steps += len(scenario.steps)
+ return num_of_steps
+
+ @abc.abstractmethod
+ def _get_features_to_run(self):
+ """
+ Implement it! Return list of features to run. Each "feature" should have "scenarios".
+ Each "scenario" should have "steps". Each "feature" may have "background" and each "background" should have
+ "steps". Duck typing.
+ :rtype list
+ :returns list of features
+ """
+ return []
+
+ @abc.abstractmethod
+ def _run_tests(self):
+ """
+ Implement it! It should launch tests using your BDD. Use "self._" functions to report results.
+ """
+ pass
+
+
diff --git a/python/helpers/pycharm/behave_runner.py b/python/helpers/pycharm/behave_runner.py
new file mode 100644
index 000000000000..4a1b2f6557c5
--- /dev/null
+++ b/python/helpers/pycharm/behave_runner.py
@@ -0,0 +1,242 @@
+# coding=utf-8
+"""
+Behave BDD runner.
+*FIRST* param now: folder to search "features" for.
+Each "features" folder should have features and "steps" subdir.
+
+Other args are tag expressionsin format (--tags=.. --tags=..).
+See https://pythonhosted.org/behave/behave.html#tag-expression
+"""
+import functools
+import sys
+import os
+import traceback
+
+from behave.formatter.base import Formatter
+from behave.model import Step, ScenarioOutline, Feature, Scenario
+from behave.tag_expression import TagExpression
+
+import _bdd_utils
+
+
+_MAX_STEPS_SEARCH_FEATURES = 5000 # Do not look for features in folder that has more that this number of children
+_FEATURES_FOLDER = 'features' # "features" folder name.
+
+__author__ = 'Ilya.Kazakevich'
+
+from behave import configuration, runner
+from behave.formatter import formatters
+
+
+def _get_dirs_to_run(base_dir_to_search):
+ """
+ Searches for "features" dirs in some base_dir
+ :return: list of feature dirs to run
+ :rtype: list
+ :param base_dir_to_search root directory to search (should not have too many children!)
+ :type base_dir_to_search str
+
+ """
+ result = set()
+ for (step, (folder, sub_folders, files)) in enumerate(os.walk(base_dir_to_search)):
+ if os.path.basename(folder) == _FEATURES_FOLDER and os.path.isdir(folder):
+ result.add(os.path.abspath(folder))
+ if step == _MAX_STEPS_SEARCH_FEATURES: # Guard
+ err = "Folder {} is too deep to find any features folder. Please provider concrete folder".format(
+ base_dir_to_search)
+ raise Exception(err)
+ return list(result)
+
+
+def _merge_hooks_wrapper(*hooks):
+ """
+ Creates wrapper that runs provided behave hooks sequentally
+ :param hooks: hooks to run
+ :return: wrapper
+ """
+ # TODO: Wheel reinvented!!!!
+ def wrapper(*args, **kwargs):
+ for hook in hooks:
+ hook(*args, **kwargs)
+
+ return wrapper
+
+
+class _RunnerWrapper(runner.Runner):
+ """
+ Wrapper around behave native wrapper. Has nothing todo with BddRunner!
+ We need it to support dry runs (to fetch data from scenarios) and hooks api
+ """
+
+ def __init__(self, config, hooks):
+ """
+ :type config configuration.Configuration
+ :param config behave configuration
+ :type hooks dict
+ :param hooks hooks in format "before_scenario" => f(context, scenario) to load after/before hooks, provided by user
+ """
+ super(_RunnerWrapper, self).__init__(config)
+ self.dry_run = False
+ """
+ Does not run tests (only fetches "self.features") if true. Runs tests otherwise.
+ """
+ self.__hooks = hooks
+
+ def load_hooks(self, filename='environment.py'):
+ """
+ Overrides parent "load_hooks" to add "self.__hooks"
+ :param filename: env. file name
+ """
+ super(_RunnerWrapper, self).load_hooks(filename)
+ for (hook_name, hook) in self.__hooks.items():
+ hook_to_add = hook
+ if hook_name in self.hooks:
+ user_hook = self.hooks[hook_name]
+ if hook_name.startswith("before"):
+ user_and_custom_hook = [user_hook, hook]
+ else:
+ user_and_custom_hook = [hook, user_hook]
+ hook_to_add = _merge_hooks_wrapper(*user_and_custom_hook)
+ self.hooks[hook_name] = hook_to_add
+
+ def run_model(self, features=None):
+ """
+ Overrides parent method to stop (do nothing) in case of "dry_run"
+ :param features: features to run
+ :return:
+ """
+ if self.dry_run: # To stop further execution
+ return
+ return super(_RunnerWrapper, self).run_model(features)
+
+ def clean(self):
+ """
+ Cleans runner after dry run (clears hooks, features etc). To be called before real run!
+ """
+ self.dry_run = False
+ self.hooks.clear()
+ self.features = []
+
+
+class _BehaveRunner(_bdd_utils.BddRunner):
+ """
+ BddRunner for behave
+ """
+
+
+ def __process_hook(self, is_started, context, element):
+ """
+ Hook to be installed. Reports steps, features etc.
+ :param is_started true if test/feature/scenario is started
+ :type is_started bool
+ :param context behave context
+ :type context behave.runner.Context
+ :param element feature/suite/step
+ """
+ element.location.file = element.location.filename # To preserve _bdd_utils contract
+ if isinstance(element, Step):
+ # Process step
+ if is_started:
+ self._test_started(element.name, element.location)
+ elif element.status == 'passed':
+ self._test_passed(element.name, element.duration)
+ elif element.status == 'failed':
+ try:
+ trace = traceback.format_exc()
+ except Exception:
+ trace = "".join(traceback.format_tb(element.exc_traceback))
+ self._test_failed(element.name, element.error_message, trace)
+ elif element.status == 'undefined':
+ self._test_undefined(element.name, element.location)
+ else:
+ self._test_skipped(element.name, element.status, element.location)
+ elif not is_started and isinstance(element, Scenario) and element.status == 'failed':
+ # To process scenarios with undefined/skipped tests
+ for step in element.steps:
+ assert isinstance(step, Step), step
+ if step.status not in ['passed', 'failed']: # Something strange, probably skipped or undefined
+ self.__process_hook(False, context, step)
+ self._feature_or_scenario(is_started, element.name, element.location)
+ elif isinstance(element, ScenarioOutline):
+ self._feature_or_scenario(is_started, str(element.examples), element.location)
+ else:
+ self._feature_or_scenario(is_started, element.name, element.location)
+
+ def __init__(self, config, base_dir):
+ """
+ :type config configuration.Configuration
+ """
+ super(_BehaveRunner, self).__init__(base_dir)
+ self.__config = config
+ # Install hooks
+ self.__real_runner = _RunnerWrapper(config, {
+ "before_feature": functools.partial(self.__process_hook, True),
+ "after_feature": functools.partial(self.__process_hook, False),
+ "before_scenario": functools.partial(self.__process_hook, True),
+ "after_scenario": functools.partial(self.__process_hook, False),
+ "before_step": functools.partial(self.__process_hook, True),
+ "after_step": functools.partial(self.__process_hook, False)
+ })
+
+ def _run_tests(self):
+ self.__real_runner.run()
+
+
+ def __filter_scenarios_by_tag(self, scenario):
+ """
+ Filters out scenarios that should be skipped by tags
+ :param scenario scenario to check
+ :return true if should pass
+ """
+ assert isinstance(scenario, Scenario), scenario
+ expected_tags = self.__config.tags
+ if not expected_tags:
+ return True # No tags are required
+ return isinstance(expected_tags, TagExpression) and expected_tags.check(scenario.tags)
+
+
+ def _get_features_to_run(self):
+ self.__real_runner.dry_run = True
+ self.__real_runner.run()
+ features_to_run = self.__real_runner.features
+ self.__real_runner.clean() # To make sure nothing left after dry run
+
+ # Change outline scenario skeletons with real scenarios
+ for feature in features_to_run:
+ assert isinstance(feature, Feature), feature
+ scenarios = []
+ for scenario in feature.scenarios:
+ if isinstance(scenario, ScenarioOutline):
+ scenarios.extend(scenario.scenarios)
+ else:
+ scenarios.append(scenario)
+ feature.scenarios = filter(self.__filter_scenarios_by_tag, scenarios)
+
+ return features_to_run
+
+
+if __name__ == "__main__":
+ # TODO: support all other params instead
+
+ class _Null(Formatter):
+ """
+ Null formater to prevent stdout output
+ """
+ pass
+
+ command_args = list(filter(None, sys.argv[1:]))
+ my_config = configuration.Configuration(command_args=command_args)
+ formatters.register_as(_Null, "com.intellij.python.null")
+ my_config.format = ["com.intellij.python.null"] # To prevent output to stdout
+ my_config.reporters = [] # To prevent summary to stdout
+ my_config.stdout_capture = False # For test output
+ my_config.stderr_capture = False # For test output
+ (base_dir, what_to_run) = _bdd_utils.get_path_by_args(sys.argv)
+ if not my_config.paths: # No path provided, trying to load dit manually
+ if os.path.isfile(what_to_run): # File is provided, load it
+ my_config.paths = [what_to_run]
+ else: # Dir is provided, find subdirs ro run
+ my_config.paths = _get_dirs_to_run(base_dir)
+ _BehaveRunner(my_config, base_dir).run()
+
+
diff --git a/python/helpers/pycharm/lettuce_runner.py b/python/helpers/pycharm/lettuce_runner.py
index 6aaa566df719..3cd112540e5f 100644
--- a/python/helpers/pycharm/lettuce_runner.py
+++ b/python/helpers/pycharm/lettuce_runner.py
@@ -1,132 +1,112 @@
# coding=utf-8
"""
BDD lettuce framework runner
+TODO: Support other params (like tags) as well.
+Supports only 1 param now: folder to search "features" for.
"""
+import _bdd_utils
+
__author__ = 'Ilya.Kazakevich'
-import os
from lettuce.exceptions import ReasonToFail
-import time
import sys
-import tcmessages
import lettuce
from lettuce import core
-# Error message about unsupported outlines
-_NO_OUTLINE_ERROR = "Outline scenarios are not supported due to https://github.com/gabrielfalcao/lettuce/issues/451"
-
-
-class LettuceRunner(object):
+class _LettuceRunner(_bdd_utils.BddRunner):
"""
- TODO: Runs lettuce
+ Lettuce runner (BddRunner for lettuce)
"""
- def __init__(self, base_dir):
+ def __init__(self, base_dir, what_to_run):
"""
+
:param base_dir base directory to run tests in
:type base_dir: str
-
- """
- self.base_dir = base_dir
- self.runner = lettuce.Runner(base_dir)
- self.messages = tcmessages.TeamcityServiceMessages()
- self.test_start_time = None
-
- def report_tests(self):
- """
- :returns : number of tests
- :rtype : int
- """
- result = 0
- for feature_file in self.runner.loader.find_feature_files():
- feature = core.Feature.from_file(feature_file)
- for scenario in feature.scenarios:
- assert isinstance(scenario, core.Scenario), scenario
- if not scenario.outlines:
- result += len(scenario.steps)
- self.messages.testCount(result)
-
- def report_scenario_started(self, scenario):
+ :param what_to_run folder or file to run
+ :type what_to_run str
"""
- Reports scenario launched
- :type scenario core.Scenario
- :param scenario: scenario
- """
- if scenario.outlines:
- self.messages.testIgnored(scenario.name,
- _NO_OUTLINE_ERROR)
- scenario.steps = [] # Clear to prevent running. TODO: Fix when this issue fixed
- scenario.background = None # TODO: undocumented
- return
- self.report_suite(True, scenario.name, scenario.described_at)
+ super(_LettuceRunner, self).__init__(base_dir)
+ self.__runner = lettuce.Runner(what_to_run)
- def report_suite(self, is_start, name, described_at):
- """
- Reports some suite (scenario, feature, background etc) is started or stopped
- :param is_start: started or not
- :param name: suite name
- :param described_at: where it is described (file, line)
- :return:
- """
- if is_start:
- self.messages.testSuiteStarted(name, self._gen_location(described_at))
- else:
- self.messages.testSuiteFinished(name)
+ def _get_features_to_run(self):
+ super(_LettuceRunner, self)._get_features_to_run()
+ if self.__runner.single_feature: # We need to run one and only one feature
+ return [core.Feature.from_file(self.__runner.single_feature)]
- def report_step(self, is_start, step):
+ # Find all features in dir
+ features = []
+ for feature_file in self.__runner.loader.find_feature_files():
+ feature = core.Feature.from_file(feature_file)
+ assert isinstance(feature, core.Feature), feature
+ # TODO: cut out due to https://github.com/gabrielfalcao/lettuce/issues/451 Fix when this issue fixed
+ feature.scenarios = filter(lambda s: not s.outlines, feature.scenarios)
+ if feature.scenarios:
+ features.append(feature)
+ return features
+
+ def _run_tests(self):
+ super(_LettuceRunner, self)._run_tests()
+ self.__install_hooks()
+ self.__runner.run()
+
+ def __step(self, is_started, step):
"""
Reports step start / stop
- :param is_start: true if step started
:type step core.Step
:param step: step
"""
test_name = step.sentence
- if is_start:
- self.test_start_time = time.time()
- self.messages.testStarted(test_name, self._gen_location(step.described_at))
+ if is_started:
+ self._test_started(test_name, step.described_at)
elif step.passed:
- duration = 0
- if self.test_start_time:
- duration = long(time.time() - self.test_start_time)
- self.messages.testFinished(test_name, duration=duration)
- self.test_start_time = None
+ self._test_passed(test_name)
elif step.failed:
reason = step.why
assert isinstance(reason, ReasonToFail), reason
- self.messages.testFailed(test_name, message=reason.exception, details=reason.traceback)
-
- def _gen_location(self, description):
- """
- :param description: "described_at" (file, line)
- :return: location in format file:line by "described_at"
- """
- return "file:///{}/{}:{}".format(self.base_dir, description.file, description.line)
+ self._test_failed(test_name, message=reason.exception, details=reason.traceback)
+ elif step.has_definition:
+ self._test_skipped(test_name, "In lettuce, we do know the reason", step.described_at)
+ else:
+ self._test_undefined(test_name, step.described_at)
- def run(self):
+ def __install_hooks(self):
"""
- Launches runner
+ Installs required hooks
"""
- self.report_tests()
- self.messages.testMatrixEntered()
- lettuce.before.each_feature(lambda f: self.report_suite(True, f.name, f.described_at))
- lettuce.after.each_feature(lambda f: self.report_suite(False, f.name, f.described_at))
+ # Install hooks
+ lettuce.before.each_feature(
+ lambda f: self._feature_or_scenario(True, f.name, f.described_at))
+ lettuce.after.each_feature(
+ lambda f: self._feature_or_scenario(False, f.name, f.described_at))
- lettuce.before.each_scenario(lambda s: self.report_scenario_started(s))
- lettuce.after.each_scenario(lambda s: self.report_suite(False, s.name, s.described_at))
+ lettuce.before.each_scenario(
+ lambda s: self.__scenario(True, s))
+ lettuce.after.each_scenario(
+ lambda s: self.__scenario(False, s))
lettuce.before.each_background(
- lambda b, *args: self.report_suite(True, "Scenario background", b.feature.described_at))
+ lambda b, *args: self._background(True, b.feature.described_at))
lettuce.after.each_background(
- lambda b, *args: self.report_suite(False, "Scenario background", b.feature.described_at))
+ lambda b, *args: self._background(False, b.feature.described_at))
- lettuce.before.each_step(lambda s: self.report_step(True, s))
- lettuce.after.each_step(lambda s: self.report_step(False, s))
+ lettuce.before.each_step(lambda s: self.__step(True, s))
+ lettuce.after.each_step(lambda s: self.__step(False, s))
- self.runner.run()
+ def __scenario(self, is_started, scenario):
+ """
+ Reports scenario launched
+ :type scenario core.Scenario
+ :param scenario: scenario
+ """
+ if scenario.outlines:
+ scenario.steps = [] # Clear to prevent running. TODO: Fix when this issue fixed
+ scenario.background = None # TODO: undocumented
+ return
+ self._feature_or_scenario(is_started, scenario.name, scenario.described_at)
if __name__ == "__main__":
- path = sys.argv[1] if len(sys.argv) > 1 else "."
- assert os.path.exists(path), "{} does not exist".format(path)
- LettuceRunner(path).run() \ No newline at end of file
+ (base_dir, what_to_run) = _bdd_utils.get_path_by_args(sys.argv)
+ _LettuceRunner(base_dir, what_to_run).run() \ No newline at end of file
diff --git a/python/helpers/pycharm/tcunittest.py b/python/helpers/pycharm/tcunittest.py
index b6950c92a11f..99b30595a191 100644
--- a/python/helpers/pycharm/tcunittest.py
+++ b/python/helpers/pycharm/tcunittest.py
@@ -6,14 +6,16 @@ from tcmessages import TeamcityServiceMessages
PYTHON_VERSION_MAJOR = sys.version_info[0]
+
def strclass(cls):
if not cls.__name__:
return cls.__module__
return "%s.%s" % (cls.__module__, cls.__name__)
+
def smart_str(s):
- encoding='utf-8'
- errors='strict'
+ encoding = 'utf-8'
+ errors = 'strict'
if PYTHON_VERSION_MAJOR < 3:
is_string = isinstance(s, basestring)
else:
@@ -33,6 +35,7 @@ def smart_str(s):
else:
return s
+
class TeamcityTestResult(TestResult):
def __init__(self, stream=sys.stdout, *args, **kwargs):
TestResult.__init__(self)
@@ -41,42 +44,47 @@ class TeamcityTestResult(TestResult):
self.output = stream
self.messages = TeamcityServiceMessages(self.output, prepend_linebreak=True)
self.messages.testMatrixEntered()
+ self.current_failed = False
self.current_suite = None
+ self.subtest_suite = None
def find_first(self, val):
quot = val[0]
count = 1
quote_ind = val[count:].find(quot)
- while quote_ind != -1 and val[count+quote_ind-1] == "\\":
+ while quote_ind != -1 and val[count + quote_ind - 1] == "\\":
count = count + quote_ind + 1
quote_ind = val[count:].find(quot)
- return val[0:quote_ind+count+1]
+ return val[0:quote_ind + count + 1]
def find_second(self, val):
val_index = val.find("!=")
if val_index != -1:
count = 1
- val = val[val_index+2:].strip()
+ val = val[val_index + 2:].strip()
quot = val[0]
quote_ind = val[count:].find(quot)
- while quote_ind != -1 and val[count+quote_ind-1] == "\\":
+ while quote_ind != -1 and val[count + quote_ind - 1] == "\\":
count = count + quote_ind + 1
quote_ind = val[count:].find(quot)
- return val[0:quote_ind+count+1]
+ return val[0:quote_ind + count + 1]
else:
quot = val[-1]
- quote_ind = val[:len(val)-1].rfind(quot)
- while quote_ind != -1 and val[quote_ind-1] == "\\":
- quote_ind = val[:quote_ind-1].rfind(quot)
+ quote_ind = val[:len(val) - 1].rfind(quot)
+ while quote_ind != -1 and val[quote_ind - 1] == "\\":
+ quote_ind = val[:quote_ind - 1].rfind(quot)
return val[quote_ind:]
def formatErr(self, err):
exctype, value, tb = err
return ''.join(traceback.format_exception(exctype, value, tb))
- def getTestName(self, test):
+ def getTestName(self, test, is_subtest=False):
+ if is_subtest:
+ test_name = self.getTestName(test.test_case)
+ return "{} {}".format(test_name, test._subDescription())
if hasattr(test, '_testMethodName'):
if test._testMethodName == "runTest":
return str(test)
@@ -95,10 +103,13 @@ class TeamcityTestResult(TestResult):
TestResult.addSuccess(self, test)
def addError(self, test, err):
+ self.init_suite(test)
+ self.current_failed = True
TestResult.addError(self, test, err)
err = self._exc_info_to_string(err, test)
+ self.messages.testStarted(self.getTestName(test))
self.messages.testError(self.getTestName(test),
message='Error', details=err)
@@ -108,6 +119,8 @@ class TeamcityTestResult(TestResult):
return error_value.split('assert')[-1].strip()
def addFailure(self, test, err):
+ self.init_suite(test)
+ self.current_failed = True
TestResult.addFailure(self, test, err)
error_value = smart_str(err[1])
@@ -119,7 +132,7 @@ class TeamcityTestResult(TestResult):
self_find_second = self.find_second(error_value)
quotes = ["'", '"']
if (self_find_first[0] == self_find_first[-1] and self_find_first[0] in quotes and
- self_find_second[0] == self_find_second[-1] and self_find_second[0] in quotes):
+ self_find_second[0] == self_find_second[-1] and self_find_second[0] in quotes):
# let's unescape strings to show sexy multiline diff in PyCharm.
# By default all caret return chars are escaped by testing framework
first = self._unescape(self_find_first)
@@ -128,10 +141,13 @@ class TeamcityTestResult(TestResult):
first = second = ""
err = self._exc_info_to_string(err, test)
+ self.messages.testStarted(self.getTestName(test))
self.messages.testFailed(self.getTestName(test),
message='Failure', details=err, expected=first, actual=second)
def addSkip(self, test, reason):
+ self.init_suite(test)
+ self.current_failed = True
self.messages.testIgnored(self.getTestName(test), message=reason)
def __getSuite(self, test):
@@ -149,10 +165,10 @@ class TeamcityTestResult(TestResult):
try:
source_file = inspect.getsourcefile(test.__class__)
if source_file:
- source_dir_splitted = source_file.split("/")[:-1]
- source_dir = "/".join(source_dir_splitted) + "/"
+ source_dir_splitted = source_file.split("/")[:-1]
+ source_dir = "/".join(source_dir_splitted) + "/"
else:
- source_dir = ""
+ source_dir = ""
except TypeError:
source_dir = ""
@@ -163,20 +179,52 @@ class TeamcityTestResult(TestResult):
return (suite, location, suite_location)
def startTest(self, test):
+ self.current_failed = False
+ setattr(test, "startTime", datetime.datetime.now())
+
+ def init_suite(self, test):
suite, location, suite_location = self.__getSuite(test)
if suite != self.current_suite:
if self.current_suite:
self.messages.testSuiteFinished(self.current_suite)
self.current_suite = suite
self.messages.testSuiteStarted(self.current_suite, location=suite_location)
- setattr(test, "startTime", datetime.datetime.now())
- self.messages.testStarted(self.getTestName(test), location=location)
+ return location
def stopTest(self, test):
start = getattr(test, "startTime", datetime.datetime.now())
d = datetime.datetime.now() - start
- duration=d.microseconds / 1000 + d.seconds * 1000 + d.days * 86400000
- self.messages.testFinished(self.getTestName(test), duration=int(duration))
+ duration = d.microseconds / 1000 + d.seconds * 1000 + d.days * 86400000
+ if not self.subtest_suite:
+ if not self.current_failed:
+ location = self.init_suite(test)
+ self.messages.testStarted(self.getTestName(test), location=location)
+ self.messages.testFinished(self.getTestName(test), duration=int(duration))
+ else:
+ self.messages.testSuiteFinished(self.subtest_suite)
+ self.subtest_suite = None
+
+
+ def addSubTest(self, test, subtest, err):
+ suite_name = self.getTestName(test) # + " (subTests)"
+ if not self.subtest_suite:
+ self.subtest_suite = suite_name
+ self.messages.testSuiteStarted(self.subtest_suite)
+ else:
+ if suite_name != self.subtest_suite:
+ self.messages.testSuiteFinished(self.subtest_suite)
+ self.subtest_suite = suite_name
+ self.messages.testSuiteStarted(self.subtest_suite)
+
+ name = self.getTestName(subtest, True)
+ if err is not None:
+ error = self._exc_info_to_string(err, test)
+ self.messages.testStarted(name)
+ self.messages.testFailed(name, message='Failure', details=error)
+ else:
+ self.messages.testStarted(name)
+ self.messages.testFinished(name)
+
def endLastSuite(self):
if self.current_suite:
@@ -187,6 +235,7 @@ class TeamcityTestResult(TestResult):
# do not use text.decode('string_escape'), it leads to problems with different string encodings given
return text.replace("\\n", "\n")
+
class TeamcityTestRunner(object):
def __init__(self, stream=sys.stdout):
self.stream = stream
diff --git a/python/ide/src/com/jetbrains/python/newProject/PyCharmNewProjectDialog.java b/python/ide/src/com/jetbrains/python/newProject/PyCharmNewProjectDialog.java
index d186f33620e5..7570e3f05b31 100644
--- a/python/ide/src/com/jetbrains/python/newProject/PyCharmNewProjectDialog.java
+++ b/python/ide/src/com/jetbrains/python/newProject/PyCharmNewProjectDialog.java
@@ -16,9 +16,11 @@
package com.jetbrains.python.newProject;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
+import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.wm.impl.welcomeScreen.CardActionsPanel;
+import com.intellij.platform.DirectoryProjectGenerator;
import com.jetbrains.python.newProject.actions.PyCharmNewProjectStep;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -42,7 +44,8 @@ public class PyCharmNewProjectDialog extends DialogWrapper {
PyCharmNewProjectDialog.this.close(OK_EXIT_CODE);
}
};
- final DefaultActionGroup root = new PyCharmNewProjectStep(runnable);
+ final DirectoryProjectGenerator[] generators = Extensions.getExtensions(DirectoryProjectGenerator.EP_NAME);
+ final DefaultActionGroup root = new PyCharmNewProjectStep(generators.length == 0 ? "Create Project" : "Select Project Type", runnable);
return new CardActionsPanel(root) {
@@ -53,6 +56,7 @@ public class PyCharmNewProjectDialog extends DialogWrapper {
@Override
public Dimension getMinimumSize() {
+ if (generators.length == 0) return new Dimension(550, 200);
return new Dimension(650, 450);
}
};
diff --git a/python/ide/src/com/jetbrains/python/newProject/actions/AbstractProjectSettingsStep.java b/python/ide/src/com/jetbrains/python/newProject/actions/AbstractProjectSettingsStep.java
index d9f3cf24f0e5..6ba283caf199 100644
--- a/python/ide/src/com/jetbrains/python/newProject/actions/AbstractProjectSettingsStep.java
+++ b/python/ide/src/com/jetbrains/python/newProject/actions/AbstractProjectSettingsStep.java
@@ -8,6 +8,7 @@ import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.openapi.actionSystem.impl.ActionButtonWithText;
+import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
import com.intellij.openapi.project.DumbAware;
@@ -45,10 +46,12 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.border.Border;
+import javax.swing.border.LineBorder;
import javax.swing.event.DocumentEvent;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
+import java.awt.event.FocusEvent;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
@@ -62,9 +65,10 @@ abstract public class AbstractProjectSettingsStep extends AbstractActionWithPane
private boolean myInstallFramework;
private TextFieldWithBrowseButton myLocationField;
protected final File myProjectDirectory;
- private ActionButtonWithText myCreateButton;
+ private Button myCreateButton;
private JLabel myErrorLabel;
private AnAction myCreateAction;
+ private Sdk mySdk;
public AbstractProjectSettingsStep(DirectoryProjectGenerator projectGenerator, NullableConsumer<AbstractProjectSettingsStep> callback) {
super();
@@ -104,16 +108,24 @@ abstract public class AbstractProjectSettingsStep extends AbstractActionWithPane
@Override
public JPanel createPanel() {
- final JPanel mainPanel = new JPanel(new BorderLayout());
+ final JPanel basePanel = createBasePanel();
+ final JPanel mainPanel = new JPanel(new BorderLayout()) {
+ @Override
+ protected void paintComponent(Graphics g) {
+ myLocationField.requestFocus();
+ }
+ };
+
final JPanel scrollPanel = new JPanel(new BorderLayout());
- mainPanel.setPreferredSize(new Dimension(mainPanel.getPreferredSize().width, 400));
+ final DirectoryProjectGenerator[] generators = Extensions.getExtensions(DirectoryProjectGenerator.EP_NAME);
+ final int height = generators.length == 0 ? 150 : 400;
+ mainPanel.setPreferredSize(new Dimension(mainPanel.getPreferredSize().width, height));
myErrorLabel = new JLabel("");
myErrorLabel.setForeground(JBColor.RED);
myCreateButton = new Button(myCreateAction, myCreateAction.getTemplatePresentation());
- final JPanel panel = createBasePanel();
- scrollPanel.add(panel, BorderLayout.NORTH);
+ scrollPanel.add(basePanel, BorderLayout.NORTH);
final JPanel advancedSettings = createAdvancedSettings();
if (advancedSettings != null) {
scrollPanel.add(advancedSettings, BorderLayout.CENTER);
@@ -125,8 +137,6 @@ abstract public class AbstractProjectSettingsStep extends AbstractActionWithPane
final JPanel bottomPanel = new JPanel(new BorderLayout());
-
- myCreateButton.setPreferredSize(new Dimension(mainPanel.getPreferredSize().width, 40));
bottomPanel.add(myErrorLabel, BorderLayout.NORTH);
bottomPanel.add(myCreateButton, BorderLayout.EAST);
mainPanel.add(bottomPanel, BorderLayout.SOUTH);
@@ -150,7 +160,22 @@ abstract public class AbstractProjectSettingsStep extends AbstractActionWithPane
final FileChooserDescriptor descriptor = FileChooserDescriptorFactory.createSingleFolderDescriptor();
myLocationField.addBrowseFolderListener("Select base directory", "Select base directory for the Project",
null, descriptor);
-
+ myLocationField.getTextField().getDocument().addDocumentListener(new DocumentAdapter() {
+ @Override
+ protected void textChanged(DocumentEvent e) {
+ if (myProjectGenerator instanceof PythonProjectGenerator) {
+ String path = myLocationField.getText().trim();
+ if (path.endsWith(File.separator)) {
+ path = path.substring(0, path.length() - File.separator.length());
+ }
+ int ind = path.lastIndexOf(File.separator);
+ if (ind != -1) {
+ String projectName = path.substring(ind + 1, path.length());
+ ((PythonProjectGenerator)myProjectGenerator).locationChanged(projectName);
+ }
+ }
+ }
+ });
final JLabel locationLabel = new JLabel("Location:");
c.gridx = 0;
c.gridy = 0;
@@ -193,13 +218,23 @@ abstract public class AbstractProjectSettingsStep extends AbstractActionWithPane
c.gridy = 1;
c.weightx = 1.;
panel.add(mySdkCombo, c);
-
+ final JPanel basePanelExtension = extendBasePanel();
+ if (basePanelExtension != null) {
+ c.gridwidth = 2;
+ c.gridy = 2;
+ c.gridx = 0;
+ panel.add(basePanelExtension, c);
+ }
registerValidators();
return panel;
}
- protected void registerValidators() {
+ @Nullable
+ protected JPanel extendBasePanel() {
+ return null;
+ }
+ protected void registerValidators() {
myLocationField.getTextField().getDocument().addDocumentListener(new DocumentAdapter() {
@Override
protected void textChanged(DocumentEvent e) {
@@ -358,7 +393,8 @@ abstract public class AbstractProjectSettingsStep extends AbstractActionWithPane
public Button(AnAction action, Presentation presentation) {
super(action, presentation, "NewProject", new Dimension(70, 50));
- myBorder = UIUtil.isUnderDarcula() ? UIUtil.getButtonBorder() : BorderFactory.createLineBorder(UIUtil.getBorderColor());
+ final Border border = new LineBorder(JBColor.border(), 1, true);
+ myBorder = UIUtil.isUnderDarcula() ? UIUtil.getButtonBorder() : border;
setBorder(myBorder);
}
@@ -368,6 +404,23 @@ abstract public class AbstractProjectSettingsStep extends AbstractActionWithPane
}
@Override
+ public boolean isFocusable() {
+ return true;
+ }
+
+ @Override
+ protected void processFocusEvent(FocusEvent e) {
+ super.processFocusEvent(e);
+ if (e.getID() == FocusEvent.FOCUS_GAINED) {
+ processMouseEvent(new MouseEvent(this, MouseEvent.MOUSE_ENTERED, System.currentTimeMillis(), 0, 0, 0, 0, false));
+
+ }
+ else if (e.getID() == FocusEvent.FOCUS_LOST) {
+ processMouseEvent(new MouseEvent(this, MouseEvent.MOUSE_EXITED, System.currentTimeMillis(), 0, 0, 0, 0, false));
+ }
+ }
+
+ @Override
public Insets getInsets() {
return new Insets(5,10,5,5);
}
@@ -377,11 +430,6 @@ abstract public class AbstractProjectSettingsStep extends AbstractActionWithPane
return SwingConstants.LEFT;
}
- @Override
- public String getToolTipText() {
- return null;
- }
-
protected void processMouseEvent(MouseEvent e) {
super.processMouseEvent(e);
if (e.getID() == MouseEvent.MOUSE_ENTERED) {
@@ -394,9 +442,14 @@ abstract public class AbstractProjectSettingsStep extends AbstractActionWithPane
}
public Sdk getSdk() {
+ if (mySdk != null) return mySdk;
return (Sdk)mySdkCombo.getComboBox().getSelectedItem();
}
+ public void setSdk(final Sdk sdk) {
+ mySdk = sdk;
+ }
+
public String getProjectLocation() {
return myLocationField.getText();
}
diff --git a/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificSettingsStep.java b/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificSettingsStep.java
index ebd0658b072c..5e60601399bb 100644
--- a/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificSettingsStep.java
+++ b/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificSettingsStep.java
@@ -15,6 +15,7 @@
*/
package com.jetbrains.python.newProject.actions;
+import com.intellij.facet.ui.ValidationResult;
import com.intellij.ide.util.projectWizard.WebProjectTemplate;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.ui.VerticalFlowLayout;
@@ -46,6 +47,12 @@ public class ProjectSpecificSettingsStep extends AbstractProjectSettingsStep imp
if (advancedSettings != null) {
final JPanel jPanel = new JPanel(new VerticalFlowLayout());
final HideableDecorator deco = new HideableDecorator(jPanel, "Mor&e Settings", false);
+ boolean isValid = checkValid();
+ deco.setOn(!isValid);
+ if (myProjectGenerator instanceof PythonProjectGenerator && !deco.isExpanded()) {
+ final ValidationResult result = ((PythonProjectGenerator)myProjectGenerator).warningValidation(getSdk());
+ deco.setOn(!result.isOk());
+ }
deco.setContentComponent(advancedSettings);
return jPanel;
}
diff --git a/python/ide/src/com/jetbrains/python/newProject/actions/PyCharmNewProjectStep.java b/python/ide/src/com/jetbrains/python/newProject/actions/PyCharmNewProjectStep.java
index b6134ed5f070..4f9f1074df68 100644
--- a/python/ide/src/com/jetbrains/python/newProject/actions/PyCharmNewProjectStep.java
+++ b/python/ide/src/com/jetbrains/python/newProject/actions/PyCharmNewProjectStep.java
@@ -62,8 +62,8 @@ import java.util.List;
public class PyCharmNewProjectStep extends DefaultActionGroup implements DumbAware {
private static final Logger LOG = Logger.getInstance(PyCharmNewProjectStep.class);
- public PyCharmNewProjectStep(@Nullable final Runnable runnable) {
- super("Select Project Type", true);
+ public PyCharmNewProjectStep(@NotNull final String name, @Nullable final Runnable runnable) {
+ super(name, true);
final NullableConsumer<AbstractProjectSettingsStep> callback = new NullableConsumer<AbstractProjectSettingsStep>() {
@Override
@@ -87,6 +87,7 @@ public class PyCharmNewProjectStep extends DefaultActionGroup implements DumbAwa
sdk = SdkConfigurationUtil.setupSdk(ProjectJdkTable.getInstance().getAllJdks(), sdkHome, PythonSdkType.getInstance(), true, null,
null);
model.addSdk(sdk);
+ settingsStep.setSdk(sdk);
try {
model.apply();
}
@@ -165,6 +166,9 @@ public class PyCharmNewProjectStep extends DefaultActionGroup implements DumbAwa
add(action);
final DirectoryProjectGenerator[] generators = Extensions.getExtensions(DirectoryProjectGenerator.EP_NAME);
+ if (generators.length == 0) {
+ action.setPopup(false);
+ }
Arrays.sort(generators, new Comparator<DirectoryProjectGenerator>() {
@Override
public int compare(DirectoryProjectGenerator o1, DirectoryProjectGenerator o2) {
@@ -188,7 +192,7 @@ public class PyCharmNewProjectStep extends DefaultActionGroup implements DumbAwa
}
public PyCharmNewProjectStep() {
- this(null);
+ this("Select Project Type", null);
}
diff --git a/python/openapi/src/com/jetbrains/python/newProject/PythonProjectGenerator.java b/python/openapi/src/com/jetbrains/python/newProject/PythonProjectGenerator.java
index 5577959178ce..1432e468f3e8 100644
--- a/python/openapi/src/com/jetbrains/python/newProject/PythonProjectGenerator.java
+++ b/python/openapi/src/com/jetbrains/python/newProject/PythonProjectGenerator.java
@@ -31,6 +31,8 @@ public abstract class PythonProjectGenerator {
myListeners.add(listener);
}
+ public void locationChanged(@NotNull final String newLocation) {}
+
public interface SettingsListener {
void stateChanged();
}
diff --git a/python/psi-api/src/com/jetbrains/python/psi/PyElementGenerator.java b/python/psi-api/src/com/jetbrains/python/psi/PyElementGenerator.java
index 9f6e7c9ff021..daa8b3063014 100644
--- a/python/psi-api/src/com/jetbrains/python/psi/PyElementGenerator.java
+++ b/python/psi-api/src/com/jetbrains/python/psi/PyElementGenerator.java
@@ -37,15 +37,17 @@ public abstract class PyElementGenerator {
public abstract PyStringLiteralExpression createStringLiteralAlreadyEscaped(String str);
-
-
/**
* Creates a string literal, adding appropriate quotes, properly escaping characters inside.
+ *
* @param destination where the literal is destined to; used to determine the encoding.
* @param unescaped the string
- * @return a newly created literal
+ * @param preferUTF8 try to use UTF8 (would use ascii if false)
+ * @return a newly created literal
*/
- public abstract PyStringLiteralExpression createStringLiteralFromString(@Nullable PsiFile destination, String unescaped);
+ public abstract PyStringLiteralExpression createStringLiteralFromString(@Nullable PsiFile destination, String unescaped,
+ boolean preferUTF8);
+
public abstract PyStringLiteralExpression createStringLiteralFromString(@NotNull String unescaped);
public abstract PyStringLiteralExpression createStringLiteral(@NotNull PyStringLiteralExpression oldElement, @NotNull String unescaped);
@@ -59,11 +61,11 @@ public abstract class PyElementGenerator {
public abstract PyBinaryExpression createBinaryExpression(String s, PyExpression expr, PyExpression listLiteral);
/**
- * @deprecated use the overload with language level specified
* @param text the text to create an expression from
* @return the expression
+ * @deprecated use the overload with language level specified
*/
- public abstract PyExpression createExpressionFromText(String text);
+ public abstract PyExpression createExpressionFromText(String text);
public abstract PyExpression createExpressionFromText(final LanguageLevel languageLevel, String text);
@@ -71,9 +73,9 @@ public abstract class PyElementGenerator {
* Adds elements to list inserting required commas.
* Method is like {@link #insertItemIntoList(PyElement, PyExpression, PyExpression)} but does not add unneeded commas.
*
- * @param list where to add
+ * @param list where to add
* @param afterThis after which element it should be added (null for add to the head)
- * @param toInsert what to insert
+ * @param toInsert what to insert
* @return newly inserted element
*/
@NotNull
@@ -92,7 +94,10 @@ public abstract class PyElementGenerator {
public abstract PyImportElement createImportElement(final LanguageLevel languageLevel, String name);
- public abstract PyFunction createProperty(final LanguageLevel languageLevel, String propertyName, String fieldName, AccessDirection accessDirection);
+ public abstract PyFunction createProperty(final LanguageLevel languageLevel,
+ String propertyName,
+ String fieldName,
+ AccessDirection accessDirection);
@NotNull
public abstract <T> T createFromText(LanguageLevel langLevel, Class<T> aClass, final String text);
@@ -103,6 +108,7 @@ public abstract class PyElementGenerator {
/**
* Creates an arbitrary PSI element from text, by creating a bigger construction and then cutting the proper subelement.
* Will produce all kinds of exceptions if the path or class would not match the PSI tree.
+ *
* @param langLevel the language level to use for parsing the text
* @param aClass class of the PSI element; may be an interface not descending from PsiElement, as long as target node can be cast to it
* @param text text to parse
@@ -122,8 +128,15 @@ public abstract class PyElementGenerator {
public abstract PsiFile createDummyFile(LanguageLevel langLevel, String contents);
public abstract PyExpressionStatement createDocstring(String content);
+
public abstract PyPassStatement createPassStatement();
@NotNull
public abstract PyDecoratorList createDecoratorList(@NotNull final String... decoratorTexts);
+
+ /**
+ * Creates new line whitespace
+ */
+ @NotNull
+ public abstract PsiElement createNewLine();
}
diff --git a/python/psi-api/src/com/jetbrains/python/psi/PyElsePart.java b/python/psi-api/src/com/jetbrains/python/psi/PyElsePart.java
index c32916242154..41b715f99aa8 100644
--- a/python/psi-api/src/com/jetbrains/python/psi/PyElsePart.java
+++ b/python/psi-api/src/com/jetbrains/python/psi/PyElsePart.java
@@ -15,17 +15,10 @@
*/
package com.jetbrains.python.psi;
-import org.jetbrains.annotations.Nullable;
-
/**
* The 'else:' part of various compound statements.
* User: dcheryasov
* Date: Mar 15, 2009 9:34:51 PM
*/
public interface PyElsePart extends PyStatementPart {
- /**
- * @return the body of the 'else' part.
- */
- @Nullable
- PyStatementList getStatementList();
}
diff --git a/python/psi-api/src/com/jetbrains/python/psi/PyStatementPart.java b/python/psi-api/src/com/jetbrains/python/psi/PyStatementPart.java
index f491a6a83688..a14a91ef9f9c 100644
--- a/python/psi-api/src/com/jetbrains/python/psi/PyStatementPart.java
+++ b/python/psi-api/src/com/jetbrains/python/psi/PyStatementPart.java
@@ -15,19 +15,19 @@
*/
package com.jetbrains.python.psi;
-import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.NotNull;
/**
* Abstract part of a multipart statement.
* User: dcheryasov
* Date: Mar 16, 2009 4:34:59 AM
*/
-public interface PyStatementPart extends PyElement {
+public interface PyStatementPart extends PyElement, PyStatementListContainer {
PyStatementPart[] EMPTY_ARRAY = new PyStatementPart[0];
/**
* @return the body of the part.
*/
- @Nullable
+ @NotNull
PyStatementList getStatementList();
}
diff --git a/python/psi-api/src/com/jetbrains/python/psi/PyWithStatement.java b/python/psi-api/src/com/jetbrains/python/psi/PyWithStatement.java
index 201ae3046785..b23ca63b6c95 100644
--- a/python/psi-api/src/com/jetbrains/python/psi/PyWithStatement.java
+++ b/python/psi-api/src/com/jetbrains/python/psi/PyWithStatement.java
@@ -18,6 +18,6 @@ package com.jetbrains.python.psi;
/**
* @author yole
*/
-public interface PyWithStatement extends PyStatement, NameDefiner {
+public interface PyWithStatement extends PyStatement, NameDefiner, PyStatementListContainer {
PyWithItem[] getWithItems();
}
diff --git a/python/psi-api/src/com/jetbrains/python/psi/StructuredDocString.java b/python/psi-api/src/com/jetbrains/python/psi/StructuredDocString.java
index fa8881062ac3..808ec477e89a 100644
--- a/python/psi-api/src/com/jetbrains/python/psi/StructuredDocString.java
+++ b/python/psi-api/src/com/jetbrains/python/psi/StructuredDocString.java
@@ -25,6 +25,15 @@ import java.util.List;
* @author vlan
*/
public interface StructuredDocString {
+ /**
+ * Creates parameter type documentation specific for certain doct type
+ * @param name param name
+ * @param type param type
+ * @return text to add to docsting
+ */
+ @NotNull
+ String createParameterType(@NotNull String name, @NotNull String type);
+
String getDescription();
String getSummary();
diff --git a/python/python-rest/src/com/jetbrains/rest/run/RestCommandLineState.java b/python/python-rest/src/com/jetbrains/rest/run/RestCommandLineState.java
index e421df82d4f7..e5b52b5dc3a7 100644
--- a/python/python-rest/src/com/jetbrains/rest/run/RestCommandLineState.java
+++ b/python/python-rest/src/com/jetbrains/rest/run/RestCommandLineState.java
@@ -19,7 +19,6 @@ import com.intellij.execution.ExecutionException;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.configurations.ParametersList;
import com.intellij.execution.configurations.ParamsGroup;
-import com.intellij.execution.filters.Filter;
import com.intellij.execution.process.ProcessAdapter;
import com.intellij.execution.process.ProcessEvent;
import com.intellij.execution.process.ProcessHandler;
@@ -33,7 +32,6 @@ import com.jetbrains.python.run.PythonProcessRunner;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
-import java.util.Collections;
/**
* User : catherine
@@ -43,7 +41,7 @@ public abstract class RestCommandLineState extends PythonCommandLineState {
public RestCommandLineState(RestRunConfiguration configuration,
ExecutionEnvironment env) {
- super(configuration, env, Collections.<Filter>emptyList());
+ super(configuration, env);
myConfiguration = configuration;
}
diff --git a/python/src/META-INF/python-core.xml b/python/src/META-INF/python-core.xml
index 88280cc2cf10..a27eb44ae3af 100644
--- a/python/src/META-INF/python-core.xml
+++ b/python/src/META-INF/python-core.xml
@@ -528,6 +528,12 @@
<!-- Packaging -->
<moduleService serviceInterface="com.jetbrains.python.packaging.PyPackageRequirementsSettings"
serviceImplementation="com.jetbrains.python.packaging.PyPackageRequirementsSettings"/>
+
+ <!-- Console -->
+ <toolWindow id="Python Console" anchor="bottom" icon=""
+ factoryClass="com.jetbrains.python.console.PythonConsoleToolWindowFactory" secondary="false"/>
+
+
</extensions>
<extensionPoints>
@@ -615,6 +621,12 @@
</component>
</project-components>
+ <project-components>
+ <component>
+ <implementation-class>com.jetbrains.python.console.PythonConsoleToolWindow</implementation-class>
+ </component>
+ </project-components>
+
<actions>
<group id="PyTypeHierarchyPopupMenu">
<reference ref="TypeHierarchyBase.BaseOnThisType"/>
diff --git a/python/src/com/jetbrains/python/PyAddImportFix.java b/python/src/com/jetbrains/python/PyAddImportFix.java
new file mode 100644
index 000000000000..c13fed13fdcb
--- /dev/null
+++ b/python/src/com/jetbrains/python/PyAddImportFix.java
@@ -0,0 +1,55 @@
+package com.jetbrains.python;
+
+import com.intellij.codeInspection.LocalQuickFix;
+import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiElement;
+import com.jetbrains.python.codeInsight.imports.AddImportHelper;
+import com.jetbrains.python.psi.LanguageLevel;
+import com.jetbrains.python.psi.PyElementGenerator;
+import com.jetbrains.python.psi.PyFile;
+import com.jetbrains.python.psi.PyImportStatementBase;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Quick fix that adds import to file
+ *
+ * @author Ilya.Kazakevich
+ */
+public class PyAddImportFix implements LocalQuickFix {
+ @NotNull
+ private final String myImportToAdd;
+ @NotNull
+ private final PyFile myFile;
+
+ /**
+ * @param importToAdd string representing what to add (i.e. "from foo import bar")
+ * @param file where to add
+ */
+ public PyAddImportFix(@NotNull final String importToAdd, @NotNull final PyFile file) {
+ myImportToAdd = importToAdd;
+ myFile = file;
+ }
+
+ @NotNull
+ @Override
+ public String getName() {
+ return PyBundle.message("QFIX.add.import", myImportToAdd);
+ }
+
+ @NotNull
+ @Override
+ public String getFamilyName() {
+ return getName();
+ }
+
+ @Override
+ public void applyFix(@NotNull final Project project, @NotNull final ProblemDescriptor descriptor) {
+ final PyElementGenerator generator = PyElementGenerator.getInstance(project);
+ final PyImportStatementBase statement =
+ generator.createFromText(LanguageLevel.forElement(myFile), PyImportStatementBase.class, myImportToAdd);
+ final PsiElement recommendedPosition = AddImportHelper.getFileInsertPosition(myFile);
+ myFile.addAfter(statement, recommendedPosition);
+ }
+}
+
diff --git a/python/src/com/jetbrains/python/PyBundle.properties b/python/src/com/jetbrains/python/PyBundle.properties
index 5d29d3f79d50..482daa88b66c 100644
--- a/python/src/com/jetbrains/python/PyBundle.properties
+++ b/python/src/com/jetbrains/python/PyBundle.properties
@@ -32,6 +32,8 @@ QFIX.create.property=Create property
QFIX.add.encoding=Add encoding declaration
+QFIX.add.import=Add "''{0}''"
+
QFIX.NAME.parameters=Parameters of functions and methods
QFIX.rename.parameter.to.$0=Rename to ''{0}''
diff --git a/python/src/com/jetbrains/python/actions/ExecuteInConsoleAction.java b/python/src/com/jetbrains/python/actions/ExecuteInConsoleAction.java
index 58b35fe5f591..cb90d498e663 100644
--- a/python/src/com/jetbrains/python/actions/ExecuteInConsoleAction.java
+++ b/python/src/com/jetbrains/python/actions/ExecuteInConsoleAction.java
@@ -17,7 +17,6 @@ package com.jetbrains.python.actions;
import com.intellij.execution.ExecutionHelper;
import com.intellij.execution.console.LanguageConsoleView;
-import com.intellij.execution.console.LanguageConsoleViewImpl;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.openapi.actionSystem.*;
@@ -215,7 +214,7 @@ public class ExecuteInConsoleAction extends AnAction {
private static void startConsole(final Project project,
final Consumer<PyCodeExecutor> consumer,
Module context) {
- PydevConsoleRunner runner = RunPythonConsoleAction.runPythonConsole(project, context);
+ PydevConsoleRunner runner = RunPythonConsoleAction.runPythonConsole(project, context, null);
runner.addConsoleListener(new PydevConsoleRunner.ConsoleListener() {
@Override
public void handleConsoleInitialized(LanguageConsoleView consoleView) {
diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/PySmartEnterProcessor.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/PySmartEnterProcessor.java
index e27f2a638899..2785b23afc56 100644
--- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/PySmartEnterProcessor.java
+++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/PySmartEnterProcessor.java
@@ -79,7 +79,7 @@ public class PySmartEnterProcessor extends SmartEnterProcessor {
}
final PsiElement[] children = element.getChildren();
- for (PsiElement child : children) {
+ for (final PsiElement child : children) {
if (element instanceof PyStatement && child instanceof PyStatement) {
continue;
}
diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/enterProcessors/PyPlainEnterProcessor.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/enterProcessors/PyPlainEnterProcessor.java
index ac2e31252dcf..ccdcf1b93f2a 100644
--- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/enterProcessors/PyPlainEnterProcessor.java
+++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/enterProcessors/PyPlainEnterProcessor.java
@@ -20,7 +20,9 @@ import com.intellij.openapi.editor.Editor;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
import com.jetbrains.python.codeInsight.editorActions.smartEnter.SmartEnterUtil;
-import com.jetbrains.python.psi.*;
+import com.jetbrains.python.psi.PyStatementList;
+import com.jetbrains.python.psi.PyStatementListContainer;
+import com.jetbrains.python.psi.PyStatementPart;
import org.jetbrains.annotations.Nullable;
/**
@@ -32,17 +34,8 @@ import org.jetbrains.annotations.Nullable;
public class PyPlainEnterProcessor implements EnterProcessor {
@Nullable
private static PyStatementList getStatementList(PsiElement psiElement, Editor editor) {
- if (psiElement instanceof PyStatementPart) {
- return ((PyStatementPart)psiElement).getStatementList();
- }
- else if (psiElement instanceof PyFunction) {
- return ((PyFunction)psiElement).getStatementList();
- }
- else if (psiElement instanceof PyClass) {
- return ((PyClass)psiElement).getStatementList();
- }
- else if (psiElement instanceof PyWithStatement) {
- return PsiTreeUtil.getChildOfType(psiElement, PyStatementList.class);
+ if (psiElement instanceof PyStatementListContainer) {
+ return ((PyStatementListContainer)psiElement).getStatementList();
}
else {
final CaretModel caretModel = editor.getCaretModel();
diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyArgumentListFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyArgumentListFixer.java
index f7d877e5bb5b..de90fa158bab 100644
--- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyArgumentListFixer.java
+++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyArgumentListFixer.java
@@ -25,26 +25,30 @@ import com.jetbrains.python.psi.PyArgumentList;
import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyDecorator;
import com.jetbrains.python.psi.PyUtil;
+import org.jetbrains.annotations.NotNull;
/**
* @author Alexey.Ivanov
*/
-public class PyArgumentListFixer implements PyFixer {
- public void apply(Editor editor, PySmartEnterProcessor processor, PsiElement psiElement) throws IncorrectOperationException {
- if (psiElement instanceof PyArgumentList) {
- final PsiElement rBrace = PyUtil.getChildByFilter(psiElement, PyTokenTypes.CLOSE_BRACES, 0);
- if (psiElement.getParent() instanceof PyClass || psiElement.getParent() instanceof PyDecorator) {
- final PsiElement lBrace = PyUtil.getChildByFilter(psiElement, PyTokenTypes.OPEN_BRACES, 0);
- if (lBrace != null && rBrace == null) {
- final Document document = editor.getDocument();
- document.insertString(psiElement.getTextRange().getEndOffset(), ")");
- }
+public class PyArgumentListFixer extends PyFixer<PyArgumentList> {
+ public PyArgumentListFixer() {
+ super(PyArgumentList.class);
+ }
+
+ @Override
+ public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyArgumentList arguments) throws IncorrectOperationException {
+ final PsiElement rBrace = PyUtil.getChildByFilter(arguments, PyTokenTypes.CLOSE_BRACES, 0);
+ if (arguments.getParent() instanceof PyClass || arguments.getParent() instanceof PyDecorator) {
+ final PsiElement lBrace = PyUtil.getChildByFilter(arguments, PyTokenTypes.OPEN_BRACES, 0);
+ if (lBrace != null && rBrace == null) {
+ final Document document = editor.getDocument();
+ document.insertString(arguments.getTextRange().getEndOffset(), ")");
}
- else {
- if (rBrace == null) {
- final Document document = editor.getDocument();
- document.insertString(psiElement.getTextRange().getEndOffset(), ")");
- }
+ }
+ else {
+ if (rBrace == null) {
+ final Document document = editor.getDocument();
+ document.insertString(arguments.getTextRange().getEndOffset(), ")");
}
}
}
diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyClassFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyClassFixer.java
index b9846e1cb894..ce51d6d46824 100644
--- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyClassFixer.java
+++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyClassFixer.java
@@ -17,7 +17,6 @@ package com.jetbrains.python.codeInsight.editorActions.smartEnter.fixers;
import com.intellij.openapi.editor.Editor;
import com.intellij.psi.PsiElement;
-import com.intellij.psi.tree.TokenSet;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
import com.jetbrains.python.PyTokenTypes;
@@ -25,6 +24,9 @@ import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterPro
import com.jetbrains.python.psi.PyArgumentList;
import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyUtil;
+import org.jetbrains.annotations.NotNull;
+
+import static com.jetbrains.python.psi.PyUtil.sure;
/**
* Created by IntelliJ IDEA.
@@ -32,21 +34,22 @@ import com.jetbrains.python.psi.PyUtil;
* Date: 16.04.2010
* Time: 18:41:08
*/
-public class PyClassFixer implements PyFixer {
- public void apply(Editor editor, PySmartEnterProcessor processor, PsiElement psiElement) throws IncorrectOperationException {
- if (psiElement instanceof PyClass) {
- final PsiElement colon = PyUtil.getChildByFilter(psiElement, TokenSet.create(PyTokenTypes.COLON), 0);
- if (colon == null) {
- final PyClass aClass = (PyClass)psiElement;
- final PyArgumentList argList = PsiTreeUtil.getChildOfType(aClass, PyArgumentList.class);
- int offset = argList.getTextRange().getEndOffset();
- String textToInsert = ":";
- if (aClass.getNameNode() == null) {
- processor.registerUnresolvedError(argList.getTextRange().getEndOffset() + 1);
- textToInsert = " :";
- }
- editor.getDocument().insertString(offset, textToInsert);
+public class PyClassFixer extends PyFixer<PyClass> {
+ public PyClassFixer() {
+ super(PyClass.class);
+ }
+
+ public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyClass pyClass) throws IncorrectOperationException {
+ final PsiElement colon = PyUtil.getFirstChildOfType(pyClass, PyTokenTypes.COLON);
+ if (colon == null) {
+ final PyArgumentList argList = PsiTreeUtil.getChildOfType(pyClass, PyArgumentList.class);
+ final int offset = sure(argList).getTextRange().getEndOffset();
+ String textToInsert = ":";
+ if (pyClass.getNameNode() == null) {
+ processor.registerUnresolvedError(argList.getTextRange().getEndOffset() + 1);
+ textToInsert = " :";
}
+ editor.getDocument().insertString(offset, textToInsert);
}
}
}
diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyConditionalStatementPartFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyConditionalStatementPartFixer.java
index 2885c63f6345..f71c61261103 100644
--- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyConditionalStatementPartFixer.java
+++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyConditionalStatementPartFixer.java
@@ -25,6 +25,9 @@ import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterPro
import com.jetbrains.python.psi.PyConditionalStatementPart;
import com.jetbrains.python.psi.PyExpression;
import com.jetbrains.python.psi.PyUtil;
+import org.jetbrains.annotations.NotNull;
+
+import static com.jetbrains.python.psi.PyUtil.sure;
/**
* Created by IntelliJ IDEA.
@@ -32,31 +35,35 @@ import com.jetbrains.python.psi.PyUtil;
* Date: 15.04.2010
* Time: 19:33:14
*/
-public class PyConditionalStatementPartFixer implements PyFixer {
- public void apply(Editor editor, PySmartEnterProcessor processor, PsiElement psiElement) throws IncorrectOperationException {
- if (psiElement instanceof PyConditionalStatementPart) {
- final PyConditionalStatementPart conditionalStatementPart = (PyConditionalStatementPart)psiElement;
- final PyExpression condition = conditionalStatementPart.getCondition();
- final Document document = editor.getDocument();
- final PsiElement colon = PyUtil.getChildByFilter(conditionalStatementPart, TokenSet.create(PyTokenTypes.COLON), 0);
- if (colon == null) {
- if (condition != null) {
- final PsiElement firstNonComment = PyUtil.getFirstNonCommentAfter(condition.getNextSibling());
- if (firstNonComment != null && !":".equals(firstNonComment.getNode().getText())) {
- document.insertString(firstNonComment.getTextRange().getEndOffset(), ":");
- }
- }
- else {
- final PsiElement keywordToken = PyUtil.getChildByFilter(conditionalStatementPart,
- TokenSet.create(PyTokenTypes.IF_KEYWORD, PyTokenTypes.ELIF_KEYWORD,
- PyTokenTypes.WHILE_KEYWORD), 0);
- final int offset = keywordToken.getTextRange().getEndOffset();
- document.insertString(offset, " :");
- processor.registerUnresolvedError(offset + 1);
+public class PyConditionalStatementPartFixer extends PyFixer<PyConditionalStatementPart> {
+ public PyConditionalStatementPartFixer() {
+ super(PyConditionalStatementPart.class);
+ }
+
+ @Override
+ public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyConditionalStatementPart statementPart)
+ throws IncorrectOperationException {
+ final PyExpression condition = statementPart.getCondition();
+ final Document document = editor.getDocument();
+ final PsiElement colon = PyUtil.getFirstChildOfType(statementPart, PyTokenTypes.COLON);
+ if (colon == null) {
+ if (condition != null) {
+ final PsiElement firstNonComment = PyUtil.getFirstNonCommentAfter(condition.getNextSibling());
+ if (firstNonComment != null && !":".equals(firstNonComment.getNode().getText())) {
+ document.insertString(firstNonComment.getTextRange().getEndOffset(), ":");
}
- } else if (condition == null) {
- processor.registerUnresolvedError(colon.getTextRange().getStartOffset());
}
+ else {
+ final TokenSet keywords = TokenSet.create(PyTokenTypes.IF_KEYWORD, PyTokenTypes.ELIF_KEYWORD, PyTokenTypes.WHILE_KEYWORD);
+ final PsiElement keywordToken = PyUtil.getChildByFilter(statementPart,
+ keywords, 0);
+ final int offset = sure(keywordToken).getTextRange().getEndOffset();
+ document.insertString(offset, " :");
+ processor.registerUnresolvedError(offset + 1);
+ }
+ }
+ else if (condition == null) {
+ processor.registerUnresolvedError(colon.getTextRange().getStartOffset());
}
}
}
diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyExceptFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyExceptFixer.java
index 8e3532cb49b3..67d5ff5c9ee5 100644
--- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyExceptFixer.java
+++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyExceptFixer.java
@@ -17,13 +17,15 @@ package com.jetbrains.python.codeInsight.editorActions.smartEnter.fixers;
import com.intellij.openapi.editor.Editor;
import com.intellij.psi.PsiElement;
-import com.intellij.psi.tree.TokenSet;
import com.intellij.util.IncorrectOperationException;
import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor;
import com.jetbrains.python.psi.PyExceptPart;
import com.jetbrains.python.psi.PyExpression;
import com.jetbrains.python.psi.PyUtil;
+import org.jetbrains.annotations.NotNull;
+
+import static com.jetbrains.python.psi.PyUtil.sure;
/**
* Created by IntelliJ IDEA.
@@ -31,24 +33,26 @@ import com.jetbrains.python.psi.PyUtil;
* Date: 22.04.2010
* Time: 18:13:34
*/
-public class PyExceptFixer implements PyFixer {
- public void apply(Editor editor, PySmartEnterProcessor processor, PsiElement psiElement) throws IncorrectOperationException {
- if (psiElement instanceof PyExceptPart) {
- PyExceptPart exceptPart = (PyExceptPart)psiElement;
- final PsiElement colon = PyUtil.getChildByFilter(exceptPart, TokenSet.create(PyTokenTypes.COLON), 0);
- if (colon == null) {
- int offset = PyUtil.getChildByFilter(exceptPart,
- TokenSet.create(PyTokenTypes.EXCEPT_KEYWORD), 0).getTextRange().getEndOffset();
- final PyExpression exceptClass = exceptPart.getExceptClass();
- if (exceptClass != null) {
- offset = exceptClass.getTextRange().getEndOffset();
- }
- final PyExpression target = exceptPart.getTarget();
- if (target != null) {
- offset = target.getTextRange().getEndOffset();
- }
- editor.getDocument().insertString(offset, ":");
+public class PyExceptFixer extends PyFixer<PyExceptPart> {
+ public PyExceptFixer() {
+ super(PyExceptPart.class);
+ }
+
+ @Override
+ public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyExceptPart exceptPart) throws IncorrectOperationException {
+ final PsiElement colon = PyUtil.getFirstChildOfType(exceptPart, PyTokenTypes.COLON);
+ if (colon == null) {
+ final PsiElement exceptToken = PyUtil.getFirstChildOfType(exceptPart, PyTokenTypes.EXCEPT_KEYWORD);
+ int offset = sure(exceptToken).getTextRange().getEndOffset();
+ final PyExpression exceptClass = exceptPart.getExceptClass();
+ if (exceptClass != null) {
+ offset = exceptClass.getTextRange().getEndOffset();
+ }
+ final PyExpression target = exceptPart.getTarget();
+ if (target != null) {
+ offset = target.getTextRange().getEndOffset();
}
+ editor.getDocument().insertString(offset, ":");
}
}
}
diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyFixer.java
index f02831d92d36..0ebdceb20e37 100644
--- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyFixer.java
+++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyFixer.java
@@ -19,6 +19,8 @@ import com.intellij.openapi.editor.Editor;
import com.intellij.psi.PsiElement;
import com.intellij.util.IncorrectOperationException;
import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor;
+import com.jetbrains.python.psi.PyElement;
+import org.jetbrains.annotations.NotNull;
/**
* Created by IntelliJ IDEA.
@@ -26,6 +28,20 @@ import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterPro
* Date: 15.04.2010
* Time: 17:10:33
*/
-public interface PyFixer {
- void apply(Editor editor, PySmartEnterProcessor processor, PsiElement psiElement) throws IncorrectOperationException;
+public abstract class PyFixer<T extends PyElement> {
+ private final Class<T> myClass;
+
+ public PyFixer(@NotNull Class<T> aClass) {
+ myClass = aClass;
+ }
+
+ public final void apply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PsiElement element)
+ throws IncorrectOperationException {
+ if (myClass.isInstance(element)) {
+ //noinspection unchecked
+ doApply(editor, processor, (T)element);
+ }
+ }
+
+ public abstract void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull T element);
}
diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyForPartFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyForPartFixer.java
index 1b8b438c68fd..eefe5cd1fc3e 100644
--- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyForPartFixer.java
+++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyForPartFixer.java
@@ -18,12 +18,13 @@ package com.jetbrains.python.codeInsight.editorActions.smartEnter.fixers;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.psi.PsiElement;
-import com.intellij.psi.tree.TokenSet;
-import com.intellij.util.IncorrectOperationException;
import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor;
import com.jetbrains.python.psi.PyForPart;
import com.jetbrains.python.psi.PyUtil;
+import org.jetbrains.annotations.NotNull;
+
+import static com.jetbrains.python.psi.PyUtil.sure;
/**
* Created by IntelliJ IDEA.
@@ -31,41 +32,42 @@ import com.jetbrains.python.psi.PyUtil;
* Date: 16.04.2010
* Time: 16:03:43
*/
-public class PyForPartFixer implements PyFixer {
- public void apply(Editor editor, PySmartEnterProcessor processor, PsiElement psiElement) throws IncorrectOperationException {
- if (psiElement instanceof PyForPart) {
- final PyForPart forPart = (PyForPart)psiElement;
- final PsiElement colon = PyUtil.getChildByFilter(psiElement, TokenSet.create(PyTokenTypes.COLON), 0);
- final Document document = editor.getDocument();
- final PsiElement forToken = PyUtil.getChildByFilter(forPart,
- TokenSet.create(PyTokenTypes.FOR_KEYWORD), 0);
- if (colon == null) {
- String textToInsert = ":";
- PsiElement sourceOrTarget = forPart.getSource();
- PsiElement positionToInsert = sourceOrTarget;
- if (sourceOrTarget == null) {
- sourceOrTarget = forPart.getTarget();
- final PsiElement inToken = PyUtil.getChildByFilter(forPart, TokenSet.create(PyTokenTypes.IN_KEYWORD), 0);
- if (inToken == null) {
- if (sourceOrTarget == null) {
- positionToInsert = forToken;
- textToInsert = " in :";
- processor.registerUnresolvedError(positionToInsert.getTextRange().getEndOffset() + 1);
- }
- else {
- positionToInsert = sourceOrTarget;
- textToInsert = " in :";
- processor.registerUnresolvedError(positionToInsert.getTextRange().getEndOffset() + 4);
- }
+public class PyForPartFixer extends PyFixer<PyForPart> {
+ public PyForPartFixer() {
+ super(PyForPart.class);
+ }
+
+ @Override
+ public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyForPart forPart) {
+ final PsiElement colon = PyUtil.getFirstChildOfType(forPart, PyTokenTypes.COLON);
+ final Document document = editor.getDocument();
+ final PsiElement forToken = PyUtil.getFirstChildOfType(forPart, PyTokenTypes.FOR_KEYWORD);
+ if (colon == null) {
+ String textToInsert = ":";
+ PsiElement sourceOrTarget = forPart.getSource();
+ PsiElement positionToInsert = sourceOrTarget;
+ if (sourceOrTarget == null) {
+ sourceOrTarget = forPart.getTarget();
+ final PsiElement inToken = PyUtil.getFirstChildOfType(forPart, PyTokenTypes.IN_KEYWORD);
+ if (inToken == null) {
+ if (sourceOrTarget == null) {
+ positionToInsert = sure(forToken);
+ textToInsert = " in :";
+ processor.registerUnresolvedError(positionToInsert.getTextRange().getEndOffset() + 1);
}
else {
- positionToInsert = inToken;
- textToInsert = " :";
- processor.registerUnresolvedError(positionToInsert.getTextRange().getEndOffset() + 1);
+ positionToInsert = sourceOrTarget;
+ textToInsert = " in :";
+ processor.registerUnresolvedError(positionToInsert.getTextRange().getEndOffset() + 4);
}
}
- document.insertString(positionToInsert.getTextRange().getEndOffset(), textToInsert);
+ else {
+ positionToInsert = inToken;
+ textToInsert = " :";
+ processor.registerUnresolvedError(positionToInsert.getTextRange().getEndOffset() + 1);
+ }
}
+ document.insertString(positionToInsert.getTextRange().getEndOffset(), textToInsert);
}
}
}
diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyFunctionFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyFunctionFixer.java
index f1988e13f57a..ad959f80ccae 100644
--- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyFunctionFixer.java
+++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyFunctionFixer.java
@@ -18,13 +18,13 @@ package com.jetbrains.python.codeInsight.editorActions.smartEnter.fixers;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.psi.PsiElement;
-import com.intellij.psi.tree.TokenSet;
import com.intellij.util.IncorrectOperationException;
import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor;
import com.jetbrains.python.psi.PyFunction;
import com.jetbrains.python.psi.PyParameterList;
import com.jetbrains.python.psi.PyUtil;
+import org.jetbrains.annotations.NotNull;
/**
* Created by IntelliJ IDEA.
@@ -32,16 +32,19 @@ import com.jetbrains.python.psi.PyUtil;
* Date: 16.04.2010
* Time: 16:59:07
*/
-public class PyFunctionFixer implements PyFixer {
- public void apply(Editor editor, PySmartEnterProcessor processor, PsiElement psiElement) throws IncorrectOperationException {
- if (psiElement instanceof PyFunction) {
- final PsiElement colon = PyUtil.getChildByFilter(psiElement, TokenSet.create(PyTokenTypes.COLON), 0);
- if (colon == null) {
- final PyFunction function = (PyFunction)psiElement;
- final PyParameterList parameterList = function.getParameterList();
- final Document document = editor.getDocument();
- document.insertString(parameterList.getTextRange().getEndOffset(), ":");
- }
+public class PyFunctionFixer extends PyFixer<PyFunction> {
+ public PyFunctionFixer() {
+ super(PyFunction.class);
+ }
+
+ @Override
+ public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyFunction function)
+ throws IncorrectOperationException {
+ final PsiElement colon = PyUtil.getFirstChildOfType(function, PyTokenTypes.COLON);
+ if (colon == null) {
+ final PyParameterList parameterList = function.getParameterList();
+ final Document document = editor.getDocument();
+ document.insertString(parameterList.getTextRange().getEndOffset(), ":");
}
}
}
diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyMissingBracesFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyMissingBracesFixer.java
index 0d8565d6960d..eb97d2bdb372 100644
--- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyMissingBracesFixer.java
+++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyMissingBracesFixer.java
@@ -20,6 +20,7 @@ import com.intellij.psi.PsiElement;
import com.intellij.util.IncorrectOperationException;
import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor;
import com.jetbrains.python.psi.*;
+import org.jetbrains.annotations.NotNull;
/**
* Created by IntelliJ IDEA.
@@ -27,10 +28,16 @@ import com.jetbrains.python.psi.*;
* Date: 15.04.2010
* Time: 17:55:46
*/
-public class PyMissingBracesFixer implements PyFixer {
- public void apply(Editor editor, PySmartEnterProcessor processor, PsiElement psiElement) throws IncorrectOperationException {
+public class PyMissingBracesFixer extends PyFixer<PyElement> {
+ public PyMissingBracesFixer() {
+ super(PyElement.class);
+ }
+
+ @Override
+ public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyElement psiElement)
+ throws IncorrectOperationException {
if (psiElement instanceof PySetLiteralExpression || psiElement instanceof PyDictLiteralExpression) {
- PsiElement lastChild = PyUtil.getFirstNonCommentBefore(psiElement.getLastChild());
+ final PsiElement lastChild = PyUtil.getFirstNonCommentBefore(psiElement.getLastChild());
if (lastChild != null && !"}".equals(lastChild.getText())) {
editor.getDocument().insertString(lastChild.getTextRange().getEndOffset(), "}");
}
@@ -38,7 +45,7 @@ public class PyMissingBracesFixer implements PyFixer {
else if (psiElement instanceof PyListLiteralExpression ||
psiElement instanceof PySliceExpression ||
psiElement instanceof PySubscriptionExpression) {
- PsiElement lastChild = PyUtil.getFirstNonCommentBefore(psiElement.getLastChild());
+ final PsiElement lastChild = PyUtil.getFirstNonCommentBefore(psiElement.getLastChild());
if (lastChild != null && !"]".equals(lastChild.getText())) {
editor.getDocument().insertString(lastChild.getTextRange().getEndOffset(), "]");
}
diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyParameterListFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyParameterListFixer.java
index 7b5970d7baf2..69a06b8b7c48 100644
--- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyParameterListFixer.java
+++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyParameterListFixer.java
@@ -23,6 +23,7 @@ import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor;
import com.jetbrains.python.psi.PyParameterList;
import com.jetbrains.python.psi.PyUtil;
+import org.jetbrains.annotations.NotNull;
/**
* Created by IntelliJ IDEA.
@@ -30,19 +31,22 @@ import com.jetbrains.python.psi.PyUtil;
* Date: 16.04.2010
* Time: 17:25:46
*/
-public class PyParameterListFixer implements PyFixer {
- public void apply(Editor editor, PySmartEnterProcessor processor, PsiElement psiElement) throws IncorrectOperationException {
- if (psiElement instanceof PyParameterList) {
- final PsiElement lBrace = PyUtil.getChildByFilter(psiElement, PyTokenTypes.OPEN_BRACES, 0);
- final PsiElement rBrace = PyUtil.getChildByFilter(psiElement, PyTokenTypes.CLOSE_BRACES, 0);
- if (lBrace == null || rBrace == null) {
- final Document document = editor.getDocument();
- if (lBrace == null) {
- document.insertString(psiElement.getTextRange().getStartOffset(), "(");
- }
- else {
- document.insertString(psiElement.getTextRange().getEndOffset(), ")");
- }
+public class PyParameterListFixer extends PyFixer<PyParameterList> {
+ public PyParameterListFixer() {
+ super(PyParameterList.class);
+ }
+
+ @Override
+ public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyParameterList psiElement) throws IncorrectOperationException {
+ final PsiElement lBrace = PyUtil.getChildByFilter(psiElement, PyTokenTypes.OPEN_BRACES, 0);
+ final PsiElement rBrace = PyUtil.getChildByFilter(psiElement, PyTokenTypes.CLOSE_BRACES, 0);
+ if (lBrace == null || rBrace == null) {
+ final Document document = editor.getDocument();
+ if (lBrace == null) {
+ document.insertString(psiElement.getTextRange().getStartOffset(), "(");
+ }
+ else {
+ document.insertString(psiElement.getTextRange().getEndOffset(), ")");
}
}
}
diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyParenthesizedFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyParenthesizedFixer.java
index a055375bc040..582e034c5603 100644
--- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyParenthesizedFixer.java
+++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyParenthesizedFixer.java
@@ -20,6 +20,7 @@ import com.intellij.psi.PsiElement;
import com.intellij.util.IncorrectOperationException;
import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor;
import com.jetbrains.python.psi.PyParenthesizedExpression;
+import org.jetbrains.annotations.NotNull;
/**
* Created by IntelliJ IDEA.
@@ -27,13 +28,17 @@ import com.jetbrains.python.psi.PyParenthesizedExpression;
* Date: 15.04.2010
* Time: 17:42:08
*/
-public class PyParenthesizedFixer implements PyFixer {
- public void apply(final Editor editor, final PySmartEnterProcessor processor, final PsiElement psiElement) throws IncorrectOperationException {
- if (psiElement instanceof PyParenthesizedExpression) {
- final PsiElement lastChild = psiElement.getLastChild();
- if (lastChild != null && !")".equals(lastChild.getText())) {
- editor.getDocument().insertString(psiElement.getTextRange().getEndOffset(), ")");
- }
+public class PyParenthesizedFixer extends PyFixer<PyParenthesizedExpression> {
+ public PyParenthesizedFixer() {
+ super(PyParenthesizedExpression.class);
+ }
+
+ @Override
+ public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyParenthesizedExpression expression)
+ throws IncorrectOperationException {
+ final PsiElement lastChild = expression.getLastChild();
+ if (lastChild != null && !")".equals(lastChild.getText())) {
+ editor.getDocument().insertString(expression.getTextRange().getEndOffset(), ")");
}
}
}
diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyStringLiteralFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyStringLiteralFixer.java
index 906aecd9c757..3e9925a86131 100644
--- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyStringLiteralFixer.java
+++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyStringLiteralFixer.java
@@ -17,10 +17,10 @@ package com.jetbrains.python.codeInsight.editorActions.smartEnter.fixers;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.psi.PsiElement;
import com.intellij.util.IncorrectOperationException;
import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor;
import com.jetbrains.python.psi.PyStringLiteralExpression;
+import org.jetbrains.annotations.NotNull;
/**
* Created by IntelliJ IDEA.
@@ -28,31 +28,35 @@ import com.jetbrains.python.psi.PyStringLiteralExpression;
* Date: 15.04.2010
* Time: 17:17:14
*/
-public class PyStringLiteralFixer implements PyFixer {
- public void apply(Editor editor, PySmartEnterProcessor processor, PsiElement psiElement) throws IncorrectOperationException {
- if (psiElement instanceof PyStringLiteralExpression) {
- final String text = psiElement.getText();
- if (StringUtil.startsWith(text, "\"\"\"")) {
- final int suffixLength = StringUtil.commonSuffixLength(text, "\"\"\"");
- if (suffixLength != 3) {
- editor.getDocument().insertString(psiElement.getTextRange().getEndOffset(), "\"\"\"".substring(suffixLength));
- }
+public class PyStringLiteralFixer extends PyFixer<PyStringLiteralExpression> {
+ public PyStringLiteralFixer() {
+ super(PyStringLiteralExpression.class);
+ }
+
+ @Override
+ public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyStringLiteralExpression psiElement)
+ throws IncorrectOperationException {
+ final String text = psiElement.getText();
+ if (StringUtil.startsWith(text, "\"\"\"")) {
+ final int suffixLength = StringUtil.commonSuffixLength(text, "\"\"\"");
+ if (suffixLength != 3) {
+ editor.getDocument().insertString(psiElement.getTextRange().getEndOffset(), "\"\"\"".substring(suffixLength));
}
- else if (StringUtil.startsWith(text, "\'\'\'")) {
- final int suffixLength = StringUtil.commonSuffixLength(text, "\'\'\'");
- if (suffixLength != 3) {
- editor.getDocument().insertString(psiElement.getTextRange().getEndOffset(), "\'\'\'".substring(suffixLength));
- }
+ }
+ else if (StringUtil.startsWith(text, "\'\'\'")) {
+ final int suffixLength = StringUtil.commonSuffixLength(text, "\'\'\'");
+ if (suffixLength != 3) {
+ editor.getDocument().insertString(psiElement.getTextRange().getEndOffset(), "\'\'\'".substring(suffixLength));
}
- else if (StringUtil.startsWith(text, "\"")) {
- if (!StringUtil.endsWith(text, "\"")) {
- editor.getDocument().insertString(psiElement.getTextRange().getEndOffset(), "\"");
- }
+ }
+ else if (StringUtil.startsWith(text, "\"")) {
+ if (!StringUtil.endsWith(text, "\"")) {
+ editor.getDocument().insertString(psiElement.getTextRange().getEndOffset(), "\"");
}
- else if (StringUtil.startsWith(text, "\'")) {
- if (!StringUtil.endsWith(text, "\'")) {
- editor.getDocument().insertString(psiElement.getTextRange().getEndOffset(), "\'");
- }
+ }
+ else if (StringUtil.startsWith(text, "\'")) {
+ if (!StringUtil.endsWith(text, "\'")) {
+ editor.getDocument().insertString(psiElement.getTextRange().getEndOffset(), "\'");
}
}
}
diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyUnconditionalStatementPartFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyUnconditionalStatementPartFixer.java
index 57bfd39f4f85..6aace3972a1b 100644
--- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyUnconditionalStatementPartFixer.java
+++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyUnconditionalStatementPartFixer.java
@@ -21,10 +21,10 @@ import com.intellij.psi.tree.TokenSet;
import com.intellij.util.IncorrectOperationException;
import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor;
-import com.jetbrains.python.psi.PyElsePart;
-import com.jetbrains.python.psi.PyFinallyPart;
-import com.jetbrains.python.psi.PyTryPart;
-import com.jetbrains.python.psi.PyUtil;
+import com.jetbrains.python.psi.*;
+import org.jetbrains.annotations.NotNull;
+
+import static com.jetbrains.python.psi.PyUtil.sure;
/**
* Created by IntelliJ IDEA.
@@ -32,16 +32,20 @@ import com.jetbrains.python.psi.PyUtil;
* Date: 16.04.2010
* Time: 14:25:20
*/
-public class PyUnconditionalStatementPartFixer implements PyFixer {
- public void apply(Editor editor, PySmartEnterProcessor processor, PsiElement psiElement) throws IncorrectOperationException {
+public class PyUnconditionalStatementPartFixer extends PyFixer<PyElement> {
+ public PyUnconditionalStatementPartFixer() {
+ super(PyElement.class);
+ }
+
+ @Override
+ public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyElement psiElement)
+ throws IncorrectOperationException {
if (PyUtil.instanceOf(psiElement, PyElsePart.class, PyTryPart.class, PyFinallyPart.class)) {
- final PsiElement colon = PyUtil.getChildByFilter(psiElement, TokenSet.create(PyTokenTypes.COLON), 0);
+ final PsiElement colon = PyUtil.getFirstChildOfType(psiElement, PyTokenTypes.COLON);
if (colon == null) {
- final PsiElement keywordToken = PyUtil.getChildByFilter(psiElement,
- TokenSet.create(PyTokenTypes.ELSE_KEYWORD, PyTokenTypes.TRY_KEYWORD,
- PyTokenTypes.FINALLY_KEYWORD),
- 0);
- editor.getDocument().insertString(keywordToken.getTextRange().getEndOffset(), ":");
+ final TokenSet keywords = TokenSet.create(PyTokenTypes.ELSE_KEYWORD, PyTokenTypes.TRY_KEYWORD, PyTokenTypes.FINALLY_KEYWORD);
+ final PsiElement keywordToken = PyUtil.getChildByFilter(psiElement, keywords, 0);
+ editor.getDocument().insertString(sure(keywordToken).getTextRange().getEndOffset(), ":");
}
}
}
diff --git a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyWithFixer.java b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyWithFixer.java
index b6d099ef7cb5..ec236d9242f5 100644
--- a/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyWithFixer.java
+++ b/python/src/com/jetbrains/python/codeInsight/editorActions/smartEnter/fixers/PyWithFixer.java
@@ -15,65 +15,59 @@
*/
package com.jetbrains.python.codeInsight.editorActions.smartEnter.fixers;
-import com.intellij.lang.ASTNode;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.psi.PsiElement;
import com.intellij.util.IncorrectOperationException;
import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.codeInsight.editorActions.smartEnter.PySmartEnterProcessor;
-import com.jetbrains.python.psi.PyElementType;
import com.jetbrains.python.psi.PyExpression;
+import com.jetbrains.python.psi.PyUtil;
import com.jetbrains.python.psi.PyWithItem;
import com.jetbrains.python.psi.PyWithStatement;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
import static com.jetbrains.python.psi.PyUtil.sure;
/**
* @author Mikhail Golubev
*/
-public class PyWithFixer implements PyFixer {
- public void apply(Editor editor, PySmartEnterProcessor processor, PsiElement psiElement) throws IncorrectOperationException {
- if (psiElement instanceof PyWithStatement) {
- final PyWithStatement withStatement = (PyWithStatement)psiElement;
- final PsiElement colonToken = getFirstChildOfType(psiElement, PyTokenTypes.COLON);
- final PsiElement withToken = getFirstChildOfType(withStatement, PyTokenTypes.WITH_KEYWORD);
- final Document document = editor.getDocument();
- if (colonToken == null) {
- int insertAt = sure(withToken).getTextRange().getEndOffset();
- String textToInsert = ":";
- final PyWithItem[] withItems = withStatement.getWithItems();
- final PyWithItem lastItem = withItems.length != 0 ? withItems[withItems.length - 1] : null;
- if (lastItem == null || lastItem.getExpression() == null) {
- textToInsert = " :";
- processor.registerUnresolvedError(insertAt + 1);
- }
- else {
- final PyExpression expression = lastItem.getExpression();
- insertAt = expression.getTextRange().getEndOffset();
- final PsiElement asToken = getFirstChildOfType(lastItem, PyTokenTypes.AS_KEYWORD);
- if (asToken != null) {
- insertAt = asToken.getTextRange().getEndOffset();
- final PyExpression target = lastItem.getTarget();
- if (target != null) {
- insertAt = target.getTextRange().getEndOffset();
- }
- else {
- textToInsert = " :";
- processor.registerUnresolvedError(insertAt + 1);
- }
+public class PyWithFixer extends PyFixer<PyWithStatement> {
+ public PyWithFixer() {
+ super(PyWithStatement.class);
+ }
+
+ @Override
+ public void doApply(@NotNull Editor editor, @NotNull PySmartEnterProcessor processor, @NotNull PyWithStatement withStatement) throws IncorrectOperationException {
+ final PsiElement colonToken = PyUtil.getFirstChildOfType(withStatement, PyTokenTypes.COLON);
+ final PsiElement withToken = PyUtil.getFirstChildOfType(withStatement, PyTokenTypes.WITH_KEYWORD);
+ final Document document = editor.getDocument();
+ if (colonToken == null) {
+ int insertAt = sure(withToken).getTextRange().getEndOffset();
+ String textToInsert = ":";
+ final PyWithItem[] withItems = withStatement.getWithItems();
+ final PyWithItem lastItem = withItems.length != 0 ? withItems[withItems.length - 1] : null;
+ if (lastItem == null || lastItem.getExpression() == null) {
+ textToInsert = " :";
+ processor.registerUnresolvedError(insertAt + 1);
+ }
+ else {
+ final PyExpression expression = lastItem.getExpression();
+ insertAt = expression.getTextRange().getEndOffset();
+ final PsiElement asToken = PyUtil.getFirstChildOfType(lastItem, PyTokenTypes.AS_KEYWORD);
+ if (asToken != null) {
+ insertAt = asToken.getTextRange().getEndOffset();
+ final PyExpression target = lastItem.getTarget();
+ if (target != null) {
+ insertAt = target.getTextRange().getEndOffset();
+ }
+ else {
+ textToInsert = " :";
+ processor.registerUnresolvedError(insertAt + 1);
}
}
- document.insertString(insertAt, textToInsert);
}
+ document.insertString(insertAt, textToInsert);
}
}
-
- @Nullable
- private static PsiElement getFirstChildOfType(@NotNull final PsiElement element, @NotNull PyElementType type) {
- final ASTNode child = element.getNode().findChildByType(type);
- return child != null ? child.getPsi() : null;
- }
}
diff --git a/python/src/com/jetbrains/python/console/PydevConsoleRunner.java b/python/src/com/jetbrains/python/console/PydevConsoleRunner.java
index 3d77ac4f62b1..848818b95e27 100644
--- a/python/src/com/jetbrains/python/console/PydevConsoleRunner.java
+++ b/python/src/com/jetbrains/python/console/PydevConsoleRunner.java
@@ -16,6 +16,10 @@
package com.jetbrains.python.console;
import com.google.common.base.CharMatcher;
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.ExecutionHelper;
@@ -59,11 +63,14 @@ import com.intellij.openapi.util.io.StreamUtil;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.encoding.EncodingManager;
+import com.intellij.openapi.wm.ToolWindow;
+import com.intellij.openapi.wm.ToolWindowManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.impl.source.tree.FileElement;
import com.intellij.remote.RemoteSshProcess;
import com.intellij.testFramework.LightVirtualFile;
+import com.intellij.ui.content.Content;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IJSwingUtilities;
import com.intellij.util.PathMappingSettings;
@@ -132,6 +139,9 @@ public class PydevConsoleRunner extends AbstractConsoleRunnerWithHistory<PythonC
private static final long APPROPRIATE_TO_WAIT = 60000;
private PyRemoteSdkCredentials myRemoteCredentials;
+ private ToolWindow myToolWindow;
+
+ private String myConsoleTitle = null;
protected PydevConsoleRunner(@NotNull final Project project,
@NotNull Sdk sdk, @NotNull final PyConsoleType consoleType,
@@ -192,8 +202,10 @@ public class PydevConsoleRunner extends AbstractConsoleRunnerWithHistory<PythonC
@NotNull final PyConsoleType consoleType,
@Nullable final String workingDirectory,
@NotNull final Map<String, String> environmentVariables,
+ @Nullable final ToolWindow toolWindow,
final String... statements2execute) {
final PydevConsoleRunner consoleRunner = create(project, sdk, consoleType, workingDirectory, environmentVariables);
+ consoleRunner.setToolWindow(toolWindow);
consoleRunner.setStatementsToExecute(statements2execute);
consoleRunner.run();
return consoleRunner;
@@ -481,6 +493,20 @@ public class PydevConsoleRunner extends AbstractConsoleRunnerWithHistory<PythonC
}
}
+ @Override
+ protected String constructConsoleTitle(@NotNull String consoleTitle) {
+ if (myConsoleTitle == null) {
+ myConsoleTitle = super.constructConsoleTitle(consoleTitle);
+ }
+ return myConsoleTitle;
+ }
+
+ @Override
+ protected void showConsole(Executor defaultExecutor, RunContentDescriptor contentDescriptor) {
+ PythonConsoleToolWindow terminalView = PythonConsoleToolWindow.getInstance(getProject());
+ terminalView.init(getToolWindow(), contentDescriptor);
+ }
+
protected AnAction createRerunAction() {
return new RestartAction(this);
}
@@ -583,9 +609,32 @@ public class PydevConsoleRunner extends AbstractConsoleRunnerWithHistory<PythonC
}
@Override
- protected AnAction createCloseAction(Executor defaultExecutor, RunContentDescriptor myDescriptor) {
- final AnAction generalCloseAction = super.createCloseAction(defaultExecutor, myDescriptor);
- return createConsoleStoppingAction(generalCloseAction);
+ protected AnAction createCloseAction(Executor defaultExecutor, final RunContentDescriptor descriptor) {
+ final AnAction generalCloseAction = super.createCloseAction(defaultExecutor, descriptor);
+
+ final AnAction stopAction = new DumbAwareAction() {
+ @Override
+ public void update(AnActionEvent e) {
+ generalCloseAction.update(e);
+ }
+
+ @Override
+ public void actionPerformed(AnActionEvent e) {
+ e = stopConsole(e);
+
+ clearContent(descriptor);
+
+ generalCloseAction.actionPerformed(e);
+ }
+ };
+ stopAction.copyFrom(generalCloseAction);
+ return stopAction;
+ }
+
+ private void clearContent(RunContentDescriptor descriptor) {
+ Content content = getToolWindow().getContentManager().findContent(descriptor.getDisplayName());
+ assert content != null;
+ getToolWindow().getContentManager().removeContent(content, true);
}
private AnAction createConsoleStoppingAction(final AnAction generalStopAction) {
@@ -597,26 +646,31 @@ public class PydevConsoleRunner extends AbstractConsoleRunnerWithHistory<PythonC
@Override
public void actionPerformed(AnActionEvent e) {
- if (myPydevConsoleCommunication != null) {
- final AnActionEvent furtherActionEvent =
- new AnActionEvent(e.getInputEvent(), e.getDataContext(), e.getPlace(),
- e.getPresentation(), e.getActionManager(), e.getModifiers());
- try {
- closeCommunication();
- // waiting for REPL communication before destroying process handler
- Thread.sleep(300);
- }
- catch (Exception ignored) {
- // Ignore
- }
- generalStopAction.actionPerformed(furtherActionEvent);
- }
+ e = stopConsole(e);
+
+ generalStopAction.actionPerformed(e);
}
};
stopAction.copyFrom(generalStopAction);
return stopAction;
}
+ private AnActionEvent stopConsole(AnActionEvent e) {
+ if (myPydevConsoleCommunication != null) {
+ e = new AnActionEvent(e.getInputEvent(), e.getDataContext(), e.getPlace(),
+ e.getPresentation(), e.getActionManager(), e.getModifiers());
+ try {
+ closeCommunication();
+ // waiting for REPL communication before destroying process handler
+ Thread.sleep(300);
+ }
+ catch (Exception ignored) {
+ // Ignore
+ }
+ }
+ return e;
+ }
+
protected AnAction createSplitLineAction() {
class ConsoleSplitLineAction extends EditorAction {
@@ -738,6 +792,17 @@ public class PydevConsoleRunner extends AbstractConsoleRunnerWithHistory<PythonC
}
}
+ public ToolWindow getToolWindow() {
+ if (myToolWindow == null) {
+ myToolWindow = ToolWindowManager.getInstance(getProject()).getToolWindow(PythonConsoleToolWindowFactory.ID);
+ }
+ return myToolWindow;
+ }
+
+ public void setToolWindow(ToolWindow toolWindow) {
+ myToolWindow = toolWindow;
+ }
+
public interface ConsoleListener {
void handleConsoleInitialized(LanguageConsoleView consoleView);
}
@@ -889,4 +954,21 @@ public class PydevConsoleRunner extends AbstractConsoleRunnerWithHistory<PythonC
return session;
}
+
+ @Override
+ protected List<String> getActiveConsoleNames(final String consoleTitle) {
+ return FluentIterable.from(
+ Lists.newArrayList(PythonConsoleToolWindow.getInstance(getProject()).getToolWindow().getContentManager().getContents())).transform(
+ new Function<Content, String>() {
+ @Override
+ public String apply(Content input) {
+ return input.getDisplayName();
+ }
+ }).filter(new Predicate<String>() {
+ @Override
+ public boolean apply(String input) {
+ return input.contains(consoleTitle);
+ }
+ }).toList();
+ }
}
diff --git a/python/src/com/jetbrains/python/console/PythonConsoleToolWindow.java b/python/src/com/jetbrains/python/console/PythonConsoleToolWindow.java
new file mode 100644
index 000000000000..e8c50e49280a
--- /dev/null
+++ b/python/src/com/jetbrains/python/console/PythonConsoleToolWindow.java
@@ -0,0 +1,127 @@
+package com.jetbrains.python.console;
+
+import com.intellij.execution.ui.RunContentDescriptor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.SimpleToolWindowPanel;
+import com.intellij.openapi.wm.ToolWindow;
+import com.intellij.openapi.wm.ToolWindowManager;
+import com.intellij.openapi.wm.ex.ToolWindowManagerEx;
+import com.intellij.openapi.wm.ex.ToolWindowManagerListener;
+import com.intellij.openapi.wm.impl.content.ToolWindowContentUi;
+import com.intellij.ui.content.Content;
+import com.intellij.ui.content.ContentFactory;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+
+/**
+ * @author traff
+ */
+public class PythonConsoleToolWindow {
+
+ private final Project myProject;
+
+ private boolean myInitialized = false;
+
+ public PythonConsoleToolWindow(Project project) {
+ myProject = project;
+ }
+
+ public static PythonConsoleToolWindow getInstance(@NotNull Project project) {
+ return project.getComponent(PythonConsoleToolWindow.class);
+ }
+
+
+ public void init(final @NotNull ToolWindow toolWindow, final @NotNull RunContentDescriptor contentDescriptor) {
+ addContent(toolWindow, contentDescriptor);
+
+ if (!myInitialized) {
+ doInit(toolWindow);
+ }
+ }
+
+ private void doInit(final ToolWindow toolWindow) {
+ myInitialized = true;
+
+ toolWindow.setToHideOnEmptyContent(true);
+
+ ((ToolWindowManagerEx)ToolWindowManager.getInstance(myProject)).addToolWindowManagerListener(new ToolWindowManagerListener() {
+ @Override
+ public void toolWindowRegistered(@NotNull String id) {
+ }
+
+ @Override
+ public void stateChanged() {
+ ToolWindow window = getToolWindow();
+ if (window != null) {
+ boolean visible = window.isVisible();
+ if (visible && toolWindow.getContentManager().getContentCount() == 0) {
+ RunPythonConsoleAction.runPythonConsole(myProject, null, toolWindow);
+ }
+ }
+ }
+ });
+ }
+
+ private static void addContent(ToolWindow toolWindow, RunContentDescriptor contentDescriptor) {
+ toolWindow.getComponent().putClientProperty(ToolWindowContentUi.HIDE_ID_LABEL, "true");
+
+ Content content = toolWindow.getContentManager().findContent(contentDescriptor.getDisplayName());
+ if (content == null) {
+ content = createContent(contentDescriptor);
+ toolWindow.getContentManager().addContent(content);
+ }
+ else {
+ SimpleToolWindowPanel panel = new SimpleToolWindowPanel(false, true);
+ resetContent(contentDescriptor, panel, content);
+ }
+
+ toolWindow.getContentManager().setSelectedContent(content);
+ }
+
+ public ToolWindow getToolWindow() {
+ return ToolWindowManager.getInstance(myProject).getToolWindow(PythonConsoleToolWindowFactory.ID);
+ }
+
+ private static Content createContent(final @NotNull RunContentDescriptor contentDescriptor) {
+ SimpleToolWindowPanel panel = new SimpleToolWindowPanel(false, true);
+
+ final Content content = ContentFactory.SERVICE.getInstance().createContent(panel, contentDescriptor.getDisplayName(), false);
+ content.setCloseable(true);
+
+ resetContent(contentDescriptor, panel, content);
+
+ return content;
+ }
+
+ private static void resetContent(RunContentDescriptor contentDescriptor, SimpleToolWindowPanel panel, Content content) {
+ panel.setContent(contentDescriptor.getComponent());
+ //panel.addFocusListener(createFocusListener(toolWindow));
+
+ content.setComponent(panel);
+ content.setPreferredFocusableComponent(contentDescriptor.getComponent());
+ }
+
+ private static FocusListener createFocusListener(final ToolWindow toolWindow) {
+ return new FocusListener() {
+ @Override
+ public void focusGained(FocusEvent e) {
+ JComponent component = getComponentToFocus(toolWindow);
+ if (component != null) {
+ component.requestFocusInWindow();
+ }
+ }
+
+ @Override
+ public void focusLost(FocusEvent e) {
+
+ }
+ };
+ }
+
+ private static JComponent getComponentToFocus(ToolWindow window) {
+ return window.getContentManager().getComponent();
+ }
+}
diff --git a/python/src/com/jetbrains/python/console/PythonConsoleToolWindowFactory.java b/python/src/com/jetbrains/python/console/PythonConsoleToolWindowFactory.java
new file mode 100644
index 000000000000..f042a539bc22
--- /dev/null
+++ b/python/src/com/jetbrains/python/console/PythonConsoleToolWindowFactory.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.jetbrains.python.console;
+
+import com.intellij.openapi.project.DumbAware;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.wm.ToolWindow;
+import com.intellij.openapi.wm.ToolWindowFactory;
+
+/**
+ * @author traff
+ */
+public class PythonConsoleToolWindowFactory implements ToolWindowFactory, DumbAware {
+ public static final String ID = "Python Console";
+
+ @Override
+ public void createToolWindowContent(Project project, ToolWindow toolWindow) {
+ RunPythonConsoleAction.runPythonConsole(project, null, toolWindow);
+ }
+}
diff --git a/python/src/com/jetbrains/python/console/RunPythonConsoleAction.java b/python/src/com/jetbrains/python/console/RunPythonConsoleAction.java
index 02a153f7a016..566adea43c87 100644
--- a/python/src/com/jetbrains/python/console/RunPythonConsoleAction.java
+++ b/python/src/com/jetbrains/python/console/RunPythonConsoleAction.java
@@ -32,6 +32,7 @@ import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.wm.ToolWindow;
import com.intellij.util.PathMappingSettings;
import com.jetbrains.python.buildout.BuildoutFacet;
import com.jetbrains.python.remote.PyRemoteSdkAdditionalDataBase;
@@ -42,6 +43,7 @@ import com.jetbrains.python.sdk.PythonEnvUtil;
import com.jetbrains.python.sdk.PythonSdkType;
import icons.PythonIcons;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.List;
@@ -77,11 +79,11 @@ public class RunPythonConsoleAction extends AnAction implements DumbAware {
public void actionPerformed(final AnActionEvent e) {
final Project project = e.getData(CommonDataKeys.PROJECT);
- runPythonConsole(project, e.getData(LangDataKeys.MODULE));
+ runPythonConsole(project, e.getData(LangDataKeys.MODULE), null);
}
@NotNull
- public static PydevConsoleRunner runPythonConsole(Project project, Module contextModule) {
+ public static PydevConsoleRunner runPythonConsole(Project project, Module contextModule, @Nullable ToolWindow toolWindow) {
assert project != null : "Project is null";
Pair<Sdk, Module> sdkAndModule = findPythonSdkAndModule(project, contextModule);
@@ -152,7 +154,7 @@ public class RunPythonConsoleAction extends AnAction implements DumbAware {
envs.put(PythonEnvUtil.IPYTHONENABLE, ipythonEnabled);
return PydevConsoleRunner
- .createAndRun(project, sdk, PyConsoleType.PYTHON, workingDir, envs, setupFragment);
+ .createAndRun(project, sdk, PyConsoleType.PYTHON, workingDir, envs, toolWindow, setupFragment);
}
public static PathMappingSettings getMappings(Project project, Sdk sdk) {
diff --git a/python/src/com/jetbrains/python/documentation/EpydocString.java b/python/src/com/jetbrains/python/documentation/EpydocString.java
index 132ef4924b5c..3d0fc3e89d9e 100644
--- a/python/src/com/jetbrains/python/documentation/EpydocString.java
+++ b/python/src/com/jetbrains/python/documentation/EpydocString.java
@@ -44,6 +44,13 @@ public class EpydocString extends StructuredDocStringBase {
"precondition", "postcondition", "invariant", "author", "organization", "copyright", "license", "contact", "summary", "see"
};
+ /**
+ * Empty doc (for {@link #createParameterType(String, String)} probably)
+ */
+ public EpydocString() {
+ this("");
+ }
+
public EpydocString(@NotNull String docstringText) {
super(docstringText, "@");
}
diff --git a/python/src/com/jetbrains/python/documentation/PyDocstringGenerator.java b/python/src/com/jetbrains/python/documentation/PyDocstringGenerator.java
index d09af58f4fc3..c05069098ea6 100644
--- a/python/src/com/jetbrains/python/documentation/PyDocstringGenerator.java
+++ b/python/src/com/jetbrains/python/documentation/PyDocstringGenerator.java
@@ -87,8 +87,6 @@ public class PyDocstringGenerator {
for (PyParameter functionParam : function.getParameterList().getParameters()) {
String paramName = functionParam.getName();
if (!functionParam.isSelf() && !StringUtil.isEmpty(paramName)) {
- assert paramName != null;
-
String type = signature != null ? signature.getArgTypeQualifiedName(paramName) : null;
if (type != null) {
@@ -140,12 +138,9 @@ public class PyDocstringGenerator {
final VirtualFile virtualFile = myFile.getVirtualFile();
if (virtualFile == null) return;
- OpenFileDescriptor descriptor = new OpenFileDescriptor(
- myProject, virtualFile, myDocStringOwner.getTextOffset() + myDocStringOwner.getTextLength()
- );
+ OpenFileDescriptor descriptor = new OpenFileDescriptor(myProject, virtualFile, myDocStringExpression.getTextOffset());
Editor targetEditor = FileEditorManager.getInstance(myProject).openTextEditor(descriptor, true);
if (targetEditor != null) {
- targetEditor.getCaretModel().moveToOffset(myDocStringExpression.getTextOffset());
TemplateManager.getInstance(myProject).startTemplate(targetEditor, template);
}
}
@@ -298,7 +293,7 @@ public class PyDocstringGenerator {
if (myDocStringOwner instanceof PyFunction) {
final PyStatementList statementList = ((PyFunction)myDocStringOwner).getStatementList();
final Document document = PsiDocumentManager.getInstance(myProject).getDocument(getFile());
- if (document != null && statementList != null && myFunction != null && statementList.getStatements().length != 0
+ if (document != null && myFunction != null && statementList.getStatements().length != 0
&& document.getLineNumber(statementList.getTextOffset()) != document.getLineNumber(myFunction.getTextOffset())) {
whitespace = PsiTreeUtil.getPrevSiblingOfType(statementList, PsiWhiteSpace.class);
}
@@ -411,7 +406,7 @@ public class PyDocstringGenerator {
final PyStatementList list = myFunction.getStatementList();
final Document document = PsiDocumentManager.getInstance(myProject).getDocument(getFile());
- if (document != null && list != null) {
+ if (document != null) {
if (document.getLineNumber(list.getTextOffset()) == document.getLineNumber(myFunction.getTextOffset()) ||
list.getStatements().length == 0) {
PyFunction func = elementGenerator.createFromText(LanguageLevel.forElement(myFunction),
diff --git a/python/src/com/jetbrains/python/documentation/PyDocumentationSettings.java b/python/src/com/jetbrains/python/documentation/PyDocumentationSettings.java
index 6ea65405ba1a..49a17efd28a6 100644
--- a/python/src/com/jetbrains/python/documentation/PyDocumentationSettings.java
+++ b/python/src/com/jetbrains/python/documentation/PyDocumentationSettings.java
@@ -15,7 +15,9 @@
*/
package com.jetbrains.python.documentation;
-import com.intellij.openapi.components.*;
+import com.intellij.openapi.components.PersistentStateComponent;
+import com.intellij.openapi.components.State;
+import com.intellij.openapi.components.Storage;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleServiceManager;
import com.intellij.openapi.util.text.StringUtil;
@@ -27,6 +29,7 @@ import com.jetbrains.python.psi.PyFile;
import com.jetbrains.python.psi.PyTargetExpression;
import com.jetbrains.python.psi.impl.PyPsiUtils;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.util.List;
@@ -54,7 +57,7 @@ public class PyDocumentationSettings implements PersistentStateComponent<PyDocum
private boolean isFormat(PsiFile file, final String format) {
if (file instanceof PyFile) {
- PyTargetExpression expr = ((PyFile) file).findTopLevelAttribute(PyNames.DOCFORMAT);
+ PyTargetExpression expr = ((PyFile)file).findTopLevelAttribute(PyNames.DOCFORMAT);
if (expr != null) {
String docformat = PyPsiUtils.strValue(expr.findAssignedValue());
if (docformat != null) {
@@ -88,4 +91,21 @@ public class PyDocumentationSettings implements PersistentStateComponent<PyDocum
public void loadState(PyDocumentationSettings state) {
XmlSerializerUtil.copyBean(state, this);
}
+
+ /**
+ * TODO: Use this factory for the whole document infrastructure to simplify new documentation engine support
+ * Factory that returns appropriate instance of {@link StructuredDocStringBase} if specificed
+ *
+ * @return instance or null if no doctype os set
+ */
+ @Nullable
+ public StructuredDocStringBase getDocString() {
+ if (myDocStringFormat.equals(DocStringFormat.EPYTEXT)) {
+ return new EpydocString();
+ }
+ if (myDocStringFormat.equals(DocStringFormat.REST)) {
+ return new SphinxDocString();
+ }
+ return null;
+ }
}
diff --git a/python/src/com/jetbrains/python/documentation/SphinxDocString.java b/python/src/com/jetbrains/python/documentation/SphinxDocString.java
index ae5c7056a90b..c04e1c9471cf 100644
--- a/python/src/com/jetbrains/python/documentation/SphinxDocString.java
+++ b/python/src/com/jetbrains/python/documentation/SphinxDocString.java
@@ -31,7 +31,14 @@ public class SphinxDocString extends StructuredDocStringBase {
":type", ":raise", ":raises", ":var", ":cvar", ":ivar",
":return", ":returns", ":rtype", ":except", ":exception" };
- public SphinxDocString(@NotNull String docstringText) {
+ /**
+ * Empty doc (for {@link #createParameterType(String, String)} probably)
+ */
+ public SphinxDocString() {
+ this("");
+ }
+
+ public SphinxDocString(@NotNull final String docstringText) {
super(docstringText, ":");
}
diff --git a/python/src/com/jetbrains/python/documentation/StructuredDocStringBase.java b/python/src/com/jetbrains/python/documentation/StructuredDocStringBase.java
index 9f6cecba7a84..36b70ec0f76a 100644
--- a/python/src/com/jetbrains/python/documentation/StructuredDocStringBase.java
+++ b/python/src/com/jetbrains/python/documentation/StructuredDocStringBase.java
@@ -43,18 +43,21 @@ public abstract class StructuredDocStringBase implements StructuredDocString {
private static final Pattern RE_LOOSE_TAG_LINE = Pattern.compile("([a-z]+) ([a-zA-Z_0-9]*):?([^:]*)");
private static final Pattern RE_ARG_TYPE = Pattern.compile("(.*) ([a-zA-Z_0-9]+)");
- public static String[] PARAM_TAGS = new String[] { "param", "parameter", "arg", "argument" };
- public static String[] PARAM_TYPE_TAGS = new String[] { "type" };
- public static String[] VARIABLE_TAGS = new String[] { "ivar", "cvar", "var" };
+ public static String[] PARAM_TAGS = new String[]{"param", "parameter", "arg", "argument"};
+ public static String[] PARAM_TYPE_TAGS = new String[]{"type"};
+ public static String[] VARIABLE_TAGS = new String[]{"ivar", "cvar", "var"};
- public static String[] RAISES_TAGS = new String[] { "raises", "raise", "except", "exception" };
- public static String[] RETURN_TAGS = new String[] { "return", "returns" };
+ public static String[] RAISES_TAGS = new String[]{"raises", "raise", "except", "exception"};
+ public static String[] RETURN_TAGS = new String[]{"return", "returns"};
+ @NotNull
+ private final String myTagPrefix;
public enum ReferenceType {PARAMETER, PARAMETER_TYPE, KEYWORD, VARIABLE, CLASS_VARIABLE, INSTANCE_VARIABLE}
public static String TYPE = "type";
protected StructuredDocStringBase(@NotNull String docStringText, String tagPrefix) {
+ myTagPrefix = tagPrefix;
final Substring docString = new Substring(docStringText);
final List<Substring> lines = docString.splitLines();
final int nlines = lines.size();
@@ -74,6 +77,12 @@ public abstract class StructuredDocStringBase implements StructuredDocString {
}
@Override
+ @NotNull
+ public String createParameterType(@NotNull final String name, @NotNull final String type) {
+ return myTagPrefix + TYPE + String.format(" %s %s", name, type);
+ }
+
+ @Override
public String getDescription() {
return myDescription;
}
@@ -82,8 +91,9 @@ public abstract class StructuredDocStringBase implements StructuredDocString {
public String getSummary() {
final List<String> strings = StringUtil.split(StringUtil.trimLeading(myDescription), "\n", true, false);
if (strings.size() > 1) {
- if (strings.get(1).isEmpty())
+ if (strings.get(1).isEmpty()) {
return strings.get(0);
+ }
}
return "";
}
@@ -216,8 +226,8 @@ public abstract class StructuredDocStringBase implements StructuredDocString {
@Override
@Nullable
- public Substring getParamByNameAndKind(@NotNull String name, String kind) {
- for (Substring s: getTagArguments(kind)) {
+ public Substring getParamByNameAndKind(@NotNull String name, String kind) {
+ for (Substring s : getTagArguments(kind)) {
if (name.equals(s.getValue())) {
return s;
}
diff --git a/python/src/com/jetbrains/python/inspections/PyInspectionVisitor.java b/python/src/com/jetbrains/python/inspections/PyInspectionVisitor.java
index 4584f06ae8d9..6c86e72b1bcd 100644
--- a/python/src/com/jetbrains/python/inspections/PyInspectionVisitor.java
+++ b/python/src/com/jetbrains/python/inspections/PyInspectionVisitor.java
@@ -78,12 +78,12 @@ public abstract class PyInspectionVisitor extends PyElementVisitor {
protected final void registerProblem(@Nullable final PsiElement element,
@NotNull final String message,
- @NotNull final LocalQuickFix quickFix) {
+ @NotNull final LocalQuickFix... quickFixes) {
if (element == null || element.getTextLength() == 0) {
return;
}
if (myHolder != null) {
- myHolder.registerProblem(element, message, quickFix);
+ myHolder.registerProblem(element, message, quickFixes);
}
}
diff --git a/python/src/com/jetbrains/python/inspections/PyShadowingNamesInspection.java b/python/src/com/jetbrains/python/inspections/PyShadowingNamesInspection.java
index 8b6143ffe092..b2ad485c24f8 100644
--- a/python/src/com/jetbrains/python/inspections/PyShadowingNamesInspection.java
+++ b/python/src/com/jetbrains/python/inspections/PyShadowingNamesInspection.java
@@ -99,7 +99,7 @@ public class PyShadowingNamesInspection extends PyInspection {
final ScopeOwner nextOwner = ScopeUtil.getScopeOwner(owner);
if (nextOwner != null) {
final ResolveProcessor processor = new ResolveProcessor(name);
- PyResolveUtil.scopeCrawlUp(processor, nextOwner, null, name, null);
+ PyResolveUtil.scopeCrawlUp(processor, nextOwner, null, name, null, null);
final PsiElement resolved = processor.getResult();
if (resolved != null) {
final PyComprehensionElement comprehension = PsiTreeUtil.getParentOfType(resolved, PyComprehensionElement.class);
diff --git a/python/src/com/jetbrains/python/inspections/quickfix/PyRemoveArgumentQuickFix.java b/python/src/com/jetbrains/python/inspections/quickfix/PyRemoveArgumentQuickFix.java
index 0ae7ac1c7812..708e91743730 100644
--- a/python/src/com/jetbrains/python/inspections/quickfix/PyRemoveArgumentQuickFix.java
+++ b/python/src/com/jetbrains/python/inspections/quickfix/PyRemoveArgumentQuickFix.java
@@ -27,6 +27,7 @@ import com.jetbrains.python.psi.PyExpression;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
+//TODO: Remove pydoc aswell
public class PyRemoveArgumentQuickFix implements LocalQuickFix {
@NotNull
diff --git a/python/src/com/jetbrains/python/psi/PyUtil.java b/python/src/com/jetbrains/python/psi/PyUtil.java
index 877da8df6dd9..cd4e582bb6f2 100644
--- a/python/src/com/jetbrains/python/psi/PyUtil.java
+++ b/python/src/com/jetbrains/python/psi/PyUtil.java
@@ -901,6 +901,20 @@ public class PyUtil {
}
/**
+ * Returns first child psi element with specified element type or {@code null} if no such element exists.
+ * Semantically it's the same as {@code getChildByFilter(element, TokenSet.create(type), 0)}.
+ *
+ * @param element tree parent node
+ * @param type element type expected
+ * @return child element described
+ */
+ @Nullable
+ public static PsiElement getFirstChildOfType(@NotNull final PsiElement element, @NotNull PyElementType type) {
+ final ASTNode child = element.getNode().findChildByType(type);
+ return child != null ? child.getPsi() : null;
+ }
+
+ /**
* If argument is a PsiDirectory, turn it into a PsiFile that points to __init__.py in that directory.
* If there's no __init__.py there, null is returned, there's no point to resolve to a dir which is not a package.
* Alas, resolve() and multiResolve() can't return anything but a PyFile or PsiFileImpl.isPsiUpToDate() would fail.
@@ -1645,6 +1659,11 @@ public class PyUtil {
return Collections2.filter(pyMemberInfos, new ObjectPredicate(false));
}
+ public static boolean isStarImportableFrom(@NotNull String name, @NotNull PyFile file) {
+ final List<String> dunderAll = file.getDunderAll();
+ return dunderAll != null ? dunderAll.contains(name) : !name.startsWith("_");
+ }
+
/**
* Filters only pyclass object (new class)
*/
diff --git a/python/src/com/jetbrains/python/psi/impl/PyElementGeneratorImpl.java b/python/src/com/jetbrains/python/psi/impl/PyElementGeneratorImpl.java
index 744dc9731b41..bb0e29f800a7 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyElementGeneratorImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyElementGeneratorImpl.java
@@ -24,6 +24,7 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiFileFactory;
+import com.intellij.psi.PsiWhiteSpace;
import com.intellij.psi.impl.PsiFileFactoryImpl;
import com.intellij.psi.impl.source.tree.LeafPsiElement;
import com.intellij.psi.tree.TokenSet;
@@ -86,8 +87,9 @@ public class PyElementGeneratorImpl extends PyElementGenerator {
}
+ @Override
public PyStringLiteralExpression createStringLiteralFromString(@NotNull String unescaped) {
- return createStringLiteralFromString(null, unescaped);
+ return createStringLiteralFromString(null, unescaped, true);
}
public PyStringLiteralExpression createStringLiteral(@NotNull PyStringLiteralExpression oldElement, @NotNull String unescaped) {
@@ -100,7 +102,11 @@ public class PyElementGeneratorImpl extends PyElementGenerator {
}
}
- public PyStringLiteralExpression createStringLiteralFromString(@Nullable PsiFile destination, @NotNull String unescaped) {
+
+ @Override
+ public PyStringLiteralExpression createStringLiteralFromString(@Nullable PsiFile destination,
+ @NotNull String unescaped,
+ final boolean preferUTF8) {
boolean useDouble = !unescaped.contains("\"");
boolean useMulti = unescaped.matches(".*(\r|\n).*");
String quotes;
@@ -115,7 +121,7 @@ public class PyElementGeneratorImpl extends PyElementGenerator {
VirtualFile vfile = destination == null ? null : destination.getVirtualFile();
Charset charset;
if (vfile == null) {
- charset = Charset.forName("US-ASCII");
+ charset = (preferUTF8 ? Charset.forName("UTF-8") : Charset.forName("US-ASCII"));
}
else {
charset = vfile.getCharset();
@@ -191,7 +197,7 @@ public class PyElementGeneratorImpl extends PyElementGenerator {
final LeafPsiElement[] leafs = PsiTreeUtil.getChildrenOfType(list, LeafPsiElement.class);
if (leafs != null) {
final Deque<LeafPsiElement> commas = Queues.newArrayDeque(Collections2.filter(Arrays.asList(leafs), COMMAS_ONLY));
- if (! commas.isEmpty()) {
+ if (!commas.isEmpty()) {
final LeafPsiElement lastComma = commas.getLast();
if (PsiTreeUtil.getNextSiblingOfType(lastComma, PyExpression.class) == null) { //Comma has no expression after it
lastComma.delete();
@@ -297,7 +303,7 @@ public class PyElementGeneratorImpl extends PyElementGenerator {
AccessDirection accessDirection) {
String propertyText;
if (accessDirection == AccessDirection.DELETE) {
- propertyText = "@" + propertyName +".deleter\ndef " + propertyName + "(self):\n del self." + fieldName;
+ propertyText = "@" + propertyName + ".deleter\ndef " + propertyName + "(self):\n del self." + fieldName;
}
else if (accessDirection == AccessDirection.WRITE) {
propertyText = "@" + propertyName + ".setter\ndef " + propertyName + "(self, value):\n self." + fieldName + " = value";
@@ -415,6 +421,12 @@ public class PyElementGeneratorImpl extends PyElementGenerator {
PyExpressionStatement.class, content + "\n");
}
+ @NotNull
+ @Override
+ public PsiElement createNewLine() {
+ return createFromText(LanguageLevel.getDefault(), PsiWhiteSpace.class, " \n\n ");
+ }
+
private static class CommasOnly extends NotNullPredicate<LeafPsiElement> {
@Override
protected boolean applyNotNull(@NotNull final LeafPsiElement input) {
diff --git a/python/src/com/jetbrains/python/psi/impl/PyElsePartImpl.java b/python/src/com/jetbrains/python/psi/impl/PyElsePartImpl.java
index ddd02d5310a3..8c69893c62a8 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyElsePartImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyElsePartImpl.java
@@ -15,26 +15,16 @@
*/
package com.jetbrains.python.psi.impl;
-import com.jetbrains.python.psi.PyElsePart;
-import com.jetbrains.python.psi.PyStatementList;
-import com.jetbrains.python.PyElementTypes;
import com.intellij.lang.ASTNode;
+import com.jetbrains.python.psi.PyElsePart;
/**
* User: dcheryasov
* Date: Mar 15, 2009 9:40:35 PM
*/
-public class PyElsePartImpl extends PyElementImpl implements PyElsePart {
+public class PyElsePartImpl extends PyStatementPartImpl implements PyElsePart {
public PyElsePartImpl(ASTNode astNode) {
super(astNode);
}
-
- public PyStatementList getStatementList() {
- ASTNode n = getNode().findChildByType(PyElementTypes.STATEMENT_LISTS);
- if (n != null) {
- return (PyStatementList)n.getPsi();
- }
- return null;
- }
}
diff --git a/python/src/com/jetbrains/python/psi/impl/PyFileImpl.java b/python/src/com/jetbrains/python/psi/impl/PyFileImpl.java
index 030fcfe3d7e5..02b790622fe7 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyFileImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyFileImpl.java
@@ -477,8 +477,9 @@ public class PyFileImpl extends PsiFileBase implements PyFile, PyExpression {
if (starImportSource != null) {
starImportSource = PyUtil.turnDirIntoInit(starImportSource);
if (starImportSource instanceof PyFile) {
- final PsiElement result = ((PyFile)starImportSource).getElementNamed(name);
- if (result != null) {
+ final PyFile file = (PyFile)starImportSource;
+ final PsiElement result = file.getElementNamed(name);
+ if (result != null && PyUtil.isStarImportableFrom(name, file)) {
return result;
}
}
diff --git a/python/src/com/jetbrains/python/psi/impl/PyFunctionBuilder.java b/python/src/com/jetbrains/python/psi/impl/PyFunctionBuilder.java
index e0cdf87b2aab..9d2be0f62205 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyFunctionBuilder.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyFunctionBuilder.java
@@ -23,6 +23,7 @@ import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.util.ArrayUtil;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.PythonFileType;
+import com.jetbrains.python.documentation.StructuredDocStringBase;
import com.jetbrains.python.psi.*;
import org.jetbrains.annotations.NotNull;
@@ -82,14 +83,21 @@ public class PyFunctionBuilder {
/**
* Adds docstring to function. Provide doc with out of comment blocks.
*
+ *
* @param docString doc
*/
public void docString(@NotNull final String docString) {
- myDocStringLines = StringUtil.splitByLines(removeIndent(docString));
+ final String[] stringsToAdd = StringUtil.splitByLines(removeIndent(docString));
+ if (myDocStringLines == null) {
+ myDocStringLines = stringsToAdd;
+ }
+ else {
+ myDocStringLines = ArrayUtil.mergeArrays(myDocStringLines, stringsToAdd);
+ }
}
@NotNull
- private String removeIndent(@NotNull final String string) {
+ private static String removeIndent(@NotNull final String string) {
return INDENT_REMOVE_PATTERN.matcher(string).replaceAll("");
}
@@ -97,6 +105,21 @@ public class PyFunctionBuilder {
myName = name;
}
+ /**
+ * Adds param and its type to doc
+ * @param name param name
+ * @param type param type
+ * @param docStyle what docstyle to use to doc param type
+ */
+ @NotNull
+ public PyFunctionBuilder parameterWithType(@NotNull final String name,
+ @NotNull final String type,
+ @NotNull final StructuredDocStringBase docStyle) {
+ parameter(name);
+ docString(docStyle.createParameterType(name, type));
+ return this;
+ }
+
public PyFunctionBuilder parameter(String baseName) {
String name = baseName;
int uniqueIndex = 0;
@@ -173,8 +196,9 @@ public class PyFunctionBuilder {
/**
* Adds decorator with argument
+ *
* @param decoratorName decorator name
- * @param value its argument
+ * @param value its argument
*/
public void decorate(@NotNull final String decoratorName, @NotNull final String value) {
decorate(decoratorName);
diff --git a/python/src/com/jetbrains/python/psi/impl/PyStarImportElementImpl.java b/python/src/com/jetbrains/python/psi/impl/PyStarImportElementImpl.java
index 4011c233e38d..88c3134481a8 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyStarImportElementImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyStarImportElementImpl.java
@@ -52,11 +52,8 @@ public class PyStarImportElementImpl extends PyElementImpl implements PyStarImpo
for (PsiElement importedFile : new HashSet<PsiElement>(importedFiles)) { // resolver gives lots of duplicates
final PsiElement source = PyUtil.turnDirIntoInit(importedFile);
if (source instanceof PyFile) {
- Iterable<PyElement> declaredNames = ((PyFile)source).iterateNames();
- if (((PyFile)source).getDunderAll() == null) {
- declaredNames = excludeUnderscoredNames(declaredNames);
- }
- chain.add(declaredNames);
+ final PyFile sourceFile = (PyFile)source;
+ chain.add(filterStarImportableNames(sourceFile.iterateNames(), sourceFile));
}
}
return chain;
@@ -64,15 +61,13 @@ public class PyStarImportElementImpl extends PyElementImpl implements PyStarImpo
return Collections.emptyList();
}
- private static Iterable<PyElement> excludeUnderscoredNames(Iterable<PyElement> declaredNames) {
+ @NotNull
+ private static Iterable<PyElement> filterStarImportableNames(@NotNull Iterable<PyElement> declaredNames, @NotNull final PyFile file) {
return Iterables.filter(declaredNames, new Predicate<PyElement>() {
@Override
public boolean apply(@Nullable PyElement input) {
final String name = input != null ? input.getName() : null;
- if (name != null && name.startsWith("_")) {
- return false;
- }
- return true;
+ return name != null && PyUtil.isStarImportableFrom(name, file);
}
});
}
@@ -93,11 +88,7 @@ public class PyStarImportElementImpl extends PyElementImpl implements PyStarImpo
final List<? extends RatedResolveResult> results = moduleType.resolveMember(name, null, AccessDirection.READ,
PyResolveContext.defaultContext());
final PsiElement result = results != null && !results.isEmpty() ? results.get(0).getElement() : null;
- if (result != null) {
- final List<String> all = sourceFile.getDunderAll();
- if (all != null ? !all.contains(name) : name.startsWith("_")) {
- continue;
- }
+ if (result != null && PyUtil.isStarImportableFrom(name, sourceFile) ) {
return result;
}
}
diff --git a/python/src/com/jetbrains/python/psi/impl/PyStatementPartImpl.java b/python/src/com/jetbrains/python/psi/impl/PyStatementPartImpl.java
index 46e9a785a9d4..7454d6741382 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyStatementPartImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyStatementPartImpl.java
@@ -15,10 +15,11 @@
*/
package com.jetbrains.python.psi.impl;
-import com.jetbrains.python.psi.PyStatementPart;
-import com.jetbrains.python.psi.PyStatementList;
-import com.jetbrains.python.PyElementTypes;
import com.intellij.lang.ASTNode;
+import com.jetbrains.python.PyElementTypes;
+import com.jetbrains.python.psi.PyStatementList;
+import com.jetbrains.python.psi.PyStatementPart;
+import org.jetbrains.annotations.NotNull;
/**
* Abstract statement part implementation; extracts the statements list.
@@ -30,11 +31,8 @@ public abstract class PyStatementPartImpl extends PyElementImpl implements PySta
super(astNode);
}
+ @NotNull
public PyStatementList getStatementList() {
- ASTNode n = getNode().findChildByType(PyElementTypes.STATEMENT_LISTS);
- if (n != null) {
- return (PyStatementList)n.getPsi();
- }
- return null;
+ return childToPsiNotNull(PyElementTypes.STATEMENT_LIST);
}
}
diff --git a/python/src/com/jetbrains/python/psi/impl/PyWithStatementImpl.java b/python/src/com/jetbrains/python/psi/impl/PyWithStatementImpl.java
index 98cd8e5703d5..3af3771e8ecd 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyWithStatementImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyWithStatementImpl.java
@@ -63,6 +63,14 @@ public class PyWithStatementImpl extends PyElementImpl implements PyWithStatemen
}
public PyWithItem[] getWithItems() {
- return childrenToPsi(WITH_ITEM, PyWithItem.EMPTY_ARRAY);
+ return childrenToPsi(WITH_ITEM, PyWithItem.EMPTY_ARRAY);
+ }
+
+ @Override
+ @NotNull
+ public PyStatementList getStatementList() {
+ final PyStatementList statementList = childToPsi(PyElementTypes.STATEMENT_LIST);
+ assert statementList != null : "Statement list missing for with statement " + getText();
+ return statementList;
}
}
diff --git a/python/src/com/jetbrains/python/psi/resolve/PyResolveUtil.java b/python/src/com/jetbrains/python/psi/resolve/PyResolveUtil.java
index da8c0d618a8b..838a4dbcc75a 100644
--- a/python/src/com/jetbrains/python/psi/resolve/PyResolveUtil.java
+++ b/python/src/com/jetbrains/python/psi/resolve/PyResolveUtil.java
@@ -38,6 +38,11 @@ import com.jetbrains.python.psi.impl.PyPsiUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
/**
* Ref resolution routines.
* User: dcheryasov
@@ -106,16 +111,17 @@ public class PyResolveUtil {
owner = outerScopeOwner;
}
}
- scopeCrawlUp(processor, owner, originalOwner, name, roof);
+ scopeCrawlUp(processor, owner, originalOwner, name, roof, realContext);
}
public static void scopeCrawlUp(@NotNull PsiScopeProcessor processor, @NotNull ScopeOwner scopeOwner, @Nullable String name,
@Nullable PsiElement roof) {
- scopeCrawlUp(processor, scopeOwner, scopeOwner, name, roof);
+ scopeCrawlUp(processor, scopeOwner, scopeOwner, name, roof, null);
}
public static void scopeCrawlUp(@NotNull PsiScopeProcessor processor, @Nullable ScopeOwner scopeOwner,
- @Nullable ScopeOwner originalScopeOwner, @Nullable String name, @Nullable PsiElement roof) {
+ @Nullable ScopeOwner originalScopeOwner, @Nullable String name, @Nullable PsiElement roof,
+ @Nullable final PsiElement anchor) {
while (scopeOwner != null) {
if (!(scopeOwner instanceof PyClass) || scopeOwner == originalScopeOwner) {
final Scope scope = ControlFlowCache.getScope(scopeOwner);
@@ -136,7 +142,31 @@ public class PyResolveUtil {
}
}
}
- for (NameDefiner definer : scope.getImportedNameDefiners()) {
+ List<NameDefiner> definers = new ArrayList<NameDefiner>(scope.getImportedNameDefiners());
+ if (anchor != null && ScopeUtil.getScopeOwner(anchor) == scopeOwner) {
+ final Comparator<NameDefiner> nearestDefinerComparator = new Comparator<NameDefiner>() {
+ @Override
+ public int compare(NameDefiner a, NameDefiner b) {
+ final boolean aIsBefore = PyPsiUtils.isBefore(a, anchor);
+ final boolean bIsBefore = PyPsiUtils.isBefore(b, anchor);
+ final int diff = a.getTextOffset() - b.getTextOffset();
+ if (aIsBefore && bIsBefore) {
+ return -diff;
+ }
+ else if (aIsBefore) {
+ return -1;
+ }
+ else if (bIsBefore) {
+ return 1;
+ }
+ else {
+ return diff;
+ }
+ }
+ };
+ Collections.sort(definers, nearestDefinerComparator);
+ }
+ for (NameDefiner definer : definers) {
if (!processor.execute(definer, ResolveState.initial())) {
found = true;
break;
diff --git a/python/src/com/jetbrains/python/run/PyRemoteTracebackFilter.java b/python/src/com/jetbrains/python/run/PyRemoteTracebackFilter.java
new file mode 100644
index 000000000000..2af1a641de83
--- /dev/null
+++ b/python/src/com/jetbrains/python/run/PyRemoteTracebackFilter.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.jetbrains.python.run;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.LocalFileSystem;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.remote.RemoteProcessHandlerBase;
+import com.intellij.util.PathMappingSettings;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author traff
+ */
+public class PyRemoteTracebackFilter extends PythonTracebackFilter {
+ private final RemoteProcessHandlerBase myHandler;
+
+ public PyRemoteTracebackFilter(Project project, String workingDirectory, RemoteProcessHandlerBase remoteProcessHandler) {
+ super(project, workingDirectory);
+
+ myHandler = remoteProcessHandler;
+ }
+
+ @Override
+ @Nullable
+ protected VirtualFile findFileByName(String fileName) {
+ VirtualFile vFile = super.findFileByName(fileName);
+ if (vFile != null) {
+ return vFile;
+ }
+ for (PathMappingSettings.PathMapping m : myHandler.getMappingSettings().getPathMappings()) {
+ if (m.canReplaceRemote(fileName)) {
+ VirtualFile file = LocalFileSystem.getInstance().findFileByPath(m.mapToLocal(fileName));
+ if (file != null && file.exists()) {
+ return file;
+ }
+ }
+ }
+
+
+
+ return null;
+ }
+}
diff --git a/python/src/com/jetbrains/python/run/PythonCommandLineState.java b/python/src/com/jetbrains/python/run/PythonCommandLineState.java
index 216e68c58e1d..a4d1718bb006 100644
--- a/python/src/com/jetbrains/python/run/PythonCommandLineState.java
+++ b/python/src/com/jetbrains/python/run/PythonCommandLineState.java
@@ -47,6 +47,7 @@ import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.vfs.JarFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.remote.RemoteProcessHandlerBase;
import com.intellij.util.PlatformUtils;
import com.intellij.util.containers.HashMap;
import com.jetbrains.python.PythonHelpersLocator;
@@ -80,7 +81,9 @@ public abstract class PythonCommandLineState extends CommandLineState {
public static final String GROUP_DEBUGGER = "Debugger";
public static final String GROUP_SCRIPT = "Script";
private final AbstractPythonRunConfiguration myConfig;
- private final List<Filter> myFilters;
+
+ private final List<Filter> myFilters = Lists.<Filter>newArrayList(new UrlFilter());
+
private Boolean myMultiprocessDebug = null;
public boolean isDebug() {
@@ -99,15 +102,9 @@ public abstract class PythonCommandLineState extends CommandLineState {
return serverSocket;
}
- public PythonCommandLineState(AbstractPythonRunConfiguration runConfiguration, ExecutionEnvironment env, List<Filter> filters) {
+ public PythonCommandLineState(AbstractPythonRunConfiguration runConfiguration, ExecutionEnvironment env) {
super(env);
myConfig = runConfiguration;
- myFilters = Lists.newArrayList(filters);
- addDefaultFilters();
- }
-
- protected void addDefaultFilters() {
- myFilters.add(new UrlFilter());
}
@Nullable
@@ -134,10 +131,23 @@ public abstract class PythonCommandLineState extends CommandLineState {
protected ConsoleView createAndAttachConsole(Project project, ProcessHandler processHandler, Executor executor)
throws ExecutionException {
final ConsoleView consoleView = createConsoleBuilder(project).filters(myFilters).getConsole();
+
+ addTracebackFilter(project, consoleView, processHandler);
+
consoleView.attachToProcess(processHandler);
return consoleView;
}
+ protected void addTracebackFilter(Project project, ConsoleView consoleView, ProcessHandler processHandler) {
+ if (PySdkUtil.isRemote(myConfig.getSdk())) {
+ assert processHandler instanceof RemoteProcessHandlerBase;
+ consoleView.addMessageFilter(new PyRemoteTracebackFilter(project, myConfig.getWorkingDirectory(), (RemoteProcessHandlerBase) processHandler));
+ }
+ else {
+ consoleView.addMessageFilter(new PythonTracebackFilter(project, myConfig.getWorkingDirectory()));
+ }
+ }
+
private TextConsoleBuilder createConsoleBuilder(Project project) {
if (isDebug()) {
return new PyDebugConsoleBuilder(project, PythonSdkType.findSdkByPath(myConfig.getInterpreterPath()));
diff --git a/python/src/com/jetbrains/python/run/PythonRunConfiguration.java b/python/src/com/jetbrains/python/run/PythonRunConfiguration.java
index bbba44441227..118c27beb548 100644
--- a/python/src/com/jetbrains/python/run/PythonRunConfiguration.java
+++ b/python/src/com/jetbrains/python/run/PythonRunConfiguration.java
@@ -15,11 +15,9 @@
*/
package com.jetbrains.python.run;
-import com.google.common.collect.Lists;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.Executor;
import com.intellij.execution.configurations.*;
-import com.intellij.execution.filters.Filter;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.openapi.components.PathMacroManager;
import com.intellij.openapi.options.SettingsEditor;
@@ -40,7 +38,6 @@ import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import java.io.File;
-import java.util.List;
/**
* @author yole
@@ -64,10 +61,7 @@ public class PythonRunConfiguration extends AbstractPythonRunConfiguration
}
public RunProfileState getState(@NotNull final Executor executor, @NotNull final ExecutionEnvironment env) throws ExecutionException {
- List<Filter> filters = Lists.newArrayList();
- filters.add(new PythonTracebackFilter(getProject(), getWorkingDirectory()));
-
- return new PythonScriptCommandLineState(this, env, filters);
+ return new PythonScriptCommandLineState(this, env);
}
public void checkConfiguration() throws RuntimeConfigurationException {
diff --git a/python/src/com/jetbrains/python/run/PythonScriptCommandLineState.java b/python/src/com/jetbrains/python/run/PythonScriptCommandLineState.java
index 53ef554838ae..81d2daaee3d0 100644
--- a/python/src/com/jetbrains/python/run/PythonScriptCommandLineState.java
+++ b/python/src/com/jetbrains/python/run/PythonScriptCommandLineState.java
@@ -18,20 +18,17 @@ package com.jetbrains.python.run;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.configurations.ParametersList;
import com.intellij.execution.configurations.ParamsGroup;
-import com.intellij.execution.filters.Filter;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.openapi.util.text.StringUtil;
-import java.util.List;
-
/**
* @author yole
*/
public class PythonScriptCommandLineState extends PythonCommandLineState {
private final PythonRunConfiguration myConfig;
- public PythonScriptCommandLineState(PythonRunConfiguration runConfiguration, ExecutionEnvironment env, List<Filter> filters) {
- super(runConfiguration, env, filters);
+ public PythonScriptCommandLineState(PythonRunConfiguration runConfiguration, ExecutionEnvironment env) {
+ super(runConfiguration, env);
myConfig = runConfiguration;
}
diff --git a/python/src/com/jetbrains/python/run/PythonTracebackFilter.java b/python/src/com/jetbrains/python/run/PythonTracebackFilter.java
index e3bd879cfe81..73a3abd222b1 100644
--- a/python/src/com/jetbrains/python/run/PythonTracebackFilter.java
+++ b/python/src/com/jetbrains/python/run/PythonTracebackFilter.java
@@ -51,10 +51,7 @@ public class PythonTracebackFilter implements Filter {
if (matcher.find()) {
String fileName = matcher.group(1).replace('\\', '/');
int lineNumber = Integer.parseInt(matcher.group(2));
- VirtualFile vFile = LocalFileSystem.getInstance().findFileByPath(fileName);
- if (vFile == null && !StringUtil.isEmptyOrSpaces(myWorkingDirectory)) {
- vFile = LocalFileSystem.getInstance().findFileByIoFile(new File(myWorkingDirectory, fileName));
- }
+ VirtualFile vFile = findFileByName(fileName);
if (vFile != null) {
OpenFileHyperlinkInfo hyperlink = new OpenFileHyperlinkInfo(myProject, vFile, lineNumber - 1);
@@ -66,4 +63,13 @@ public class PythonTracebackFilter implements Filter {
}
return null;
}
+
+ @Nullable
+ protected VirtualFile findFileByName(String fileName) {
+ VirtualFile vFile = LocalFileSystem.getInstance().findFileByPath(fileName);
+ if (vFile == null && !StringUtil.isEmptyOrSpaces(myWorkingDirectory)) {
+ vFile = LocalFileSystem.getInstance().findFileByIoFile(new File(myWorkingDirectory, fileName));
+ }
+ return vFile;
+ }
}
diff --git a/python/src/com/jetbrains/python/sdk/PyDetectedSdk.java b/python/src/com/jetbrains/python/sdk/PyDetectedSdk.java
index 098462ef44fb..f288bd99ce3b 100644
--- a/python/src/com/jetbrains/python/sdk/PyDetectedSdk.java
+++ b/python/src/com/jetbrains/python/sdk/PyDetectedSdk.java
@@ -8,4 +8,8 @@ public class PyDetectedSdk extends ProjectJdkImpl {
setHomePath(name);
}
+ @Override
+ public String getVersionString() {
+ return "";
+ }
}
diff --git a/python/src/com/jetbrains/python/testing/PythonTestCommandLineStateBase.java b/python/src/com/jetbrains/python/testing/PythonTestCommandLineStateBase.java
index 39e4e96b836b..1a5aafe59051 100644
--- a/python/src/com/jetbrains/python/testing/PythonTestCommandLineStateBase.java
+++ b/python/src/com/jetbrains/python/testing/PythonTestCommandLineStateBase.java
@@ -22,7 +22,6 @@ import com.intellij.execution.ExecutionResult;
import com.intellij.execution.Executor;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.configurations.ParamsGroup;
-import com.intellij.execution.filters.Filter;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.testframework.TestFrameworkRunningModel;
@@ -42,12 +41,10 @@ import com.jetbrains.python.console.PythonDebugLanguageConsoleView;
import com.jetbrains.python.run.AbstractPythonRunConfiguration;
import com.jetbrains.python.run.CommandLinePatcher;
import com.jetbrains.python.run.PythonCommandLineState;
-import com.jetbrains.python.run.PythonTracebackFilter;
import com.jetbrains.python.sdk.PythonSdkType;
import org.jetbrains.annotations.NotNull;
import java.io.File;
-import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -62,7 +59,7 @@ public abstract class PythonTestCommandLineStateBase extends PythonCommandLineSt
}
public PythonTestCommandLineStateBase(AbstractPythonRunConfiguration configuration, ExecutionEnvironment env) {
- super(configuration, env, Collections.<Filter>emptyList());
+ super(configuration, env);
myConfiguration = configuration;
}
@@ -77,7 +74,6 @@ public abstract class PythonTestCommandLineStateBase extends PythonCommandLineSt
consoleProperties,
getEnvironment());
final ConsoleView consoleView = new PythonDebugLanguageConsoleView(project, PythonSdkType.findSdkByPath(myConfiguration.getInterpreterPath()), testsOutputConsoleView);
- consoleView.addMessageFilter(new PythonTracebackFilter(project, myConfiguration.getWorkingDirectory()));
consoleView.attachToProcess(processHandler);
return consoleView;
}
@@ -85,7 +81,7 @@ public abstract class PythonTestCommandLineStateBase extends PythonCommandLineSt
processHandler,
consoleProperties,
getEnvironment());
- consoleView.addMessageFilter(new PythonTracebackFilter(project, myConfiguration.getWorkingDirectory()));
+ addTracebackFilter(project, consoleView, processHandler);
return consoleView;
}
diff --git a/python/src/com/jetbrains/python/testing/pytest/PyTestCommandLineState.java b/python/src/com/jetbrains/python/testing/pytest/PyTestCommandLineState.java
index 3637f37ca91c..581e688de1d5 100644
--- a/python/src/com/jetbrains/python/testing/pytest/PyTestCommandLineState.java
+++ b/python/src/com/jetbrains/python/testing/pytest/PyTestCommandLineState.java
@@ -81,7 +81,7 @@ public class PyTestCommandLineState extends PythonTestCommandLineStateBase {
protected ConsoleView createAndAttachConsole(Project project, ProcessHandler processHandler, Executor executor)
throws ExecutionException {
final ConsoleView consoleView = super.createAndAttachConsole(project, processHandler, executor);
- consoleView.addMessageFilter(new PyTestTracebackFilter(project, myConfiguration.getWorkingDirectory()));
+ addTracebackFilter(project, consoleView, processHandler);
return consoleView;
}
}
diff --git a/python/testData/codeInsight/smartEnter/withExpressionMissing.py b/python/testData/codeInsight/smartEnter/withExpressionMissing.py
new file mode 100644
index 000000000000..25526ea4e55f
--- /dev/null
+++ b/python/testData/codeInsight/smartEnter/withExpressionMissing.py
@@ -0,0 +1 @@
+with <caret> \ No newline at end of file
diff --git a/python/testData/codeInsight/smartEnter/withExpressionMissing_after.py b/python/testData/codeInsight/smartEnter/withExpressionMissing_after.py
new file mode 100644
index 000000000000..722e64a456b8
--- /dev/null
+++ b/python/testData/codeInsight/smartEnter/withExpressionMissing_after.py
@@ -0,0 +1 @@
+with <caret>: \ No newline at end of file
diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportBeforeStarDunderAll/a.py b/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportBeforeStarDunderAll/a.py
new file mode 100644
index 000000000000..6d444960ee9d
--- /dev/null
+++ b/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportBeforeStarDunderAll/a.py
@@ -0,0 +1,3 @@
+import b
+<warning descr="Unused import statement">from p1 import *</warning>
+print(b)
diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportBeforeStarDunderAll/b.py b/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportBeforeStarDunderAll/b.py
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportBeforeStarDunderAll/b.py
diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportBeforeStarDunderAll/p1/__init__.py b/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportBeforeStarDunderAll/p1/__init__.py
new file mode 100644
index 000000000000..31f7e1aa969c
--- /dev/null
+++ b/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportBeforeStarDunderAll/p1/__init__.py
@@ -0,0 +1 @@
+from p1.m1 import *
diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportBeforeStarDunderAll/p1/m1.py b/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportBeforeStarDunderAll/p1/m1.py
new file mode 100644
index 000000000000..3f8018db03f2
--- /dev/null
+++ b/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportBeforeStarDunderAll/p1/m1.py
@@ -0,0 +1,2 @@
+import b
+__all__ = []
diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportBeforeStarImport/a.py b/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportBeforeStarImport/a.py
new file mode 100644
index 000000000000..7495833ba2c8
--- /dev/null
+++ b/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportBeforeStarImport/a.py
@@ -0,0 +1,5 @@
+import m1
+
+print(m1.foo)
+
+<warning descr="Unused import statement">from m2 import *</warning>
diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportBeforeStarImport/m1.py b/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportBeforeStarImport/m1.py
new file mode 100644
index 000000000000..1cfbade675f2
--- /dev/null
+++ b/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportBeforeStarImport/m1.py
@@ -0,0 +1 @@
+foo = 0
diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportBeforeStarImport/m2.py b/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportBeforeStarImport/m2.py
new file mode 100644
index 000000000000..5215a01f7c64
--- /dev/null
+++ b/python/testData/inspections/PyUnresolvedReferencesInspection/UnusedImportBeforeStarImport/m2.py
@@ -0,0 +1 @@
+import m1
diff --git a/python/testSrc/com/jetbrains/python/PySmartEnterTest.java b/python/testSrc/com/jetbrains/python/PySmartEnterTest.java
index b8421c9d7e18..09e0317051a0 100644
--- a/python/testSrc/com/jetbrains/python/PySmartEnterTest.java
+++ b/python/testSrc/com/jetbrains/python/PySmartEnterTest.java
@@ -179,4 +179,9 @@ public class PySmartEnterTest extends PyTestCase {
public void testWithTargetIncomplete() {
doTest();
}
+
+ // PY-12877
+ public void testWithExpressionMissing() {
+ doTest();
+ }
}
diff --git a/python/testSrc/com/jetbrains/python/fixtures/PyTestCase.java b/python/testSrc/com/jetbrains/python/fixtures/PyTestCase.java
index 6850c3b049a8..45d582a783a8 100644
--- a/python/testSrc/com/jetbrains/python/fixtures/PyTestCase.java
+++ b/python/testSrc/com/jetbrains/python/fixtures/PyTestCase.java
@@ -15,6 +15,9 @@
*/
package com.jetbrains.python.fixtures;
+import com.intellij.codeInsight.intention.IntentionAction;
+import com.intellij.codeInspection.LocalQuickFix;
+import com.intellij.codeInspection.ex.QuickFixWrapper;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.module.Module;
@@ -28,6 +31,7 @@ import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiReference;
import com.intellij.testFramework.LightProjectDescriptor;
import com.intellij.testFramework.PlatformTestCase;
@@ -131,8 +135,32 @@ public abstract class PyTestCase extends UsefulTestCase {
}
}
- protected static void assertNotParsed(PyFile file) {
- assertNull(PARSED_ERROR_MSG, ((PyFileImpl)file).getTreeElement());
+ /**
+ * Searches for quickfix itetion by its class
+ * @param clazz quick fix class
+ * @param <T> quick fix class
+ * @return quick fix or null if nothing found
+ */
+ @Nullable
+ public <T extends LocalQuickFix> T findQuickFixByClassInIntentions(@NotNull final Class<T> clazz) {
+
+ for (final IntentionAction action : myFixture.getAvailableIntentions()) {
+ if ((action instanceof QuickFixWrapper)) {
+ final QuickFixWrapper quickFixWrapper = (QuickFixWrapper)action;
+ final LocalQuickFix fix = quickFixWrapper.getFix();
+ if (clazz.isInstance(fix)) {
+ @SuppressWarnings("unchecked")
+ final T result = (T)fix;
+ return result;
+ }
+ }
+ }
+ return null;
+ }
+
+
+ protected static void assertNotParsed(PyFile file) {
+ assertNull(PARSED_ERROR_MSG, ((PyFileImpl)file).getTreeElement());
}
/**
@@ -144,6 +172,18 @@ public abstract class PyTestCase extends UsefulTestCase {
return myFixture.findElementByText("class " + name, PyClass.class);
}
+ /**
+ * Finds some text and moves cursor to it (if found)
+ *
+ * @param testToFind text to find
+ * @throws AssertionError if element not found
+ */
+ protected void moveByText(@NotNull final String testToFind) {
+ final PsiElement element = myFixture.findElementByText(testToFind, PsiElement.class);
+ assert element != null : "No element found by text: " + testToFind;
+ myFixture.getEditor().getCaretModel().moveToOffset(element.getTextOffset());
+ }
+
protected static class PyLightProjectDescriptor implements LightProjectDescriptor {
private final String myPythonVersion;
diff --git a/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java
index 0c5e87ab1001..a0a2a1232b2e 100644
--- a/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java
+++ b/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java
@@ -371,6 +371,16 @@ public class PyUnresolvedReferencesInspectionTest extends PyInspectionTestCase {
doMultiFileTest();
}
+ // PY-11472
+ public void testUnusedImportBeforeStarImport() {
+ doMultiFileTest();
+ }
+
+ // PY-13585
+ public void testUnusedImportBeforeStarDunderAll() {
+ doMultiFileTest();
+ }
+
@NotNull
@Override
protected Class<? extends PyInspection> getInspectionClass() {
diff --git a/resources-en/src/messages/DebuggerBundle.properties b/resources-en/src/messages/DebuggerBundle.properties
index fa51256eb277..f245bb59ddaa 100644
--- a/resources-en/src/messages/DebuggerBundle.properties
+++ b/resources-en/src/messages/DebuggerBundle.properties
@@ -204,9 +204,6 @@ button.move.up=Move &Up
button.move.down=Move &Down
label.compound.renderer.configurable.table.header.name=Name
label.compound.renderer.configurable.table.header.expression=Expression
-debugger.launching.configurable.display.name=Launching
-debugger.hotswap.configurable.display.name=HotSwap
-label.debugger.launching.configurable.hide.window=Hide debug &window on process termination
label.debugger.hotswap.configurable.hotswap.background=Reload classes in &background
label.debugger.hotswap.configurable.compile.before.hotswap=Make project before reloading classes
label.debugger.hotswap.configurable.enable.vm.hang.warning=Enable 'JVM will hang' warning
@@ -214,7 +211,6 @@ label.debugger.hotswap.configurable.reload.classes=Reload classes after compilat
label.debugger.hotswap.configurable.always=&Always
label.debugger.hotswap.configurable.never=&Never
label.debugger.hotswap.configurable.ask=As&k
-label.debugger.general.configurable.group.launching=Launching
label.debugger.launching.configurable.force.classic.vm=Force Class&ic VM for JDK 1.3.x and earlier
label.debugger.launching.configurable.disable.jit=Disable JIT
label.debugger.launching.configurable.debugger.transport=Transport:
@@ -232,7 +228,7 @@ label.threads.view.configurable.current.thread.on.top=Move current thread to the
label.threads.view.configurable.show.stack.frames.for.synthetic.methods=Show stack &frames for synthetic methods
label.threads.view.configurable.show.thread.groups=Show thread &groups
threads.view.configurable.display.name=Customize Threads View
-user.renderers.configurable.display.name=Data Type Renderers
+user.renderers.configurable.display.name=Java Data Type Renderers
label.user.renderers.configurable.renderer.name=Renderer name:
text.user.renderers.configurable.no.renderers=No renderers
button.copy=Copy
diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml
index 9764417638d6..726049771790 100644
--- a/resources/src/META-INF/IdeaPlugin.xml
+++ b/resources/src/META-INF/IdeaPlugin.xml
@@ -27,7 +27,8 @@
<implementation-class>com.intellij.util.xml.impl.JavaDomApplicationComponent</implementation-class>
</component>
<component>
- <implementation-class>com.intellij.codeInspection.bytecodeAnalysis.BytecodeAnalysisConverter</implementation-class>
+ <interface-class>com.intellij.codeInspection.bytecodeAnalysis.BytecodeAnalysisConverter</interface-class>
+ <implementation-class>com.intellij.codeInspection.bytecodeAnalysis.BytecodeAnalysisConverterImpl</implementation-class>
</component>
</application-components>
@@ -238,6 +239,8 @@
<extensionPoint name="hierarchy.referenceProcessor" interface="com.intellij.ide.hierarchy.call.CallReferenceProcessor"/>
<extensionPoint name="lang.psiAugmentProvider" interface="com.intellij.psi.augment.PsiAugmentProvider"/>
+
+ <extensionPoint name="custom.exception.handler" interface="com.intellij.codeInsight.CustomExceptionHandler"/>
</extensionPoints>
<extensions defaultExtensionNs="com.intellij">
diff --git a/resources/src/idea/RichPlatformActions.xml b/resources/src/idea/RichPlatformActions.xml
index 12a8d342c956..562f7c4177c7 100644
--- a/resources/src/idea/RichPlatformActions.xml
+++ b/resources/src/idea/RichPlatformActions.xml
@@ -389,12 +389,6 @@
<add-to-group group-id="NavbarPopupMenu" anchor="after" relative-to-action="WeighingNewGroup"/>
</action>
-
- <group id="DiffPanel.Toolbar.IDEA">
- <reference ref="Find"/>
- <add-to-group group-id="DiffPanel.Toolbar" anchor="after" relative-to-action="$Copy"/>
- </group>
-
<group>
<group id="MarkSourceRootGroup" class="com.intellij.ide.projectView.actions.MarkSourceRootActionGroup"/>
<action id="MarkExcludeRoot" class="com.intellij.ide.projectView.actions.MarkExcludeRootAction" icon="AllIcons.Modules.ExcludeRoot"/>
diff --git a/resources/src/idea/RichPlatformPlugin.xml b/resources/src/idea/RichPlatformPlugin.xml
index 92ae7046006e..93aa37c999c8 100644
--- a/resources/src/idea/RichPlatformPlugin.xml
+++ b/resources/src/idea/RichPlatformPlugin.xml
@@ -339,6 +339,7 @@
<stepsBeforeRunProvider implementation="com.intellij.compiler.options.CompileStepBeforeRunNoErrorCheck" id="compileBeforeRunNoErrorCheck" order="after compileBeforeRun"/>
<stepsBeforeRunProvider implementation="com.intellij.packaging.impl.run.BuildArtifactsBeforeRunTaskProvider" order="after compileBeforeRunNoErrorCheck"/>
<programRunner id="defaultRunRunner" implementation="com.intellij.execution.impl.DefaultJavaProgramRunner"/>
+ <programRunner implementation="com.intellij.execution.runners.BasicProgramRunner" order="last"/>
<hectorComponentProvider implementation="com.intellij.codeInsight.daemon.impl.ImportPopupHectorComponentProvider"/>
@@ -372,6 +373,8 @@
<projectStructure.sourceRootEditHandler implementation="com.intellij.openapi.roots.ui.configuration.JavaTestResourceRootEditHandler"/>
<buildProcess.parametersProvider implementation="com.intellij.compiler.classFilesIndex.api.index.ClassFilesIndexerBuilderParametersProvider"/>
+
+ <org.jetbrains.webServerRootsProvider implementation="org.jetbrains.builtInWebServer.ArtifactWebServerRootsProvider" order="last"/>
</extensions>
<xi:include href="/META-INF/xdebugger.xml" xpointer="xpointer(/idea-plugin/*)"/>
diff --git a/spellchecker/src/com/intellij/spellchecker/jetbrains.dic b/spellchecker/src/com/intellij/spellchecker/jetbrains.dic
index 52b856089b10..bb2388b83709 100644
--- a/spellchecker/src/com/intellij/spellchecker/jetbrains.dic
+++ b/spellchecker/src/com/intellij/spellchecker/jetbrains.dic
@@ -228,6 +228,8 @@ junit
keepduplicates
keychain
keychains
+keyframe
+keyframes
kotlin
labeler
labelers
diff --git a/xml/impl/src/com/intellij/application/options/CodeStyleHtmlPanel.form b/xml/impl/src/com/intellij/application/options/CodeStyleHtmlPanel.form
index 01f7df00f6bd..0ddd4cf577f3 100644
--- a/xml/impl/src/com/intellij/application/options/CodeStyleHtmlPanel.form
+++ b/xml/impl/src/com/intellij/application/options/CodeStyleHtmlPanel.form
@@ -17,7 +17,7 @@
<border type="none"/>
<children/>
</xy>
- <grid id="1b801" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <grid id="1b801" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
@@ -27,14 +27,14 @@
<children>
<scrollpane id="3e3f1" class="com.intellij.ui.components.JBScrollPane" binding="myJBScrollPane" custom-create="true">
<constraints>
- <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="0" anchor="9" fill="0" indent="0" use-parent-layout="false"/>
+ <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="0" anchor="9" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<horizontalScrollBarPolicy value="31"/>
</properties>
<border type="empty"/>
<children>
- <grid id="b4cfb" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <grid id="b4cfb" layout-manager="GridLayoutManager" row-count="4" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints/>
<properties/>
@@ -43,7 +43,7 @@
<grid id="ca5bb" layout-manager="GridLayoutManager" row-count="7" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
- <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ <grid row="3" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
@@ -185,7 +185,7 @@
<grid id="b8acc" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
- <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
@@ -277,7 +277,7 @@
<grid id="6dece" layout-manager="GridLayoutManager" row-count="4" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
- <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
@@ -336,6 +336,15 @@
</component>
</children>
</grid>
+ <grid id="eb695" binding="myRightMarginPanel" custom-create="true" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children/>
+ </grid>
</children>
</grid>
</children>
diff --git a/xml/impl/src/com/intellij/application/options/CodeStyleHtmlPanel.java b/xml/impl/src/com/intellij/application/options/CodeStyleHtmlPanel.java
index ba5a72a80beb..476181ff256d 100644
--- a/xml/impl/src/com/intellij/application/options/CodeStyleHtmlPanel.java
+++ b/xml/impl/src/com/intellij/application/options/CodeStyleHtmlPanel.java
@@ -15,6 +15,7 @@
*/
package com.intellij.application.options;
+import com.intellij.application.options.codeStyle.RightMarginForm;
import com.intellij.ide.highlighter.XmlHighlighterFactory;
import com.intellij.openapi.application.ApplicationBundle;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
@@ -30,6 +31,7 @@ import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import com.intellij.ui.components.JBScrollPane;
import com.intellij.util.ArrayUtil;
import com.intellij.util.PlatformIcons;
+import com.intellij.util.ui.Centerizer;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -64,6 +66,8 @@ public class CodeStyleHtmlPanel extends CodeStyleAbstractPanel {
private JCheckBox myShouldKeepLineBreaksInText;
private TextFieldWithBrowseButton myDontBreakIfInlineContent;
private JBScrollPane myJBScrollPane;
+ private JPanel myRightMarginPanel;
+ private RightMarginForm myRightMarginForm;
public CodeStyleHtmlPanel(CodeStyleSettings settings) {
super(settings);
@@ -95,6 +99,8 @@ public class CodeStyleHtmlPanel extends CodeStyleAbstractPanel {
}
private void createUIComponents() {
+ myRightMarginForm = new RightMarginForm(StdFileTypes.HTML.getLanguage(), getSettings());
+ myRightMarginPanel = myRightMarginForm.getTopPanel();
myJBScrollPane = new JBScrollPane() {
@Override
public Dimension getPreferredSize() {
@@ -158,6 +164,7 @@ public class CodeStyleHtmlPanel extends CodeStyleAbstractPanel {
settings.HTML_KEEP_WHITESPACES_INSIDE = myKeepWhiteSpacesTagNames.getText();
settings.HTML_KEEP_LINE_BREAKS = myShouldKeepBlankLines.isSelected();
settings.HTML_KEEP_LINE_BREAKS_IN_TEXT = myShouldKeepLineBreaksInText.isSelected();
+ myRightMarginForm.apply(settings);
}
private static int getIntValue(JTextField keepBlankLines) {
@@ -190,6 +197,7 @@ public class CodeStyleHtmlPanel extends CodeStyleAbstractPanel {
myInlineElementsTagNames.setText(settings.HTML_INLINE_ELEMENTS);
myDontBreakIfInlineContent.setText(settings.HTML_DONT_ADD_BREAKS_IF_INLINE_CONTENT);
myKeepWhiteSpacesTagNames.setText(settings.HTML_KEEP_WHITESPACES_INSIDE);
+ myRightMarginForm.reset(settings);
}
@Override
@@ -260,7 +268,7 @@ public class CodeStyleHtmlPanel extends CodeStyleAbstractPanel {
return true;
}
- return false;
+ return myRightMarginForm.isModified(settings);
}
@Override
diff --git a/xml/impl/src/com/intellij/application/options/CodeStyleXmlPanel.form b/xml/impl/src/com/intellij/application/options/CodeStyleXmlPanel.form
index 28d48d089cc1..c7895930be0f 100644
--- a/xml/impl/src/com/intellij/application/options/CodeStyleXmlPanel.form
+++ b/xml/impl/src/com/intellij/application/options/CodeStyleXmlPanel.form
@@ -17,7 +17,7 @@
</properties>
<border type="empty"/>
<children>
- <grid id="265f" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <grid id="265f" layout-manager="GridLayoutManager" row-count="4" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints/>
<properties/>
@@ -26,7 +26,7 @@
<grid id="417cd" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
- <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
@@ -114,7 +114,7 @@
<grid id="e7045" layout-manager="GridLayoutManager" row-count="4" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
- <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
@@ -176,7 +176,7 @@
<grid id="bcc6c" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
- <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ <grid row="3" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<clientProperties>
@@ -215,6 +215,15 @@
</component>
</children>
</grid>
+ <grid id="3d661" binding="myRightMarginPanel" custom-create="true" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children/>
+ </grid>
</children>
</grid>
</children>
diff --git a/xml/impl/src/com/intellij/application/options/CodeStyleXmlPanel.java b/xml/impl/src/com/intellij/application/options/CodeStyleXmlPanel.java
index ab3126162dde..8767e00de1ec 100644
--- a/xml/impl/src/com/intellij/application/options/CodeStyleXmlPanel.java
+++ b/xml/impl/src/com/intellij/application/options/CodeStyleXmlPanel.java
@@ -15,6 +15,7 @@
*/
package com.intellij.application.options;
+import com.intellij.application.options.codeStyle.RightMarginForm;
import com.intellij.ide.highlighter.XmlHighlighterFactory;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.highlighter.EditorHighlighter;
@@ -25,6 +26,7 @@ import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import com.intellij.psi.formatter.xml.XmlCodeStyleSettings;
import com.intellij.ui.components.JBScrollPane;
+import org.apache.xmlbeans.XmlLanguage;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -48,6 +50,8 @@ public class CodeStyleXmlPanel extends CodeStyleAbstractPanel{
private JComboBox myWhiteSpaceAroundCDATA;
private JCheckBox myKeepWhitespaceInsideCDATACheckBox;
private JBScrollPane myJBScrollPane;
+ private JPanel myRightMarginPanel;
+ private RightMarginForm myRightMarginForm;
public CodeStyleXmlPanel(CodeStyleSettings settings) {
super(settings);
@@ -83,6 +87,7 @@ public class CodeStyleXmlPanel extends CodeStyleAbstractPanel{
xmlSettings.XML_SPACE_INSIDE_EMPTY_TAG = myInEmptyTag.isSelected();
xmlSettings.XML_WHITE_SPACE_AROUND_CDATA = myWhiteSpaceAroundCDATA.getSelectedIndex();
xmlSettings.XML_KEEP_WHITE_SPACES_INSIDE_CDATA = myKeepWhitespaceInsideCDATACheckBox.isSelected();
+ myRightMarginForm.apply(settings);
}
private int getIntValue(JTextField keepBlankLines) {
@@ -109,6 +114,7 @@ public class CodeStyleXmlPanel extends CodeStyleAbstractPanel{
myWrapText.setSelected(wrapText(settings));
myWhiteSpaceAroundCDATA.setSelectedIndex(xmlSettings.XML_WHITE_SPACE_AROUND_CDATA);
myKeepWhitespaceInsideCDATACheckBox.setSelected(xmlSettings.XML_KEEP_WHITE_SPACES_INSIDE_CDATA);
+ myRightMarginForm.reset(settings);
}
@Override
@@ -156,7 +162,7 @@ public class CodeStyleXmlPanel extends CodeStyleAbstractPanel{
return true;
}
- return false;
+ return myRightMarginForm.isModified(settings);
}
private boolean wrapText(final CodeStyleSettings settings) {
@@ -193,5 +199,7 @@ public class CodeStyleXmlPanel extends CodeStyleAbstractPanel{
return new Dimension(prefSize.width + 15, prefSize.height);
}
};
+ myRightMarginForm = new RightMarginForm(StdFileTypes.XML.getLanguage(), getSettings());
+ myRightMarginPanel = myRightMarginForm.getTopPanel();
}
}
diff --git a/xml/impl/src/com/intellij/application/options/HtmlLanguageCodeStyleSettings.java b/xml/impl/src/com/intellij/application/options/HtmlLanguageCodeStyleSettings.java
index aa36d1b9aa60..d970ee5008cf 100644
--- a/xml/impl/src/com/intellij/application/options/HtmlLanguageCodeStyleSettings.java
+++ b/xml/impl/src/com/intellij/application/options/HtmlLanguageCodeStyleSettings.java
@@ -17,10 +17,13 @@ package com.intellij.application.options;
import com.intellij.lang.Language;
import com.intellij.lang.html.HTMLLanguage;
+import com.intellij.psi.codeStyle.CodeStyleSettingsCustomizable;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import com.intellij.psi.codeStyle.LanguageCodeStyleSettingsProvider;
import org.jetbrains.annotations.NotNull;
+import java.util.Set;
+
/**
* @author Rustam Vishnyakov
*/
@@ -37,6 +40,14 @@ public class HtmlLanguageCodeStyleSettings extends LanguageCodeStyleSettingsProv
}
@Override
+ public void customizeSettings(@NotNull CodeStyleSettingsCustomizable consumer,
+ @NotNull SettingsType settingsType) {
+ if (settingsType == SettingsType.WRAPPING_AND_BRACES_SETTINGS) {
+ consumer.showStandardOptions("RIGHT_MARGIN");
+ }
+ }
+
+ @Override
public CommonCodeStyleSettings getDefaultCommonSettings() {
CommonCodeStyleSettings defaultSettings = new CommonCodeStyleSettings(HTMLLanguage.INSTANCE);
defaultSettings.initIndentOptions();
diff --git a/xml/impl/src/com/intellij/application/options/XmlLanguageCodeStyleSettingsProvider.java b/xml/impl/src/com/intellij/application/options/XmlLanguageCodeStyleSettingsProvider.java
index 651c71e7ee7d..89311331d59b 100644
--- a/xml/impl/src/com/intellij/application/options/XmlLanguageCodeStyleSettingsProvider.java
+++ b/xml/impl/src/com/intellij/application/options/XmlLanguageCodeStyleSettingsProvider.java
@@ -17,6 +17,7 @@ package com.intellij.application.options;
import com.intellij.lang.Language;
import com.intellij.lang.xml.XMLLanguage;
+import com.intellij.psi.codeStyle.CodeStyleSettingsCustomizable;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import com.intellij.psi.codeStyle.LanguageCodeStyleSettingsProvider;
import com.intellij.util.PlatformUtils;
@@ -41,6 +42,14 @@ public class XmlLanguageCodeStyleSettingsProvider extends LanguageCodeStyleSetti
}
@Override
+ public void customizeSettings(@NotNull CodeStyleSettingsCustomizable consumer,
+ @NotNull SettingsType settingsType) {
+ if (settingsType == SettingsType.WRAPPING_AND_BRACES_SETTINGS) {
+ consumer.showStandardOptions("RIGHT_MARGIN");
+ }
+ }
+
+ @Override
public CommonCodeStyleSettings getDefaultCommonSettings() {
CommonCodeStyleSettings xmlSettings = new CommonCodeStyleSettings(getLanguage());
CommonCodeStyleSettings.IndentOptions indentOptions = xmlSettings.initIndentOptions();
diff --git a/xml/impl/src/com/intellij/codeInsight/completion/HtmlTextCompletionConfidence.java b/xml/impl/src/com/intellij/codeInsight/completion/HtmlTextCompletionConfidence.java
index ec6c806ffa1f..6d95604dc077 100644
--- a/xml/impl/src/com/intellij/codeInsight/completion/HtmlTextCompletionConfidence.java
+++ b/xml/impl/src/com/intellij/codeInsight/completion/HtmlTextCompletionConfidence.java
@@ -33,7 +33,9 @@ public class HtmlTextCompletionConfidence extends CompletionConfidence {
if (node != null && node.getElementType() == XmlTokenType.XML_DATA_CHARACTERS) {
PsiElement parent = contextElement.getParent();
if (parent instanceof XmlText || parent instanceof XmlDocument) {
- String prefix = contextElement.getText().substring(0, offset - contextElement.getTextRange().getStartOffset());
+ String contextElementText = contextElement.getText();
+ int endOffset = offset - contextElement.getTextRange().getStartOffset();
+ String prefix = contextElementText.substring(0, Math.min(contextElementText.length(), endOffset));
if (!StringUtil.startsWithChar(prefix, '<') && !StringUtil.startsWithChar(prefix, '&')) {
return ThreeState.YES;
}
diff --git a/xml/impl/src/com/intellij/codeInsight/template/emmet/filters/TrimZenCodingFilter.java b/xml/impl/src/com/intellij/codeInsight/template/emmet/filters/TrimZenCodingFilter.java
index ceb0d1dd61b9..421fbdd46564 100644
--- a/xml/impl/src/com/intellij/codeInsight/template/emmet/filters/TrimZenCodingFilter.java
+++ b/xml/impl/src/com/intellij/codeInsight/template/emmet/filters/TrimZenCodingFilter.java
@@ -18,6 +18,7 @@ package com.intellij.codeInsight.template.emmet.filters;
import com.intellij.codeInsight.template.emmet.nodes.GenerationNode;
import com.intellij.codeInsight.template.emmet.tokens.TemplateToken;
import com.intellij.lang.xml.XMLLanguage;
+import com.intellij.openapi.application.ApplicationManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.XmlElementVisitor;
import com.intellij.psi.xml.XmlDocument;
@@ -25,6 +26,7 @@ import com.intellij.psi.xml.XmlTag;
import com.intellij.psi.xml.XmlTagValue;
import org.jetbrains.annotations.NotNull;
+import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
@@ -57,18 +59,27 @@ public class TrimZenCodingFilter extends ZenCodingFilter {
if (document != null) {
XmlTag tag = document.getRootTag();
if (tag != null && !tag.getText().isEmpty()) {
- new XmlElementVisitor() {
+ tag.accept(new XmlElementVisitor() {
@Override
- public void visitXmlTag(XmlTag tag) {
- if(!tag.isEmpty()) {
- XmlTagValue tagValue = tag.getValue();
- tagValue.setText(PATTERN.matcher(tagValue.getText()).replaceAll(""));
+ public void visitXmlTag(final XmlTag tag) {
+ if (!tag.isEmpty()) {
+ final XmlTagValue tagValue = tag.getValue();
+ final Matcher matcher = PATTERN.matcher(tagValue.getText());
+ if (matcher.matches()) {
+ ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ @Override
+ public void run() {
+ tagValue.setText(matcher.replaceAll(""));
+ }
+ });
+ }
}
tag.acceptChildren(this);
}
- }.visitXmlTag(tag);
+ });
return tag.getText();
- } else {
+ }
+ else {
return PATTERN.matcher(document.getText()).replaceAll("");
}
}
diff --git a/xml/impl/src/com/intellij/ide/browsers/BrowserLauncherImpl.java b/xml/impl/src/com/intellij/ide/browsers/BrowserLauncherImpl.java
index 86d2994c0e00..4f7f4efa5085 100644
--- a/xml/impl/src/com/intellij/ide/browsers/BrowserLauncherImpl.java
+++ b/xml/impl/src/com/intellij/ide/browsers/BrowserLauncherImpl.java
@@ -18,6 +18,7 @@ package com.intellij.ide.browsers;
import com.intellij.concurrency.JobScheduler;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.util.ExecUtil;
+import com.intellij.ide.GeneralSettings;
import com.intellij.ide.IdeBundle;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.options.ShowSettingsUtil;
@@ -25,14 +26,30 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.AppUIUtil;
+import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.net.URI;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
final class BrowserLauncherImpl extends BrowserLauncherAppless {
@Override
+ protected void browseUsingNotSystemDefaultBrowserPolicy(@NotNull URI uri, @NotNull GeneralSettings settings, @Nullable Project project) {
+ WebBrowserManager browserManager = WebBrowserManager.getInstance();
+ if (browserManager.getDefaultBrowserPolicy() == DefaultBrowserPolicy.FIRST) {
+ WebBrowser browser = browserManager.getFirstActiveBrowser();
+ if (browser != null) {
+ browseUsingPath(uri.toString(), null, browser, project, ArrayUtil.EMPTY_STRING_ARRAY);
+ return;
+ }
+ }
+
+ super.browseUsingNotSystemDefaultBrowserPolicy(uri, settings, project);
+ }
+
+ @Override
protected void doShowError(@Nullable final String error, @Nullable final WebBrowser browser, @Nullable final Project project, final String title, @Nullable final Runnable launchTask) {
AppUIUtil.invokeOnEdt(new Runnable() {
@Override
diff --git a/xml/impl/src/com/intellij/ide/browsers/BrowserSelector.java b/xml/impl/src/com/intellij/ide/browsers/BrowserSelector.java
index 3ae67def8424..af04e5896387 100644
--- a/xml/impl/src/com/intellij/ide/browsers/BrowserSelector.java
+++ b/xml/impl/src/com/intellij/ide/browsers/BrowserSelector.java
@@ -81,8 +81,8 @@ public class BrowserSelector {
boolean hasFocus) {
Icon baseIcon;
if (value == null) {
- WebBrowser defaultBrowser = WebBrowserManager.getInstance().getDefaultBrowser();
- baseIcon = defaultBrowser == null ? PlatformIcons.WEB_ICON : defaultBrowser.getIcon();
+ WebBrowser firstBrowser = WebBrowserManager.getInstance().getFirstActiveBrowser();
+ baseIcon = firstBrowser == null ? PlatformIcons.WEB_ICON : firstBrowser.getIcon();
}
else {
baseIcon = value.getIcon();
diff --git a/xml/impl/src/com/intellij/ide/browsers/BrowserSettingsPanel.form b/xml/impl/src/com/intellij/ide/browsers/BrowserSettingsPanel.form
index 52d074347bbc..23d7bf2ea873 100644
--- a/xml/impl/src/com/intellij/ide/browsers/BrowserSettingsPanel.form
+++ b/xml/impl/src/com/intellij/ide/browsers/BrowserSettingsPanel.form
@@ -22,7 +22,7 @@
</constraints>
<properties/>
</component>
- <component id="95daa" class="com.intellij.openapi.ui.ComboBox" binding="defaultBrowserComboBox">
+ <component id="95daa" class="com.intellij.openapi.ui.ComboBox" binding="defaultBrowserPolicyComboBox">
<constraints>
<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>
diff --git a/xml/impl/src/com/intellij/ide/browsers/BrowserSettingsPanel.java b/xml/impl/src/com/intellij/ide/browsers/BrowserSettingsPanel.java
index 477d527ecbac..f43c0f6f4929 100644
--- a/xml/impl/src/com/intellij/ide/browsers/BrowserSettingsPanel.java
+++ b/xml/impl/src/com/intellij/ide/browsers/BrowserSettingsPanel.java
@@ -23,7 +23,6 @@ import com.intellij.openapi.options.ShowSettingsUtil;
import com.intellij.openapi.ui.ComboBox;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.openapi.util.Comparing;
-import com.intellij.ui.EnumComboBoxModel;
import com.intellij.ui.ListCellRendererWrapper;
import com.intellij.ui.TitledSeparator;
import com.intellij.util.Function;
@@ -34,6 +33,7 @@ import com.intellij.util.ui.LocalPathCellEditor;
import com.intellij.util.ui.UIUtil;
import com.intellij.util.ui.table.IconTableCellRenderer;
import com.intellij.util.ui.table.TableModelEditor;
+import org.jdesktop.swingx.combobox.ListComboBoxModel;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -46,9 +46,9 @@ import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
+import java.util.ArrayList;
import java.util.UUID;
-import static com.intellij.ide.browsers.WebBrowserManager.DefaultBrowser;
import static com.intellij.util.ui.table.TableModelEditor.EditableColumnInfo;
final class BrowserSettingsPanel {
@@ -73,7 +73,7 @@ final class BrowserSettingsPanel {
}
};
- private static final ColumnInfo[] COLUMNS = {new EditableColumnInfo<ConfigurableWebBrowser, Boolean>() {
+ private static final EditableColumnInfo<ConfigurableWebBrowser, Boolean> ACTIVE_COLUMN_INFO = new EditableColumnInfo<ConfigurableWebBrowser, Boolean>() {
@Override
public Class getColumnClass() {
return Boolean.class;
@@ -88,44 +88,49 @@ final class BrowserSettingsPanel {
public void setValue(ConfigurableWebBrowser item, Boolean value) {
item.setActive(value);
}
- }, new EditableColumnInfo<ConfigurableWebBrowser, String>("Name") {
- @Override
- public String valueOf(ConfigurableWebBrowser item) {
- return item.getName();
- }
+ };
- @Override
- public void setValue(ConfigurableWebBrowser item, String value) {
- item.setName(value);
- }
- }, new ColumnInfo<ConfigurableWebBrowser, BrowserFamily>("Family") {
- @Override
- public Class getColumnClass() {
- return BrowserFamily.class;
- }
+ private static final ColumnInfo[] COLUMNS = {ACTIVE_COLUMN_INFO,
+ new EditableColumnInfo<ConfigurableWebBrowser, String>("Name") {
+ @Override
+ public String valueOf(ConfigurableWebBrowser item) {
+ return item.getName();
+ }
- @Override
- public BrowserFamily valueOf(ConfigurableWebBrowser item) {
- return item.getFamily();
- }
+ @Override
+ public void setValue(ConfigurableWebBrowser item, String value) {
+ item.setName(value);
+ }
+ },
+ new ColumnInfo<ConfigurableWebBrowser, BrowserFamily>("Family") {
+ @Override
+ public Class getColumnClass() {
+ return BrowserFamily.class;
+ }
- @Override
- public void setValue(ConfigurableWebBrowser item, BrowserFamily value) {
- item.setFamily(value);
- item.setSpecificSettings(value.createBrowserSpecificSettings());
- }
+ @Override
+ public BrowserFamily valueOf(ConfigurableWebBrowser item) {
+ return item.getFamily();
+ }
- @Nullable
- @Override
- public TableCellRenderer getRenderer(ConfigurableWebBrowser item) {
- return IconTableCellRenderer.ICONABLE;
- }
+ @Override
+ public void setValue(ConfigurableWebBrowser item, BrowserFamily value) {
+ item.setFamily(value);
+ item.setSpecificSettings(value.createBrowserSpecificSettings());
+ }
- @Override
- public boolean isCellEditable(ConfigurableWebBrowser item) {
- return !WebBrowserManager.getInstance().isPredefinedBrowser(item);
- }
- }, PATH_COLUMN_INFO};
+ @Nullable
+ @Override
+ public TableCellRenderer getRenderer(ConfigurableWebBrowser item) {
+ return IconTableCellRenderer.ICONABLE;
+ }
+
+ @Override
+ public boolean isCellEditable(ConfigurableWebBrowser item) {
+ return !WebBrowserManager.getInstance().isPredefinedBrowser(item);
+ }
+ },
+ PATH_COLUMN_INFO};
private JPanel root;
@@ -138,7 +143,7 @@ final class BrowserSettingsPanel {
@SuppressWarnings("UnusedDeclaration")
private JComponent browsersTable;
- private ComboBox defaultBrowserComboBox;
+ private ComboBox defaultBrowserPolicyComboBox;
private TableModelEditor<ConfigurableWebBrowser> browsersEditor;
@@ -148,53 +153,55 @@ final class BrowserSettingsPanel {
alternativeBrowserPathField.addBrowseFolderListener(IdeBundle.message("title.select.path.to.browser"), null, null, APP_FILE_CHOOSER_DESCRIPTOR);
defaultBrowserPanel.setBorder(TitledSeparator.EMPTY_BORDER);
- //noinspection unchecked
- defaultBrowserComboBox.setModel(new EnumComboBoxModel<DefaultBrowser>(DefaultBrowser.class));
- if (BrowserLauncherAppless.canStartDefaultBrowser()) {
- defaultBrowserComboBox.addItemListener(new ItemListener() {
- @Override
- public void itemStateChanged(ItemEvent e) {
- boolean customPathEnabled = e.getItem() == DefaultBrowser.ALTERNATIVE;
- if (e.getStateChange() == ItemEvent.DESELECTED) {
- if (customPathEnabled) {
- customPathValue = alternativeBrowserPathField.getText();
- }
- }
- else if (e.getStateChange() == ItemEvent.SELECTED) {
- alternativeBrowserPathField.setEnabled(customPathEnabled);
- updateCustomPathTextFieldValue((DefaultBrowser)e.getItem());
- }
- }
- });
+ ArrayList<DefaultBrowserPolicy> defaultBrowserPolicies = new ArrayList<DefaultBrowserPolicy>();
+ if (BrowserLauncherAppless.canUseSystemDefaultBrowserPolicy()) {
+ defaultBrowserPolicies.add(DefaultBrowserPolicy.SYSTEM);
+ }
+ defaultBrowserPolicies.add(DefaultBrowserPolicy.FIRST);
+ defaultBrowserPolicies.add(DefaultBrowserPolicy.ALTERNATIVE);
- defaultBrowserComboBox.setRenderer(new ListCellRendererWrapper<DefaultBrowser>() {
- @Override
- public void customize(JList list, DefaultBrowser value, int index, boolean selected, boolean hasFocus) {
- String name;
- switch (value) {
- case SYSTEM:
- name = "System default";
- break;
- case FIRST:
- name = "First listed";
- break;
- case ALTERNATIVE:
- name = "Custom path";
- break;
- default:
- throw new IllegalStateException();
+ //noinspection Since15,unchecked
+ defaultBrowserPolicyComboBox.setModel(new ListComboBoxModel<DefaultBrowserPolicy>(defaultBrowserPolicies));
+ defaultBrowserPolicyComboBox.addItemListener(new ItemListener() {
+ @Override
+ public void itemStateChanged(ItemEvent e) {
+ boolean customPathEnabled = e.getItem() == DefaultBrowserPolicy.ALTERNATIVE;
+ if (e.getStateChange() == ItemEvent.DESELECTED) {
+ if (customPathEnabled) {
+ customPathValue = alternativeBrowserPathField.getText();
}
+ }
+ else if (e.getStateChange() == ItemEvent.SELECTED) {
+ alternativeBrowserPathField.setEnabled(customPathEnabled);
+ updateCustomPathTextFieldValue((DefaultBrowserPolicy)e.getItem());
+ }
+ }
+ });
- setText(name);
+ defaultBrowserPolicyComboBox.setRenderer(new ListCellRendererWrapper<DefaultBrowserPolicy>() {
+ @Override
+ public void customize(JList list, DefaultBrowserPolicy value, int index, boolean selected, boolean hasFocus) {
+ String name;
+ switch (value) {
+ case SYSTEM:
+ name = "System default";
+ break;
+ case FIRST:
+ name = "First listed";
+ break;
+ case ALTERNATIVE:
+ name = "Custom path";
+ break;
+ default:
+ throw new IllegalStateException();
}
- });
- if (UIUtil.isUnderAquaLookAndFeel()) {
- defaultBrowserComboBox.setBorder(new EmptyBorder(3, 0, 0, 0));
+ setText(name);
}
- }
- else {
- defaultBrowserComboBox.setVisible(false);
+ });
+
+ if (UIUtil.isUnderAquaLookAndFeel()) {
+ defaultBrowserPolicyComboBox.setBorder(new EmptyBorder(3, 0, 0, 0));
}
clearExtractedFiles.addActionListener(new ActionListener() {
@@ -205,11 +212,11 @@ final class BrowserSettingsPanel {
});
}
- private void updateCustomPathTextFieldValue(DefaultBrowser browser) {
- if (browser == DefaultBrowser.ALTERNATIVE) {
+ private void updateCustomPathTextFieldValue(@NotNull DefaultBrowserPolicy browser) {
+ if (browser == DefaultBrowserPolicy.ALTERNATIVE) {
alternativeBrowserPathField.setText(customPathValue);
}
- else if (browser == DefaultBrowser.FIRST) {
+ else if (browser == DefaultBrowserPolicy.FIRST) {
setCustomPathToFirstListed();
}
else {
@@ -272,18 +279,18 @@ final class BrowserSettingsPanel {
.modelListener(new TableModelEditor.DataChangedListener<ConfigurableWebBrowser>() {
@Override
public void tableChanged(TableModelEvent event) {
- update(event.getFirstRow());
+ update();
}
@Override
public void dataChanged(@NotNull ColumnInfo<ConfigurableWebBrowser, ?> columnInfo, int rowIndex) {
- if (columnInfo == PATH_COLUMN_INFO) {
- update(rowIndex);
+ if (columnInfo == PATH_COLUMN_INFO || columnInfo == ACTIVE_COLUMN_INFO) {
+ update();
}
}
- private void update(int rowIndex) {
- if (rowIndex == 0 && getDefaultBrowser() == DefaultBrowser.FIRST) {
+ private void update() {
+ if (getDefaultBrowser() == DefaultBrowserPolicy.FIRST) {
setCustomPathToFirstListed();
}
}
@@ -293,7 +300,15 @@ final class BrowserSettingsPanel {
private void setCustomPathToFirstListed() {
ListTableModel<ConfigurableWebBrowser> model = browsersEditor.getModel();
- alternativeBrowserPathField.setText(model.getRowCount() == 0 ? "" : model.getRowValue(0).getPath());
+ for (int i = 0, n = model.getRowCount(); i < n; i++) {
+ ConfigurableWebBrowser browser = model.getRowValue(i);
+ if (browser.isActive() && browser.getPath() != null) {
+ alternativeBrowserPathField.setText(browser.getPath());
+ return;
+ }
+ }
+
+ alternativeBrowserPathField.setText("");
}
@NotNull
@@ -305,12 +320,12 @@ final class BrowserSettingsPanel {
WebBrowserManager browserManager = WebBrowserManager.getInstance();
GeneralSettings generalSettings = GeneralSettings.getInstance();
- DefaultBrowser defaultBrowser = getDefaultBrowser();
- if (browserManager.getDefaultBrowserMode() != defaultBrowser || generalSettings.isConfirmExtractFiles() != confirmExtractFiles.isSelected()) {
+ DefaultBrowserPolicy defaultBrowserPolicy = getDefaultBrowser();
+ if (browserManager.getDefaultBrowserPolicy() != defaultBrowserPolicy || generalSettings.isConfirmExtractFiles() != confirmExtractFiles.isSelected()) {
return true;
}
- if (defaultBrowser == DefaultBrowser.ALTERNATIVE &&
+ if (defaultBrowserPolicy == DefaultBrowserPolicy.ALTERNATIVE &&
!Comparing.strEqual(generalSettings.getBrowserPath(), alternativeBrowserPathField.getText())) {
return true;
}
@@ -321,7 +336,7 @@ final class BrowserSettingsPanel {
public void apply() {
GeneralSettings settings = GeneralSettings.getInstance();
- settings.setUseDefaultBrowser(getDefaultBrowser() == DefaultBrowser.SYSTEM);
+ settings.setUseDefaultBrowser(getDefaultBrowser() == DefaultBrowserPolicy.SYSTEM);
if (alternativeBrowserPathField.isEnabled()) {
settings.setBrowserPath(alternativeBrowserPathField.getText());
@@ -330,26 +345,27 @@ final class BrowserSettingsPanel {
settings.setConfirmExtractFiles(confirmExtractFiles.isSelected());
WebBrowserManager browserManager = WebBrowserManager.getInstance();
- browserManager.defaultBrowser = getDefaultBrowser();
+ browserManager.defaultBrowserPolicy = getDefaultBrowser();
browserManager.setList(browsersEditor.apply());
}
- private DefaultBrowser getDefaultBrowser() {
- return (DefaultBrowser)defaultBrowserComboBox.getSelectedItem();
+ private DefaultBrowserPolicy getDefaultBrowser() {
+ return (DefaultBrowserPolicy)defaultBrowserPolicyComboBox.getSelectedItem();
}
public void reset() {
- GeneralSettings settings = GeneralSettings.getInstance();
-
- DefaultBrowser defaultBrowser = WebBrowserManager.getInstance().getDefaultBrowserMode();
- defaultBrowserComboBox.setSelectedItem(defaultBrowser);
+ DefaultBrowserPolicy defaultBrowserPolicy = WebBrowserManager.getInstance().getDefaultBrowserPolicy();
+ DefaultBrowserPolicy effectiveDefaultBrowserPolicy = defaultBrowserPolicy == DefaultBrowserPolicy.SYSTEM && !BrowserLauncherAppless.canUseSystemDefaultBrowserPolicy()
+ ? DefaultBrowserPolicy.ALTERNATIVE : defaultBrowserPolicy;
+ defaultBrowserPolicyComboBox.setSelectedItem(effectiveDefaultBrowserPolicy);
+ GeneralSettings settings = GeneralSettings.getInstance();
confirmExtractFiles.setSelected(settings.isConfirmExtractFiles());
browsersEditor.reset(WebBrowserManager.getInstance().getList());
customPathValue = settings.getBrowserPath();
- alternativeBrowserPathField.setEnabled(defaultBrowser == DefaultBrowser.ALTERNATIVE);
- updateCustomPathTextFieldValue(defaultBrowser);
+ alternativeBrowserPathField.setEnabled(effectiveDefaultBrowserPolicy == DefaultBrowserPolicy.ALTERNATIVE);
+ updateCustomPathTextFieldValue(effectiveDefaultBrowserPolicy);
}
public void selectBrowser(@NotNull WebBrowser browser) {
diff --git a/xml/impl/src/com/intellij/ide/browsers/ConfigurableWebBrowser.java b/xml/impl/src/com/intellij/ide/browsers/ConfigurableWebBrowser.java
index 11502b5119a9..9f48b35905ae 100644
--- a/xml/impl/src/com/intellij/ide/browsers/ConfigurableWebBrowser.java
+++ b/xml/impl/src/com/intellij/ide/browsers/ConfigurableWebBrowser.java
@@ -56,7 +56,7 @@ final class ConfigurableWebBrowser extends WebBrowser {
@Override
public Icon getIcon() {
if (family == BrowserFamily.CHROME) {
- if (checkNameAndPath("Yandex")) {
+ if (WebBrowserManager.isYandexBrowser(this)) {
return AllIcons.Xml.Browsers.Yandex16;
}
else if (checkNameAndPath("Dartium") || checkNameAndPath("Chromium")) {
@@ -76,14 +76,7 @@ final class ConfigurableWebBrowser extends WebBrowser {
}
private boolean checkNameAndPath(@NotNull String what) {
- if (StringUtil.containsIgnoreCase(name, what)) {
- return true;
- }
- if (path != null) {
- int index = path.lastIndexOf('/');
- return index > 0 ? path.indexOf(what, index + 1) != -1 : path.contains(what);
- }
- return false;
+ return WebBrowserManager.checkNameAndPath(what, this);
}
@Nullable
diff --git a/java/jsp-openapi/src/com/intellij/psi/jsp/JspImplicitVariable.java b/xml/impl/src/com/intellij/ide/browsers/DefaultBrowserPolicy.java
index 921cc8055dd1..4e1f0b2e0dc2 100644
--- a/java/jsp-openapi/src/com/intellij/psi/jsp/JspImplicitVariable.java
+++ b/xml/impl/src/com/intellij/ide/browsers/DefaultBrowserPolicy.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,18 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.intellij.psi.jsp;
+package com.intellij.ide.browsers;
-import com.intellij.pom.Navigatable;
-import com.intellij.psi.ImplicitVariable;
-import com.intellij.psi.PsiElement;
-import com.intellij.navigation.NavigationItem;
-
-public interface JspImplicitVariable extends ImplicitVariable, NavigationItem {
- JspImplicitVariable[] EMPTY_ARRAY = new JspImplicitVariable[0];
- int INSIDE = 1;
- int AFTER = 2;
- int getDeclarationRange();
-
- PsiElement getDeclaration();
+public enum DefaultBrowserPolicy {
+ SYSTEM, FIRST, ALTERNATIVE
} \ No newline at end of file
diff --git a/xml/impl/src/com/intellij/ide/browsers/WebBrowserManager.java b/xml/impl/src/com/intellij/ide/browsers/WebBrowserManager.java
index ce51ee07eebc..0b2ba6cb18c1 100644
--- a/xml/impl/src/com/intellij/ide/browsers/WebBrowserManager.java
+++ b/xml/impl/src/com/intellij/ide/browsers/WebBrowserManager.java
@@ -17,10 +17,7 @@ package com.intellij.ide.browsers;
import com.intellij.openapi.components.*;
import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.util.Condition;
-import com.intellij.openapi.util.Conditions;
-import com.intellij.openapi.util.JDOMUtil;
-import com.intellij.openapi.util.SimpleModificationTracker;
+import com.intellij.openapi.util.*;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.SmartList;
import com.intellij.util.xmlb.SkipDefaultValuesSerializationFilters;
@@ -36,53 +33,75 @@ public class WebBrowserManager extends SimpleModificationTracker implements Pers
private static final Logger LOG = Logger.getInstance(WebBrowserManager.class);
// default standard browser ID must be constant across all IDE versions on all machines for all users
- private static final UUID DEFAULT_CHROME_ID = UUID.fromString("98CA6316-2F89-46D9-A9E5-FA9E2B0625B3");
+ private static final UUID PREDEFINED_CHROME_ID = UUID.fromString("98CA6316-2F89-46D9-A9E5-FA9E2B0625B3");
// public, but only internal use
- public static final UUID DEFAULT_FIREFOX_ID = UUID.fromString("A7BB68E0-33C0-4D6F-A81A-AAC1FDB870C8");
- private static final UUID DEFAULT_SAFARI_ID = UUID.fromString("E5120D43-2C3F-47EF-9F26-65E539E05186");
- private static final UUID DEFAULT_OPERA_ID = UUID.fromString("53E2F627-B1A7-4DFA-BFA7-5B83CC034776");
- private static final UUID DEFAULT_EXPLORER_ID = UUID.fromString("16BF23D4-93E0-4FFC-BFD6-CB13575177B0");
+ public static final UUID PREDEFINED_FIREFOX_ID = UUID.fromString("A7BB68E0-33C0-4D6F-A81A-AAC1FDB870C8");
+ private static final UUID PREDEFINED_SAFARI_ID = UUID.fromString("E5120D43-2C3F-47EF-9F26-65E539E05186");
+ private static final UUID PREDEFINED_OPERA_ID = UUID.fromString("53E2F627-B1A7-4DFA-BFA7-5B83CC034776");
+ private static final UUID PREDEFINED_YANDEX_ID = UUID.fromString("B1B2EC2C-20BD-4EE2-89C4-616DB004BCD4");
+ private static final UUID PREDEFINED_EXPLORER_ID = UUID.fromString("16BF23D4-93E0-4FFC-BFD6-CB13575177B0");
+
+ private static final List<ConfigurableWebBrowser> PREDEFINED_BROWSERS = Arrays.asList(
+ new ConfigurableWebBrowser(PREDEFINED_CHROME_ID, BrowserFamily.CHROME),
+ new ConfigurableWebBrowser(PREDEFINED_FIREFOX_ID, BrowserFamily.FIREFOX),
+ new ConfigurableWebBrowser(PREDEFINED_SAFARI_ID, BrowserFamily.SAFARI),
+ new ConfigurableWebBrowser(PREDEFINED_OPERA_ID, BrowserFamily.OPERA),
+ new ConfigurableWebBrowser(PREDEFINED_YANDEX_ID, BrowserFamily.CHROME, "Yandex", SystemInfo.isWindows ? "browser" : (SystemInfo.isMac ? "Yandex" : "yandex"), false, BrowserFamily.CHROME.createBrowserSpecificSettings()),
+ new ConfigurableWebBrowser(PREDEFINED_EXPLORER_ID, BrowserFamily.EXPLORER)
+ );
private List<ConfigurableWebBrowser> browsers;
- DefaultBrowser defaultBrowser = DefaultBrowser.SYSTEM;
+ DefaultBrowserPolicy defaultBrowserPolicy = DefaultBrowserPolicy.SYSTEM;
public WebBrowserManager() {
- browsers = new ArrayList<ConfigurableWebBrowser>();
- browsers.add(new ConfigurableWebBrowser(DEFAULT_CHROME_ID, BrowserFamily.CHROME));
- browsers.add(new ConfigurableWebBrowser(DEFAULT_FIREFOX_ID, BrowserFamily.FIREFOX));
- browsers.add(new ConfigurableWebBrowser(DEFAULT_SAFARI_ID, BrowserFamily.SAFARI));
- browsers.add(new ConfigurableWebBrowser(DEFAULT_OPERA_ID, BrowserFamily.OPERA));
- browsers.add(new ConfigurableWebBrowser(DEFAULT_EXPLORER_ID, BrowserFamily.EXPLORER));
+ browsers = new ArrayList<ConfigurableWebBrowser>(PREDEFINED_BROWSERS);
}
public static WebBrowserManager getInstance() {
return ServiceManager.getService(WebBrowserManager.class);
}
- boolean isPredefinedBrowser(@NotNull ConfigurableWebBrowser browser) {
- UUID id = browser.getId();
- return id.equals(DEFAULT_CHROME_ID) ||
- id.equals(DEFAULT_FIREFOX_ID) ||
- id.equals(DEFAULT_SAFARI_ID) ||
- id.equals(DEFAULT_OPERA_ID) ||
- id.equals(DEFAULT_EXPLORER_ID);
+ public static boolean isYandexBrowser(@NotNull WebBrowser browser) {
+ return browser.getFamily().equals(BrowserFamily.CHROME) && (browser.getId().equals(PREDEFINED_YANDEX_ID) || checkNameAndPath("Yandex", browser));
+ }
+
+ public static boolean isDartium(@NotNull WebBrowser browser) {
+ return browser.getFamily().equals(BrowserFamily.CHROME) && checkNameAndPath("Dartium", browser);
+ }
+
+ static boolean checkNameAndPath(@NotNull String what, @NotNull WebBrowser browser) {
+ if (StringUtil.containsIgnoreCase(browser.getName(), what)) {
+ return true;
+ }
+ String path = browser.getPath();
+ if (path != null) {
+ int index = path.lastIndexOf('/');
+ return index > 0 ? path.indexOf(what, index + 1) != -1 : path.contains(what);
+ }
+ return false;
}
- public enum DefaultBrowser {
- SYSTEM, FIRST, ALTERNATIVE
+ boolean isPredefinedBrowser(@NotNull ConfigurableWebBrowser browser) {
+ UUID id = browser.getId();
+ for (ConfigurableWebBrowser predefinedBrowser : PREDEFINED_BROWSERS) {
+ if (id.equals(predefinedBrowser.getId())) {
+ return true;
+ }
+ }
+ return false;
}
@NotNull
- public DefaultBrowser getDefaultBrowserMode() {
- return defaultBrowser;
+ public DefaultBrowserPolicy getDefaultBrowserPolicy() {
+ return defaultBrowserPolicy;
}
@Override
public Element getState() {
Element state = new Element("state");
- if (defaultBrowser != DefaultBrowser.SYSTEM) {
- state.setAttribute("default", defaultBrowser.name().toLowerCase(Locale.ENGLISH));
+ if (defaultBrowserPolicy != DefaultBrowserPolicy.SYSTEM) {
+ state.setAttribute("default", defaultBrowserPolicy.name().toLowerCase(Locale.ENGLISH));
}
for (ConfigurableWebBrowser browser : browsers) {
@@ -137,19 +156,19 @@ public class WebBrowserManager extends SimpleModificationTracker implements Pers
UUID id;
switch (family) {
case CHROME:
- id = DEFAULT_CHROME_ID;
+ id = PREDEFINED_CHROME_ID;
break;
case EXPLORER:
- id = DEFAULT_EXPLORER_ID;
+ id = PREDEFINED_EXPLORER_ID;
break;
case FIREFOX:
- id = DEFAULT_FIREFOX_ID;
+ id = PREDEFINED_FIREFOX_ID;
break;
case OPERA:
- id = DEFAULT_OPERA_ID;
+ id = PREDEFINED_OPERA_ID;
break;
case SAFARI:
- id = DEFAULT_SAFARI_ID;
+ id = PREDEFINED_SAFARI_ID;
break;
default:
@@ -180,7 +199,7 @@ public class WebBrowserManager extends SimpleModificationTracker implements Pers
String defaultValue = element.getAttributeValue("default");
if (!StringUtil.isEmpty(defaultValue)) {
try {
- defaultBrowser = DefaultBrowser.valueOf(defaultValue.toUpperCase(Locale.ENGLISH));
+ defaultBrowserPolicy = DefaultBrowserPolicy.valueOf(defaultValue.toUpperCase(Locale.ENGLISH));
}
catch (IllegalArgumentException e) {
LOG.warn(e);
@@ -225,6 +244,18 @@ public class WebBrowserManager extends SimpleModificationTracker implements Pers
specificSettings));
}
+ // add removed/new predefined browsers
+ int n = list.size();
+ pb: for (ConfigurableWebBrowser predefinedBrowser : PREDEFINED_BROWSERS) {
+ //noinspection ForLoopReplaceableByForEach
+ for (int i = 0; i < n; i++) {
+ if (list.get(i).getId().equals(predefinedBrowser.getId())) {
+ continue pb;
+ }
+ }
+ list.add(predefinedBrowser);
+ }
+
setList(list);
}
@@ -349,9 +380,9 @@ public class WebBrowserManager extends SimpleModificationTracker implements Pers
}
@Nullable
- public WebBrowser getDefaultBrowser() {
+ public WebBrowser getFirstActiveBrowser() {
for (ConfigurableWebBrowser browser : browsers) {
- if (browser.isActive()) {
+ if (browser.isActive() && browser.getPath() != null) {
return browser;
}
}
diff --git a/xml/impl/src/com/intellij/ide/browsers/actions/BaseOpenInBrowserAction.java b/xml/impl/src/com/intellij/ide/browsers/actions/BaseOpenInBrowserAction.java
index 8ec2a2e55b67..e3bf3b5e6f6f 100644
--- a/xml/impl/src/com/intellij/ide/browsers/actions/BaseOpenInBrowserAction.java
+++ b/xml/impl/src/com/intellij/ide/browsers/actions/BaseOpenInBrowserAction.java
@@ -151,7 +151,7 @@ public abstract class BaseOpenInBrowserAction extends DumbAwareAction {
boolean applicable = false;
WebBrowserUrlProvider provider = null;
if (request != null) {
- applicable = HtmlUtil.isHtmlFile(request.getFile()) && !(request.getVirtualFile() instanceof LightVirtualFile);
+ applicable = WebBrowserServiceImpl.isHtmlOrXmlFile(request.getFile()) && !(request.getVirtualFile() instanceof LightVirtualFile);
if (!applicable) {
provider = WebBrowserServiceImpl.getProvider(request);
applicable = provider != null;
diff --git a/xml/impl/src/com/intellij/ide/browsers/actions/OpenFileInDefaultBrowserAction.java b/xml/impl/src/com/intellij/ide/browsers/actions/OpenFileInDefaultBrowserAction.java
index 45cf021bbef8..1ead1b6faeb4 100644
--- a/xml/impl/src/com/intellij/ide/browsers/actions/OpenFileInDefaultBrowserAction.java
+++ b/xml/impl/src/com/intellij/ide/browsers/actions/OpenFileInDefaultBrowserAction.java
@@ -16,10 +16,7 @@
package com.intellij.ide.browsers.actions;
import com.intellij.ide.GeneralSettings;
-import com.intellij.ide.browsers.OpenInBrowserRequest;
-import com.intellij.ide.browsers.WebBrowser;
-import com.intellij.ide.browsers.WebBrowserManager;
-import com.intellij.ide.browsers.WebBrowserUrlProvider;
+import com.intellij.ide.browsers.*;
import com.intellij.openapi.actionSystem.ActionPlaces;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.Presentation;
@@ -68,10 +65,11 @@ public class OpenFileInDefaultBrowserAction extends DumbAwareAction {
@Nullable
private static WebBrowser findUsingBrowser() {
WebBrowserManager browserManager = WebBrowserManager.getInstance();
- if (browserManager.getDefaultBrowserMode() == WebBrowserManager.DefaultBrowser.FIRST) {
- return browserManager.getDefaultBrowser();
+ DefaultBrowserPolicy defaultBrowserPolicy = browserManager.getDefaultBrowserPolicy();
+ if (defaultBrowserPolicy == DefaultBrowserPolicy.FIRST || (defaultBrowserPolicy == DefaultBrowserPolicy.SYSTEM && !BrowserLauncherAppless.canUseSystemDefaultBrowserPolicy())) {
+ return browserManager.getFirstActiveBrowser();
}
- else if (browserManager.getDefaultBrowserMode() == WebBrowserManager.DefaultBrowser.ALTERNATIVE) {
+ else if (defaultBrowserPolicy == DefaultBrowserPolicy.ALTERNATIVE) {
String path = GeneralSettings.getInstance().getBrowserPath();
if (!StringUtil.isEmpty(path)) {
WebBrowser browser = browserManager.findBrowserById(path);
diff --git a/xml/impl/src/com/intellij/ide/browsers/impl/WebBrowserServiceImpl.java b/xml/impl/src/com/intellij/ide/browsers/impl/WebBrowserServiceImpl.java
index 5cd056f869d9..3d0451d71b3d 100644
--- a/xml/impl/src/com/intellij/ide/browsers/impl/WebBrowserServiceImpl.java
+++ b/xml/impl/src/com/intellij/ide/browsers/impl/WebBrowserServiceImpl.java
@@ -18,6 +18,10 @@ package com.intellij.ide.browsers.impl;
import com.intellij.ide.browsers.OpenInBrowserRequest;
import com.intellij.ide.browsers.WebBrowserService;
import com.intellij.ide.browsers.WebBrowserUrlProvider;
+import com.intellij.lang.Language;
+import com.intellij.lang.html.HTMLLanguage;
+import com.intellij.lang.xhtml.XHTMLLanguage;
+import com.intellij.lang.xml.XMLLanguage;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.impl.http.HttpVirtualFile;
@@ -34,6 +38,11 @@ import java.util.Collection;
import java.util.Collections;
public class WebBrowserServiceImpl extends WebBrowserService {
+ public static boolean isHtmlOrXmlFile(@NotNull PsiElement element) {
+ Language language = element.getLanguage();
+ return language == HTMLLanguage.INSTANCE || language == XHTMLLanguage.INSTANCE || language == XMLLanguage.INSTANCE;
+ }
+
@NotNull
@Override
public Collection<Url> getUrlsToOpen(@NotNull OpenInBrowserRequest request, boolean preferLocalUrl) throws WebBrowserUrlProvider.BrowserException {
@@ -42,7 +51,7 @@ public class WebBrowserServiceImpl extends WebBrowserService {
return Collections.singleton(Urls.newFromVirtualFile(virtualFile));
}
- if (!preferLocalUrl || !HtmlUtil.isHtmlFile(request.getFile())) {
+ if (!preferLocalUrl || !isHtmlOrXmlFile(request.getFile())) {
WebBrowserUrlProvider provider = getProvider(request);
if (provider != null) {
if (request.getResult() != null) {
diff --git a/xml/impl/src/com/intellij/psi/formatter/xml/AbstractXmlBlock.java b/xml/impl/src/com/intellij/psi/formatter/xml/AbstractXmlBlock.java
index 6e1b89912814..b2b5b5ff8eee 100644
--- a/xml/impl/src/com/intellij/psi/formatter/xml/AbstractXmlBlock.java
+++ b/xml/impl/src/com/intellij/psi/formatter/xml/AbstractXmlBlock.java
@@ -17,6 +17,7 @@ package com.intellij.psi.formatter.xml;
import com.intellij.formatting.*;
import com.intellij.lang.*;
+import com.intellij.lang.xml.XMLLanguage;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.util.TextRange;
@@ -464,11 +465,28 @@ public abstract class AbstractXmlBlock extends AbstractBlock {
return myNode.getElementType() == XmlTokenType.XML_CDATA_END;
}
- public static boolean containsWhiteSpacesOnly(ASTNode node) {
- WhiteSpaceFormattingStrategy strategy = WhiteSpaceFormattingStrategyFactory.getStrategy(node.getPsi().getLanguage());
- String nodeText = node.getText();
- int length = nodeText.length();
- return strategy.check(nodeText, 0, length) >= length;
+ public static boolean containsWhiteSpacesOnly(@NotNull ASTNode node) {
+ PsiElement psiElement = node.getPsi();
+ if (psiElement instanceof PsiWhiteSpace) return true;
+ Language nodeLang = psiElement.getLanguage();
+ if (!nodeLang.isKindOf(XMLLanguage.INSTANCE) ||
+ isTextOnlyNode(node) ||
+ node.getElementType() == XmlElementType.XML_PROLOG) {
+ WhiteSpaceFormattingStrategy strategy = WhiteSpaceFormattingStrategyFactory.getStrategy(nodeLang);
+ int length = node.getTextLength();
+ return strategy.check(node.getChars(), 0, length) >= length;
+ }
+ return false;
+ }
+
+ private static boolean isTextOnlyNode(@NotNull ASTNode node) {
+ if (node.getPsi() instanceof XmlText) return true;
+ ASTNode firstChild = node.getFirstChildNode();
+ ASTNode lastChild = node.getLastChildNode();
+ if (firstChild != null && firstChild == lastChild && firstChild.getPsi() instanceof XmlText) {
+ return true;
+ }
+ return false;
}
}
diff --git a/xml/impl/src/org/jetbrains/builtInWebServer/BuiltInServerConfigurableUi.form b/xml/impl/src/org/jetbrains/builtInWebServer/BuiltInServerConfigurableUi.form
new file mode 100644
index 000000000000..3aa78b3be81c
--- /dev/null
+++ b/xml/impl/src/org/jetbrains/builtInWebServer/BuiltInServerConfigurableUi.form
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.builtInWebServer.BuiltInServerConfigurableUi">
+ <grid id="27dc6" binding="mainPanel" layout-manager="GridLayoutManager" row-count="2" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <xy x="20" y="20" width="1077" height="321"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="696ad" class="javax.swing.JLabel">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <text resource-bundle="messages/XmlBundle" key="setting.value.builtin.server.port.label"/>
+ </properties>
+ </component>
+ <component id="e47e0" class="com.intellij.ui.PortField" binding="builtInServerPort">
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ </component>
+ <component id="33218" class="javax.swing.JCheckBox" binding="builtInServerAvailableExternallyCheckBox" default-binding="true">
+ <constraints>
+ <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <text resource-bundle="messages/XmlBundle" key="setting.value.can.accept.external.connections"/>
+ </properties>
+ </component>
+ <vspacer id="c36c4">
+ <constraints>
+ <grid row="1" column="0" row-span="1" col-span="3" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
+ </constraints>
+ </vspacer>
+ </children>
+ </grid>
+</form>
diff --git a/xml/impl/src/org/jetbrains/builtInWebServer/BuiltInServerConfigurableUi.java b/xml/impl/src/org/jetbrains/builtInWebServer/BuiltInServerConfigurableUi.java
new file mode 100644
index 000000000000..edbef65543af
--- /dev/null
+++ b/xml/impl/src/org/jetbrains/builtInWebServer/BuiltInServerConfigurableUi.java
@@ -0,0 +1,47 @@
+package org.jetbrains.builtInWebServer;
+
+import com.intellij.openapi.options.ConfigurableUi;
+import com.intellij.ui.PortField;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+
+class BuiltInServerConfigurableUi implements ConfigurableUi<BuiltInServerOptions> {
+ private JPanel mainPanel;
+
+ private PortField builtInServerPort;
+ private JCheckBox builtInServerAvailableExternallyCheckBox;
+
+ public BuiltInServerConfigurableUi() {
+ builtInServerPort.setMin(1024);
+ }
+
+ @Override
+ @NotNull
+ public JComponent getComponent() {
+ return mainPanel;
+ }
+
+ @Override
+ public boolean isModified(@NotNull BuiltInServerOptions settings) {
+ return builtInServerPort.getNumber() != settings.builtInServerPort ||
+ builtInServerAvailableExternallyCheckBox.isSelected() != settings.builtInServerAvailableExternally;
+ }
+
+ @Override
+ public void apply(@NotNull BuiltInServerOptions settings) {
+ boolean builtInServerPortChanged = settings.builtInServerPort != builtInServerPort.getNumber() || settings.builtInServerAvailableExternally != builtInServerAvailableExternallyCheckBox.isSelected();
+ if (builtInServerPortChanged) {
+ settings.builtInServerPort = builtInServerPort.getNumber();
+ settings.builtInServerAvailableExternally = builtInServerAvailableExternallyCheckBox.isSelected();
+
+ BuiltInServerOptions.onBuiltInServerPortChanged();
+ }
+ }
+
+ @Override
+ public void reset(@NotNull BuiltInServerOptions settings) {
+ builtInServerPort.setNumber(settings.builtInServerPort);
+ builtInServerAvailableExternallyCheckBox.setSelected(settings.builtInServerAvailableExternally);
+ }
+}
diff --git a/xml/impl/src/org/jetbrains/builtInWebServer/BuiltInServerOptions.java b/xml/impl/src/org/jetbrains/builtInWebServer/BuiltInServerOptions.java
new file mode 100644
index 000000000000..5eb65c1f9cbc
--- /dev/null
+++ b/xml/impl/src/org/jetbrains/builtInWebServer/BuiltInServerOptions.java
@@ -0,0 +1,116 @@
+package org.jetbrains.builtInWebServer;
+
+import com.intellij.notification.Notification;
+import com.intellij.notification.NotificationDisplayType;
+import com.intellij.notification.NotificationType;
+import com.intellij.notification.Notifications;
+import com.intellij.openapi.application.ApplicationNamesInfo;
+import com.intellij.openapi.application.PathManager;
+import com.intellij.openapi.components.*;
+import com.intellij.openapi.options.Configurable;
+import com.intellij.openapi.options.SimpleConfigurable;
+import com.intellij.openapi.util.Getter;
+import com.intellij.util.xmlb.XmlSerializerUtil;
+import com.intellij.util.xmlb.annotations.Attribute;
+import com.intellij.xdebugger.settings.DebuggerConfigurableProvider;
+import com.intellij.xdebugger.settings.DebuggerSettingsCategory;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.ide.BuiltInServerManager;
+import org.jetbrains.ide.CustomPortServerManager;
+import org.jetbrains.io.CustomPortServerManagerBase;
+
+import java.io.File;
+import java.util.Collection;
+import java.util.Collections;
+
+@State(
+ name = "BuiltInServerOptions",
+ storages = {
+ @Storage(
+ file = StoragePathMacros.APP_CONFIG + "/other.xml"
+ )}
+)
+public class BuiltInServerOptions implements PersistentStateComponent<BuiltInServerOptions>, ExportableComponent, Getter<BuiltInServerOptions> {
+ @Attribute
+ public int builtInServerPort = 63342;
+ @Attribute
+ public boolean builtInServerAvailableExternally = false;
+
+ public static BuiltInServerOptions getInstance() {
+ return ServiceManager.getService(BuiltInServerOptions.class);
+ }
+
+ @Override
+ public BuiltInServerOptions get() {
+ return this;
+ }
+
+ static final class BuiltInServerDebuggerConfigurableProvider extends DebuggerConfigurableProvider {
+ @NotNull
+ @Override
+ public Collection<? extends Configurable> getConfigurables(@NotNull DebuggerSettingsCategory category) {
+ if (category == DebuggerSettingsCategory.GENERAL) {
+ return Collections.singletonList(SimpleConfigurable.create("builtInServer", "", BuiltInServerConfigurableUi.class, getInstance()));
+ }
+ return Collections.emptyList();
+ }
+ }
+
+ @NotNull
+ @Override
+ public File[] getExportFiles() {
+ return new File[]{PathManager.getOptionsFile("other")};
+ }
+
+ @NotNull
+ @Override
+ public String getPresentableName() {
+ return "Built-in server";
+ }
+
+ @Nullable
+ @Override
+ public BuiltInServerOptions getState() {
+ return this;
+ }
+
+ @Override
+ public void loadState(BuiltInServerOptions state) {
+ XmlSerializerUtil.copyBean(state, this);
+ }
+
+ public int getEffectiveBuiltInServerPort() {
+ MyCustomPortServerManager portServerManager = CustomPortServerManager.EP_NAME.findExtension(MyCustomPortServerManager.class);
+ if (!portServerManager.isBound()) {
+ return BuiltInServerManager.getInstance().getPort();
+ }
+ return builtInServerPort;
+ }
+
+ public static final class MyCustomPortServerManager extends CustomPortServerManagerBase {
+ @Override
+ public void cannotBind(Exception e, int port) {
+ String groupDisplayId = "Built-in Web Server";
+ Notifications.Bus.register(groupDisplayId, NotificationDisplayType.STICKY_BALLOON);
+ new Notification(groupDisplayId, "Built-in HTTP server on custom port " + port + " disabled",
+ "Cannot start built-in HTTP server on custom port " + port + ". " +
+ "Please ensure that port is free (or check your firewall settings) and restart " + ApplicationNamesInfo.getInstance().getFullProductName(),
+ NotificationType.ERROR).notify(null);
+ }
+
+ @Override
+ public int getPort() {
+ return getInstance().builtInServerPort;
+ }
+
+ @Override
+ public boolean isAvailableExternally() {
+ return getInstance().builtInServerAvailableExternally;
+ }
+ }
+
+ public static void onBuiltInServerPortChanged() {
+ CustomPortServerManager.EP_NAME.findExtension(MyCustomPortServerManager.class).portChanged();
+ }
+} \ No newline at end of file
diff --git a/xml/impl/src/org/jetbrains/builtInWebServer/BuiltInWebBrowserUrlProvider.java b/xml/impl/src/org/jetbrains/builtInWebServer/BuiltInWebBrowserUrlProvider.java
new file mode 100644
index 000000000000..f58d42587cab
--- /dev/null
+++ b/xml/impl/src/org/jetbrains/builtInWebServer/BuiltInWebBrowserUrlProvider.java
@@ -0,0 +1,78 @@
+package org.jetbrains.builtInWebServer;
+
+import com.intellij.ide.browsers.OpenInBrowserRequest;
+import com.intellij.ide.browsers.WebBrowserUrlProvider;
+import com.intellij.openapi.project.DumbAware;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiFile;
+import com.intellij.testFramework.LightVirtualFile;
+import com.intellij.util.Url;
+import com.intellij.util.Urls;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.xml.util.HtmlUtil;
+import org.jetbrains.ide.BuiltInServerManager;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+public class BuiltInWebBrowserUrlProvider extends WebBrowserUrlProvider implements DumbAware {
+ @NotNull
+ public static List<Url> getUrls(@NotNull VirtualFile file, @NotNull Project project, @Nullable String currentAuthority) {
+ if (currentAuthority != null && !compareAuthority(currentAuthority)) {
+ return Collections.emptyList();
+ }
+
+ String path = WebServerPathToFileManager.getInstance(project).getPath(file);
+ if (path == null) {
+ return Collections.emptyList();
+ }
+
+ int effectiveBuiltInServerPort = BuiltInServerOptions.getInstance().getEffectiveBuiltInServerPort();
+ Url url = Urls.newHttpUrl(currentAuthority == null ? "localhost:" + effectiveBuiltInServerPort : currentAuthority, '/' + project.getName() + '/' + path);
+ int defaultPort = BuiltInServerManager.getInstance().getPort();
+ if (currentAuthority != null || defaultPort == effectiveBuiltInServerPort) {
+ return Collections.singletonList(url);
+ }
+ return Arrays.asList(url, Urls.newHttpUrl("localhost:" + defaultPort, '/' + project.getName() + '/' + path));
+ }
+
+ public static boolean compareAuthority(@Nullable String currentAuthority) {
+ if (currentAuthority == null) {
+ return false;
+ }
+
+ int portIndex = currentAuthority.indexOf(':');
+ if (portIndex < 0) {
+ return false;
+ }
+
+ String host = currentAuthority.substring(0, portIndex);
+ if (!BuiltInWebServer.isOwnHostName(host)) {
+ return false;
+ }
+
+ int port = StringUtil.parseInt(currentAuthority.substring(portIndex + 1), -1);
+ return port == BuiltInServerOptions.getInstance().getEffectiveBuiltInServerPort() ||
+ port == BuiltInServerManager.getInstance().getPort();
+ }
+
+ @Override
+ public boolean canHandleElement(@NotNull OpenInBrowserRequest request) {
+ return request.getFile().getViewProvider().isPhysical() && !(request.getVirtualFile() instanceof LightVirtualFile) && isMyLanguage(request.getFile());
+ }
+
+ protected boolean isMyLanguage(PsiFile psiFile) {
+ return HtmlUtil.isHtmlFile(psiFile);
+ }
+
+ @Nullable
+ @Override
+ protected Url getUrl(@NotNull OpenInBrowserRequest request, @NotNull VirtualFile virtualFile) throws BrowserException {
+ return ContainerUtil.getFirstItem(getUrls(virtualFile, request.getProject(), null));
+ }
+}
diff --git a/xml/impl/src/org/jetbrains/builtInWebServer/BuiltInWebServer.java b/xml/impl/src/org/jetbrains/builtInWebServer/BuiltInWebServer.java
new file mode 100644
index 000000000000..2dc24ba01706
--- /dev/null
+++ b/xml/impl/src/org/jetbrains/builtInWebServer/BuiltInWebServer.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.builtInWebServer;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.project.ProjectManager;
+import com.intellij.openapi.util.SystemInfoRt;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.VfsUtilCore;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.UriUtil;
+import com.intellij.util.io.URLUtil;
+import com.intellij.util.net.NetUtils;
+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.ide.HttpRequestHandler;
+import org.jetbrains.io.FileResponses;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import static org.jetbrains.io.Responses.sendOptionsResponse;
+import static org.jetbrains.io.Responses.sendStatus;
+
+public final class BuiltInWebServer extends HttpRequestHandler {
+ static final Logger LOG = Logger.getInstance(BuiltInWebServer.class);
+
+ @Nullable
+ public static VirtualFile findIndexFile(@NotNull VirtualFile basedir) {
+ VirtualFile[] children = basedir.getChildren();
+ if (children == null || children.length == 0) {
+ return null;
+ }
+
+ for (String indexNamePrefix : new String[]{"index.", "default."}) {
+ VirtualFile index = null;
+ String preferredName = indexNamePrefix + "html";
+ for (VirtualFile child : children) {
+ if (!child.isDirectory()) {
+ String name = child.getName();
+ if (name.equals(preferredName)) {
+ return child;
+ }
+ else if (index == null && name.startsWith(indexNamePrefix)) {
+ index = child;
+ }
+ }
+ }
+ if (index != null) {
+ return index;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isSupported(@NotNull FullHttpRequest request) {
+ return super.isSupported(request) || request.method() == HttpMethod.POST || request.method() == HttpMethod.OPTIONS;
+ }
+
+ @Override
+ public boolean process(@NotNull QueryStringDecoder urlDecoder, @NotNull FullHttpRequest request, @NotNull ChannelHandlerContext context) {
+ if (request.method() == HttpMethod.OPTIONS) {
+ sendOptionsResponse("GET, POST, HEAD, OPTIONS", request, context);
+ return true;
+ }
+
+ String host = HttpHeaders.getHost(request);
+ if (StringUtil.isEmpty(host)) {
+ return false;
+ }
+
+ int portIndex = host.indexOf(':');
+ if (portIndex > 0) {
+ host = host.substring(0, portIndex);
+ }
+
+ String projectName;
+ boolean isIpv6 = host.charAt(0) == '[' && host.length() > 2 && host.charAt(host.length() - 1) == ']';
+ if (isIpv6) {
+ host = host.substring(1, host.length() - 1);
+ }
+
+ if (isIpv6 || Character.digit(host.charAt(0), 10) != -1 || host.charAt(0) == ':' || isOwnHostName(host)) {
+ if (urlDecoder.path().length() < 2) {
+ return false;
+ }
+ projectName = null;
+ }
+ else {
+ projectName = host;
+ }
+ return doProcess(request, context.channel(), projectName);
+ }
+
+ public static boolean isOwnHostName(@NotNull String host) {
+ if (NetUtils.isLocalhost(host)) {
+ return true;
+ }
+
+ try {
+ InetAddress address = InetAddress.getByName(host);
+ if (host.equals(address.getHostAddress()) || host.equalsIgnoreCase(address.getCanonicalHostName())) {
+ return true;
+ }
+
+ String localHostName = InetAddress.getLocalHost().getHostName();
+ // WEB-8889
+ // develar.local is own host name: develar. equals to "develar.labs.intellij.net" (canonical host name)
+ return localHostName.equalsIgnoreCase(host) ||
+ (host.endsWith(".local") && localHostName.regionMatches(true, 0, host, 0, host.length() - ".local".length()));
+ }
+ catch (UnknownHostException ignored) {
+ return false;
+ }
+ }
+
+ private static boolean doProcess(@NotNull FullHttpRequest request, @NotNull Channel channel, @Nullable String projectName) {
+ final String decodedPath = URLUtil.unescapePercentSequences(UriUtil.trimParameters(request.uri()));
+ int offset;
+ boolean emptyPath;
+ boolean isCustomHost = projectName != null;
+ if (isCustomHost) {
+ // host mapped to us
+ offset = 0;
+ emptyPath = decodedPath.isEmpty();
+ }
+ else {
+ offset = decodedPath.indexOf('/', 1);
+ projectName = decodedPath.substring(1, offset == -1 ? decodedPath.length() : offset);
+ emptyPath = offset == -1;
+ }
+
+ Project project = findProject(projectName, isCustomHost);
+ if (project == null) {
+ return false;
+ }
+
+ if (emptyPath) {
+ if (!SystemInfoRt.isFileSystemCaseSensitive) {
+ // may be passed path is not correct
+ projectName = project.getName();
+ }
+
+ // we must redirect "jsdebug" to "jsdebug/" as nginx does, otherwise browser will treat it as file instead of directory, so, relative path will not work
+ WebServerPathHandler.redirectToDirectory(request, channel, projectName);
+ return true;
+ }
+
+ final String path = FileUtil.toCanonicalPath(decodedPath.substring(offset + 1), '/');
+ LOG.assertTrue(path != null);
+
+ for (WebServerPathHandler pathHandler : WebServerPathHandler.EP_NAME.getExtensions()) {
+ try {
+ if (pathHandler.process(path, project, request, channel, projectName, decodedPath, isCustomHost)) {
+ return true;
+ }
+ }
+ catch (Throwable e) {
+ LOG.error(e);
+ }
+ }
+ return false;
+ }
+
+ static final class StaticFileHandler extends WebServerFileHandler {
+ @Override
+ public boolean process(@NotNull VirtualFile file,
+ @NotNull CharSequence canonicalRequestPath,
+ @NotNull Project project,
+ @NotNull FullHttpRequest request,
+ @NotNull Channel channel) throws IOException {
+ File ioFile = VfsUtilCore.virtualToIoFile(file);
+ if (hasAccess(ioFile)) {
+ FileResponses.sendFile(request, channel, ioFile);
+ }
+ else {
+ sendStatus(HttpResponseStatus.FORBIDDEN, channel, request);
+ }
+ return true;
+ }
+
+ private static boolean hasAccess(File result) {
+ // deny access to .htaccess files
+ return !result.isDirectory() && result.canRead() && !(result.isHidden() || result.getName().startsWith(".ht"));
+ }
+ }
+
+ @Nullable
+ private static Project findProject(String projectName, boolean isCustomHost) {
+ // user can rename project directory, so, we should support this case - find project by base directory name
+ Project candidateByDirectoryName = null;
+ for (Project project : ProjectManager.getInstance().getOpenProjects()) {
+ String name = project.getName();
+ // domain name is case-insensitive
+ if (!project.isDisposed() && ((isCustomHost || !SystemInfoRt.isFileSystemCaseSensitive) ? projectName.equalsIgnoreCase(name) : projectName.equals(name))) {
+ return project;
+ }
+
+ if (candidateByDirectoryName == null && compareNameAndProjectBasePath(projectName, project)) {
+ candidateByDirectoryName = project;
+ }
+ }
+ return candidateByDirectoryName;
+ }
+
+ public static boolean compareNameAndProjectBasePath(String projectName, Project project) {
+ String basePath = project.getBasePath();
+ return basePath != null && basePath.length() > projectName.length() && basePath.endsWith(projectName) && basePath.charAt(basePath.length() - projectName.length() - 1) == '/';
+ }
+} \ No newline at end of file
diff --git a/xml/impl/src/org/jetbrains/builtInWebServer/DefaultWebServerPathHandler.java b/xml/impl/src/org/jetbrains/builtInWebServer/DefaultWebServerPathHandler.java
new file mode 100644
index 000000000000..1b4acb07556f
--- /dev/null
+++ b/xml/impl/src/org/jetbrains/builtInWebServer/DefaultWebServerPathHandler.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.builtInWebServer;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import io.netty.channel.Channel;
+import io.netty.handler.codec.http.FullHttpRequest;
+import io.netty.handler.codec.http.HttpResponseStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.io.Responses;
+
+final class DefaultWebServerPathHandler extends WebServerPathHandler {
+ @Override
+ public boolean process(@NotNull String path,
+ @NotNull Project project,
+ @NotNull FullHttpRequest request,
+ @NotNull Channel channel,
+ @Nullable String projectName,
+ @NotNull String decodedRawPath,
+ boolean isCustomHost) {
+ WebServerPathToFileManager pathToFileManager = WebServerPathToFileManager.getInstance(project);
+ VirtualFile result = pathToFileManager.pathToFileCache.getIfPresent(path);
+ boolean indexUsed = false;
+ if (result == null || !result.isValid()) {
+ result = pathToFileManager.findByRelativePath(project, path);
+ if (result == null) {
+ if (path.isEmpty()) {
+ Responses.sendStatus(HttpResponseStatus.NOT_FOUND, channel, "Index file doesn't exist.", request);
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+ else if (result.isDirectory()) {
+ if (!endsWithSlash(decodedRawPath)) {
+ redirectToDirectory(request, channel, isCustomHost ? path : (projectName + '/' + path));
+ return true;
+ }
+
+ result = BuiltInWebServer.findIndexFile(result);
+ if (result == null) {
+ Responses.sendStatus(HttpResponseStatus.NOT_FOUND, channel, "Index file doesn't exist.", request);
+ return true;
+ }
+ indexUsed = true;
+ }
+
+ pathToFileManager.pathToFileCache.put(path, result);
+ }
+ else if (!path.endsWith(result.getName())) {
+ if (endsWithSlash(decodedRawPath)) {
+ indexUsed = true;
+ }
+ else {
+ // FallbackResource feature in action, /login requested, /index.php retrieved, we must not redirect /login to /login/
+ if (path.endsWith(result.getParent().getName())) {
+ redirectToDirectory(request, channel, isCustomHost ? path : (projectName + '/' + path));
+ return true;
+ }
+ }
+ }
+
+ StringBuilder canonicalRequestPath = new StringBuilder();
+ canonicalRequestPath.append('/');
+ if (!isCustomHost) {
+ canonicalRequestPath.append(projectName).append('/');
+ }
+ canonicalRequestPath.append(path);
+ if (indexUsed) {
+ canonicalRequestPath.append('/').append(result.getName());
+ }
+
+ for (WebServerFileHandler fileHandler : WebServerFileHandler.EP_NAME.getExtensions()) {
+ try {
+ if (fileHandler.process(result, canonicalRequestPath, project, request, channel)) {
+ return true;
+ }
+ }
+ catch (Throwable e) {
+ BuiltInWebServer.LOG.error(e);
+ }
+ }
+
+ return false;
+ }
+} \ No newline at end of file
diff --git a/xml/impl/src/org/jetbrains/builtInWebServer/DefaultWebServerRootsProvider.java b/xml/impl/src/org/jetbrains/builtInWebServer/DefaultWebServerRootsProvider.java
new file mode 100644
index 000000000000..b5621295957d
--- /dev/null
+++ b/xml/impl/src/org/jetbrains/builtInWebServer/DefaultWebServerRootsProvider.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.builtInWebServer;
+
+import com.intellij.openapi.application.AccessToken;
+import com.intellij.openapi.application.ReadAction;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.ModuleRootManager;
+import com.intellij.openapi.roots.ProjectFileIndex;
+import com.intellij.openapi.roots.ProjectRootManager;
+import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.PairFunction;
+import com.intellij.util.PlatformUtils;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+final class DefaultWebServerRootsProvider extends WebServerRootsProvider {
+ @Nullable
+ @Override
+ public PathInfo resolve(@NotNull String path, @NotNull Project project) {
+ PairFunction<String, VirtualFile, VirtualFile> resolver;
+ if (PlatformUtils.isIntelliJ()) {
+ int index = path.indexOf('/');
+ if (index > 0 && !path.regionMatches(!SystemInfo.isFileSystemCaseSensitive, 0, project.getName(), 0, index)) {
+ String moduleName = path.substring(0, index);
+ AccessToken token = ReadAction.start();
+ Module module;
+ try {
+ module = ModuleManager.getInstance(project).findModuleByName(moduleName);
+ }
+ finally {
+ token.finish();
+ }
+
+ if (module != null && !module.isDisposed()) {
+ path = path.substring(index + 1);
+ resolver = WebServerPathToFileManager.getInstance(project).getResolver(path);
+
+ ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(module);
+ PathInfo result = resolve(path, moduleRootManager.getSourceRoots(), resolver, moduleName);
+ if (result == null) {
+ result = resolve(path, moduleRootManager.getContentRoots(), resolver, moduleName);
+ }
+ if (result != null) {
+ return result;
+ }
+ }
+ }
+ }
+
+ Module[] modules;
+ AccessToken token = ReadAction.start();
+ try {
+ modules = ModuleManager.getInstance(project).getModules();
+ }
+ finally {
+ token.finish();
+ }
+
+ resolver = WebServerPathToFileManager.getInstance(project).getResolver(path);
+ PathInfo result = findByRelativePath(project, path, modules, true, resolver);
+ if (result == null) {
+ // let's find in content roots
+ return findByRelativePath(project, path, modules, false, resolver);
+ }
+ else {
+ return result;
+ }
+ }
+
+ @Nullable
+ @Override
+ public PathInfo getRoot(@NotNull VirtualFile file, @NotNull Project project) {
+ AccessToken token = ReadAction.start();
+ try {
+ VirtualFile root = null;
+ ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex();
+ if (fileIndex.isInSourceContent(file)) {
+ root = fileIndex.getSourceRootForFile(file);
+ }
+ else if (fileIndex.isInContent(file)) {
+ root = fileIndex.getContentRootForFile(file);
+ }
+ else if (fileIndex.isInLibraryClasses(file)) {
+ root = fileIndex.getClassRootForFile(file);
+ }
+ assert root != null : file.getPresentableUrl();
+ return new PathInfo(file, root, getModuleNameQualifier(project, fileIndex.getModuleForFile(file)));
+ }
+ finally {
+ token.finish();
+ }
+ }
+
+ @Nullable
+ private static String getModuleNameQualifier(@NotNull Project project, @Nullable Module module) {
+ if (module != null &&
+ PlatformUtils.isIntelliJ() &&
+ !(module.getName().equalsIgnoreCase(project.getName()) || BuiltInWebServer.compareNameAndProjectBasePath(module.getName(), project))) {
+ return module.getName();
+ }
+ return null;
+ }
+
+ @Nullable
+ private static PathInfo resolve(@NotNull String path, @NotNull VirtualFile[] roots, @NotNull PairFunction<String, VirtualFile, VirtualFile> resolver, @Nullable String moduleName) {
+ for (VirtualFile root : roots) {
+ VirtualFile file = resolver.fun(path, root);
+ if (file != null) {
+ return new PathInfo(file, root, moduleName);
+ }
+ }
+ return null;
+ }
+
+ @Nullable
+ private static PathInfo findByRelativePath(@NotNull Project project,
+ @NotNull String path,
+ @NotNull Module[] modules,
+ boolean inSourceRoot,
+ @NotNull PairFunction<String, VirtualFile, VirtualFile> resolver) {
+ for (Module module : modules) {
+ if (!module.isDisposed()) {
+ ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(module);
+ PathInfo result = resolve(path, inSourceRoot ? moduleRootManager.getSourceRoots() : moduleRootManager.getContentRoots(), resolver, null);
+ if (result != null) {
+ result.moduleName = getModuleNameQualifier(project, module);
+ return result;
+ }
+ }
+ }
+ return null;
+ }
+} \ No newline at end of file
diff --git a/xml/impl/src/org/jetbrains/builtInWebServer/PathInfo.java b/xml/impl/src/org/jetbrains/builtInWebServer/PathInfo.java
new file mode 100644
index 000000000000..b55b16be84b2
--- /dev/null
+++ b/xml/impl/src/org/jetbrains/builtInWebServer/PathInfo.java
@@ -0,0 +1,47 @@
+package org.jetbrains.builtInWebServer;
+
+import com.intellij.openapi.vfs.VfsUtilCore;
+import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class PathInfo {
+ private final VirtualFile child;
+ private final VirtualFile root;
+ String moduleName;
+
+ private String computedPath;
+
+ public PathInfo(@NotNull VirtualFile child, @NotNull VirtualFile root, @Nullable String moduleName) {
+ this.child = child;
+ this.root = root;
+ this.moduleName = moduleName;
+ }
+
+ public PathInfo(@NotNull VirtualFile child, @NotNull VirtualFile root) {
+ this(child, root, null);
+ }
+
+ @NotNull
+ public VirtualFile getChild() {
+ return child;
+ }
+
+ @NotNull
+ public VirtualFile getRoot() {
+ return root;
+ }
+
+ @Nullable
+ public String getModuleName() {
+ return moduleName;
+ }
+
+ @NotNull
+ public String getPath() {
+ if (computedPath == null) {
+ computedPath = (moduleName == null ? "" : moduleName + '/') + VfsUtilCore.getRelativePath(child, root, '/');
+ }
+ return computedPath;
+ }
+} \ No newline at end of file
diff --git a/xml/impl/src/org/jetbrains/builtInWebServer/PrefixlessWebServerRootsProvider.java b/xml/impl/src/org/jetbrains/builtInWebServer/PrefixlessWebServerRootsProvider.java
new file mode 100644
index 000000000000..145fdedb350e
--- /dev/null
+++ b/xml/impl/src/org/jetbrains/builtInWebServer/PrefixlessWebServerRootsProvider.java
@@ -0,0 +1,18 @@
+package org.jetbrains.builtInWebServer;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.PairFunction;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public abstract class PrefixlessWebServerRootsProvider extends WebServerRootsProvider {
+ @Nullable
+ @Override
+ public final PathInfo resolve(@NotNull String path, @NotNull Project project) {
+ return resolve(path, project, WebServerPathToFileManager.getInstance(project).getResolver(path));
+ }
+
+ @Nullable
+ public abstract PathInfo resolve(@NotNull String path, @NotNull Project project, @NotNull PairFunction<String, VirtualFile, VirtualFile> resolver);
+} \ No newline at end of file
diff --git a/xml/impl/src/org/jetbrains/builtInWebServer/WebServerFileHandler.java b/xml/impl/src/org/jetbrains/builtInWebServer/WebServerFileHandler.java
new file mode 100644
index 000000000000..9035af6c52cc
--- /dev/null
+++ b/xml/impl/src/org/jetbrains/builtInWebServer/WebServerFileHandler.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.builtInWebServer;
+
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import io.netty.channel.Channel;
+import io.netty.handler.codec.http.FullHttpRequest;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.IOException;
+
+public abstract class WebServerFileHandler {
+ static final ExtensionPointName<WebServerFileHandler> EP_NAME = ExtensionPointName.create("org.jetbrains.webServerFileHandler");
+
+ public abstract boolean process(@NotNull VirtualFile file,
+ @NotNull CharSequence canonicalRequestPath,
+ @NotNull Project project,
+ @NotNull FullHttpRequest request,
+ @NotNull Channel channel) throws IOException;
+} \ No newline at end of file
diff --git a/xml/impl/src/org/jetbrains/builtInWebServer/WebServerPathHandler.java b/xml/impl/src/org/jetbrains/builtInWebServer/WebServerPathHandler.java
new file mode 100644
index 000000000000..807c3b31b49a
--- /dev/null
+++ b/xml/impl/src/org/jetbrains/builtInWebServer/WebServerPathHandler.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.builtInWebServer;
+
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VfsUtil;
+import io.netty.channel.Channel;
+import io.netty.handler.codec.http.*;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.io.Responses;
+
+import java.net.URI;
+
+/**
+ * By default {@link WebServerPathToFileManager} will be used to map request to file.
+ * If file physically exists in the file system, you must use {@link WebServerRootsProvider}.
+ *
+ * Consider to extend {@link WebServerPathHandlerAdapter} instead of implement low-level {@link #process(String, com.intellij.openapi.project.Project, io.netty.handler.codec.http.FullHttpRequest, io.netty.channel.Channel, String, String, boolean)}
+ */
+public abstract class WebServerPathHandler {
+ static final ExtensionPointName<WebServerPathHandler> EP_NAME = ExtensionPointName.create("org.jetbrains.webServerPathHandler");
+
+ public abstract boolean process(@NotNull String path,
+ @NotNull Project project,
+ @NotNull FullHttpRequest request,
+ @NotNull Channel channel,
+ @Nullable String projectName,
+ @NotNull String decodedRawPath,
+ boolean isCustomHost);
+
+ protected static void redirectToDirectory(@NotNull HttpRequest request, @NotNull Channel channel, @NotNull String path) {
+ FullHttpResponse response = Responses.response(HttpResponseStatus.MOVED_PERMANENTLY);
+ URI url = VfsUtil.toUri("http://" + HttpHeaders.getHost(request) + '/' + path + '/');
+ BuiltInWebServer.LOG.assertTrue(url != null);
+ response.headers().add(HttpHeaders.Names.LOCATION, url.toASCIIString());
+ Responses.send(response, channel, request);
+ }
+
+ protected static boolean endsWithSlash(@NotNull String path) {
+ return path.charAt(path.length() - 1) == '/';
+ }
+} \ No newline at end of file
diff --git a/xml/impl/src/org/jetbrains/builtInWebServer/WebServerPathHandlerAdapter.java b/xml/impl/src/org/jetbrains/builtInWebServer/WebServerPathHandlerAdapter.java
new file mode 100644
index 000000000000..a1f1e1790195
--- /dev/null
+++ b/xml/impl/src/org/jetbrains/builtInWebServer/WebServerPathHandlerAdapter.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.builtInWebServer;
+
+import com.intellij.openapi.project.Project;
+import io.netty.channel.Channel;
+import io.netty.handler.codec.http.FullHttpRequest;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public abstract class WebServerPathHandlerAdapter extends WebServerPathHandler {
+ protected abstract boolean process(@NotNull String path, @NotNull Project project, @NotNull FullHttpRequest request, @NotNull Channel channel);
+
+ @Override
+ public final boolean process(@NotNull String path,
+ @NotNull Project project,
+ @NotNull FullHttpRequest request,
+ @NotNull Channel channel,
+ @Nullable String projectName,
+ @NotNull String decodedRawPath,
+ boolean isCustomHost) {
+ return process(path, project, request, channel);
+ }
+} \ No newline at end of file
diff --git a/xml/impl/src/org/jetbrains/builtInWebServer/WebServerPathToFileManager.java b/xml/impl/src/org/jetbrains/builtInWebServer/WebServerPathToFileManager.java
new file mode 100644
index 000000000000..987fdcd3a139
--- /dev/null
+++ b/xml/impl/src/org/jetbrains/builtInWebServer/WebServerPathToFileManager.java
@@ -0,0 +1,142 @@
+package org.jetbrains.builtInWebServer;
+
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+import com.intellij.ProjectTopics;
+import com.intellij.openapi.application.Application;
+import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.ModuleRootAdapter;
+import com.intellij.openapi.roots.ModuleRootEvent;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.vfs.VirtualFileManager;
+import com.intellij.openapi.vfs.newvfs.BulkFileListener;
+import com.intellij.openapi.vfs.newvfs.events.VFileContentChangeEvent;
+import com.intellij.openapi.vfs.newvfs.events.VFileEvent;
+import com.intellij.util.PairFunction;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Implement {@link WebServerRootsProvider} to add your provider
+ */
+public class WebServerPathToFileManager {
+ private static final PairFunction<String, VirtualFile, VirtualFile> RELATIVE_PATH_RESOLVER = new PairFunction<String, VirtualFile, VirtualFile>() {
+ @Nullable
+ @Override
+ public VirtualFile fun(String path, VirtualFile parent) {
+ return parent.findFileByRelativePath(path);
+ }
+ };
+
+ private static final PairFunction<String, VirtualFile, VirtualFile> EMPTY_PATH_RESOLVER = new PairFunction<String, VirtualFile, VirtualFile>() {
+ @Nullable
+ @Override
+ public VirtualFile fun(String path, VirtualFile parent) {
+ return BuiltInWebServer.findIndexFile(parent);
+ }
+ };
+
+ private final Project project;
+
+ final Cache<String, VirtualFile> pathToFileCache = CacheBuilder.newBuilder().maximumSize(512).expireAfterAccess(10, TimeUnit.MINUTES).build();
+ // time to expire should be greater than pathToFileCache
+ private final Cache<VirtualFile, PathInfo> fileToRoot = CacheBuilder.newBuilder().maximumSize(512).expireAfterAccess(11, TimeUnit.MINUTES).build();
+
+ public static WebServerPathToFileManager getInstance(@NotNull Project project) {
+ return ServiceManager.getService(project, WebServerPathToFileManager.class);
+ }
+
+ public WebServerPathToFileManager(@NotNull Application application, @NotNull Project project) {
+ this.project = project;
+ application.getMessageBus().connect(project).subscribe(VirtualFileManager.VFS_CHANGES, new BulkFileListener.Adapter() {
+ @Override
+ public void after(@NotNull List<? extends VFileEvent> events) {
+ for (VFileEvent event : events) {
+ if (event instanceof VFileContentChangeEvent) {
+ VirtualFile file = ((VFileContentChangeEvent)event).getFile();
+ for (WebServerRootsProvider rootsProvider : WebServerRootsProvider.EP_NAME.getExtensions()) {
+ if (rootsProvider.isClearCacheOnFileContentChanged(file)) {
+ clearCache();
+ break;
+ }
+ }
+ }
+ else {
+ clearCache();
+ break;
+ }
+ }
+ }
+ });
+ project.getMessageBus().connect().subscribe(ProjectTopics.PROJECT_ROOTS, new ModuleRootAdapter() {
+ @Override
+ public void rootsChanged(ModuleRootEvent event) {
+ clearCache();
+ }
+ });
+ }
+
+ private void clearCache() {
+ pathToFileCache.invalidateAll();
+ fileToRoot.invalidateAll();
+ }
+
+ @Nullable
+ public VirtualFile get(@NotNull String path) {
+ return get(path, true);
+ }
+
+ @Nullable
+ public VirtualFile get(@NotNull String path, boolean cacheResult) {
+ VirtualFile result = pathToFileCache.getIfPresent(path);
+ if (result == null || !result.isValid()) {
+ result = findByRelativePath(project, path);
+ if (cacheResult && result != null && result.isValid()) {
+ pathToFileCache.put(path, result);
+ }
+ }
+ return result;
+ }
+
+ @Nullable
+ public String getPath(@NotNull VirtualFile file) {
+ PathInfo pathInfo = getRoot(file);
+ return pathInfo == null ? null : pathInfo.getPath();
+ }
+
+ @Nullable
+ public PathInfo getRoot(@NotNull VirtualFile child) {
+ PathInfo result = fileToRoot.getIfPresent(child);
+ if (result == null) {
+ for (WebServerRootsProvider rootsProvider : WebServerRootsProvider.EP_NAME.getExtensions()) {
+ result = rootsProvider.getRoot(child, project);
+ if (result != null) {
+ fileToRoot.put(child, result);
+ break;
+ }
+ }
+ }
+ return result;
+ }
+
+ @Nullable
+ VirtualFile findByRelativePath(@NotNull Project project, @NotNull String path) {
+ for (WebServerRootsProvider rootsProvider : WebServerRootsProvider.EP_NAME.getExtensions()) {
+ PathInfo result = rootsProvider.resolve(path, project);
+ if (result != null) {
+ fileToRoot.put(result.getChild(), result);
+ return result.getChild();
+ }
+ }
+ return null;
+ }
+
+ @NotNull
+ public PairFunction<String, VirtualFile, VirtualFile> getResolver(@NotNull String path) {
+ return path.isEmpty() ? EMPTY_PATH_RESOLVER : RELATIVE_PATH_RESOLVER;
+ }
+} \ No newline at end of file
diff --git a/xml/impl/src/org/jetbrains/builtInWebServer/WebServerRootsProvider.java b/xml/impl/src/org/jetbrains/builtInWebServer/WebServerRootsProvider.java
new file mode 100644
index 000000000000..bb8972591ac5
--- /dev/null
+++ b/xml/impl/src/org/jetbrains/builtInWebServer/WebServerRootsProvider.java
@@ -0,0 +1,21 @@
+package org.jetbrains.builtInWebServer;
+
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public abstract class WebServerRootsProvider {
+ static final ExtensionPointName<WebServerRootsProvider> EP_NAME = ExtensionPointName.create("org.jetbrains.webServerRootsProvider");
+
+ @Nullable
+ public abstract PathInfo resolve(@NotNull String path, @NotNull Project project);
+
+ @Nullable
+ public abstract PathInfo getRoot(@NotNull VirtualFile file, @NotNull Project project);
+
+ public boolean isClearCacheOnFileContentChanged(@NotNull VirtualFile file) {
+ return false;
+ }
+} \ No newline at end of file
diff --git a/xml/impl/src/org/jetbrains/io/fastCgi/FastCgiChannelHandler.java b/xml/impl/src/org/jetbrains/io/fastCgi/FastCgiChannelHandler.java
new file mode 100644
index 000000000000..d24078221b30
--- /dev/null
+++ b/xml/impl/src/org/jetbrains/io/fastCgi/FastCgiChannelHandler.java
@@ -0,0 +1,108 @@
+package org.jetbrains.io.fastCgi;
+
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.util.text.StringUtilRt;
+import com.intellij.util.containers.ConcurrentIntObjectMap;
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelHandler;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.http.*;
+import org.jetbrains.io.Responses;
+import org.jetbrains.io.SimpleChannelInboundHandlerAdapter;
+
+import static org.jetbrains.io.fastCgi.FastCgiService.LOG;
+
+@ChannelHandler.Sharable
+public class FastCgiChannelHandler extends SimpleChannelInboundHandlerAdapter<FastCgiResponse> {
+ private final ConcurrentIntObjectMap<Channel> requestToChannel;
+
+ public FastCgiChannelHandler(ConcurrentIntObjectMap<Channel> channel) {
+ requestToChannel = channel;
+ }
+
+ @Override
+ protected void messageReceived(ChannelHandlerContext context, FastCgiResponse response) throws Exception {
+ ByteBuf buffer = response.getData();
+ Channel channel = requestToChannel.remove(response.getId());
+ if (channel == null || !channel.isActive()) {
+ if (buffer != null) {
+ buffer.release();
+ }
+ return;
+ }
+
+ if (buffer == null) {
+ Responses.sendStatus(HttpResponseStatus.BAD_GATEWAY, channel);
+ return;
+ }
+
+ HttpResponse httpResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, buffer);
+ try {
+ parseHeaders(httpResponse, buffer);
+ Responses.addServer(httpResponse);
+ if (!HttpHeaders.isContentLengthSet(httpResponse)) {
+ HttpHeaders.setContentLength(httpResponse, buffer.readableBytes());
+ }
+ }
+ catch (Throwable e) {
+ buffer.release();
+ Responses.sendStatus(HttpResponseStatus.INTERNAL_SERVER_ERROR, channel);
+ LOG.error(e);
+ }
+ channel.writeAndFlush(httpResponse);
+ }
+
+ private static void parseHeaders(HttpResponse response, ByteBuf buffer) {
+ StringBuilder builder = new StringBuilder();
+ while (buffer.isReadable()) {
+ builder.setLength(0);
+
+ String key = null;
+ boolean valueExpected = true;
+ while (true) {
+ int b = buffer.readByte();
+ if (b < 0 || b == '\n') {
+ break;
+ }
+
+ if (b != '\r') {
+ if (valueExpected && b == ':') {
+ valueExpected = false;
+
+ key = builder.toString();
+ builder.setLength(0);
+ skipWhitespace(buffer);
+ }
+ else {
+ builder.append((char)b);
+ }
+ }
+ }
+
+ if (builder.length() == 0) {
+ // end of headers
+ return;
+ }
+
+ // skip standard headers
+ if (StringUtil.isEmpty(key) || StringUtilRt.startsWithIgnoreCase(key, "http") || StringUtilRt.startsWithIgnoreCase(key, "X-Accel-")) {
+ continue;
+ }
+
+ String value = builder.toString();
+ if (key.equalsIgnoreCase("status")) {
+ response.setStatus(HttpResponseStatus.valueOf(Integer.parseInt(value.substring(0, value.indexOf(' ')))));
+ }
+ else if (!(key.startsWith("http") || key.startsWith("HTTP"))) {
+ response.headers().add(key, value);
+ }
+ }
+ }
+
+ private static void skipWhitespace(ByteBuf buffer) {
+ while (buffer.isReadable() && buffer.getByte(buffer.readerIndex()) == ' ') {
+ buffer.skipBytes(1);
+ }
+ }
+} \ No newline at end of file
diff --git a/xml/impl/src/org/jetbrains/io/fastCgi/FastCgiConstants.java b/xml/impl/src/org/jetbrains/io/fastCgi/FastCgiConstants.java
new file mode 100644
index 000000000000..23a85dead1f9
--- /dev/null
+++ b/xml/impl/src/org/jetbrains/io/fastCgi/FastCgiConstants.java
@@ -0,0 +1,5 @@
+package org.jetbrains.io.fastCgi;
+
+public final class FastCgiConstants {
+ public static final int HEADER_LENGTH = 8;
+} \ No newline at end of file
diff --git a/xml/impl/src/org/jetbrains/io/fastCgi/FastCgiDecoder.java b/xml/impl/src/org/jetbrains/io/fastCgi/FastCgiDecoder.java
new file mode 100644
index 000000000000..1cd7adbef5d4
--- /dev/null
+++ b/xml/impl/src/org/jetbrains/io/fastCgi/FastCgiDecoder.java
@@ -0,0 +1,149 @@
+package org.jetbrains.io.fastCgi;
+
+import com.intellij.util.Consumer;
+import gnu.trove.TIntObjectHashMap;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.CompositeByteBuf;
+import io.netty.buffer.Unpooled;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.util.CharsetUtil;
+import org.jetbrains.io.Decoder;
+
+import static org.jetbrains.io.fastCgi.FastCgiService.LOG;
+
+public class FastCgiDecoder extends Decoder {
+ private enum State {
+ HEADER, CONTENT
+ }
+
+ private State state = State.HEADER;
+
+ private enum ProtocolStatus {
+ REQUEST_COMPLETE, CANT_MPX_CONN, OVERLOADED, UNKNOWN_ROLE
+ }
+
+ public static final class RecordType {
+ public static final int END_REQUEST = 3;
+ public static final int STDOUT = 6;
+ public static final int STDERR = 7;
+ }
+
+ private int type;
+ private int id;
+ private int contentLength;
+ private int paddingLength;
+
+ private final TIntObjectHashMap<ByteBuf> dataBuffers = new TIntObjectHashMap<ByteBuf>();
+
+ private final Consumer<String> errorOutputConsumer;
+
+ public FastCgiDecoder(Consumer<String> errorOutputConsumer) {
+ this.errorOutputConsumer = errorOutputConsumer;
+ }
+
+ @Override
+ protected void messageReceived(ChannelHandlerContext context, ByteBuf input) throws Exception {
+ while (true) {
+ switch (state) {
+ case HEADER: {
+ if (paddingLength > 0) {
+ if (input.readableBytes() >= paddingLength) {
+ input.skipBytes(paddingLength);
+ paddingLength = 0;
+ }
+ else {
+ paddingLength -= input.readableBytes();
+ input.skipBytes(input.readableBytes());
+ input.release();
+ return;
+ }
+ }
+
+ ByteBuf buffer = getBufferIfSufficient(input, FastCgiConstants.HEADER_LENGTH, context);
+ if (buffer == null) {
+ input.release();
+ return;
+ }
+
+ decodeHeader(buffer);
+ state = State.CONTENT;
+ }
+
+ case CONTENT: {
+ if (contentLength > 0) {
+ ByteBuf buffer = getBufferIfSufficient(input, contentLength, context);
+ if (buffer == null) {
+ input.release();
+ return;
+ }
+
+ FastCgiResponse response = readContent(buffer);
+ if (response != null) {
+ context.fireChannelRead(response);
+ }
+ }
+ state = State.HEADER;
+ }
+ }
+ }
+ }
+
+ private void decodeHeader(ByteBuf buffer) {
+ buffer.skipBytes(1);
+ type = buffer.readUnsignedByte();
+ id = buffer.readUnsignedShort();
+ contentLength = buffer.readUnsignedShort();
+ paddingLength = buffer.readUnsignedByte();
+ buffer.skipBytes(1);
+ }
+
+ private FastCgiResponse readContent(ByteBuf buffer) {
+ switch (type) {
+ case RecordType.END_REQUEST:
+ int appStatus = buffer.readInt();
+ int protocolStatus = buffer.readUnsignedByte();
+ buffer.skipBytes(3);
+ if (appStatus != 0 || protocolStatus != ProtocolStatus.REQUEST_COMPLETE.ordinal()) {
+ LOG.warn("Protocol status " + protocolStatus);
+ dataBuffers.remove(id);
+ return new FastCgiResponse(id, null);
+ }
+ else if (protocolStatus == ProtocolStatus.REQUEST_COMPLETE.ordinal()) {
+ return new FastCgiResponse(id, dataBuffers.remove(id));
+ }
+ break;
+
+ case RecordType.STDOUT:
+ ByteBuf data = dataBuffers.get(id);
+ ByteBuf sliced = buffer.slice(buffer.readerIndex(), contentLength);
+ if (data == null) {
+ dataBuffers.put(id, sliced);
+ }
+ else if (data instanceof CompositeByteBuf) {
+ ((CompositeByteBuf)data).addComponent(sliced);
+ data.writerIndex(data.writerIndex() + sliced.readableBytes());
+ }
+ else {
+ dataBuffers.put(id, Unpooled.wrappedBuffer(data, sliced));
+ }
+ sliced.retain();
+ buffer.skipBytes(contentLength);
+ break;
+
+ case RecordType.STDERR:
+ try {
+ errorOutputConsumer.consume(buffer.toString(buffer.readerIndex(), contentLength, CharsetUtil.UTF_8));
+ }
+ catch (Throwable e) {
+ LOG.error(e);
+ }
+ buffer.skipBytes(contentLength);
+ break;
+
+ default:
+ LOG.error("Unknown type " + type);
+ break;
+ }
+ return null;
+ }
+} \ No newline at end of file
diff --git a/xml/impl/src/org/jetbrains/io/fastCgi/FastCgiRequest.java b/xml/impl/src/org/jetbrains/io/fastCgi/FastCgiRequest.java
new file mode 100644
index 000000000000..e92d20eebffc
--- /dev/null
+++ b/xml/impl/src/org/jetbrains/io/fastCgi/FastCgiRequest.java
@@ -0,0 +1,149 @@
+package org.jetbrains.io.fastCgi;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufAllocator;
+import io.netty.buffer.Unpooled;
+import io.netty.channel.Channel;
+import io.netty.handler.codec.http.FullHttpRequest;
+import io.netty.handler.codec.http.HttpHeaders;
+import io.netty.util.CharsetUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.builtInWebServer.PathInfo;
+import org.jetbrains.builtInWebServer.WebServerPathToFileManager;
+import org.jetbrains.io.Responses;
+
+import java.net.InetSocketAddress;
+import java.util.Locale;
+import java.util.Map;
+
+public class FastCgiRequest {
+ private static final int PARAMS = 4;
+ private static final int BEGIN_REQUEST = 1;
+ private static final int RESPONDER = 1;
+ private static final int FCGI_KEEP_CONNECTION = 1;
+ private static final int STDIN = 5;
+ private static final int VERSION = 1;
+
+ private final ByteBuf buffer;
+ final int requestId;
+
+ public FastCgiRequest(int requestId, @NotNull ByteBufAllocator allocator) {
+ this.requestId = requestId;
+
+ buffer = allocator.buffer();
+ writeHeader(buffer, BEGIN_REQUEST, FastCgiConstants.HEADER_LENGTH);
+ buffer.writeShort(RESPONDER);
+ buffer.writeByte(FCGI_KEEP_CONNECTION);
+ buffer.writeZero(5);
+ }
+
+ public void writeFileHeaders(@NotNull VirtualFile file, @NotNull Project project, @NotNull CharSequence canonicalRequestPath) {
+ PathInfo root = WebServerPathToFileManager.getInstance(project).getRoot(file);
+ FastCgiService.LOG.assertTrue(root != null);
+ addHeader("DOCUMENT_ROOT", root.getRoot().getPath());
+ addHeader("SCRIPT_FILENAME", file.getPath());
+ addHeader("SCRIPT_NAME", canonicalRequestPath);
+ }
+
+ public final void addHeader(@NotNull String key, @Nullable CharSequence value) {
+ if (value == null) {
+ return;
+ }
+
+ int keyLength = key.length();
+ int valLength = value.length();
+ writeHeader(buffer, PARAMS, keyLength + valLength + (keyLength < 0x80 ? 1 : 4) + (valLength < 0x80 ? 1 : 4));
+
+ if (keyLength < 0x80) {
+ buffer.writeByte(keyLength);
+ }
+ else {
+ buffer.writeByte(0x80 | (keyLength >> 24));
+ buffer.writeByte(keyLength >> 16);
+ buffer.writeByte(keyLength >> 8);
+ buffer.writeByte(keyLength);
+ }
+
+ if (valLength < 0x80) {
+ buffer.writeByte(valLength);
+ }
+ else {
+ buffer.writeByte(0x80 | (valLength >> 24));
+ buffer.writeByte(valLength >> 16);
+ buffer.writeByte(valLength >> 8);
+ buffer.writeByte(valLength);
+ }
+
+ buffer.writeBytes(key.getBytes(CharsetUtil.US_ASCII));
+ buffer.writeBytes(Unpooled.copiedBuffer(value, CharsetUtil.UTF_8));
+ }
+
+ public void writeHeaders(FullHttpRequest request, Channel clientChannel) {
+ addHeader("REQUEST_URI", request.uri());
+ addHeader("REQUEST_METHOD", request.method().name());
+
+ InetSocketAddress remote = (InetSocketAddress)clientChannel.remoteAddress();
+ addHeader("REMOTE_ADDR", remote.getAddress().getHostAddress());
+ addHeader("REMOTE_PORT", Integer.toString(remote.getPort()));
+
+ InetSocketAddress local = (InetSocketAddress)clientChannel.localAddress();
+ addHeader("SERVER_SOFTWARE", Responses.getServerHeaderValue());
+ addHeader("SERVER_NAME", Responses.getServerHeaderValue());
+
+ addHeader("SERVER_ADDR", local.getAddress().getHostAddress());
+ addHeader("SERVER_PORT", Integer.toString(local.getPort()));
+
+ addHeader("GATEWAY_INTERFACE", "CGI/1.1");
+ addHeader("SERVER_PROTOCOL", request.protocolVersion().text());
+ addHeader("CONTENT_TYPE", request.headers().get(HttpHeaders.Names.CONTENT_TYPE));
+
+ // PHP only, required if PHP was built with --enable-force-cgi-redirect
+ addHeader("REDIRECT_STATUS", "200");
+
+ String queryString = "";
+ int queryIndex = request.uri().indexOf('?');
+ if (queryIndex != -1) {
+ queryString = request.uri().substring(queryIndex + 1);
+ }
+ addHeader("QUERY_STRING", queryString);
+
+ addHeader("CONTENT_LENGTH", String.valueOf(request.content().readableBytes()));
+
+ for (Map.Entry<String, String> entry : request.headers()) {
+ addHeader("HTTP_" + entry.getKey().replace('-', '_').toUpperCase(Locale.ENGLISH), entry.getValue());
+ }
+ }
+
+ final void writeToServerChannel(ByteBuf content, Channel fastCgiChannel) {
+ writeHeader(buffer, PARAMS, 0);
+ fastCgiChannel.write(buffer);
+
+ if (content.isReadable()) {
+ ByteBuf headerBuffer = fastCgiChannel.alloc().buffer(FastCgiConstants.HEADER_LENGTH, FastCgiConstants.HEADER_LENGTH);
+ writeHeader(headerBuffer, STDIN, content.readableBytes());
+ fastCgiChannel.write(headerBuffer);
+
+ fastCgiChannel.write(content);
+
+ headerBuffer = fastCgiChannel.alloc().buffer(FastCgiConstants.HEADER_LENGTH, FastCgiConstants.HEADER_LENGTH);
+ writeHeader(headerBuffer, STDIN, 0);
+ fastCgiChannel.write(headerBuffer);
+ }
+ else {
+ content.release();
+ }
+
+ fastCgiChannel.flush();
+ }
+
+ private void writeHeader(ByteBuf buffer, int type, int length) {
+ buffer.writeByte(VERSION);
+ buffer.writeByte(type);
+ buffer.writeShort(requestId);
+ buffer.writeShort(length);
+ buffer.writeZero(2);
+ }
+} \ No newline at end of file
diff --git a/xml/impl/src/org/jetbrains/io/fastCgi/FastCgiResponse.java b/xml/impl/src/org/jetbrains/io/fastCgi/FastCgiResponse.java
new file mode 100644
index 000000000000..e249f7152c7c
--- /dev/null
+++ b/xml/impl/src/org/jetbrains/io/fastCgi/FastCgiResponse.java
@@ -0,0 +1,21 @@
+package org.jetbrains.io.fastCgi;
+
+import io.netty.buffer.ByteBuf;
+
+public class FastCgiResponse {
+ private final int id;
+ private final ByteBuf data;
+
+ public FastCgiResponse(int id, ByteBuf data) {
+ this.id = id;
+ this.data = data;
+ }
+
+ public ByteBuf getData() {
+ return data;
+ }
+
+ public int getId() {
+ return id;
+ }
+} \ No newline at end of file
diff --git a/xml/impl/src/org/jetbrains/io/fastCgi/FastCgiService.java b/xml/impl/src/org/jetbrains/io/fastCgi/FastCgiService.java
new file mode 100644
index 000000000000..54f13c6c8ea1
--- /dev/null
+++ b/xml/impl/src/org/jetbrains/io/fastCgi/FastCgiService.java
@@ -0,0 +1,249 @@
+package org.jetbrains.io.fastCgi;
+
+import com.intellij.concurrency.JobScheduler;
+import com.intellij.execution.filters.TextConsoleBuilder;
+import com.intellij.execution.filters.TextConsoleBuilderFactory;
+import com.intellij.execution.process.OSProcessHandler;
+import com.intellij.execution.process.ProcessAdapter;
+import com.intellij.execution.process.ProcessEvent;
+import com.intellij.execution.ui.ConsoleView;
+import com.intellij.execution.ui.ConsoleViewContentType;
+import com.intellij.openapi.Disposable;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.AsyncResult;
+import com.intellij.openapi.util.AsyncValueLoader;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.wm.ToolWindow;
+import com.intellij.openapi.wm.ToolWindowAnchor;
+import com.intellij.openapi.wm.ToolWindowManager;
+import com.intellij.ui.content.ContentFactory;
+import com.intellij.util.Consumer;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.StripedLockIntObjectConcurrentHashMap;
+import com.intellij.util.net.NetUtils;
+import io.netty.bootstrap.Bootstrap;
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelInitializer;
+import io.netty.handler.codec.http.HttpResponseStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.io.ChannelExceptionHandler;
+import org.jetbrains.io.NettyUtil;
+import org.jetbrains.io.Responses;
+
+import javax.swing.*;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+// todo send FCGI_ABORT_REQUEST if client channel disconnected
+public abstract class FastCgiService implements Disposable {
+ static final Logger LOG = Logger.getInstance(FastCgiService.class);
+
+ protected final Project project;
+
+ private final AtomicInteger requestIdCounter = new AtomicInteger();
+ private final StripedLockIntObjectConcurrentHashMap<Channel> requests = new StripedLockIntObjectConcurrentHashMap<Channel>();
+
+ private volatile Channel fastCgiChannel;
+
+ protected final AsyncValueLoader<OSProcessHandler> processHandler = new AsyncValueLoader<OSProcessHandler>() {
+ @Override
+ protected boolean isCancelOnReject() {
+ return true;
+ }
+
+ @Override
+ protected void load(@NotNull final AsyncResult<OSProcessHandler> result) throws IOException {
+ final int port = NetUtils.findAvailableSocketPort();
+ final OSProcessHandler processHandler = createProcessHandler(project, port);
+ if (processHandler == null) {
+ result.setRejected();
+ return;
+ }
+
+ result.doWhenRejected(new Runnable() {
+ @Override
+ public void run() {
+ processHandler.destroyProcess();
+ }
+ });
+
+ final MyProcessAdapter processListener = new MyProcessAdapter();
+ processHandler.addProcessListener(processListener);
+ processHandler.startNotify();
+
+ if (result.isRejected()) {
+ return;
+ }
+
+ JobScheduler.getScheduler().schedule(new Runnable() {
+ @Override
+ public void run() {
+ if (result.isRejected()) {
+ return;
+ }
+
+ ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
+ @Override
+ public void run() {
+ if (!result.isRejected()) {
+ try {
+ connectToProcess(result, port, processHandler, processListener);
+ }
+ catch (Throwable e) {
+ result.setRejected();
+ LOG.error(e);
+ }
+ }
+ }
+ });
+ }
+ }, NettyUtil.MIN_START_TIME, TimeUnit.MILLISECONDS);
+ }
+
+ @Override
+ protected void disposeResult(@NotNull OSProcessHandler processHandler) {
+ try {
+ Channel currentFastCgiChannel = fastCgiChannel;
+ if (currentFastCgiChannel != null) {
+ fastCgiChannel = null;
+ NettyUtil.closeAndReleaseFactory(currentFastCgiChannel);
+ }
+ processHandler.destroyProcess();
+ }
+ finally {
+ requestIdCounter.set(0);
+ if (!requests.isEmpty()) {
+ List<Channel> waitingClients = ContainerUtil.toList(requests.elements());
+ requests.clear();
+ for (Channel channel : waitingClients) {
+ try {
+ if (channel.isActive()) {
+ Responses.sendStatus(HttpResponseStatus.BAD_GATEWAY, channel);
+ }
+ }
+ catch (Throwable e) {
+ NettyUtil.log(e, LOG);
+ }
+ }
+ }
+ }
+ }
+ };
+
+ private ConsoleView console;
+
+ protected FastCgiService(Project project) {
+ this.project = project;
+ }
+
+ protected abstract OSProcessHandler createProcessHandler(Project project, int port);
+
+ private void connectToProcess(final AsyncResult<OSProcessHandler> asyncResult, final int port, final OSProcessHandler processHandler, final Consumer<String> errorOutputConsumer) {
+ Bootstrap bootstrap = NettyUtil.oioClientBootstrap();
+ final FastCgiChannelHandler fastCgiChannelHandler = new FastCgiChannelHandler(requests);
+ bootstrap.handler(new ChannelInitializer() {
+ @Override
+ protected void initChannel(Channel channel) throws Exception {
+ channel.pipeline().addLast(new FastCgiDecoder(errorOutputConsumer), fastCgiChannelHandler, ChannelExceptionHandler.getInstance());
+ }
+ });
+ fastCgiChannel = NettyUtil.connectClient(bootstrap, new InetSocketAddress(NetUtils.getLoopbackAddress(), port), asyncResult);
+ if (fastCgiChannel != null) {
+ asyncResult.setDone(processHandler);
+ }
+ }
+
+ public void send(final FastCgiRequest fastCgiRequest, final ByteBuf content) {
+ content.retain();
+
+ if (processHandler.has()) {
+ fastCgiRequest.writeToServerChannel(content, fastCgiChannel);
+ }
+ else {
+ processHandler.get().doWhenDone(new Runnable() {
+ @Override
+ public void run() {
+ fastCgiRequest.writeToServerChannel(content, fastCgiChannel);
+ }
+ }).doWhenRejected(new Runnable() {
+ @Override
+ public void run() {
+ content.release();
+ Channel channel = requests.get(fastCgiRequest.requestId);
+ if (channel != null && channel.isActive()) {
+ Responses.sendStatus(HttpResponseStatus.BAD_GATEWAY, channel);
+ }
+ }
+ });
+ }
+ }
+
+ public int allocateRequestId(Channel channel) {
+ int requestId = requestIdCounter.getAndIncrement();
+ if (requestId >= Short.MAX_VALUE) {
+ requestIdCounter.set(0);
+ requestId = requestIdCounter.getAndDecrement();
+ }
+ requests.put(requestId, channel);
+ return requestId;
+ }
+
+ @Override
+ public void dispose() {
+ processHandler.reset();
+ }
+
+ protected abstract void buildConsole(@NotNull TextConsoleBuilder consoleBuilder);
+
+ @NotNull
+ protected abstract String getConsoleToolWindowId();
+
+ @NotNull
+ protected abstract Icon getConsoleToolWindowIcon();
+
+ private final class MyProcessAdapter extends ProcessAdapter implements Consumer<String> {
+ private void createConsole() {
+ TextConsoleBuilder consoleBuilder = TextConsoleBuilderFactory.getInstance().createBuilder(project);
+ buildConsole(consoleBuilder);
+ console = consoleBuilder.getConsole();
+
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ ToolWindow toolWindow = ToolWindowManager.getInstance(project).registerToolWindow(getConsoleToolWindowId(), false, ToolWindowAnchor.BOTTOM, project, true);
+ toolWindow.setIcon(getConsoleToolWindowIcon());
+ toolWindow.getContentManager().addContent(ContentFactory.SERVICE.getInstance().createContent(console.getComponent(), "", false));
+ }
+ }, project.getDisposed());
+ }
+
+ @Override
+ public void onTextAvailable(ProcessEvent event, Key outputType) {
+ print(event.getText(), ConsoleViewContentType.getConsoleViewType(outputType));
+ }
+
+ private void print(String text, ConsoleViewContentType contentType) {
+ if (console == null) {
+ createConsole();
+ }
+ console.print(text, contentType);
+ }
+
+ @Override
+ public void processTerminated(ProcessEvent event) {
+ processHandler.reset();
+ print(getConsoleToolWindowId() + " terminated\n", ConsoleViewContentType.SYSTEM_OUTPUT);
+ }
+
+ @Override
+ public void consume(String message) {
+ print(message, ConsoleViewContentType.ERROR_OUTPUT);
+ }
+ }
+} \ No newline at end of file
diff --git a/xml/impl/src/org/jetbrains/notification/SingletonNotificationManager.java b/xml/impl/src/org/jetbrains/notification/SingletonNotificationManager.java
new file mode 100644
index 000000000000..4ea4a10dcf85
--- /dev/null
+++ b/xml/impl/src/org/jetbrains/notification/SingletonNotificationManager.java
@@ -0,0 +1,86 @@
+package org.jetbrains.notification;
+
+import com.intellij.notification.*;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.wm.ToolWindowManager;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.concurrent.atomic.AtomicReference;
+
+public final class SingletonNotificationManager {
+ private final AtomicReference<Notification> notification = new AtomicReference<Notification>();
+
+ private final NotificationGroup group;
+ private final NotificationType type;
+ @Nullable
+ private final NotificationListener listener;
+
+ private Runnable expiredListener;
+
+ public SingletonNotificationManager(@NotNull String groupId, @NotNull NotificationType type, @Nullable NotificationListener listener) {
+ this(new NotificationGroup(groupId, NotificationDisplayType.STICKY_BALLOON, true), type, listener);
+ }
+
+ public SingletonNotificationManager(@NotNull NotificationGroup group, @NotNull NotificationType type, @Nullable NotificationListener listener) {
+ this.group = group;
+ this.type = type;
+ this.listener = listener;
+ }
+
+ public boolean notify(@NotNull String title, @NotNull String content) {
+ return notify(title, content, null);
+ }
+
+ public boolean notify(@NotNull String title, @NotNull String content, @Nullable Project project) {
+ return notify(title, content, listener, project);
+ }
+
+ public boolean notify(@NotNull String content, @Nullable Project project) {
+ return notify("", content, listener, project);
+ }
+
+ public boolean notify(@NotNull String title,
+ @NotNull String content,
+ @Nullable NotificationListener listener,
+ @Nullable Project project) {
+ Notification oldNotification = notification.get();
+ // !oldNotification.isExpired() is not enough - notification could be closed, but not expired
+ if (oldNotification != null) {
+ if (!oldNotification.isExpired() && (oldNotification.getBalloon() != null ||
+ (project != null &&
+ group.getDisplayType() == NotificationDisplayType.TOOL_WINDOW &&
+ ToolWindowManager.getInstance(project).getToolWindowBalloon(group.getToolWindowId()) != null))) {
+ return false;
+ }
+ oldNotification.whenExpired(null);
+ oldNotification.expire();
+ }
+
+ if (expiredListener == null) {
+ expiredListener = new Runnable() {
+ @Override
+ public void run() {
+ Notification currentNotification = notification.get();
+ if (currentNotification != null && currentNotification.isExpired()) {
+ notification.compareAndSet(currentNotification, null);
+ }
+ }
+ };
+ }
+
+ Notification newNotification = group.createNotification(title, content, type, listener);
+ newNotification.whenExpired(expiredListener);
+ notification.set(newNotification);
+ newNotification.notify(project);
+ return true;
+ }
+
+ public void clear() {
+ Notification oldNotification = notification.getAndSet(null);
+ if (oldNotification != null) {
+ oldNotification.whenExpired(null);
+ oldNotification.expire();
+ }
+ }
+} \ No newline at end of file
diff --git a/xml/impl/xml.iml b/xml/impl/xml.iml
index 60e210829091..2fb3ee7ea262 100644
--- a/xml/impl/xml.iml
+++ b/xml/impl/xml.iml
@@ -21,6 +21,8 @@
<orderEntry type="module" module-name="xml-analysis-impl" exported="" />
<orderEntry type="library" name="swingx" level="project" />
<orderEntry type="module" module-name="xml-structure-view-impl" exported="" />
+ <orderEntry type="library" name="Netty" level="project" />
+ <orderEntry type="module" module-name="xdebugger-api" />
</component>
<component name="copyright">
<Base>
diff --git a/xml/xml-psi-impl/src/com/intellij/javaee/ExternalResourceManagerExImpl.java b/xml/xml-psi-impl/src/com/intellij/javaee/ExternalResourceManagerExImpl.java
index 2eee2882613e..d030ccf9f189 100644
--- a/xml/xml-psi-impl/src/com/intellij/javaee/ExternalResourceManagerExImpl.java
+++ b/xml/xml-psi-impl/src/com/intellij/javaee/ExternalResourceManagerExImpl.java
@@ -47,7 +47,7 @@ import java.util.*;
@State(name = "ExternalResourceManagerImpl",
storages = {@Storage( file = StoragePathMacros.APP_CONFIG + "/other.xml")})
-public class ExternalResourceManagerExImpl extends ExternalResourceManagerEx {
+public class ExternalResourceManagerExImpl extends ExternalResourceManagerEx implements JDOMExternalizable {
static final Logger LOG = Logger.getInstance("#com.intellij.j2ee.openapi.impl.ExternalResourceManagerImpl");
@NonNls public static final String J2EE_1_3 = "http://java.sun.com/dtd/";
@@ -374,6 +374,7 @@ public class ExternalResourceManagerExImpl extends ExternalResourceManagerEx {
return getProjectResources(project).getModificationCount();
}
+ @Override
public void readExternal(Element element) {
final ExpandMacroToPathMap macroExpands = new ExpandMacroToPathMap();
myPathMacros.addMacroExpands(macroExpands);
@@ -404,6 +405,7 @@ public class ExternalResourceManagerExImpl extends ExternalResourceManagerEx {
}
}
+ @Override
public void writeExternal(Element element) {
final String[] urls = getAvailableUrls();
for (String url : urls) {
diff --git a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/html/HtmlFileImpl.java b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/html/HtmlFileImpl.java
index 86b2368b6489..be3b9724a958 100644
--- a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/html/HtmlFileImpl.java
+++ b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/html/HtmlFileImpl.java
@@ -59,10 +59,18 @@ public class HtmlFileImpl extends XmlFileImpl implements FileReferenceResolver {
return null;
}
- VirtualFile childFile = file.findChild(name);
- HttpFileSystem fileSystem = (HttpFileSystem)getVirtualFile().getFileSystem();
+ VirtualFile parent = file;
+ if (!parent.isDirectory()) {
+ parent = parent.getParent();
+ if (parent == null) {
+ parent = file;
+ }
+ }
+
+ VirtualFile childFile = parent.findChild(name);
+ HttpFileSystem fileSystem = (HttpFileSystem)parent.getFileSystem();
if (childFile == null) {
- childFile = fileSystem.createChild(getVirtualFile(), name, !reference.isLast());
+ childFile = fileSystem.createChild(parent, name, !reference.isLast());
}
if (childFile.isDirectory()) {
// pre create children
@@ -72,7 +80,6 @@ public class HtmlFileImpl extends XmlFileImpl implements FileReferenceResolver {
FileReference childReference = references[i];
childParent = fileSystem.createChild(childParent, childReference.decode(childReference.getText()), i != (n - 1));
}
-
return getManager().findDirectory(childFile);
}
else {