summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Norbye <tnorbye@google.com>2014-08-20 17:01:23 -0700
committerTor Norbye <tnorbye@google.com>2014-08-20 17:01:23 -0700
commit1aa2e09bdbd413eacb677e9fa4b50630530d0656 (patch)
tree2f4cc6d69645bd460aa253fdecb606d764fbd25d
parent02cf98d65c798d368fcec43ed64a001d513bdd4f (diff)
downloadidea-1aa2e09bdbd413eacb677e9fa4b50630530d0656.tar.gz
Snapshot idea/138.1696 from git://git.jetbrains.org/idea/community.git
Change-Id: I50c97b83a815ce635e49a38380ba5b8765e4b16a
-rw-r--r--.idea/modules.xml6
-rw-r--r--LICENSE.txt202
-rw-r--r--README.md31
-rw-r--r--RegExpSupport/src/org/intellij/lang/regexp/intention/CheckRegExpForm.form8
-rw-r--r--RegExpSupport/src/org/intellij/lang/regexp/intention/CheckRegExpForm.java127
-rw-r--r--RegExpSupport/src/org/intellij/lang/regexp/intention/CheckRegExpIntentionAction.java12
-rw-r--r--build/scripts/layouts.gant6
-rw-r--r--build/scripts/libLicenses.gant1
-rw-r--r--build/scripts/utils.gant4
-rw-r--r--community-resources/src/plugins/OtherTools.pngbin2344 -> 0 bytes
-rw-r--r--java/compiler/impl/src/com/intellij/compiler/options/AnnotationProcessorsConfigurable.java1
-rw-r--r--java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java9
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/DebuggerManagerEx.java18
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/DefaultDebugEnvironment.java45
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/DefaultDebugUIEnvironment.java71
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/actions/ShowReferringObjectsAction.java131
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/engine/JavaStackFrame.java37
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/engine/JavaValue.java111
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/engine/PositionManagerImpl.java14
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/impl/DebuggerManagerImpl.java29
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/impl/DebuggerSession.java18
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/impl/GenericDebuggerRunner.java77
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/settings/UserRenderersConfigurable.java15
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/ui/DebuggerPanelsManager.java87
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/ui/DebuggerSessionTab.java8
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/ui/XBreakpointGroupingByClassRule.java2
-rw-r--r--java/debugger/impl/src/com/intellij/debugger/ui/impl/VariablesPanel.java8
-rw-r--r--java/execution/impl/src/com/intellij/execution/impl/DefaultJavaProgramRunner.java19
-rw-r--r--java/execution/openapi/src/com/intellij/execution/JavaExecutionUtil.java15
-rw-r--r--java/idea-ui/src/com/intellij/facet/impl/ui/libraries/FacetLibrariesValidatorImpl.java3
-rw-r--r--java/idea-ui/src/com/intellij/facet/impl/ui/libraries/FrameworkLibraryValidatorImpl.java4
-rw-r--r--java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTemplateList.java21
-rw-r--r--java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypeStep.java10
-rw-r--r--java/idea-ui/src/com/intellij/ide/util/newProjectWizard/FrameworkSupportNodeBase.java19
-rw-r--r--java/idea-ui/src/com/intellij/ide/util/newProjectWizard/ProjectTypesList.java10
-rw-r--r--java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectJdksConfigurable.java2
-rw-r--r--java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/SidePanel.java18
-rw-r--r--java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java5
-rw-r--r--java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java19
-rw-r--r--java/java-analysis-impl/src/com/intellij/codeInspection/JavaSuppressionUtil.java12
-rw-r--r--java/java-analysis-impl/src/com/intellij/codeInspection/StreamApiMigrationInspection.java14
-rw-r--r--java/java-analysis-impl/src/com/intellij/codeInspection/canBeFinal/CanBeFinalInspection.java3
-rw-r--r--java/java-analysis-impl/src/com/intellij/codeInspection/javaDoc/JavaDocLocalInspectionBase.java21
-rw-r--r--java/java-analysis-impl/src/com/intellij/codeInspection/unneededThrows/RedundantThrows.java5
-rw-r--r--java/java-analysis-impl/src/com/intellij/refactoring/util/duplicates/DuplicatesFinder.java12
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java20
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/JavaGenerateMemberCompletionContributor.java10
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodCallElement.java6
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/LambdaCompletionProvider.java22
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/completion/MethodReferenceCompletionProvider.java15
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageBaseFix.java2
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateGetterOrSetterFix.java6
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateInnerClassFromNewFix.java3
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/generation/surroundWith/SurroundWithUtil.java3
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/intention/impl/BaseMoveInitializerToMethodAction.java16
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/intention/impl/CopyAbstractMethodImplementationHandler.java15
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/intention/impl/SplitDeclarationAction.java8
-rw-r--r--java/java-impl/src/com/intellij/codeInsight/template/postfix/util/JavaPostfixTemplatesUtils.java8
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/actions/ReplaceImplementsWithStaticImportAction.java89
-rw-r--r--java/java-impl/src/com/intellij/codeInspection/javaDoc/JavaDocLocalInspection.java6
-rw-r--r--java/java-impl/src/com/intellij/ide/projectView/impl/PackageViewPane.java4
-rw-r--r--java/java-impl/src/com/intellij/javadoc/JavadocGenerationManager.java11
-rw-r--r--java/java-impl/src/com/intellij/javadoc/JavadocGenerationPanel.java4
-rw-r--r--java/java-impl/src/com/intellij/psi/RefQueueIndex.java119
-rw-r--r--java/java-impl/src/com/intellij/psi/RefResolveServiceImpl.java773
-rw-r--r--java/java-impl/src/com/intellij/psi/filters/FilterUtil.java6
-rw-r--r--java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java265
-rw-r--r--java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaCodeStyleManagerImpl.java2
-rw-r--r--java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/JavaLangClassMemberReference.java6
-rw-r--r--java/java-impl/src/com/intellij/refactoring/copy/CopyClassesHandler.java28
-rw-r--r--java/java-impl/src/com/intellij/refactoring/extractSuperclass/ExtractSuperclassHandler.java22
-rw-r--r--java/java-impl/src/com/intellij/refactoring/inline/InlineConstantFieldHandler.java22
-rw-r--r--java/java-impl/src/com/intellij/refactoring/inline/InlineParameterHandler.java2
-rw-r--r--java/java-impl/src/com/intellij/refactoring/inline/InlineToAnonymousClassHandler.java11
-rw-r--r--java/java-impl/src/com/intellij/refactoring/makeStatic/MakeMethodStaticProcessor.java15
-rw-r--r--java/java-impl/src/com/intellij/refactoring/memberPullUp/JavaPullUpHandler.java23
-rw-r--r--java/java-impl/src/com/intellij/refactoring/memberPullUp/PullUpProcessor.java51
-rw-r--r--java/java-impl/src/com/intellij/refactoring/memberPushDown/PushDownProcessor.java26
-rw-r--r--java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesImpl.java17
-rw-r--r--java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesProcessor.java6
-rw-r--r--java/java-impl/src/com/intellij/refactoring/move/moveInner/MoveInnerClassJavaUsagesHandler.java58
-rw-r--r--java/java-impl/src/com/intellij/refactoring/move/moveInner/MoveInnerClassUsagesHandler.java28
-rw-r--r--java/java-impl/src/com/intellij/refactoring/move/moveInner/MoveInnerProcessor.java36
-rw-r--r--java/java-impl/src/com/intellij/refactoring/turnRefsToSuper/TurnRefsToSuperProcessorBase.java16
-rw-r--r--java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationProcessor.java36
-rw-r--r--java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java2
-rw-r--r--java/java-impl/src/com/intellij/slicer/SliceNullnessAnalyzer.java11
-rw-r--r--java/java-impl/src/com/intellij/slicer/SliceUtil.java3
-rw-r--r--java/java-impl/src/com/intellij/testIntegration/JavaTestFinder.java39
-rw-r--r--java/java-impl/src/com/intellij/testIntegration/createTest/CreateTestAction.java10
-rw-r--r--java/java-impl/src/com/intellij/testIntegration/createTest/CreateTestDialog.java6
-rw-r--r--java/java-psi-api/src/com/intellij/codeInsight/AnnotationUtil.java32
-rw-r--r--java/java-psi-api/src/com/intellij/codeInsight/NullableNotNullManager.java20
-rw-r--r--java/java-psi-api/src/com/intellij/psi/JavaRecursiveElementWalkingVisitor.java5
-rw-r--r--java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceUtil.java21
-rw-r--r--java/java-psi-api/src/com/intellij/psi/PsiType.java32
-rw-r--r--java/java-psi-api/src/com/intellij/psi/infos/MethodCandidateInfo.java17
-rw-r--r--java/java-psi-api/src/com/intellij/psi/util/RedundantCastUtil.java13
-rw-r--r--java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocUtil.java5
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowAnalyzer.java16
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/JavaConstantExpressionEvaluator.java24
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java4
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/PsiAnnotationMethodImpl.java6
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/PsiFieldImpl.java4
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java3
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveCache.java4
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java51
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceVariable.java10
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/PsiMethodReferenceCompatibilityConstraint.java15
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/MethodReferenceResolver.java14
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiConditionalExpressionImpl.java2
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiKeywordImpl.java3
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiLiteralExpressionImpl.java4
-rw-r--r--java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiReferenceExpressionImpl.java2
-rw-r--r--java/java-structure-view/src/com/intellij/ide/structureView/impl/java/PsiMethodTreeElement.java19
-rw-r--r--java/java-tests/testData/codeInsight/completion/smartType/ConstructorRef-out.java14
-rw-r--r--java/java-tests/testData/codeInsight/completion/smartType/ConstructorRef.java14
-rw-r--r--java/java-tests/testData/codeInsight/completion/smartType/InLambdaPositionSameNames-out.java10
-rw-r--r--java/java-tests/testData/codeInsight/completion/smartType/InLambdaPositionSameNames.java10
-rw-r--r--java/java-tests/testData/codeInsight/createSubclass/innerClassImplement/after/Test.java2
-rw-r--r--java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/AssignToFinal.java1
-rw-r--r--java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/TypeCastInInstanceof.java13
-rw-r--r--java/java-tests/testData/codeInsight/daemonCodeAnalyzer/annotations/dupMethods.java4
-rw-r--r--java/java-tests/testData/codeInsight/daemonCodeAnalyzer/annotations/privateInaccessibleConstant.java8
-rw-r--r--java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA55510.java17
-rw-r--r--java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA78402.java18
-rw-r--r--java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA78402.java18
-rw-r--r--java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/IDEA127928.java21
-rw-r--r--java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/OuterCallOverloads.java16
-rw-r--r--java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/interfaceMethods/AnnotationTypeExtensionsNotSupported.java9
-rw-r--r--java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/IDEA123951.java8
-rw-r--r--java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/IDEA124190.java12
-rw-r--r--java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/IDEA124424.java12
-rw-r--r--java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/IDEA124983.java9
-rw-r--r--java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/IDEA125674.java8
-rw-r--r--java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/IDEA127124comment.java30
-rw-r--r--java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/IDEA127275.java18
-rw-r--r--java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/IDEA127275_.java19
-rw-r--r--java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/IDEA128534.java10
-rw-r--r--java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/IDEA128712.java19
-rw-r--r--java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/UnresolvedMethodReference.java9
-rw-r--r--java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createInnerClassFromNew/afterTypeParamSetup.java11
-rw-r--r--java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createInnerClassFromNew/afterTypeParamSetup1.java11
-rw-r--r--java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createInnerClassFromNew/beforeTypeParamSetup.java6
-rw-r--r--java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createInnerClassFromNew/beforeTypeParamSetup1.java6
-rw-r--r--java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/fixAll/after1.java2
-rw-r--r--java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/fixAll/after2.java2
-rw-r--r--java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/fixAll/afterAssertFalse.java2
-rw-r--r--java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/fixAll/afterAssertTrue.java2
-rw-r--r--java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/fixAll/before1.java2
-rw-r--r--java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/fixAll/before2.java2
-rw-r--r--java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/fixAll/beforeAssertFalse.java2
-rw-r--r--java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/fixAll/beforeAssertTrue.java2
-rw-r--r--java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/fixAllAnnotator/after1.java2
-rw-r--r--java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/fixAllAnnotator/before1.java2
-rw-r--r--java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/moveInitializerToConstructor/afterArrayInitializer.java8
-rw-r--r--java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/moveInitializerToConstructor/beforeArrayInitializer.java7
-rw-r--r--java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/surroundWithTry/afterArrayInitializer.java22
-rw-r--r--java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/surroundWithTry/beforeArrayInitializer.java17
-rw-r--r--java/java-tests/testSrc/com/intellij/codeInsight/OverrideImplementTest.java4
-rw-r--r--java/java-tests/testSrc/com/intellij/codeInsight/completion/JavadocCompletionTest.groovy14
-rw-r--r--java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartType18CompletionTest.java7
-rw-r--r--java/java-tests/testSrc/com/intellij/codeInsight/daemon/AnnotationsHighlightingTest.java2
-rw-r--r--java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java1
-rw-r--r--java/java-tests/testSrc/com/intellij/codeInsight/daemon/JavadocHighlightingTest.java4
-rw-r--r--java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk7Test.java1
-rw-r--r--java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GenericsHighlighting8Test.java2
-rw-r--r--java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GraphInferenceHighlightingTest.java13
-rw-r--r--java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Interface8MethodsHighlightingTest.java3
-rw-r--r--java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java22
-rw-r--r--java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java24
-rw-r--r--java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/I18nizeTest.java5
-rw-r--r--java/java-tests/testSrc/com/intellij/codeInspection/JavaDocInspectionTest.java5
-rw-r--r--java/java-tests/testSrc/com/intellij/execution/ConfigurationsTest.java86
-rw-r--r--java/java-tests/testSrc/com/intellij/find/FindManagerTest.java12
-rw-r--r--java/java-tests/testSrc/com/intellij/openapi/roots/impl/DirectoryIndexTest.java8
-rw-r--r--java/java-tests/testSrc/com/intellij/projectView/ProjectViewSwitchingTest.java9
-rw-r--r--java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterAlignmentTest.java8
-rw-r--r--java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterBracesTest.java49
-rw-r--r--java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterInEditorTest.java6
-rw-r--r--java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterTest.java69
-rw-r--r--java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterWrapTest.java34
-rw-r--r--java/java-tests/testSrc/com/intellij/psi/formatter/java/JavadocFormatterTest.java38
-rw-r--r--java/jdkAnnotations/java/awt/annotations.xml6
-rw-r--r--java/jdkAnnotations/java/util/annotations.xml9
-rw-r--r--java/jdkAnnotations/java/util/concurrent/atomic/annotations.xml36
-rw-r--r--java/jsp-base-openapi/src/com/intellij/lang/jsp/JspVersion.java2
-rw-r--r--java/manifest/test/org/jetbrains/lang/manifest/ManifestCompletionTest.java10
-rw-r--r--java/mockJDK-1.8/jre/lib/rt.jarbin5387286 -> 5403267 bytes
-rw-r--r--java/openapi/src/com/intellij/util/xml/ClassMappingNameConverter.java9
-rw-r--r--java/structuralsearch-java/src/com/intellij/structuralsearch/JavaStructuralSearchProfile.java1
-rw-r--r--java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/JavaMatchingVisitor.java13
-rw-r--r--java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/compiler/JavaCompilingVisitor.java10
-rw-r--r--java/testFramework/src/com/intellij/codeInsight/CodeInsightTestCase.java5
-rw-r--r--java/testFramework/src/com/intellij/debugger/DebuggerTestCase.java49
-rw-r--r--java/testFramework/src/com/intellij/testFramework/TestSourceBasedTestCase.java2
-rw-r--r--java/testFramework/src/com/intellij/testFramework/fixtures/LightCodeInsightFixtureTestCase.java6
-rw-r--r--java/typeMigration/src/com/intellij/refactoring/typeMigration/intentions/ConvertFieldToAtomicIntention.java1
-rw-r--r--java/typeMigration/src/com/intellij/refactoring/typeMigration/intentions/ConvertFieldToThreadLocalIntention.java1
-rw-r--r--java/typeMigration/testData/intentions/atomic/afterNormalize.java8
-rw-r--r--java/typeMigration/testData/intentions/atomic/beforeNormalize.java4
-rw-r--r--java/typeMigration/testData/intentions/threadLocal/afterNormalize.java11
-rw-r--r--java/typeMigration/testData/intentions/threadLocal/beforeNormalize.java4
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleBuildTarget.java4
-rw-r--r--platform/analysis-api/src/com/intellij/analysis/AnalysisScope.java12
-rw-r--r--platform/analysis-api/src/com/intellij/codeInspection/InspectionProfileEntry.java3
-rw-r--r--platform/analysis-api/src/com/intellij/codeInspection/ex/InspectionToolsRegistrarCore.java29
-rw-r--r--platform/analysis-api/src/com/intellij/psi/search/scope/NonProjectFilesScope.java4
-rw-r--r--platform/analysis-api/src/com/intellij/psi/search/scope/ProjectProductionScope.java6
-rw-r--r--platform/annotations/src/org/intellij/lang/annotations/Flow.java6
-rw-r--r--platform/bootstrap/src/com/intellij/ide/startup/StartupActionScriptManager.java22
-rw-r--r--platform/core-api/src/com/intellij/codeInsight/controlflow/ConditionalInstruction.java (renamed from platform/lang-api/src/com/intellij/codeInsight/controlflow/ConditionalInstruction.java)2
-rw-r--r--platform/core-api/src/com/intellij/codeInsight/controlflow/ControlFlow.java23
-rw-r--r--platform/core-api/src/com/intellij/codeInsight/controlflow/Instruction.java (renamed from platform/lang-api/src/com/intellij/codeInsight/controlflow/Instruction.java)2
-rw-r--r--platform/core-api/src/com/intellij/concurrency/JobScheduler.java3
-rw-r--r--platform/core-api/src/com/intellij/openapi/application/ModalityInvokator.java14
-rw-r--r--platform/core-api/src/com/intellij/openapi/progress/ProgressIndicatorProvider.java8
-rw-r--r--platform/core-api/src/com/intellij/openapi/progress/ProgressManager.java47
-rw-r--r--platform/core-api/src/com/intellij/openapi/util/SimpleModificationTracker.java3
-rw-r--r--platform/core-api/src/com/intellij/openapi/vfs/VfsUtilCore.java15
-rw-r--r--platform/core-api/src/com/intellij/openapi/vfs/VirtualFile.java1
-rw-r--r--platform/core-api/src/com/intellij/psi/PsiElementResolveResult.java2
-rw-r--r--platform/core-api/src/com/intellij/psi/PsiFileFactory.java4
-rw-r--r--platform/core-api/src/com/intellij/psi/PsiWalkingState.java7
-rw-r--r--platform/core-api/src/com/intellij/psi/ReferenceRange.java15
-rw-r--r--platform/core-api/src/com/intellij/testFramework/LightVirtualFile.java7
-rw-r--r--platform/core-impl/src/com/intellij/core/CoreApplicationEnvironment.java1
-rw-r--r--platform/core-impl/src/com/intellij/ide/plugins/IdeaPluginDescriptorImpl.java4
-rw-r--r--platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java14
-rw-r--r--platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java18
-rw-r--r--platform/core-impl/src/com/intellij/openapi/application/ex/ApplicationInfoEx.java4
-rw-r--r--platform/core-impl/src/com/intellij/openapi/application/ex/ApplicationUtil.java6
-rw-r--r--platform/core-impl/src/com/intellij/openapi/application/impl/ApplicationInfoImpl.java14
-rw-r--r--platform/core-impl/src/com/intellij/psi/impl/DocumentCommitProcessor.java14
-rw-r--r--platform/core-impl/src/com/intellij/psi/impl/source/tree/PsiCommentImpl.java (renamed from platform/lang-impl/src/com/intellij/psi/impl/source/tree/PsiCommentImpl.java)2
-rw-r--r--platform/core-impl/src/com/intellij/psi/impl/source/tree/injected/CommentLiteralEscaper.java (renamed from platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/CommentLiteralEscaper.java)2
-rw-r--r--platform/duplicates-analysis/src/com/intellij/dupLocator/index/DuplicatesIndex.java2
-rw-r--r--platform/dvcs-api/dvcs-api.iml18
-rw-r--r--platform/dvcs-api/src/com/intellij/dvcs/push/CommitLoader.java20
-rw-r--r--platform/dvcs-api/src/com/intellij/dvcs/push/OutgoingCommitsProvider.java35
-rw-r--r--platform/dvcs-api/src/com/intellij/dvcs/push/OutgoingResult.java41
-rw-r--r--platform/dvcs-api/src/com/intellij/dvcs/push/PushSource.java26
-rw-r--r--platform/dvcs-api/src/com/intellij/dvcs/push/PushSpec.java43
-rw-r--r--platform/dvcs-api/src/com/intellij/dvcs/push/PushSupport.java88
-rw-r--r--platform/dvcs-api/src/com/intellij/dvcs/push/PushTarget.java (renamed from platform/remote-servers/agent-rt/src/com/intellij/remoteServer/agent/util/CloudLoggingHandler.java)14
-rw-r--r--platform/dvcs-api/src/com/intellij/dvcs/push/Pusher.java39
-rw-r--r--platform/dvcs-api/src/com/intellij/dvcs/push/TreeNodeLinkListener.java24
-rw-r--r--platform/dvcs-api/src/com/intellij/dvcs/push/VcsError.java43
-rw-r--r--platform/dvcs-api/src/com/intellij/dvcs/push/VcsErrorHandler.java22
-rw-r--r--platform/dvcs-api/src/com/intellij/dvcs/push/VcsPushOptionValue.java19
-rw-r--r--platform/dvcs-api/src/com/intellij/dvcs/push/VcsPushOptionsPanel.java29
-rw-r--r--platform/dvcs-api/src/com/intellij/dvcs/push/VcsPushReferenceStrategy.java26
-rw-r--r--platform/dvcs-api/src/com/intellij/dvcs/repo/Repository.java (renamed from platform/dvcs/src/com/intellij/dvcs/repo/Repository.java)4
-rw-r--r--platform/dvcs-api/src/com/intellij/dvcs/repo/RepositoryManager.java (renamed from platform/dvcs/src/com/intellij/dvcs/repo/RepositoryManager.java)0
-rw-r--r--platform/dvcs-impl/dvcs-impl.iml (renamed from platform/dvcs/dvcs.iml)3
-rw-r--r--platform/dvcs-impl/resources/icons/Loading@2x.gifbin0 -> 3233 bytes
-rw-r--r--platform/dvcs-impl/resources/icons/Loading@2x_dark.gifbin0 -> 3332 bytes
-rw-r--r--platform/dvcs-impl/resources/icons/loading.gifbin0 -> 1460 bytes
-rw-r--r--platform/dvcs-impl/resources/icons/loading_dark.gifbin0 -> 1496 bytes
-rw-r--r--platform/dvcs-impl/src/META-INF/dvcs.xml12
-rw-r--r--platform/dvcs-impl/src/com/intellij/dvcs/DvcsCommitAdditionalComponent.java (renamed from platform/dvcs/src/com/intellij/dvcs/DvcsCommitAdditionalComponent.java)0
-rw-r--r--platform/dvcs-impl/src/com/intellij/dvcs/DvcsPlatformFacade.java (renamed from platform/dvcs/src/com/intellij/dvcs/DvcsPlatformFacade.java)0
-rw-r--r--platform/dvcs-impl/src/com/intellij/dvcs/DvcsPlatformFacadeImpl.java (renamed from platform/dvcs/src/com/intellij/dvcs/DvcsPlatformFacadeImpl.java)0
-rw-r--r--platform/dvcs-impl/src/com/intellij/dvcs/DvcsRememberedInputs.java (renamed from platform/dvcs/src/com/intellij/dvcs/DvcsRememberedInputs.java)0
-rw-r--r--platform/dvcs-impl/src/com/intellij/dvcs/DvcsUtil.java (renamed from platform/dvcs/src/com/intellij/dvcs/DvcsUtil.java)19
-rw-r--r--platform/dvcs-impl/src/com/intellij/dvcs/push/PushController.java445
-rw-r--r--platform/dvcs-impl/src/com/intellij/dvcs/push/RepositoryNodeListener.java23
-rw-r--r--platform/dvcs-impl/src/com/intellij/dvcs/push/ui/CustomRenderedTreeNode.java24
-rw-r--r--platform/dvcs-impl/src/com/intellij/dvcs/push/ui/DvcsStrategyPanel.java43
-rw-r--r--platform/dvcs-impl/src/com/intellij/dvcs/push/ui/EditableTreeNode.java33
-rw-r--r--platform/dvcs-impl/src/com/intellij/dvcs/push/ui/LoadingTreeNode.java51
-rw-r--r--platform/dvcs-impl/src/com/intellij/dvcs/push/ui/NodeImageObserver.java46
-rw-r--r--platform/dvcs-impl/src/com/intellij/dvcs/push/ui/PushLog.java289
-rw-r--r--platform/dvcs-impl/src/com/intellij/dvcs/push/ui/PushLogTreeUtil.java52
-rw-r--r--platform/dvcs-impl/src/com/intellij/dvcs/push/ui/RepositoryNode.java97
-rw-r--r--platform/dvcs-impl/src/com/intellij/dvcs/push/ui/RepositoryWithBranchPanel.java185
-rw-r--r--platform/dvcs-impl/src/com/intellij/dvcs/push/ui/SingleRepositoryNode.java52
-rw-r--r--platform/dvcs-impl/src/com/intellij/dvcs/push/ui/TextWithLinkNode.java52
-rw-r--r--platform/dvcs-impl/src/com/intellij/dvcs/push/ui/TooltipNode.java21
-rw-r--r--platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsBranchEditorListener.java61
-rw-r--r--platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsFullCommitDetailsNode.java54
-rw-r--r--platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsLinkListener.java24
-rw-r--r--platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsLinkedText.java70
-rw-r--r--platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsPushDialog.java144
-rw-r--r--platform/dvcs-impl/src/com/intellij/dvcs/repo/AbstractRepositoryManager.java (renamed from platform/dvcs/src/com/intellij/dvcs/repo/AbstractRepositoryManager.java)0
-rw-r--r--platform/dvcs-impl/src/com/intellij/dvcs/repo/RepoStateException.java (renamed from platform/dvcs/src/com/intellij/dvcs/repo/RepoStateException.java)0
-rw-r--r--platform/dvcs-impl/src/com/intellij/dvcs/repo/RepositoryImpl.java (renamed from platform/dvcs/src/com/intellij/dvcs/repo/RepositoryImpl.java)0
-rw-r--r--platform/dvcs-impl/src/com/intellij/dvcs/repo/RepositoryUtil.java (renamed from platform/dvcs/src/com/intellij/dvcs/repo/RepositoryUtil.java)0
-rw-r--r--platform/dvcs-impl/src/com/intellij/dvcs/ui/BranchActionGroupPopup.java (renamed from platform/dvcs/src/com/intellij/dvcs/ui/BranchActionGroupPopup.java)5
-rw-r--r--platform/dvcs-impl/src/com/intellij/dvcs/ui/CloneDvcsDialog.form (renamed from platform/dvcs/src/com/intellij/dvcs/ui/CloneDvcsDialog.form)0
-rw-r--r--platform/dvcs-impl/src/com/intellij/dvcs/ui/CloneDvcsDialog.java (renamed from platform/dvcs/src/com/intellij/dvcs/ui/CloneDvcsDialog.java)0
-rw-r--r--platform/dvcs-impl/src/com/intellij/dvcs/ui/DvcsBundle.java (renamed from platform/dvcs/src/com/intellij/dvcs/ui/DvcsBundle.java)0
-rw-r--r--platform/dvcs-impl/src/com/intellij/dvcs/ui/DvcsBundle.properties (renamed from platform/dvcs/src/com/intellij/dvcs/ui/DvcsBundle.properties)0
-rw-r--r--platform/dvcs-impl/src/com/intellij/dvcs/ui/NewBranchAction.java (renamed from platform/dvcs/src/com/intellij/dvcs/ui/NewBranchAction.java)5
-rw-r--r--platform/dvcs-impl/src/com/intellij/dvcs/ui/RootAction.java (renamed from platform/dvcs/src/com/intellij/dvcs/ui/RootAction.java)0
-rw-r--r--platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogAction.java (renamed from platform/dvcs/src/com/intellij/dvcs/ui/VcsLogAction.java)0
-rw-r--r--platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogOneCommitPerRepoAction.java (renamed from platform/dvcs/src/com/intellij/dvcs/ui/VcsLogOneCommitPerRepoAction.java)0
-rw-r--r--platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogSingleCommitAction.java (renamed from platform/dvcs/src/com/intellij/dvcs/ui/VcsLogSingleCommitAction.java)0
-rw-r--r--platform/dvcs-impl/testFramework/com/intellij/dvcs/test/MockProject.java (renamed from platform/dvcs/testFramework/com/intellij/dvcs/test/MockProject.java)8
-rw-r--r--platform/dvcs-impl/testFramework/com/intellij/dvcs/test/MockProjectRootManager.java (renamed from platform/dvcs/testFramework/com/intellij/dvcs/test/MockProjectRootManager.java)0
-rw-r--r--platform/dvcs-impl/testFramework/com/intellij/dvcs/test/MockVcsHelper.java (renamed from platform/dvcs/testFramework/com/intellij/dvcs/test/MockVcsHelper.java)0
-rw-r--r--platform/dvcs-impl/testFramework/com/intellij/dvcs/test/MockVirtualFile.java (renamed from platform/dvcs/testFramework/com/intellij/dvcs/test/MockVirtualFile.java)0
-rw-r--r--platform/editor-ui-api/src/com/intellij/ide/ui/UISettings.java28
-rw-r--r--platform/editor-ui-api/src/com/intellij/ide/ui/UISettingsListener.java4
-rw-r--r--platform/editor-ui-api/src/com/intellij/openapi/actionSystem/AnAction.java6
-rw-r--r--platform/editor-ui-api/src/com/intellij/openapi/actionSystem/AnActionEvent.java37
-rw-r--r--platform/editor-ui-api/src/com/intellij/openapi/actionSystem/CommonDataKeys.java12
-rw-r--r--platform/editor-ui-api/src/com/intellij/openapi/actionSystem/DataContextWrapper.java51
-rw-r--r--platform/editor-ui-api/src/com/intellij/openapi/actionSystem/RightAlignedToolbarAction.java22
-rw-r--r--platform/editor-ui-api/src/com/intellij/ui/switcher/QuickActionProvider.java1
-rw-r--r--platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemTaskDebugRunner.java13
-rw-r--r--platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemTaskRunner.java8
-rw-r--r--platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/settings/AbstractExternalSystemConfigurable.java2
-rw-r--r--platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/task/ui/AbstractExternalSystemToolWindowFactory.java4
-rw-r--r--platform/icons/src/actions/GroupByClass.pngbin0 -> 494 bytes
-rw-r--r--platform/icons/src/actions/GroupByClass@2x.pngbin0 -> 1218 bytes
-rw-r--r--platform/icons/src/actions/GroupByClass@2x_dark.pngbin0 -> 1216 bytes
-rw-r--r--platform/icons/src/actions/GroupByClass_dark.pngbin0 -> 507 bytes
-rw-r--r--platform/icons/src/gutter/extAnnotation.pngbin144 -> 322 bytes
-rw-r--r--platform/icons/src/gutter/extAnnotation@2x.pngbin192 -> 724 bytes
-rw-r--r--platform/icons/src/gutter/extAnnotation@2x_dark.pngbin269 -> 730 bytes
-rw-r--r--platform/icons/src/gutter/extAnnotation_dark.pngbin216 -> 321 bytes
-rw-r--r--platform/indexing-api/src/com/intellij/psi/RefResolveService.java50
-rw-r--r--platform/indexing-api/src/com/intellij/psi/search/PsiSearchHelper.java6
-rw-r--r--platform/indexing-api/src/com/intellij/psi/stubs/StubIndex.java4
-rw-r--r--platform/indexing-impl/src/com/intellij/psi/impl/PersistentIntList.java386
-rw-r--r--platform/indexing-impl/src/com/intellij/psi/impl/file/impl/ResolveScopeManagerImpl.java51
-rw-r--r--platform/lang-api/src/com/intellij/codeInsight/controlflow/ControlFlow.java8
-rw-r--r--platform/lang-api/src/com/intellij/execution/BeforeRunTaskProvider.java2
-rw-r--r--platform/lang-api/src/com/intellij/execution/ExecutionManager.java41
-rw-r--r--platform/lang-api/src/com/intellij/execution/ExecutionTargetManager.java9
-rw-r--r--platform/lang-api/src/com/intellij/execution/ExecutorRegistry.java9
-rw-r--r--platform/lang-api/src/com/intellij/execution/RunnerRegistry.java2
-rw-r--r--platform/lang-api/src/com/intellij/execution/configurations/LogFileOptions.java7
-rw-r--r--platform/lang-api/src/com/intellij/execution/runners/ExecutionEnvironment.java80
-rw-r--r--platform/lang-api/src/com/intellij/execution/runners/ExecutionEnvironmentBuilder.java179
-rw-r--r--platform/lang-api/src/com/intellij/execution/runners/ExecutionUtil.java74
-rw-r--r--platform/lang-api/src/com/intellij/execution/runners/GenericProgramRunner.java3
-rw-r--r--platform/lang-api/src/com/intellij/execution/ui/RunContentDescriptor.java71
-rw-r--r--platform/lang-api/src/com/intellij/execution/ui/RunContentManager.java59
-rw-r--r--platform/lang-api/src/com/intellij/execution/ui/RunContentWithExecutorListener.java (renamed from platform/lang-impl/src/com/intellij/execution/ui/RunContentWithExecutorListener.java)6
-rw-r--r--platform/lang-api/src/com/intellij/execution/ui/layout/ViewContext.java3
-rw-r--r--platform/lang-api/src/com/intellij/facet/frameworks/SettingsConnectionService.java27
-rw-r--r--platform/lang-api/src/com/intellij/facet/ui/FacetEditorValidator.java6
-rw-r--r--platform/lang-api/src/com/intellij/ide/IdeView.java4
-rw-r--r--platform/lang-api/src/com/intellij/openapi/actionSystem/LangDataKeys.java9
-rw-r--r--platform/lang-api/src/com/intellij/psi/WeigherExtensionPoint.java18
-rw-r--r--platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettings.java40
-rw-r--r--platform/lang-api/src/com/intellij/psi/util/PsiUtilBase.java20
-rw-r--r--platform/lang-impl/src/com/intellij/application/options/CodeStyleSchemesConfigurable.java14
-rw-r--r--platform/lang-impl/src/com/intellij/application/options/GeneralCodeStylePanel.java8
-rw-r--r--platform/lang-impl/src/com/intellij/application/options/OtherTabsAndIndentsPanel.java2
-rw-r--r--platform/lang-impl/src/com/intellij/application/options/codeStyle/RightMarginForm.java8
-rw-r--r--platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontOptions.java4
-rw-r--r--platform/lang-impl/src/com/intellij/application/options/editor/EditorTabsConfigurable.form54
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java4
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonListeners.java2
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/HectorComponent.java4
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/editorActions/CodeBlockEndAction.java4
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/editorActions/CodeBlockEndWithSelectionAction.java4
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/editorActions/CodeBlockStartAction.java4
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/editorActions/CodeBlockStartWithSelectionAction.java4
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/editorActions/EnterHandler.java4
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/editorActions/JoinLinesHandler.java2
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/editorActions/SelectWordHandler.java7
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/editorActions/UnSelectWordHandler.java9
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/editorActions/smartEnter/SmartEnterAction.java30
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/folding/impl/FoldingUpdate.java2
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/folding/impl/PsiNamesElementSignatureProvider.java47
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditAction.java7
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditHandler.java76
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java140
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/template/impl/actions/NextVariableAction.java19
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/template/impl/actions/PreviousVariableAction.java18
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/template/impl/editorActions/EnterHandler.java5
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/template/impl/editorActions/ExpandLiveTemplateByTabAction.java4
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/template/postfix/settings/PostfixTemplatesCheckboxTree.java15
-rw-r--r--platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java10
-rw-r--r--platform/lang-impl/src/com/intellij/codeInspection/ex/SeverityEditorDialog.java4
-rw-r--r--platform/lang-impl/src/com/intellij/diagnostic/logging/LogConsoleManagerBase.java6
-rw-r--r--platform/lang-impl/src/com/intellij/diagnostic/logging/LogFilesManager.java16
-rw-r--r--platform/lang-impl/src/com/intellij/diagnostic/logging/OutputFileUtil.java61
-rw-r--r--platform/lang-impl/src/com/intellij/execution/ExecutionHelper.java54
-rw-r--r--platform/lang-impl/src/com/intellij/execution/ExecutionTargetManagerImpl.java62
-rw-r--r--platform/lang-impl/src/com/intellij/execution/ExecutorRegistryImpl.java65
-rw-r--r--platform/lang-impl/src/com/intellij/execution/ProgramRunnerUtil.java138
-rw-r--r--platform/lang-impl/src/com/intellij/execution/actions/ChooseRunConfigurationPopup.java57
-rw-r--r--platform/lang-impl/src/com/intellij/execution/actions/RunContextAction.java20
-rw-r--r--platform/lang-impl/src/com/intellij/execution/actions/StopAction.java72
-rw-r--r--platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java2
-rw-r--r--platform/lang-impl/src/com/intellij/execution/impl/ConfigurationSettingsEditor.java12
-rw-r--r--platform/lang-impl/src/com/intellij/execution/impl/ExecutionManagerImpl.java410
-rw-r--r--platform/lang-impl/src/com/intellij/execution/impl/ProjectRunConfigurationManager.java4
-rw-r--r--platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationBeforeRunProvider.java22
-rw-r--r--platform/lang-impl/src/com/intellij/execution/impl/RunDialog.java5
-rw-r--r--platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.java23
-rw-r--r--platform/lang-impl/src/com/intellij/execution/impl/RunnerRegistryImpl.java10
-rw-r--r--platform/lang-impl/src/com/intellij/execution/impl/SingleConfigurationConfigurable.java10
-rw-r--r--platform/lang-impl/src/com/intellij/execution/runners/AbstractConsoleRunnerWithHistory.java2
-rw-r--r--platform/lang-impl/src/com/intellij/execution/runners/DefaultProgramRunner.java8
-rw-r--r--platform/lang-impl/src/com/intellij/execution/runners/FakeRerunAction.java116
-rw-r--r--platform/lang-impl/src/com/intellij/execution/runners/RerunTestsAction.java71
-rw-r--r--platform/lang-impl/src/com/intellij/execution/runners/RestartAction.java124
-rw-r--r--platform/lang-impl/src/com/intellij/execution/runners/RunContentBuilder.java186
-rw-r--r--platform/lang-impl/src/com/intellij/execution/runners/RunTab.java94
-rw-r--r--platform/lang-impl/src/com/intellij/execution/ui/RunContentManagerImpl.java307
-rw-r--r--platform/lang-impl/src/com/intellij/execution/ui/layout/impl/GridCellImpl.java11
-rw-r--r--platform/lang-impl/src/com/intellij/execution/ui/layout/impl/JBRunnerTabs.java4
-rw-r--r--platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java73
-rw-r--r--platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerLayoutUiImpl.java41
-rw-r--r--platform/lang-impl/src/com/intellij/find/FindSettings.java3
-rw-r--r--platform/lang-impl/src/com/intellij/find/actions/ShowUsagesTableCellRenderer.java2
-rw-r--r--platform/lang-impl/src/com/intellij/find/findInProject/FindInProjectManager.java11
-rw-r--r--platform/lang-impl/src/com/intellij/find/impl/FindDialog.java34
-rw-r--r--platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java1
-rw-r--r--platform/lang-impl/src/com/intellij/find/impl/FindManagerImpl.java3
-rw-r--r--platform/lang-impl/src/com/intellij/find/impl/FindSettingsImpl.java11
-rw-r--r--platform/lang-impl/src/com/intellij/formatting/FormatProcessor.java5
-rw-r--r--platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java39
-rw-r--r--platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java43
-rw-r--r--platform/lang-impl/src/com/intellij/ide/actions/SelectInAction.java8
-rw-r--r--platform/lang-impl/src/com/intellij/ide/commander/CommanderPanel.java3
-rw-r--r--platform/lang-impl/src/com/intellij/ide/favoritesTreeView/FavoritesProjectViewPane.java3
-rw-r--r--platform/lang-impl/src/com/intellij/ide/favoritesTreeView/FavoritesTreeViewPanel.java3
-rw-r--r--platform/lang-impl/src/com/intellij/ide/impl/ProjectViewSelectInGroupTarget.java4
-rw-r--r--platform/lang-impl/src/com/intellij/ide/impl/ProjectViewSelectInTarget.java18
-rw-r--r--platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarIdeView.java4
-rw-r--r--platform/lang-impl/src/com/intellij/ide/projectView/ProjectView.java24
-rw-r--r--platform/lang-impl/src/com/intellij/ide/projectView/impl/AbstractProjectViewPSIPane.java4
-rw-r--r--platform/lang-impl/src/com/intellij/ide/projectView/impl/AbstractProjectViewPane.java4
-rw-r--r--platform/lang-impl/src/com/intellij/ide/projectView/impl/FavoritesViewToolWindowFactory.java5
-rw-r--r--platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewImpl.java178
-rw-r--r--platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewToolWindowFactory.java5
-rw-r--r--platform/lang-impl/src/com/intellij/ide/projectView/impl/ShowModulesAction.java2
-rw-r--r--platform/lang-impl/src/com/intellij/ide/scopeView/ScopeTreeViewPanel.java9
-rw-r--r--platform/lang-impl/src/com/intellij/ide/scopeView/ScopeViewPane.java7
-rw-r--r--platform/lang-impl/src/com/intellij/ide/structureView/impl/StructureViewToolWindowFactory.java5
-rw-r--r--platform/lang-impl/src/com/intellij/ide/todo/TodoToolWindowFactory.java5
-rw-r--r--platform/lang-impl/src/com/intellij/ide/util/MemberChooser.java32
-rw-r--r--platform/lang-impl/src/com/intellij/lang/parser/GeneratedParserUtilBase.java4
-rw-r--r--platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectWordAtCaretAction.java17
-rw-r--r--platform/lang-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorPsiDataProvider.java98
-rw-r--r--platform/lang-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexImpl.java100
-rw-r--r--platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentRootPanel.java4
-rw-r--r--platform/lang-impl/src/com/intellij/platform/templates/github/DownloadUtil.java3
-rw-r--r--platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ScopesOrderDialog.java2
-rw-r--r--platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java6
-rw-r--r--platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/InspectionsConfigTreeTable.java4
-rw-r--r--platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/ScopesAndSeveritiesTable.java32
-rw-r--r--platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/ThreeStateCheckBoxRenderer.java7
-rw-r--r--platform/lang-impl/src/com/intellij/psi/impl/DocumentCommitThread.java95
-rw-r--r--platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java18
-rw-r--r--platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeFormatterFacade.java5
-rw-r--r--platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerImpl.java2
-rw-r--r--platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedFileViewProvider.java2
-rw-r--r--platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java53
-rw-r--r--platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/MultiHostRegistrarImpl.java2
-rw-r--r--platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/Place.java6
-rw-r--r--platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/ShredImpl.java1
-rw-r--r--platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java2
-rw-r--r--platform/lang-impl/src/com/intellij/refactoring/changeSignature/MethodNodeBase.java10
-rw-r--r--platform/lang-impl/src/com/intellij/refactoring/inline/GenericInlineHandler.java2
-rw-r--r--platform/lang-impl/src/com/intellij/refactoring/rename/RenameProcessor.java6
-rw-r--r--platform/lang-impl/src/com/intellij/refactoring/safeDelete/SafeDeleteProcessor.java8
-rw-r--r--platform/lang-impl/src/com/intellij/tools/BaseToolManager.java6
-rw-r--r--platform/lang-impl/src/com/intellij/tools/ScanSourceCommentsAction.java31
-rw-r--r--platform/lang-impl/src/com/intellij/tools/Tool.java15
-rw-r--r--platform/lang-impl/src/com/intellij/ui/DuplicateNodeRenderer.java7
-rw-r--r--platform/lang-impl/src/com/intellij/ui/popup/PopupPositionManager.java2
-rw-r--r--platform/lang-impl/src/com/intellij/ui/tabs/ColorSelectionComponent.java20
-rw-r--r--platform/lang-impl/src/com/intellij/ui/tabs/FileColorManagerImpl.java41
-rw-r--r--platform/lang-impl/src/com/intellij/usageView/UsageViewUtil.java16
-rw-r--r--platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java3
-rw-r--r--platform/lang-impl/src/com/intellij/util/indexing/MapReduceIndex.java42
-rw-r--r--platform/platform-api/src/com/intellij/execution/process/AnsiEscapeDecoder.java101
-rw-r--r--platform/platform-api/src/com/intellij/execution/process/CapturingAnsiEscapesAwareProcessHandler.java3
-rw-r--r--platform/platform-api/src/com/intellij/execution/process/ColoredOutputTypeRegistry.java2
-rw-r--r--platform/platform-api/src/com/intellij/ide/CompositeSelectInTarget.java4
-rw-r--r--platform/platform-api/src/com/intellij/ide/SelectInTarget.java3
-rw-r--r--platform/platform-api/src/com/intellij/openapi/actionSystem/AbbreviationManager.java9
-rw-r--r--platform/platform-api/src/com/intellij/openapi/editor/actionSystem/CaretSpecificDataContext.java47
-rw-r--r--platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorAction.java18
-rw-r--r--platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorActionHandler.java128
-rw-r--r--platform/platform-api/src/com/intellij/openapi/fileEditor/EditorDataProvider.java6
-rw-r--r--platform/platform-api/src/com/intellij/openapi/fileEditor/FileEditorManager.java10
-rw-r--r--platform/platform-api/src/com/intellij/openapi/ui/ComboBoxTableRenderer.java2
-rw-r--r--platform/platform-api/src/com/intellij/openapi/ui/ComponentWithActions.java18
-rw-r--r--platform/platform-api/src/com/intellij/openapi/ui/MasterDetailsComponent.java8
-rw-r--r--platform/platform-api/src/com/intellij/openapi/ui/PanelWithText.java4
-rw-r--r--platform/platform-api/src/com/intellij/openapi/ui/popup/ListItemDescriptorAdapter.java44
-rw-r--r--platform/platform-api/src/com/intellij/openapi/vfs/VfsUtil.java12
-rw-r--r--platform/platform-api/src/com/intellij/openapi/wm/FocusCommand.java6
-rw-r--r--platform/platform-api/src/com/intellij/openapi/wm/IdeFocusManager.java5
-rw-r--r--platform/platform-api/src/com/intellij/openapi/wm/ToolWindowFactory.java5
-rw-r--r--platform/platform-api/src/com/intellij/openapi/wm/ToolWindowManager.java25
-rw-r--r--platform/platform-api/src/com/intellij/ui/components/JBScrollPane.java8
-rw-r--r--platform/platform-api/src/com/intellij/ui/content/ContentManagerEvent.java12
-rw-r--r--platform/platform-api/src/com/intellij/ui/table/JBTable.java43
-rw-r--r--platform/platform-api/src/com/intellij/ui/tabs/impl/JBEditorTabs.java2
-rw-r--r--platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java62
-rw-r--r--platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayout.java19
-rw-r--r--platform/platform-api/src/com/intellij/ui/tabs/impl/table/TableLayout.java12
-rw-r--r--platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java8
-rw-r--r--platform/platform-api/src/com/intellij/util/net/HttpConfigurable.java8
-rw-r--r--platform/platform-api/src/com/intellij/util/ui/AsyncProcessIcon.java11
-rw-r--r--platform/platform-api/src/com/intellij/util/ui/ButtonlessScrollBarUI.java22
-rw-r--r--platform/platform-api/src/com/intellij/util/ui/JTableCellEditorHelper.java76
-rw-r--r--platform/platform-impl/src/com/intellij/errorreport/itn/ITNProxy.java2
-rw-r--r--platform/platform-impl/src/com/intellij/help/impl/HelpManagerImpl.java11
-rw-r--r--platform/platform-impl/src/com/intellij/help/impl/MacHelpUtil.java12
-rw-r--r--platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java7
-rw-r--r--platform/platform-impl/src/com/intellij/ide/SwingCleanuper.java5
-rw-r--r--platform/platform-impl/src/com/intellij/ide/actions/CreateLauncherScriptAction.java3
-rw-r--r--platform/platform-impl/src/com/intellij/ide/customize/CustomizeFeaturedPluginsStepPanel.java8
-rw-r--r--platform/platform-impl/src/com/intellij/ide/customize/CustomizeIDEWizardDialog.java27
-rw-r--r--platform/platform-impl/src/com/intellij/ide/customize/CustomizeIDEWizardStepsProvider.java25
-rw-r--r--platform/platform-impl/src/com/intellij/ide/customize/CustomizeKeyboardSchemeStepPanel.java2
-rw-r--r--platform/platform-impl/src/com/intellij/ide/customize/CustomizePluginsStepPanel.java39
-rw-r--r--platform/platform-impl/src/com/intellij/ide/customize/CustomizeUIThemeStepPanel.java56
-rw-r--r--platform/platform-impl/src/com/intellij/ide/customize/IdSet.java6
-rw-r--r--platform/platform-impl/src/com/intellij/ide/customize/PluginGroups.java116
-rw-r--r--platform/platform-impl/src/com/intellij/ide/passwordSafe/PasswordSafeException.java29
-rw-r--r--platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/BasePasswordSafeProvider.java1
-rw-r--r--platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/EncryptionUtil.java12
-rw-r--r--platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterKeyPasswordSafe.java172
-rw-r--r--platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/memory/MemoryPasswordSafe.java1
-rw-r--r--platform/platform-impl/src/com/intellij/ide/passwordSafe/ui/PasswordPromptComponent.java6
-rw-r--r--platform/platform-impl/src/com/intellij/ide/plugins/PluginInstaller.java28
-rw-r--r--platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerConfigurable.java18
-rw-r--r--platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java4
-rw-r--r--platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerUISettings.java4
-rw-r--r--platform/platform-impl/src/com/intellij/ide/plugins/RepositoryHelper.java8
-rw-r--r--platform/platform-impl/src/com/intellij/ide/ui/AppearanceConfigurable.java6
-rw-r--r--platform/platform-impl/src/com/intellij/ide/util/TipDialog.java10
-rw-r--r--platform/platform-impl/src/com/intellij/notification/EventLogToolWindowFactory.java5
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/AbbreviationManagerImpl.java31
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionManagerImpl.java7
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionToolbarImpl.java64
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java7
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/application/impl/ModalityInvokatorImpl.java14
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/EditorLinePainter.java32
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/LineExtensionInfo.java71
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/actions/EnterAction.java6
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/actions/IndentSelectionAction.java2
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/actions/SplitLineAction.java14
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/actions/StartNewLineAction.java10
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/actions/StartNewLineBeforeAction.java4
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/actions/UnselectWordAtCaretAction.java6
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/ex/EditorMarkupModel.java4
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorHeaderComponent.java7
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java30
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java2
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileTextFieldImpl.java6
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/fileEditor/ex/FileEditorManagerEx.java7
-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.java6
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/HistoryEntry.java13
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorComponent.java3
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/keymap/impl/ModifierKeyDoubleClickHandler.java4
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ActionsTree.java42
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableExtensionPointUtil.java7
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/options/ex/MixedConfigurableGroup.java26
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/options/ex/NodeConfigurable.java71
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditor.java103
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsTree.java129
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java864
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java24
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressIndicatorUtils.java79
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java22
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java17
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/PluginDownloader.java32
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java34
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdatesXmlLoader.java6
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/wm/ex/ToolWindowManagerEx.java4
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/wm/impl/FocusManagerImpl.java3
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeGlassPaneImpl.java23
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeadlessManagerImpl.java15
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowImpl.java49
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java33
-rw-r--r--platform/platform-impl/src/com/intellij/remote/RemoteSdkAdditionalData.java3
-rw-r--r--platform/platform-impl/src/com/intellij/remote/RemoteSdkCredentialsHolder.java10
-rw-r--r--platform/platform-impl/src/com/intellij/remote/RemoteSdkProperties.java10
-rw-r--r--platform/platform-impl/src/com/intellij/remote/RemoteSdkPropertiesHolder.java18
-rw-r--r--platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java57
-rw-r--r--platform/platform-impl/src/com/intellij/ui/BalloonImpl.java2
-rw-r--r--platform/platform-impl/src/com/intellij/ui/JBTabsPaneImpl.java8
-rw-r--r--platform/platform-impl/src/com/intellij/ui/LibNotifyWrapper.java8
-rw-r--r--platform/platform-impl/src/com/intellij/ui/SpeedSearchBase.java4
-rw-r--r--platform/platform-impl/src/com/intellij/ui/TableSpeedSearch.java23
-rw-r--r--platform/platform-impl/src/com/intellij/ui/content/impl/ContentImpl.java6
-rw-r--r--platform/platform-impl/src/com/intellij/ui/content/impl/ContentManagerImpl.java145
-rw-r--r--platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java36
-rw-r--r--platform/platform-impl/src/com/intellij/ui/popup/list/PopupListElementRenderer.java9
-rw-r--r--platform/platform-impl/src/icons/PlatformImplIcons.java28
-rw-r--r--platform/platform-impl/src/icons/plugins/Android.png (renamed from community-resources/src/plugins/Android.png)bin1610 -> 1610 bytes
-rw-r--r--platform/platform-impl/src/icons/plugins/Android@2x.png (renamed from community-resources/src/plugins/Android@2x.png)bin3137 -> 3137 bytes
-rw-r--r--platform/platform-impl/src/icons/plugins/ApplicationServers.png (renamed from community-resources/src/plugins/ApplicationServers.png)bin429 -> 429 bytes
-rw-r--r--platform/platform-impl/src/icons/plugins/ApplicationServers@2x.png (renamed from community-resources/src/plugins/ApplicationServers@2x.png)bin908 -> 908 bytes
-rw-r--r--platform/platform-impl/src/icons/plugins/BuildTools.png (renamed from community-resources/src/plugins/BuildTools.png)bin1086 -> 1086 bytes
-rw-r--r--platform/platform-impl/src/icons/plugins/BuildTools@2x.png (renamed from community-resources/src/plugins/BuildTools@2x.png)bin2744 -> 2744 bytes
-rw-r--r--platform/platform-impl/src/icons/plugins/Clouds.png (renamed from community-resources/src/plugins/Clouds.png)bin2100 -> 2100 bytes
-rw-r--r--platform/platform-impl/src/icons/plugins/Clouds@2x.png (renamed from community-resources/src/plugins/Clouds@2x.png)bin4545 -> 4545 bytes
-rw-r--r--platform/platform-impl/src/icons/plugins/DatabaseTools.png (renamed from community-resources/src/plugins/DatabaseTools.png)bin1936 -> 1936 bytes
-rw-r--r--platform/platform-impl/src/icons/plugins/DatabaseTools@2x.png (renamed from community-resources/src/plugins/DatabaseTools@2x.png)bin3661 -> 3661 bytes
-rw-r--r--platform/platform-impl/src/icons/plugins/JavaFrameworks.png (renamed from community-resources/src/plugins/JavaFrameworks.png)bin2155 -> 2155 bytes
-rw-r--r--platform/platform-impl/src/icons/plugins/JavaFrameworks@2x.png (renamed from community-resources/src/plugins/JavaFrameworks@2x.png)bin4711 -> 4711 bytes
-rw-r--r--platform/platform-impl/src/icons/plugins/OtherTools.pngbin0 -> 2343 bytes
-rw-r--r--platform/platform-impl/src/icons/plugins/OtherTools@2x.png (renamed from community-resources/src/plugins/OtherTools@2x.png)bin5449 -> 5449 bytes
-rw-r--r--platform/platform-impl/src/icons/plugins/PluginDevelopment.png (renamed from community-resources/src/plugins/PluginDevelopment.png)bin1633 -> 1633 bytes
-rw-r--r--platform/platform-impl/src/icons/plugins/PluginDevelopment@2x.png (renamed from community-resources/src/plugins/PluginDevelopment@2x.png)bin3271 -> 3271 bytes
-rw-r--r--platform/platform-impl/src/icons/plugins/Swing.png (renamed from community-resources/src/plugins/Swing.png)bin711 -> 711 bytes
-rw-r--r--platform/platform-impl/src/icons/plugins/Swing@2x.png (renamed from community-resources/src/plugins/Swing@2x.png)bin1226 -> 1226 bytes
-rw-r--r--platform/platform-impl/src/icons/plugins/TestTools.png (renamed from community-resources/src/plugins/TestTools.png)bin711 -> 711 bytes
-rw-r--r--platform/platform-impl/src/icons/plugins/TestTools@2x.png (renamed from community-resources/src/plugins/TestTools@2x.png)bin1503 -> 1503 bytes
-rw-r--r--platform/platform-impl/src/icons/plugins/VersionControls.png (renamed from community-resources/src/plugins/VersionControls.png)bin967 -> 967 bytes
-rw-r--r--platform/platform-impl/src/icons/plugins/VersionControls@2x.png (renamed from community-resources/src/plugins/VersionControls@2x.png)bin2013 -> 2013 bytes
-rw-r--r--platform/platform-impl/src/icons/plugins/WebDevelopment.png (renamed from community-resources/src/plugins/WebDevelopment.png)bin2247 -> 2247 bytes
-rw-r--r--platform/platform-impl/src/icons/plugins/WebDevelopment@2x.png (renamed from community-resources/src/plugins/WebDevelopment@2x.png)bin5416 -> 5416 bytes
-rw-r--r--platform/platform-resources-en/src/messages/ActionsBundle.properties1
-rw-r--r--platform/platform-resources-en/src/messages/ApplicationBundle.properties2
-rw-r--r--platform/platform-resources-en/src/messages/ExecutionBundle.properties1
-rw-r--r--platform/platform-resources-en/src/messages/FindBundle.properties3
-rw-r--r--platform/platform-resources-en/src/messages/InspectionsBundle.properties2
-rw-r--r--platform/platform-resources-en/src/messages/OptionsBundle.properties2
-rw-r--r--platform/platform-resources-en/src/messages/RefactoringBundle.properties1
-rw-r--r--platform/platform-resources/src/META-INF/LangExtensions.xml10
-rw-r--r--platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml2
-rw-r--r--platform/platform-resources/src/META-INF/PlatformExtensions.xml4
-rw-r--r--platform/platform-resources/src/META-INF/PlatformLangPlugin.xml3
-rw-r--r--platform/platform-resources/src/META-INF/PlatformPlugin.xml3
-rw-r--r--platform/platform-resources/src/META-INF/xdebugger.xml1
-rw-r--r--platform/platform-resources/src/brokenPlugins.txt11
-rw-r--r--platform/platform-resources/src/componentSets/Execution.xml12
-rw-r--r--platform/platform-resources/src/componentSets/UICore.xml4
-rw-r--r--platform/platform-resources/src/idea/LangActions.xml2
-rw-r--r--platform/platform-resources/src/idea/PlatformActions.xml3
-rw-r--r--platform/platform-tests/testSrc/com/intellij/execution/process/AnsiEscapeDecoderTest.java55
-rw-r--r--platform/platform-tests/testSrc/com/intellij/history/integration/ui/LocalHistoryActionsTest.java10
-rw-r--r--platform/platform-tests/testSrc/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterKeyPasswordSafeTest.java19
-rw-r--r--platform/platform-tests/testSrc/com/intellij/ide/util/treeView/TreeUiTest.java19
-rw-r--r--platform/platform-tests/testSrc/com/intellij/psi/impl/PsiDocumentManagerImplTest.java (renamed from platform/platform-tests/testSrc/com/intellij/psi/PsiDocumentManagerImplTest.java)33
-rw-r--r--platform/platform-tests/testSrc/com/intellij/ui/tabs/impl/JBTabsDemo.java5
-rw-r--r--platform/projectModel-api/src/com/intellij/openapi/roots/ProjectFileIndex.java20
-rw-r--r--platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryIndex.java9
-rw-r--r--platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ModuleFileIndexImpl.java104
-rw-r--r--platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectFileIndexImpl.java24
-rw-r--r--platform/projectModel-impl/src/com/intellij/openapi/roots/impl/RootIndex.java24
-rw-r--r--platform/remote-servers/agent-rt/src/com/intellij/remoteServer/agent/util/CloudAgentLoggingHandler.java4
-rw-r--r--platform/remote-servers/agent-rt/src/com/intellij/remoteServer/agent/util/CloudAgentWithDeployment.java5
-rw-r--r--platform/remote-servers/agent-rt/src/com/intellij/remoteServer/agent/util/CloudGitAgent.java2
-rw-r--r--platform/remote-servers/agent-rt/src/com/intellij/remoteServer/agent/util/log/LogListener.java4
-rw-r--r--platform/remote-servers/agent-rt/src/com/intellij/remoteServer/agent/util/log/LogPipe.java6
-rw-r--r--platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudGitApplicationRuntime.java6
-rw-r--r--platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudLoggingHandlerImpl.java6
-rw-r--r--platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudSilentLoggingHandlerImpl.java4
-rw-r--r--platform/script-debugger/backend/src/org/jetbrains/rpc/MessageManager.java5
-rw-r--r--platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java10
-rw-r--r--platform/structuralsearch/source/com/intellij/structuralsearch/StructuralSearchProfile.java6
-rw-r--r--platform/structuralsearch/source/com/intellij/structuralsearch/StructuralSearchProfileBase.java6
-rw-r--r--platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/CompiledPattern.java4
-rw-r--r--platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/CompileContext.java4
-rw-r--r--platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/FindInFilesOptimizingSearchHelper.java2
-rw-r--r--platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/PatternCompiler.java47
-rw-r--r--platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java31
-rw-r--r--platform/testFramework/src/com/intellij/mock/Mock.java43
-rw-r--r--platform/testFramework/src/com/intellij/projectView/TestProjectTreeStructure.java2
-rw-r--r--platform/testFramework/src/com/intellij/projectView/TestProjectViewPSIPane.java57
-rw-r--r--platform/testFramework/src/com/intellij/testFramework/EditorTestUtil.java45
-rw-r--r--platform/testFramework/src/com/intellij/testFramework/LightPlatformCodeInsightTestCase.java29
-rw-r--r--platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java5
-rw-r--r--platform/testFramework/src/com/intellij/testFramework/ParsingTestCase.java4
-rw-r--r--platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java1
-rw-r--r--platform/testFramework/src/com/intellij/testFramework/ProjectViewTestUtil.java28
-rw-r--r--platform/testFramework/src/com/intellij/testFramework/TestDataProvider.java14
-rw-r--r--platform/testFramework/src/com/intellij/testFramework/fixtures/CodeInsightTestFixture.java3
-rw-r--r--platform/testFramework/src/com/intellij/testFramework/fixtures/impl/HeavyIdeaTestFixtureImpl.java3
-rw-r--r--platform/testRunner/src/com/intellij/execution/testframework/actions/AbstractRerunFailedTestsAction.java32
-rw-r--r--platform/testRunner/src/com/intellij/execution/testframework/autotest/AutoTestManager.java34
-rw-r--r--platform/testRunner/src/com/intellij/execution/testframework/autotest/ToggleAutoTestAction.java8
-rw-r--r--platform/usageView/src/com/intellij/usages/UsageViewPresentation.java9
-rw-r--r--platform/usageView/src/com/intellij/usages/impl/UsageGroupingRuleProviderImpl.java2
-rw-r--r--platform/util/resources/misc/registry.properties4
-rw-r--r--platform/util/src/com/intellij/icons/AllIcons.java1
-rw-r--r--platform/util/src/com/intellij/openapi/diagnostic/Log.java8
-rw-r--r--platform/util/src/com/intellij/openapi/progress/ProcessCanceledException.java5
-rw-r--r--platform/util/src/com/intellij/openapi/util/TextRange.java10
-rw-r--r--platform/util/src/com/intellij/openapi/util/io/FileUtil.java6
-rw-r--r--platform/util/src/com/intellij/openapi/util/registry/Registry.java45
-rw-r--r--platform/util/src/com/intellij/openapi/util/registry/RegistryValue.java47
-rw-r--r--platform/util/src/com/intellij/openapi/util/text/StringUtil.java3
-rw-r--r--platform/util/src/com/intellij/util/ReflectionUtil.java14
-rw-r--r--platform/util/src/com/intellij/util/containers/ClassMap.java10
-rw-r--r--platform/util/src/com/intellij/util/containers/ContainerUtil.java4
-rw-r--r--platform/util/src/com/intellij/util/containers/TransferToEDTQueue.java8
-rw-r--r--platform/util/src/com/intellij/util/containers/WeakStringInterner.java15
-rw-r--r--platform/util/src/com/intellij/util/io/IntToIntBtree.java85
-rw-r--r--platform/util/src/com/intellij/util/io/PagedFileStorage.java23
-rw-r--r--platform/util/src/com/intellij/util/io/RandomAccessDataFile.java29
-rw-r--r--platform/util/src/com/intellij/util/io/storage/HeavyProcessLatch.java46
-rw-r--r--platform/util/src/com/intellij/util/text/StringSearcher.java6
-rw-r--r--platform/util/src/com/intellij/util/xmlb/MapBinding.java33
-rw-r--r--platform/util/testSrc/com/intellij/openapi/util/io/FileUtilLightTest.java9
-rw-r--r--platform/util/testSrc/com/intellij/util/text/StringUtilTest.java12
-rw-r--r--platform/vcs-api/src/com/intellij/openapi/vcs/ProjectLevelVcsManager.java3
-rw-r--r--platform/vcs-api/src/com/intellij/openapi/vcs/update/FileGroup.java3
-rw-r--r--platform/vcs-api/src/com/intellij/openapi/vcs/update/UpdatedFiles.java4
-rw-r--r--platform/vcs-api/src/com/intellij/vcsUtil/VcsUtil.java12
-rw-r--r--platform/vcs-api/vcs-api-core/src/com/intellij/lifecycle/PeriodicalTasksCloser.java (renamed from platform/vcs-api/src/com/intellij/lifecycle/PeriodicalTasksCloser.java)2
-rw-r--r--platform/vcs-api/vcs-api-core/src/com/intellij/openapi/vcs/FilePath.java (renamed from platform/vcs-api/src/com/intellij/openapi/vcs/FilePath.java)2
-rw-r--r--platform/vcs-api/vcs-api-core/src/com/intellij/openapi/vcs/VcsException.java (renamed from platform/vcs-api/src/com/intellij/openapi/vcs/VcsException.java)2
-rw-r--r--platform/vcs-api/vcs-api-core/src/com/intellij/openapi/vcs/VcsKey.java (renamed from platform/vcs-api/src/com/intellij/openapi/vcs/VcsKey.java)2
-rw-r--r--platform/vcs-api/vcs-api-core/src/com/intellij/openapi/vcs/changes/Change.java (renamed from platform/vcs-api/src/com/intellij/openapi/vcs/changes/Change.java)7
-rw-r--r--platform/vcs-api/vcs-api-core/src/com/intellij/openapi/vcs/changes/ContentRevision.java (renamed from platform/vcs-api/src/com/intellij/openapi/vcs/changes/ContentRevision.java)2
-rw-r--r--platform/vcs-api/vcs-api-core/src/com/intellij/openapi/vcs/changes/MergeTexts.java (renamed from platform/vcs-api/src/com/intellij/openapi/vcs/changes/MergeTexts.java)2
-rw-r--r--platform/vcs-api/vcs-api-core/src/com/intellij/openapi/vcs/history/LongRevisionNumber.java (renamed from platform/vcs-api/src/com/intellij/openapi/vcs/history/LongRevisionNumber.java)2
-rw-r--r--platform/vcs-api/vcs-api-core/src/com/intellij/openapi/vcs/history/VcsRevisionNumber.java (renamed from platform/vcs-api/src/com/intellij/openapi/vcs/history/VcsRevisionNumber.java)2
-rw-r--r--platform/vcs-api/vcs-api-core/src/com/intellij/openapi/vcs/impl/VcsPathPresenter.java (renamed from platform/vcs-api/src/com/intellij/openapi/vcs/impl/VcsPathPresenter.java)2
-rw-r--r--platform/vcs-api/vcs-api-core/src/com/intellij/vcsUtil/Rethrow.java (renamed from platform/vcs-api/src/com/intellij/vcsUtil/Rethrow.java)2
-rw-r--r--platform/vcs-api/vcs-api-core/src/com/intellij/vcsUtil/VcsFilePathUtil.java32
-rw-r--r--platform/vcs-api/vcs-api-core/vcs-api-core.iml15
-rw-r--r--platform/vcs-api/vcs-api.iml1
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/actions/CommonCheckinFilesAction.java6
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/changes/AbstractRefreshablePanel.java2
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangesFragmentedDiffPanel.java2
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/changes/FragmentedDiffRequestFromChange.java4
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CommittedChangesCache.java25
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesBrowserNode.java2
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesModuleGroupingPolicy.java6
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsBackgroundOperationsConfigurable.java77
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsBackgroundOperationsConfigurationPanel.java26
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsGeneralConfigurationConfigurable.java111
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsGeneralConfigurationPanel.java27
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsManagerConfigurable.java33
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/ex/CopyLineStatusRangeAction.java2
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTracker.java701
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTrackerDrawing.java6
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/ex/Range.java84
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/ex/RangesBuilder.java10
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/ex/RollbackLineStatusAction.java41
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/ex/RollbackLineStatusRangeAction.java2
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/ex/SegmentTree.java116
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/ex/ShowLineStatusRangeDiffAction.java18
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ModuleDefaultVcsRootPolicy.java3
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ModuleVcsPathPresenter.java9
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ProjectLevelVcsManagerImpl.java2
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/impl/UpToDateLineNumberProviderImpl.java12
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/impl/projectlevelman/MappingsToRoots.java2
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/impl/projectlevelman/NewMappings.java2
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/update/AbstractCommonUpdateAction.java23
-rw-r--r--platform/vcs-impl/src/com/intellij/vcsUtil/AuthDialog.java3
-rw-r--r--platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogSettings.java18
-rw-r--r--platform/vcs-log/api/vcs-log-api.iml3
-rw-r--r--platform/xdebugger-api/src/com/intellij/xdebugger/XDebugSession.java2
-rw-r--r--platform/xdebugger-api/src/com/intellij/xdebugger/XDebuggerManager.java14
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java87
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerManagerImpl.java47
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerWatchesManager.java13
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/EditBreakpointAction.java4
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XExpressionImpl.java5
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XExpressionState.java7
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEditorLinePainter.java75
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEvaluationDialog.java1
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XValueCompactPresentation.java28
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/common/AbstractValueHint.java3
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/DebuggerFramesList.java8
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XDebugView.java58
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XDebugViewSessionListener.java10
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XDebuggerFramesList.java3
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XFramesView.java128
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XStandaloneVariablesView.java8
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XVariablesView.java50
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XVariablesViewBase.java11
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XWatchesViewImpl.java58
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/BreakpointEditor.java3
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/DebuggerSessionTabBase.java41
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebugSessionTab.java204
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XValueTextProvider.java23
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/TreeInplaceEditor.java24
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XDebuggerTree.java43
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XAddToWatchesAction.java2
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XFetchValueActionBase.java10
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/WatchesRootNode.java11
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XDebuggerTreeNode.java5
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java33
-rw-r--r--platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueTextRendererImpl.java4
-rw-r--r--plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml2
-rw-r--r--plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties6
-rw-r--r--plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/MakeFieldFinalFix.java7
-rw-r--r--plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/internationalization/ImplicitDefaultCharsetUsageInspection.java8
-rw-r--r--plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/logging/LoggerInitializedWithForeignClassInspectionBase.java9
-rw-r--r--plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/logging/PlaceholderCountMatchesArgumentCountInspection.java21
-rw-r--r--plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/MethodMayBeStaticInspectionBase.java181
-rw-r--r--plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/VariablePassedAsArgumentExcludedVisitor.java44
-rw-r--r--plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/VariablePassedAsArgumentVisitor.java28
-rw-r--r--plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryConstructorInspection.java3
-rw-r--r--plugins/InspectionGadgets/src/com/siyeh/ig/performance/MethodMayBeStaticInspection.java164
-rw-r--r--plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspection.java18
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/mismatched_collection_query_update/MismatchedCollectionQueryUpdate.java14
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/mismatched_string_builder_query_update/MismatchedStringBuilderQueryUpdate.java12
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/if_statement_with_identical_branches/IfStatementWithIdenticalBranches.java11
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/errorhandling/try_identical_catches/TryIdenticalCatches.after.java14
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/errorhandling/try_identical_catches/TryIdenticalCatches.java14
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/internationalization/implicit_default_charset_usage/ImplicitDefaultCharsetUsage.java11
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/logging/logger_initialized_with_foreign_class/LoggerInitializedWithForeignClass.java13
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_fully_qualified_name/test1/package-info.java3
-rw-r--r--plugins/InspectionGadgets/testsrc/com/siyeh/ig/internationalization/ImplicitDefaultCharsetUsageInspectionTest.java9
-rw-r--r--plugins/InspectionGadgets/testsrc/com/siyeh/ig/logging/LoggerInitializedWithForeignClassInspectionTest.java51
-rw-r--r--plugins/InspectionGadgets/testsrc/com/siyeh/ig/logging/PlaceholderCountMatchesArgumentCountInspectionTest.java15
-rw-r--r--plugins/InspectionGadgets/testsrc/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspectionTest.java15
-rw-r--r--plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/AdvancedSettingsUI.form2
-rw-r--r--plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/AdvancedSettingsUI.java312
-rw-r--r--plugins/IntentionPowerPak/src/com/siyeh/ipp/fqnames/FullyQualifiedNamePredicate.java8
-rw-r--r--plugins/IntentionPowerPak/src/com/siyeh/ipp/initialization/SplitDeclarationAndInitializationIntention.java24
-rw-r--r--plugins/IntentionPowerPak/test/com/siyeh/ipp/initialization/ArrayInitializer.java3
-rw-r--r--plugins/IntentionPowerPak/test/com/siyeh/ipp/initialization/ArrayInitializer_after.java7
-rw-r--r--plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/initialization/SplitDeclarationAndInitializationIntentionTest.java38
-rw-r--r--plugins/ant/src/com/intellij/lang/ant/config/impl/AntToolWindowFactory.java5
-rw-r--r--plugins/ant/src/com/intellij/lang/ant/dom/AntDomProperty.java26
-rw-r--r--plugins/ant/src/com/intellij/lang/ant/dom/AntResolveInspection.java7
-rw-r--r--plugins/ant/src/com/intellij/lang/ant/validation/AntMissingPropertiesFileInspection.java21
-rw-r--r--plugins/commander/src/com/intellij/ide/commander/CommanderToolWindowFactory.java5
-rw-r--r--plugins/editorconfig/LICENSE.txt21
-rw-r--r--plugins/editorconfig/editorconfig.iml28
-rw-r--r--plugins/editorconfig/lib/editorconfig-core-java.jarbin0 -> 15685 bytes
-rw-r--r--plugins/editorconfig/src/META-INF/plugin.xml30
-rw-r--r--plugins/editorconfig/src/org/editorconfig/Utils.java24
-rw-r--r--plugins/editorconfig/src/org/editorconfig/configmanagement/CodeStyleManager.java184
-rw-r--r--plugins/editorconfig/src/org/editorconfig/configmanagement/EditorSettingsManager.java85
-rw-r--r--plugins/editorconfig/src/org/editorconfig/configmanagement/EncodingManager.java73
-rw-r--r--plugins/editorconfig/src/org/editorconfig/configmanagement/LineEndingsManager.java95
-rw-r--r--plugins/editorconfig/src/org/editorconfig/plugincomponents/ConfigProjectComponent.java61
-rw-r--r--plugins/editorconfig/src/org/editorconfig/plugincomponents/SettingsProviderComponent.java49
-rw-r--r--plugins/generate-tostring/src/org/jetbrains/generate/tostring/velocity/VelocityFactory.java74
-rw-r--r--plugins/git4idea/git4idea.iml3
-rw-r--r--plugins/git4idea/remote-servers-git/remote-servers-git.iml1
-rw-r--r--plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudGitDeploymentRuntime.java4
-rw-r--r--plugins/git4idea/src/git4idea/GitContentRevision.java5
-rw-r--r--plugins/git4idea/src/git4idea/GitRevisionNumber.java3
-rw-r--r--plugins/git4idea/src/git4idea/GitUtil.java12
-rw-r--r--plugins/git4idea/src/git4idea/actions/GitCompareWithBranchAction.java3
-rw-r--r--plugins/git4idea/src/git4idea/annotate/GitAnnotationProvider.java46
-rw-r--r--plugins/git4idea/src/git4idea/annotate/GitFileAnnotation.java143
-rw-r--r--plugins/git4idea/src/git4idea/history/GitDiffFromHistoryHandler.java5
-rw-r--r--plugins/git4idea/src/git4idea/i18n/GitBundle.properties14
-rw-r--r--plugins/git4idea/src/git4idea/push/GitPushDialog.java3
-rw-r--r--plugins/git4idea/src/git4idea/push/GitPushLog.java5
-rw-r--r--plugins/git4idea/src/git4idea/rebase/GitRebaser.java23
-rw-r--r--plugins/git4idea/src/git4idea/repo/GitRepositoryImpl.java8
-rw-r--r--plugins/git4idea/src/git4idea/reset/GitNewResetDialog.java6
-rw-r--r--plugins/git4idea/src/git4idea/ui/GitCommitListPanel.java4
-rw-r--r--plugins/git4idea/src/git4idea/ui/GitUnstashDialog.java7
-rw-r--r--plugins/git4idea/src/git4idea/ui/branch/GitBranchPopup.java45
-rw-r--r--plugins/git4idea/src/git4idea/ui/branch/GitBranchPopupActions.java6
-rw-r--r--plugins/git4idea/src/git4idea/update/GitRebaseUpdater.java32
-rw-r--r--plugins/git4idea/src/git4idea/update/GitUpdateLocallyModifiedDialog.form71
-rw-r--r--plugins/git4idea/src/git4idea/update/GitUpdateLocallyModifiedDialog.java211
-rw-r--r--plugins/git4idea/src/git4idea/util/LocalChangesWouldBeOverwrittenHelper.java45
-rw-r--r--plugins/git4idea/tests/git4idea/history/GitHistoryUtilsTest.java2
-rw-r--r--plugins/git4idea/tests/git4idea/log/GitRefManagerTest.java7
-rw-r--r--plugins/github/github.iml3
-rw-r--r--plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java6
-rw-r--r--plugins/google-app-engine/source/com/intellij/appengine/facet/AppEngineFacetEditor.java3
-rw-r--r--plugins/gradle/src/META-INF/plugin.xml1
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/execution/test/runner/events/BeforeSuiteEvent.java2
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/execution/test/runner/events/BeforeTestEvent.java14
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleSettings.java62
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleSystemSettings.java92
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/annotator/inspections/GroovySingletonAnnotationInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyAssignabilityCheckInspection.java19
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyAssignmentCanBeOperatorAssignmentInspection.java3
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyAssignmentToForLoopParameterInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyNestedAssignmentInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyResultOfAssignmentUsedInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyConstructorNamedArgumentsInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyDivideByZeroInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyDocCheckInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyInfiniteLoopStatementInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyInfiniteRecursionInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyLabeledStatementInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyNonShortCircuitBooleanInspection.java3
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyResultOfObjectAllocationIgnoredInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/NewInstanceOfSingletonInspection.java3
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/ClashingTraitMethodsInspectionBase.java153
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GrDeprecatedAPIUsageInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GrPackageInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GrUnusedIncDecInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyConditionalInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyDoubleNegationInspection.java3
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyEmptyStatementBodyInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyNegatedConditionalInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyNegatedIfInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyNestedConditionalInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyNestedSwitchInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyOctalIntegerInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyOverlyComplexArithmeticExpressionInspectionBase.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyOverlyComplexBooleanExpressionInspectionBase.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyPointlessBooleanInspection.java3
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyResultOfIncrementOrDecrementUsedInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyBreakInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyConditionalCanBeElvisInspection.java3
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyConditionalWithIdenticalBranchesInspection.java3
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyConstantConditionalInspection.java3
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyConstantIfStatementInspection.java3
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyContinueInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyFallthroughInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyIfStatementWithIdenticalBranchesInspection.java3
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyIfStatementWithTooManyBranchesInspectionBase.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyLoopStatementThatDoesntLoopInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyReturnFromClosureCanBeImplicitInspection.java3
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovySwitchStatementWithNoDefaultInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyTrivialConditionalInspection.java3
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyTrivialIfInspection.java3
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyUnnecessaryContinueInspection.java3
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyUnnecessaryReturnInspection.java3
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyContinueOrBreakFromFinallyBlockInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyEmptyFinallyBlockInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyEmptyTryBlockInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyReturnFromFinallyBlockInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyThrowFromFinallyBlockInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyUnusedCatchParameterInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/gpath/GroovyListGetCanBeKeyedAccessInspection.java3
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/gpath/GroovyListSetCanBeKeyedAccessInspection.java3
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/gpath/GroovyMapGetCanBeKeyedAccessInspection.java3
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/gpath/GroovyMapPutCanBeKeyedAccessInspection.java3
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyMethodParameterCountInspectionBase.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyMethodWithMoreThanThreeNegationsInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyMultipleReturnPointsPerMethodInspectionBase.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyOverlyComplexMethodInspectionBase.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyOverlyLongMethodInspectionBase.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyOverlyNestedMethodInspectionBase.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyConstantNamingConventionInspection.java3
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyInstanceMethodNamingConventionInspection.java3
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyInstanceVariableNamingConventionInspection.java3
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyLocalVariableNamingConventionInspection.java3
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyParameterNamingConventionInspection.java3
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyStaticMethodNamingConventionInspection.java3
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyStaticVariableNamingConventionInspection.java3
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyAccessToStaticFieldLockedOnInstanceInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyBusyWaitInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyDoubleCheckedLockingInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyEmptySyncBlockInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyNestedSynchronizedStatementInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyNotifyWhileNotSynchronizedInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyPublicFieldAccessedInSynchronizedContextInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovySynchronizationOnNonFinalFieldInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovySynchronizationOnThisInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovySynchronizationOnVariableInitializedWithLiteralInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovySynchronizedMethodInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovySystemRunFinalizersOnExitInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyThreadStopSuspendResumeInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyUnconditionalWaitInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyUnsynchronizedMethodOverridesSynchronizedMethodInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyWaitCallNotInLoopInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyWaitWhileNotSynchronizedInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyWhileLoopSpinsOnFieldInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/untypedUnresolvedAccess/GrUnresolvedAccessChecker.java7
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/validity/GroovyDuplicateSwitchBranchInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/validity/GroovyUnreachableStatementInspection.java1
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/dsl/GroovyDslFileIndex.java2
-rw-r--r--plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrDelegatesToUtil.java3
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/codeInsight/GroovyMarkerTypes.java37
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyQuickFixFactoryImpl.java3
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/confusing/ClashingTraitMethodsInspection.java161
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/codeStyle/GroovyLanguageCodeStyleSettingsProvider.java1
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/griffon/GriffonDebuggerRunner.java15
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovySmartCompletionContributor.java8
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/projectView/MvcProjectViewPane.java1
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/projectView/MvcToolWindowDescriptor.java2
-rw-r--r--plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/memberPullUp/GrPullUpHandler.java14
-rw-r--r--plugins/groovy/structuralsearch-groovy/testSrc/com/intellij/structuralsearch/GroovyStructuralSearchTest.java1
-rw-r--r--plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTestCase.java3
-rw-r--r--plugins/groovy/test/org/jetbrains/plugins/groovy/lang/formatter/WrappingTest.groovy3
-rw-r--r--plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveWithDelegatesToTest.groovy18
-rw-r--r--plugins/hg4idea/hg4idea.iml3
-rw-r--r--plugins/hg4idea/src/META-INF/plugin.xml1
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAbstractGlobalAction.java29
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAbstractGlobalSingleRepoAction.java47
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/action/HgActionUtil.java58
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchesAction.java2
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCreateTagAction.java2
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/action/HgMerge.java2
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/action/HgProcessRebaseAction.java4
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/action/HgPullAction.java2
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/action/HgPushAction.java8
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/action/HgRunConflictResolverAction.java2
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/action/HgUpdateToAction.java2
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/command/HgIdentifyCommand.java2
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/command/HgOutgoingCommand.java27
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/execution/HgCommandAuthenticator.java39
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/execution/HgRemoteCommandExecutor.java26
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/log/HgHistoryUtil.java42
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/log/HgLogProvider.java12
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/provider/commit/HgCheckinEnvironment.java9
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/push/HgOutgoingCommitsProvider.java90
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPushOptionsPanel.java51
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPushSource.java38
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPushSupport.java109
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPusher.java (renamed from plugins/hg4idea/src/org/zmlx/hg4idea/HgPusher.java)95
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/push/HgTarget.java34
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/push/HgVcsPushOptionValue.java22
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepositoryImpl.java7
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/util/HgErrorUtil.java13
-rw-r--r--plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java10
-rw-r--r--plugins/java-i18n/src/META-INF/plugin.xml1
-rw-r--r--plugins/java-i18n/src/com/intellij/refactoring/inline/InlinePropertyHandler.java120
-rw-r--r--plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderEditor.java39
-rw-r--r--plugins/junit/src/com/intellij/execution/junit/TestPackage.java13
-rw-r--r--plugins/junit_rt/src/com/intellij/junit4/JUnit4IdeaTestRunner.java16
-rw-r--r--plugins/junit_rt/src/com/intellij/junit4/JUnit4TestRunnerUtil.java10
-rw-r--r--plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenResumeAction.java2
-rw-r--r--plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunConfigurationType.java22
-rw-r--r--plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/actions/MavenRunConfigurationMenu.java8
-rw-r--r--plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenProjectImportProvider.java14
-rw-r--r--plugins/properties/properties-psi-api/resources/messages/PropertiesBundle.properties5
-rw-r--r--plugins/properties/properties-psi-impl/properties-psi-impl.iml2
-rw-r--r--plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/PropertiesImplUtil.java8
-rw-r--r--plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/editor/ResourceBundleEditorViewElement.java2
-rw-r--r--plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/editor/ResourceBundlePropertyStructureViewElement.java5
-rw-r--r--plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/structureView/GroupByWordPrefixes.java13
-rw-r--r--plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/structureView/PropertiesPrefixGroup.java18
-rw-r--r--plugins/properties/src/com/intellij/lang/properties/editor/NewPropertyAction.java2
-rw-r--r--plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleAsVirtualFile.java (renamed from plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/editor/ResourceBundleAsVirtualFile.java)0
-rw-r--r--plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleEditor.java62
-rw-r--r--plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleStructureViewComponent.java18
-rw-r--r--plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleUtil.java (renamed from plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/editor/ResourceBundleUtil.java)0
-rw-r--r--plugins/properties/src/com/intellij/lang/properties/refactoring/rename/ResourceBundleFromEditorRenameHandler.java2
-rw-r--r--plugins/svn4idea/src/META-INF/plugin.xml14
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/RootsToWorkingCopies.java4
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBundle.properties1
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProviderContext.java9
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java1
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileUrlMappingImpl.java15
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/SvnScopeZipper.java94
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java11
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java18
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/actions/AbstractIntegrateChangesAction.java1
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SvnMergeProvider.java10
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/SvnAnnotationProvider.java4
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/auth/SvnAuthenticationNotifier.java2
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/BranchConfigurationDialog.form (renamed from plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/BranchConfigurationDialog.form)2
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/BranchConfigurationDialog.java (renamed from plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/BranchConfigurationDialog.java)12
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/BranchesLoader.java64
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/ConfigureBranchesAction.java (renamed from plugins/svn4idea/src/org/jetbrains/idea/svn/actions/ConfigureBranchesAction.java)4
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/CreateBranchOrTagAction.java (renamed from plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CreateBranchOrTagAction.java)4
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/CreateBranchOrTagDialog.form (renamed from plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/CreateBranchOrTagDialog.form)2
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/CreateBranchOrTagDialog.java (renamed from plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/CreateBranchOrTagDialog.java)5
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/DefaultBranchConfigInitializer.java155
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/DefaultConfigLoader.java113
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/InfoStorage.java14
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/NewRootBunch.java186
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SelectBranchPopup.java (renamed from plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SelectBranchPopup.java)18
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchConfigManager.java47
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchConfiguration.java (renamed from plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBranchConfiguration.java)21
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchConfigurationManager.java (renamed from plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBranchConfigurationManager.java)207
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchConfigurationNew.java3
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchItem.java (renamed from plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SvnBranchItem.java)2
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchMapperManager.java (renamed from plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBranchMapperManager.java)23
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnLoadedBranchesStorage.java (renamed from plugins/svn4idea/src/org/jetbrains/idea/svn/SvnLoadedBrachesStorage.java)28
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/UrlSerializationHelper.java111
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnCheckinEnvironment.java2
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/UpdateOutputLineConverter.java103
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/CopiesPanel.java3
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/PropertiesComponent.java3
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserComponent.java2
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CompareWithBranchAction.java2
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/history/LoadedRevisionsCache.java30
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCommittedChangesProvider.java2
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnFileRevision.java47
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java4
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnMergeInfoRootPanelManual.java4
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/history/WcInfoLoader.java3
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/info/Info.java38
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/IntegratedSelectedOptionsDialog.java1
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SourceUrlCorrectionTask.java2
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SvnIntegrateChangesActionPerformer.java2
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SvnIntegrateChangesTask.java46
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/BranchInfo.java13
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneRecursiveShotMergeInfoWorker.java8
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/properties/CmdPropertyClient.java20
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/rollback/SvnRollbackEnvironment.java8
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/status/CmdStatusClient.java1
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/update/AbstractSvnUpdateIntegrateEnvironment.java2
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateEnvironment.java2
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateRootOptionsPanel.java2
-rw-r--r--plugins/svn4idea/src/org/jetbrains/idea/svn/update/UpdateEventHandler.java35
-rw-r--r--plugins/svn4idea/testSource/org/jetbrains/idea/SvnTestCase.java9
-rw-r--r--plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnAnnotationIsClosedTest.java11
-rw-r--r--plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnQuickMergeTest.java3
-rw-r--r--plugins/tasks/tasks-core/src/com/intellij/tasks/pivotal/PivotalTrackerRepository.java2
-rw-r--r--plugins/terminal/src/org/jetbrains/plugins/terminal/AbstractTerminalRunner.java3
-rw-r--r--plugins/terminal/src/org/jetbrains/plugins/terminal/TerminalToolWindowFactory.java18
-rw-r--r--plugins/ui-designer/src/com/intellij/uiDesigner/actions/PreviewFormAction.java11
-rw-r--r--plugins/ui-designer/src/com/intellij/uiDesigner/snapShooter/CreateSnapShotAction.java16
-rw-r--r--plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltCommandLineState.java11
-rw-r--r--python/edu/build/build.xml46
-rw-r--r--python/edu/build/desktop.ini100
-rw-r--r--python/edu/build/idea.nsi1228
-rw-r--r--python/edu/build/plugin-list.txt6
-rw-r--r--python/edu/build/pycharm_edu_build.gant74
-rw-r--r--python/edu/build/resources/logo.bmpbin154544 -> 0 bytes
-rw-r--r--python/edu/build/resources/logo.pngbin0 -> 46439 bytes
-rw-r--r--python/edu/learn-python/gen/icons/StudyIcons.java29
-rw-r--r--python/edu/learn-python/learn-python.iml20
-rw-r--r--python/edu/learn-python/resources/META-INF/plugin.xml73
-rw-r--r--python/edu/learn-python/resources/com/jetbrains/python/edu/user_tester.py58
-rw-r--r--python/edu/learn-python/resources/courses/introduction_course.zipbin0 -> 93360 bytes
-rw-r--r--python/edu/learn-python/resources/icons/com/jetbrains/python/edu/Run.pngbin0 -> 1260 bytes
-rw-r--r--python/edu/learn-python/resources/icons/com/jetbrains/python/edu/WatchInput.pngbin0 -> 1328 bytes
-rw-r--r--python/edu/learn-python/resources/icons/com/jetbrains/python/edu/add.pngbin0 -> 213 bytes
-rw-r--r--python/edu/learn-python/resources/icons/com/jetbrains/python/edu/checked.pngbin0 -> 606 bytes
-rw-r--r--python/edu/learn-python/resources/icons/com/jetbrains/python/edu/failed.pngbin0 -> 549 bytes
-rw-r--r--python/edu/learn-python/resources/icons/com/jetbrains/python/edu/icon.jpgbin0 -> 4389 bytes
-rw-r--r--python/edu/learn-python/resources/icons/com/jetbrains/python/edu/next.pngbin0 -> 1345 bytes
-rw-r--r--python/edu/learn-python/resources/icons/com/jetbrains/python/edu/playground.pngbin0 -> 855 bytes
-rw-r--r--python/edu/learn-python/resources/icons/com/jetbrains/python/edu/prev.pngbin0 -> 1354 bytes
-rw-r--r--python/edu/learn-python/resources/icons/com/jetbrains/python/edu/refresh.pngbin0 -> 657 bytes
-rw-r--r--python/edu/learn-python/resources/icons/com/jetbrains/python/edu/refresh24.pngbin0 -> 1569 bytes
-rw-r--r--python/edu/learn-python/resources/icons/com/jetbrains/python/edu/resolve.pngbin0 -> 342 bytes
-rw-r--r--python/edu/learn-python/resources/icons/com/jetbrains/python/edu/resolve_dark.pngbin0 -> 449 bytes
-rw-r--r--python/edu/learn-python/resources/icons/com/jetbrains/python/edu/showHint.pngbin0 -> 1218 bytes
-rw-r--r--python/edu/learn-python/resources/icons/com/jetbrains/python/edu/unchecked.pngbin0 -> 604 bytes
-rw-r--r--python/edu/learn-python/src/com/jetbrains/python/edu/StudyDirectoryProjectGenerator.java393
-rw-r--r--python/edu/learn-python/src/com/jetbrains/python/edu/StudyDocumentListener.java65
-rw-r--r--python/edu/learn-python/src/com/jetbrains/python/edu/StudyEditorFactoryListener.java100
-rw-r--r--python/edu/learn-python/src/com/jetbrains/python/edu/StudyHighlightErrorFilter.java23
-rw-r--r--python/edu/learn-python/src/com/jetbrains/python/edu/StudyInitialConfigurator.java67
-rw-r--r--python/edu/learn-python/src/com/jetbrains/python/edu/StudyInstructionPainter.java47
-rw-r--r--python/edu/learn-python/src/com/jetbrains/python/edu/StudyResourceManger.java5
-rw-r--r--python/edu/learn-python/src/com/jetbrains/python/edu/StudyTaskManager.java296
-rw-r--r--python/edu/learn-python/src/com/jetbrains/python/edu/StudyUtils.java151
-rw-r--r--python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyCheckAction.java340
-rw-r--r--python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyEditInputAction.java213
-rw-r--r--python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyNextStudyTaskAction.java24
-rw-r--r--python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyNextWindowAction.java32
-rw-r--r--python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyPrevWindowAction.java34
-rw-r--r--python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyPreviousStudyTaskAction.java25
-rw-r--r--python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyRefreshTaskAction.java122
-rw-r--r--python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyRunAction.java89
-rw-r--r--python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyShowHintAction.java95
-rw-r--r--python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyTaskNavigationAction.java97
-rw-r--r--python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyWindowNavigationAction.java65
-rw-r--r--python/edu/learn-python/src/com/jetbrains/python/edu/course/Course.java104
-rw-r--r--python/edu/learn-python/src/com/jetbrains/python/edu/course/CourseInfo.java52
-rw-r--r--python/edu/learn-python/src/com/jetbrains/python/edu/course/Lesson.java109
-rw-r--r--python/edu/learn-python/src/com/jetbrains/python/edu/course/LessonInfo.java60
-rw-r--r--python/edu/learn-python/src/com/jetbrains/python/edu/course/Stateful.java6
-rw-r--r--python/edu/learn-python/src/com/jetbrains/python/edu/course/StudyStatus.java8
-rw-r--r--python/edu/learn-python/src/com/jetbrains/python/edu/course/Task.java201
-rw-r--r--python/edu/learn-python/src/com/jetbrains/python/edu/course/TaskFile.java228
-rw-r--r--python/edu/learn-python/src/com/jetbrains/python/edu/course/TaskWindow.java177
-rw-r--r--python/edu/learn-python/src/com/jetbrains/python/edu/course/UserTest.java41
-rw-r--r--python/edu/learn-python/src/com/jetbrains/python/edu/editor/StudyEditor.java347
-rw-r--r--python/edu/learn-python/src/com/jetbrains/python/edu/editor/StudyFileEditorProvider.java64
-rw-r--r--python/edu/learn-python/src/com/jetbrains/python/edu/projectView/StudyDirectoryNode.java112
-rw-r--r--python/edu/learn-python/src/com/jetbrains/python/edu/projectView/StudyTreeStructureProvider.java83
-rw-r--r--python/edu/learn-python/src/com/jetbrains/python/edu/ui/StudyCondition.java25
-rw-r--r--python/edu/learn-python/src/com/jetbrains/python/edu/ui/StudyNewProjectPanel.form84
-rw-r--r--python/edu/learn-python/src/com/jetbrains/python/edu/ui/StudyNewProjectPanel.java196
-rw-r--r--python/edu/learn-python/src/com/jetbrains/python/edu/ui/StudyProgressBar.java92
-rw-r--r--python/edu/learn-python/src/com/jetbrains/python/edu/ui/StudyTestContentPanel.java67
-rw-r--r--python/edu/learn-python/src/com/jetbrains/python/edu/ui/StudyToolWindowFactory.java81
-rw-r--r--python/edu/learn-python/testData/course.json130
-rw-r--r--python/edu/learn-python/tests/JsonParserTest.java37
-rw-r--r--python/edu/main_pycharm_edu.iml2
-rw-r--r--python/edu/resources/idea/PyCharmEduApplicationInfo.xml6
-rw-r--r--python/edu/resources/pycharm_edu_about.pngbin0 -> 86973 bytes
-rw-r--r--python/edu/resources/pycharm_edu_about@2x.pngbin0 -> 193243 bytes
-rw-r--r--python/edu/resources/pycharm_edu_logo.pngbin0 -> 102281 bytes
-rw-r--r--python/edu/resources/pycharm_edu_logo@2x.pngbin0 -> 223425 bytes
-rw-r--r--python/edu/src/META-INF/PyCharmEduPlugin.xml8
-rw-r--r--python/edu/src/com/jetbrains/python/edu/PyCharmEduInitialConfigurator.java91
-rw-r--r--python/gen/icons/PythonIcons.java2
-rw-r--r--python/helpers/pycharm/_bdd_utils.py11
-rw-r--r--python/helpers/pycharm/behave_runner.py13
-rw-r--r--python/helpers/pycharm/docrunner.py6
-rw-r--r--python/helpers/pycharm_generator_utils/module_redeclarator.py2
-rw-r--r--python/helpers/pycharm_generator_utils/util_methods.py19
-rw-r--r--python/helpers/pydev/LICENSE203
-rw-r--r--python/helpers/pydev/README.md2
-rw-r--r--python/helpers/pydev/_pydev_execfile.py38
-rw-r--r--python/helpers/pydev/_pydev_getopt.py130
-rw-r--r--python/helpers/pydev/_pydev_imports_tipper.py118
-rw-r--r--python/helpers/pydev/_pydev_imps/__init__.py0
-rw-r--r--python/helpers/pydev/_pydev_imps/_pydev_BaseHTTPServer.py604
-rw-r--r--python/helpers/pydev/_pydev_imps/_pydev_Queue.py244
-rw-r--r--python/helpers/pydev/_pydev_imps/_pydev_SimpleXMLRPCServer.py610
-rw-r--r--python/helpers/pydev/_pydev_imps/_pydev_SocketServer.py715
-rw-r--r--python/helpers/pydev/_pydev_imps/_pydev_execfile.py18
-rw-r--r--python/helpers/pydev/_pydev_imps/_pydev_inspect.py794
-rw-r--r--python/helpers/pydev/_pydev_imps/_pydev_select.py1
-rw-r--r--python/helpers/pydev/_pydev_imps/_pydev_socket.py1
-rw-r--r--python/helpers/pydev/_pydev_imps/_pydev_thread.py4
-rw-r--r--python/helpers/pydev/_pydev_imps/_pydev_time.py1
-rw-r--r--python/helpers/pydev/_pydev_imps/_pydev_xmlrpclib.py1493
-rw-r--r--python/helpers/pydev/_pydev_jy_imports_tipper.py170
-rw-r--r--python/helpers/pydev/_pydev_thread.py1
-rw-r--r--python/helpers/pydev/_pydev_threading.py10
-rw-r--r--python/helpers/pydev/_pydev_tipper_common.py29
-rw-r--r--python/helpers/pydev/_pydev_xmlrpc_hook.py74
-rw-r--r--python/helpers/pydev/_pydevd_re.py11
-rw-r--r--python/helpers/pydev/django_debug.py23
-rw-r--r--python/helpers/pydev/django_frame.py57
-rw-r--r--python/helpers/pydev/merge_pydev_pycharm.txt138
-rw-r--r--python/helpers/pydev/pycompletion.py6
-rw-r--r--python/helpers/pydev/pycompletionserver.py14
-rw-r--r--python/helpers/pydev/pydev_console_utils.py165
-rw-r--r--python/helpers/pydev/pydev_coverage.py54
-rw-r--r--python/helpers/pydev/pydev_imports.py28
-rw-r--r--python/helpers/pydev/pydev_ipython/inputhookglut.py3
-rw-r--r--python/helpers/pydev/pydev_ipython/inputhookpyglet.py3
-rw-r--r--python/helpers/pydev/pydev_ipython/inputhookqt4.py8
-rw-r--r--python/helpers/pydev/pydev_ipython/inputhookwx.py2
-rw-r--r--python/helpers/pydev/pydev_ipython_console.py62
-rw-r--r--python/helpers/pydev/pydev_ipython_console_010.py129
-rw-r--r--python/helpers/pydev/pydev_ipython_console_011.py422
-rw-r--r--python/helpers/pydev/pydev_localhost.py15
-rw-r--r--python/helpers/pydev/pydev_monkey.py220
-rw-r--r--python/helpers/pydev/pydev_override.py49
-rw-r--r--python/helpers/pydev/pydev_pysrc.py1
-rw-r--r--python/helpers/pydev/pydev_runfiles.py831
-rw-r--r--python/helpers/pydev/pydev_runfiles_coverage.py76
-rw-r--r--python/helpers/pydev/pydev_runfiles_nose.py180
-rw-r--r--python/helpers/pydev/pydev_runfiles_parallel.py298
-rw-r--r--python/helpers/pydev/pydev_runfiles_parallel_client.py214
-rw-r--r--python/helpers/pydev/pydev_runfiles_pytest2.py230
-rw-r--r--python/helpers/pydev/pydev_runfiles_unittest.py174
-rw-r--r--python/helpers/pydev/pydev_runfiles_xml_rpc.py269
-rw-r--r--python/helpers/pydev/pydev_sitecustomize/__not_in_default_pythonpath.txt1
-rw-r--r--python/helpers/pydev/pydev_sitecustomize/sitecustomize.py192
-rw-r--r--python/helpers/pydev/pydev_umd.py172
-rw-r--r--python/helpers/pydev/pydevconsole.py132
-rw-r--r--python/helpers/pydev/pydevd.py834
-rw-r--r--python/helpers/pydev/pydevd_additional_thread_info.py43
-rw-r--r--python/helpers/pydev/pydevd_breakpoints.py141
-rw-r--r--python/helpers/pydev/pydevd_comm.py387
-rw-r--r--python/helpers/pydev/pydevd_console.py212
-rw-r--r--python/helpers/pydev/pydevd_constants.py53
-rw-r--r--python/helpers/pydev/pydevd_dont_trace.py127
-rw-r--r--python/helpers/pydev/pydevd_file_utils.py134
-rw-r--r--python/helpers/pydev/pydevd_frame.py451
-rw-r--r--python/helpers/pydev/pydevd_io.py8
-rw-r--r--python/helpers/pydev/pydevd_referrers.py238
-rw-r--r--python/helpers/pydev/pydevd_resolver.py56
-rw-r--r--python/helpers/pydev/pydevd_save_locals.py11
-rw-r--r--python/helpers/pydev/pydevd_signature.py8
-rw-r--r--python/helpers/pydev/pydevd_stackless.py7
-rw-r--r--python/helpers/pydev/pydevd_traceproperty.py108
-rw-r--r--python/helpers/pydev/pydevd_tracing.py2
-rw-r--r--python/helpers/pydev/pydevd_vars.py174
-rw-r--r--python/helpers/pydev/pydevd_xml.py47
-rw-r--r--python/helpers/pydev/runfiles.py707
-rw-r--r--python/helpers/pydev/stubs/_django_manager_body.py414
-rw-r--r--python/helpers/pydev/stubs/_get_tips.py280
-rw-r--r--python/helpers/pydev/test_debug.py2
-rw-r--r--python/helpers/pydev/test_pydevd_reload/test_pydevd_reload.py516
-rw-r--r--python/helpers/pydev/tests/__not_in_default_pythonpath.txt1
-rw-r--r--python/helpers/pydev/tests/check_pydevconsole.py105
-rw-r--r--python/helpers/pydev/tests/test_get_referrers.py139
-rw-r--r--python/helpers/pydev/tests/test_jyserver.py165
-rw-r--r--python/helpers/pydev/tests/test_jysimpleTipper.py255
-rw-r--r--python/helpers/pydev/tests/test_pydev_ipython_010.py80
-rw-r--r--python/helpers/pydev/tests/test_pydev_ipython_011.py193
-rw-r--r--python/helpers/pydev/tests/test_pydevconsole.py231
-rw-r--r--python/helpers/pydev/tests/test_pyserver.py173
-rw-r--r--python/helpers/pydev/tests/test_simpleTipper.py209
-rw-r--r--python/helpers/pydev/tests_mainloop/README4
-rw-r--r--python/helpers/pydev/tests_mainloop/__not_in_default_pythonpath.txt1
-rw-r--r--python/helpers/pydev/tests_mainloop/gui-glut.py50
-rw-r--r--python/helpers/pydev/tests_mainloop/gui-gtk.py34
-rw-r--r--python/helpers/pydev/tests_mainloop/gui-gtk3.py32
-rw-r--r--python/helpers/pydev/tests_mainloop/gui-pyglet.py27
-rw-r--r--python/helpers/pydev/tests_mainloop/gui-qt.py35
-rw-r--r--python/helpers/pydev/tests_mainloop/gui-tk.py31
-rw-r--r--python/helpers/pydev/tests_mainloop/gui-wx.py101
-rw-r--r--python/helpers/pydev/tests_python/__not_in_default_pythonpath.txt1
-rw-r--r--python/helpers/pydev/tests_python/_debugger_case1.py61
-rw-r--r--python/helpers/pydev/tests_python/_debugger_case10.py18
-rw-r--r--python/helpers/pydev/tests_python/_debugger_case13.py43
-rw-r--r--python/helpers/pydev/tests_python/_debugger_case14.py29
-rw-r--r--python/helpers/pydev/tests_python/_debugger_case15.py29
-rw-r--r--python/helpers/pydev/tests_python/_debugger_case15_execfile.py1
-rw-r--r--python/helpers/pydev/tests_python/_debugger_case16.py12
-rw-r--r--python/helpers/pydev/tests_python/_debugger_case17.py38
-rw-r--r--python/helpers/pydev/tests_python/_debugger_case18.py23
-rw-r--r--python/helpers/pydev/tests_python/_debugger_case19.py10
-rw-r--r--python/helpers/pydev/tests_python/_debugger_case2.py24
-rw-r--r--python/helpers/pydev/tests_python/_debugger_case3.py8
-rw-r--r--python/helpers/pydev/tests_python/_debugger_case4.py8
-rw-r--r--python/helpers/pydev/tests_python/_debugger_case56.py9
-rw-r--r--python/helpers/pydev/tests_python/_debugger_case7.py8
-rw-r--r--python/helpers/pydev/tests_python/_debugger_case89.py16
-rw-r--r--python/helpers/pydev/tests_python/test_additional_thread_info.py111
-rw-r--r--python/helpers/pydev/tests_python/test_debugger.py1205
-rw-r--r--python/helpers/pydev/tests_python/test_pydev_monkey.py21
-rw-r--r--python/helpers/pydev/tests_python/test_save_locals.py99
-rw-r--r--python/helpers/pydev/tests_runfiles/not_in_default_pythonpath.txt1
-rw-r--r--python/helpers/pydev/tests_runfiles/samples/.cvsignore2
-rw-r--r--python/helpers/pydev/tests_runfiles/samples/__init__.py0
-rw-r--r--python/helpers/pydev/tests_runfiles/samples/nested_dir/__init__.py1
-rw-r--r--python/helpers/pydev/tests_runfiles/samples/nested_dir/nested2/__init__.py1
-rw-r--r--python/helpers/pydev/tests_runfiles/samples/nested_dir/nested2/deep_nest_test.py22
-rw-r--r--python/helpers/pydev/tests_runfiles/samples/nested_dir/nested2/non_test_file.py3
-rw-r--r--python/helpers/pydev/tests_runfiles/samples/nested_dir/nested3/__init__.py1
-rw-r--r--python/helpers/pydev/tests_runfiles/samples/nested_dir/nested3/junk.txt1
-rw-r--r--python/helpers/pydev/tests_runfiles/samples/nested_dir/nested3/non_test_file.py3
-rw-r--r--python/helpers/pydev/tests_runfiles/samples/nested_dir/non_test_file.py3
-rw-r--r--python/helpers/pydev/tests_runfiles/samples/nested_dir/simple4_test.py16
-rw-r--r--python/helpers/pydev/tests_runfiles/samples/non_test_file.py3
-rw-r--r--python/helpers/pydev/tests_runfiles/samples/simple2_test.py16
-rw-r--r--python/helpers/pydev/tests_runfiles/samples/simple3_test.py16
-rw-r--r--python/helpers/pydev/tests_runfiles/samples/simpleClass_test.py14
-rw-r--r--python/helpers/pydev/tests_runfiles/samples/simpleModule_test.py16
-rw-r--r--python/helpers/pydev/tests_runfiles/samples/simple_test.py45
-rw-r--r--python/helpers/pydev/tests_runfiles/test_pydevd_property.py134
-rw-r--r--python/helpers/pydev/tests_runfiles/test_pydevdio.py40
-rw-r--r--python/helpers/pydev/tests_runfiles/test_runfiles.py393
-rw-r--r--python/ide/src/com/jetbrains/python/PythonSdkChooserCombo.java7
-rw-r--r--python/ide/src/com/jetbrains/python/newProject/actions/AbstractProjectSettingsStep.java40
-rw-r--r--python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificAction.java1
-rw-r--r--python/openapi/src/com/jetbrains/python/newProject/PythonProjectGenerator.java5
-rw-r--r--python/openapi/src/com/jetbrains/python/templateLanguages/TemplateLanguagePanel.java27
-rw-r--r--python/pluginResources/META-INF/plugin.xml7
-rw-r--r--python/pluginSrc/META-INF/python-plugin-core.xml7
-rw-r--r--python/pluginSrc/com/jetbrains/python/run/RunPythonConsoleAction.java58
-rw-r--r--python/psi-api/src/com/jetbrains/python/PyNames.java30
-rw-r--r--python/psi-api/src/com/jetbrains/python/psi/PyElementGenerator.java30
-rw-r--r--python/psi-api/src/com/jetbrains/python/psi/PyStatementPart.java8
-rw-r--r--python/pydevSrc/com/jetbrains/python/debugger/pydev/RemoteDebugger.java14
-rw-r--r--python/resources/icons/com/jetbrains/python/pythonConsole.pngbin0 -> 714 bytes
-rw-r--r--python/resources/icons/com/jetbrains/python/pythonConsole@2x.pngbin0 -> 1530 bytes
-rw-r--r--python/resources/icons/com/jetbrains/python/pythonConsole@2x_dark.pngbin0 -> 1519 bytes
-rw-r--r--python/resources/icons/com/jetbrains/python/pythonConsoleToolWindow.pngbin0 -> 558 bytes
-rw-r--r--python/resources/icons/com/jetbrains/python/pythonConsoleToolWindow@2x.pngbin0 -> 1360 bytes
-rw-r--r--python/resources/icons/com/jetbrains/python/pythonConsoleToolWindow@2x_dark.pngbin0 -> 1346 bytes
-rw-r--r--python/resources/icons/com/jetbrains/python/pythonConsoleToolWindow_dark.pngbin0 -> 590 bytes
-rw-r--r--python/resources/icons/com/jetbrains/python/pythonConsole_dark.pngbin0 -> 725 bytes
-rw-r--r--python/resources/idea/PyCharmCoreApplicationInfo.xml2
-rw-r--r--python/resources/pycharm_core_logo.pngbin150234 -> 36429 bytes
-rw-r--r--python/resources/pycharm_core_logo@2x.pngbin483297 -> 67503 bytes
-rw-r--r--python/src/META-INF/PyCharmCorePlugin.xml2
-rw-r--r--python/src/META-INF/pycharm-community.xml11
-rw-r--r--python/src/META-INF/pycharm-core.xml10
-rw-r--r--python/src/META-INF/python-core.xml19
-rw-r--r--python/src/com/jetbrains/python/actions/PyExecuteSelectionAction.java (renamed from python/src/com/jetbrains/python/actions/ExecuteInConsoleAction.java)49
-rw-r--r--python/src/com/jetbrains/python/buildout/BuildoutConfigPanel.java3
-rw-r--r--python/src/com/jetbrains/python/codeInsight/imports/AddImportHelper.java69
-rw-r--r--python/src/com/jetbrains/python/codeInsight/imports/AutoImportQuickFix.java34
-rw-r--r--python/src/com/jetbrains/python/codeInsight/imports/ImportCandidateHolder.java75
-rw-r--r--python/src/com/jetbrains/python/codeInsight/imports/ImportFromExistingAction.java30
-rw-r--r--python/src/com/jetbrains/python/codeInsight/imports/PyImportOptimizer.java2
-rw-r--r--python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibTypeProvider.java19
-rw-r--r--python/src/com/jetbrains/python/configuration/PyIntegratedToolsConfigurable.java3
-rw-r--r--python/src/com/jetbrains/python/console/PyConsoleOptions.java2
-rw-r--r--python/src/com/jetbrains/python/console/PydevConsoleRunner.java167
-rw-r--r--python/src/com/jetbrains/python/console/PydevConsoleRunnerFactory.java122
-rw-r--r--python/src/com/jetbrains/python/console/PythonConsoleRunnerFactory.java34
-rw-r--r--python/src/com/jetbrains/python/console/PythonConsoleToolWindow.java39
-rw-r--r--python/src/com/jetbrains/python/console/PythonConsoleToolWindowFactory.java13
-rw-r--r--python/src/com/jetbrains/python/console/PythonConsoleView.java69
-rw-r--r--python/src/com/jetbrains/python/console/PythonToolWindowConsoleRunner.java85
-rw-r--r--python/src/com/jetbrains/python/console/PythonToolWindowConsoleRunnerFactory.java34
-rw-r--r--python/src/com/jetbrains/python/console/RunPythonConsoleAction.java240
-rw-r--r--python/src/com/jetbrains/python/formatter/PyLanguageCodeStyleSettingsProvider.java3
-rw-r--r--python/src/com/jetbrains/python/inspections/PyStringFormatInspection.java5
-rw-r--r--python/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesInspection.java4
-rw-r--r--python/src/com/jetbrains/python/packaging/PyPIPackageUtil.java2
-rw-r--r--python/src/com/jetbrains/python/psi/impl/PyElementGeneratorImpl.java24
-rw-r--r--python/src/com/jetbrains/python/psi/types/PyFunctionType.java76
-rw-r--r--python/src/com/jetbrains/python/refactoring/PyRefactoringUtil.java2
-rw-r--r--python/src/com/jetbrains/python/refactoring/PyReplaceExpressionUtil.java9
-rw-r--r--python/src/com/jetbrains/python/refactoring/inline/PyInlineLocalHandler.java2
-rw-r--r--python/src/com/jetbrains/python/refactoring/introduce/IntroduceHandler.java7
-rw-r--r--python/src/com/jetbrains/python/refactoring/introduce/constant/PyIntroduceConstantHandler.java6
-rw-r--r--python/src/com/jetbrains/python/run/PythonCommandLineState.java14
-rw-r--r--python/src/com/jetbrains/python/run/PythonRunner.java5
-rw-r--r--python/src/com/jetbrains/python/sdk/PythonSdkType.java12
-rw-r--r--python/src/com/jetbrains/python/sdk/skeletons/PySkeletonRefresher.java36
-rw-r--r--python/src/com/jetbrains/python/sdk/skeletons/SkeletonErrorsDialog.form61
-rw-r--r--python/src/com/jetbrains/python/sdk/skeletons/SkeletonErrorsDialog.java94
-rw-r--r--python/src/com/jetbrains/python/testing/PyRerunFailedTestsAction.java2
-rw-r--r--python/testData/MockSdk2.7/python_stubs/__builtin__.py13
-rw-r--r--python/testData/MockSdk3.2/python_stubs/builtins.py14
-rw-r--r--python/testData/__init__.py1
-rw-r--r--python/testData/addImport/localFromImport.after.py6
-rw-r--r--python/testData/addImport/localFromImport.py4
-rw-r--r--python/testData/addImport/localImport.after.py8
-rw-r--r--python/testData/addImport/localImport.py6
-rw-r--r--python/testData/addImport/localImportInlineBranch.after.py6
-rw-r--r--python/testData/addImport/localImportInlineBranch.py3
-rw-r--r--python/testData/addImport/localImportInlineFunctionBody.after.py5
-rw-r--r--python/testData/addImport/localImportInlineFunctionBody.py2
-rw-r--r--python/testData/completion/boundMethodSpecialAttributes.py5
-rw-r--r--python/testData/completion/lambdaSpecialAttributes.py1
-rw-r--r--python/testData/completion/reassignedMethodSpecialAttributes.py6
-rw-r--r--python/testData/completion/staticMethodSpecialAttributes.py6
-rw-r--r--python/testData/completion/unboundMethodSpecialAttributes.py5
-rw-r--r--python/testData/completion/weakQualifierBoundMethodAttributes.py10
-rw-r--r--python/testData/debug/Adder-0.1.eggbin0 -> 1626 bytes
-rw-r--r--python/testData/debug/Test_Resume.py8
-rw-r--r--python/testData/debug/__init__.py1
-rw-r--r--python/testData/debug/pycharm-debug.eggbin0 -> 117209 bytes
-rw-r--r--python/testData/debug/test1.py5
-rw-r--r--python/testData/debug/test2.py8
-rw-r--r--python/testData/debug/test3.py26
-rw-r--r--python/testData/debug/test4.py5
-rw-r--r--python/testData/debug/test_continuation.py16
-rw-r--r--python/testData/debug/test_continuation2.py8
-rw-r--r--python/testData/debug/test_egg.py4
-rw-r--r--python/testData/debug/test_exceptbreak.py8
-rw-r--r--python/testData/debug/test_input.py7
-rw-r--r--python/testData/debug/test_multiprocess.py13
-rw-r--r--python/testData/debug/test_multithread.py24
-rw-r--r--python/testData/debug/test_remote.py19
-rw-r--r--python/testData/debug/test_runtoline.py8
-rw-r--r--python/testData/debug/test_stepOverCondition.py4
-rw-r--r--python/testData/debug/zipped_lib.zipbin0 -> 155 bytes
-rw-r--r--python/testData/dotNet/PythonLibs.dllbin0 -> 4096 bytes
-rw-r--r--python/testData/dotNet/SingleNameSpace.dllbin0 -> 4096 bytes
-rw-r--r--python/testData/dotNet/__init__.py1
-rw-r--r--python/testData/dotNet/expected.skeleton.Deep.py17
-rw-r--r--python/testData/dotNet/expected.skeleton.SingleNameSpace.py22
-rw-r--r--python/testData/dotNet/expected.skeleton.java.py24
-rw-r--r--python/testData/dotNet/import_class_from_module.py6
-rw-r--r--python/testData/dotNet/import_class_from_module_alias.py6
-rw-r--r--python/testData/dotNet/import_module_from_package.py7
-rw-r--r--python/testData/dotNet/import_several_classes_from_module.py7
-rw-r--r--python/testData/dotNet/import_system.py2
-rw-r--r--python/testData/dotNet/inner_class.py6
-rw-r--r--python/testData/dotNet/single_class.py6
-rw-r--r--python/testData/dotNet/testSkeleton.py6
-rw-r--r--python/testData/dotNet/whole_namespace.py6
-rw-r--r--python/testData/inspections/PyStringFormatInspection/expected.xml16
-rw-r--r--python/testData/inspections/PyStringFormatInspection/src/string-format.py24
-rw-r--r--python/testData/inspections/PyUnresolvedReferencesInspection/methodSpecialAttributes.py25
-rw-r--r--python/testData/refactoring/introduceConstant/fromParameterDefaultValue.after.py5
-rw-r--r--python/testData/refactoring/introduceConstant/fromParameterDefaultValue.py2
-rw-r--r--python/testData/refactoring/introduceVariable/selectionBreaksBinaryOperator.after.py3
-rw-r--r--python/testData/refactoring/introduceVariable/selectionBreaksBinaryOperator.py2
-rw-r--r--python/testData/testRunner/__init__.py1
-rw-r--r--python/testData/testRunner/env/__init__.py1
-rw-r--r--python/testData/testRunner/env/doc/__init__.py1
-rw-r--r--python/testData/testRunner/env/doc/test1.py39
-rw-r--r--python/testData/testRunner/env/doc/test2.py39
-rw-r--r--python/testData/testRunner/env/nose/__init__.py1
-rw-r--r--python/testData/testRunner/env/nose/test1.py11
-rw-r--r--python/testData/testRunner/env/nose/test2.py18
-rw-r--r--python/testData/testRunner/env/pytest/__init__.py1
-rw-r--r--python/testData/testRunner/env/pytest/test1.py9
-rw-r--r--python/testData/testRunner/env/pytest/test2.py16
-rw-r--r--python/testData/testRunner/env/unit/__init__.py1
-rw-r--r--python/testData/testRunner/env/unit/dependentTests/__init__.py1
-rw-r--r--python/testData/testRunner/env/unit/dependentTests/test_my_class.py7
-rw-r--r--python/testData/testRunner/env/unit/dependentTests/testedCode/__init__.py0
-rw-r--r--python/testData/testRunner/env/unit/dependentTests/testedCode/my_class.py4
-rw-r--r--python/testData/testRunner/env/unit/subfolder/__init__.py1
-rw-r--r--python/testData/testRunner/env/unit/subfolder/test2.py7
-rw-r--r--python/testData/testRunner/env/unit/test1.py8
-rw-r--r--python/testData/testRunner/env/unit/test2.py11
-rw-r--r--python/testData/testRunner/env/unit/test_file.py12
-rw-r--r--python/testData/testRunner/env/unit/test_folder/__init__.py1
-rw-r--r--python/testData/testRunner/env/unit/test_folder/test1.py8
-rw-r--r--python/testData/testRunner/env/unit/test_folder/test2.py11
-rw-r--r--python/testSrc/com/jetbrains/env/PyEnvSufficiencyTest.java51
-rw-r--r--python/testSrc/com/jetbrains/env/PyEnvTaskRunner.java112
-rw-r--r--python/testSrc/com/jetbrains/env/PyEnvTestCase.java201
-rw-r--r--python/testSrc/com/jetbrains/env/PyExecutionFixtureTestTask.java174
-rw-r--r--python/testSrc/com/jetbrains/env/PyTestTask.java81
-rw-r--r--python/testSrc/com/jetbrains/env/python/IPythonConsoleTest.java100
-rw-r--r--python/testSrc/com/jetbrains/env/python/PyPackageRequirementsInspectionTest.java83
-rw-r--r--python/testSrc/com/jetbrains/env/python/PyPackagingTest.java164
-rw-r--r--python/testSrc/com/jetbrains/env/python/PythonConsoleTest.java130
-rw-r--r--python/testSrc/com/jetbrains/env/python/PythonDebuggerTest.java579
-rw-r--r--python/testSrc/com/jetbrains/env/python/PythonGeneratorTest.java24
-rw-r--r--python/testSrc/com/jetbrains/env/python/PythonSkeletonsTest.java202
-rw-r--r--python/testSrc/com/jetbrains/env/python/console/PyConsoleTask.java380
-rw-r--r--python/testSrc/com/jetbrains/env/python/debug/PyBaseDebuggerTask.java361
-rw-r--r--python/testSrc/com/jetbrains/env/python/debug/PyDebuggerTask.java211
-rw-r--r--python/testSrc/com/jetbrains/env/python/dotNet/PyIronPythonTest.java145
-rw-r--r--python/testSrc/com/jetbrains/env/python/dotNet/SkeletonTestTask.java142
-rw-r--r--python/testSrc/com/jetbrains/env/python/dotNet/package-info.java5
-rw-r--r--python/testSrc/com/jetbrains/env/python/testing/PythonDocTestingTest.java66
-rw-r--r--python/testSrc/com/jetbrains/env/python/testing/PythonNoseTestingTest.java33
-rw-r--r--python/testSrc/com/jetbrains/env/python/testing/PythonPyTestingTest.java33
-rw-r--r--python/testSrc/com/jetbrains/env/python/testing/PythonUnitTestingTest.java78
-rw-r--r--python/testSrc/com/jetbrains/env/ut/PyDocTestTask.java24
-rw-r--r--python/testSrc/com/jetbrains/env/ut/PyNoseTestTask.java32
-rw-r--r--python/testSrc/com/jetbrains/env/ut/PyTestTestTask.java40
-rw-r--r--python/testSrc/com/jetbrains/env/ut/PyUnitTestTask.java241
-rw-r--r--python/testSrc/com/jetbrains/python/PyAddImportTest.java47
-rw-r--r--python/testSrc/com/jetbrains/python/PyTypeTest.java6
-rw-r--r--python/testSrc/com/jetbrains/python/PythonCompletionTest.java98
-rw-r--r--python/testSrc/com/jetbrains/python/fixtures/PyCommandLineTestCase.java29
-rw-r--r--python/testSrc/com/jetbrains/python/fixtures/PyTestCase.java40
-rw-r--r--python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java5
-rw-r--r--python/testSrc/com/jetbrains/python/refactoring/PyIntroduceConstantTest.java7
-rw-r--r--python/testSrc/com/jetbrains/python/refactoring/PyIntroduceVariableTest.java2
-rw-r--r--python/testSrc/com/jetbrains/python/sdkTools/PyTestSdkTools.java142
-rw-r--r--python/testSrc/com/jetbrains/python/sdkTools/SdkCreationType.java20
-rw-r--r--python/testSrc/com/jetbrains/python/sdkTools/package-info.java6
-rw-r--r--python/testSrc/python-community-tests.iml3
-rw-r--r--resources-en/src/messages/AntBundle.properties2
-rw-r--r--resources-en/src/messages/DebuggerBundle.properties6
-rw-r--r--resources-en/src/search/searchableOptions.xml4
-rw-r--r--resources/src/META-INF/IdeaPlugin.xml11
-rw-r--r--resources/src/idea/JavaActions.xml3
-rw-r--r--resources/src/idea/RichPlatformPlugin.xml3
-rw-r--r--spellchecker/src/com/intellij/spellchecker/inspections/SpellCheckingInspection.java13
-rw-r--r--spellchecker/src/com/intellij/spellchecker/jetbrains.dic1
-rw-r--r--spellchecker/src/com/intellij/spellchecker/quickfixes/RenameTo.java8
-rw-r--r--spellchecker/src/com/intellij/spellchecker/tokenizer/SpellcheckingStrategy.java8
-rw-r--r--xml/dom-impl/src/com/intellij/util/xml/ui/DomUIFactoryImpl.java4
-rw-r--r--xml/dom-openapi/src/com/intellij/util/xml/ui/DomUIFactory.java4
-rw-r--r--xml/impl/src/com/intellij/codeInsight/template/emmet/ZenCodingTemplate.java3
-rw-r--r--xml/impl/src/com/intellij/codeInsight/template/emmet/generators/XmlZenCodingGenerator.java8
-rw-r--r--xml/impl/src/org/jetbrains/builtInWebServer/DefaultWebServerRootsProvider.java6
-rw-r--r--xml/relaxng/src/resources/html5-schema/html5-svg-mathml.rnc2
-rwxr-xr-xxml/relaxng/src/resources/html5-schema/html5/applications.rnc12
-rwxr-xr-xxml/relaxng/src/resources/html5-schema/html5/aria.rnc10
-rwxr-xr-xxml/relaxng/src/resources/html5-schema/html5/block.rnc1
-rwxr-xr-xxml/relaxng/src/resources/html5-schema/html5/common.rnc15
-rwxr-xr-xxml/relaxng/src/resources/html5-schema/html5/core-scripting.rnc2
-rwxr-xr-xxml/relaxng/src/resources/html5-schema/html5/embed.rnc71
-rw-r--r--xml/relaxng/src/resources/html5-schema/html5/legacy.rnc6
-rwxr-xr-xxml/relaxng/src/resources/html5-schema/html5/media.rnc6
-rwxr-xr-xxml/relaxng/src/resources/html5-schema/html5/meta.rnc1
-rw-r--r--xml/relaxng/src/resources/html5-schema/html5/microdata.rnc3
-rw-r--r--xml/relaxng/src/resources/html5-schema/html5/rdfa.rnc30
-rwxr-xr-xxml/relaxng/src/resources/html5-schema/html5/tables.rnc33
-rw-r--r--xml/relaxng/src/resources/html5-schema/legacy/legacy.rnc6
-rw-r--r--xml/relaxng/src/resources/html5-schema/svg11/svg-basic-font.rnc4
-rw-r--r--xml/relaxng/src/resources/html5-schema/svg11/svg-conditional.rnc3
-rw-r--r--xml/relaxng/src/resources/html5-schema/svg11/svg-extensibility.rnc11
-rw-r--r--xml/relaxng/src/resources/patches/0004_ping.patch2
-rw-r--r--xml/relaxng/src/resources/patches/patch_build.patch53
-rwxr-xr-xxml/relaxng/src/resources/update_html5_schema.sh4
-rw-r--r--xml/tests/src/com/intellij/psi/formatter/XmlFormatterTestCase.java2
-rw-r--r--xml/xml-psi-api/src/com/intellij/psi/XmlRecursiveElementWalkingVisitor.java58
-rw-r--r--xml/xml-psi-impl/src/com/intellij/psi/impl/source/xml/XmlAttributeReference.java8
1538 files changed, 46706 insertions, 11294 deletions
diff --git a/.idea/modules.xml b/.idea/modules.xml
index 101efac37338..0322352e9df9 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -47,7 +47,8 @@
<module fileurl="file://$PROJECT_DIR$/xml/dom-openapi/dom-openapi.iml" filepath="$PROJECT_DIR$/xml/dom-openapi/dom-openapi.iml" group="xml" />
<module fileurl="file://$PROJECT_DIR$/xml/dom-tests/dom-tests.iml" filepath="$PROJECT_DIR$/xml/dom-tests/dom-tests.iml" group="xml" />
<module fileurl="file://$PROJECT_DIR$/platform/duplicates-analysis/duplicates-analysis.iml" filepath="$PROJECT_DIR$/platform/duplicates-analysis/duplicates-analysis.iml" />
- <module fileurl="file://$PROJECT_DIR$/platform/dvcs/dvcs.iml" filepath="$PROJECT_DIR$/platform/dvcs/dvcs.iml" group="platform" />
+ <module fileurl="file://$PROJECT_DIR$/platform/dvcs-impl/dvcs-impl.iml" filepath="$PROJECT_DIR$/platform/dvcs-impl/dvcs-impl.iml" group="platform" />
+ <module fileurl="file://$PROJECT_DIR$/platform/dvcs-api/dvcs-api.iml" filepath="$PROJECT_DIR$/platform/dvcs-api/dvcs-api.iml" group="platform"/>
<module fileurl="file://$PROJECT_DIR$/plugins/eclipse/eclipse.iml" filepath="$PROJECT_DIR$/plugins/eclipse/eclipse.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/plugins/eclipse/jps-plugin/eclipse-jps-plugin.iml" filepath="$PROJECT_DIR$/plugins/eclipse/jps-plugin/eclipse-jps-plugin.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/platform/editor-ui-api/editor-ui-api.iml" filepath="$PROJECT_DIR$/platform/editor-ui-api/editor-ui-api.iml" group="platform" />
@@ -197,6 +198,7 @@
<module fileurl="file://$PROJECT_DIR$/platform/util/util.iml" filepath="$PROJECT_DIR$/platform/util/util.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/platform/util-rt/util-rt.iml" filepath="$PROJECT_DIR$/platform/util-rt/util-rt.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/platform/vcs-api/vcs-api.iml" filepath="$PROJECT_DIR$/platform/vcs-api/vcs-api.iml" group="platform" />
+ <module fileurl="file://$PROJECT_DIR$/platform/vcs-api/vcs-api-core/vcs-api-core.iml" filepath="$PROJECT_DIR$/platform/vcs-api/vcs-api-core/vcs-api-core.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/platform/vcs-impl/vcs-impl.iml" filepath="$PROJECT_DIR$/platform/vcs-impl/vcs-impl.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/platform/vcs-log/api/vcs-log-api.iml" filepath="$PROJECT_DIR$/platform/vcs-log/api/vcs-log-api.iml" group="platform/vcs-log" />
<module fileurl="file://$PROJECT_DIR$/platform/vcs-log/graph/vcs-log-graph.iml" filepath="$PROJECT_DIR$/platform/vcs-log/graph/vcs-log-graph.iml" group="platform/vcs-log" />
@@ -218,6 +220,8 @@
<module fileurl="file://$PROJECT_DIR$/plugins/xslt-debugger/engine/xslt-debugger-engine.iml" filepath="$PROJECT_DIR$/plugins/xslt-debugger/engine/xslt-debugger-engine.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/plugins/xslt-debugger/engine/impl/xslt-debugger-engine-impl.iml" filepath="$PROJECT_DIR$/plugins/xslt-debugger/engine/impl/xslt-debugger-engine-impl.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/plugins/xpath/xslt-rt/xslt-rt.iml" filepath="$PROJECT_DIR$/plugins/xpath/xslt-rt/xslt-rt.iml" group="plugins" />
+ <module fileurl="file://$PROJECT_DIR$/plugins/editorconfig/editorconfig.iml" filepath="$PROJECT_DIR$/plugins/editorconfig/editorconfig.iml" group="plugins"/>
+
</modules>
</component>
</project>
diff --git a/LICENSE.txt b/LICENSE.txt
deleted file mode 100644
index d64569567334..000000000000
--- a/LICENSE.txt
+++ /dev/null
@@ -1,202 +0,0 @@
-
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- 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.
diff --git a/README.md b/README.md
deleted file mode 100644
index 127e3222d0eb..000000000000
--- a/README.md
+++ /dev/null
@@ -1,31 +0,0 @@
-# IntelliJ IDEA Community Edition
-
-This is the official GitHub mirror of the [IntelliJ IDEA Community Edition](http://www.jetbrains.com/idea/) and
-[PyCharm Community Edition](http://www.jetbrains.com/pycharm/) source code.
-
-## Building
-
-To develop IntelliJ IDEA, you can use either IntelliJ IDEA Community Edition or IntelliJ IDEA Ultimate. To build and run the code:
-
-* Make sure you have the Groovy plugin enabled. Parts of IntelliJ IDEA are written in Groovy, and you will get compilation errors if you don't have the plugin enabled.
-* Make sure you have the UI Designer plugin enabled. Most of IntelliJ IDEA's UI is built using the UI Designer, and the version you build will not run correctly if you don't have the plugin enabled.
-* Open the directory with the source code as a directory-based project
-* Configure a JSDK named "IDEA jdk", pointing to an installation of JDK 1.6
-* On Windows or Linux, add lib\tools.jar from the JDK installation directory to the classpath of IDEA jdk
-* Use Build | Make Project to build the code
-* To run the code, use the provided shared run configuration "IDEA".
-
-To build the distribution archive of IntelliJ IDEA Community Edition, execute build.xml Ant build script in the root directory of the
-source code. The results of the build execution can be found at out/artifacts.
-
-## Contributing
-
-Pull requests are welcome. Please make sure that you follow the [IntelliJ Coding Guidelines](http://www.jetbrains.org/display/IJOS/IntelliJ+Coding+Guidelines).
-Note that you'll need to submit a [Contributor Agreement](http://www.jetbrains.org/display/IJOS/Contributor+Agreement) before we can accept your pull request.
-
-See http://www.jetbrains.org/ for more information.
-
-## Developer Documentation
-
-You can find information on the internal architecture of IntelliJ IDEA and plugin development at the
-[PluginDevelopment](http://confluence.jetbrains.com/display/IDEADEV/PluginDevelopment) site.
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/intention/CheckRegExpForm.form b/RegExpSupport/src/org/intellij/lang/regexp/intention/CheckRegExpForm.form
index b04addde5858..9029a33969fc 100644
--- a/RegExpSupport/src/org/intellij/lang/regexp/intention/CheckRegExpForm.form
+++ b/RegExpSupport/src/org/intellij/lang/regexp/intention/CheckRegExpForm.form
@@ -17,7 +17,9 @@
<grid id="a052" layout-manager="BorderLayout" hgap="0" vgap="0">
<constraints border-constraint="Center"/>
<properties/>
- <border type="none"/>
+ <border type="empty">
+ <size top="5" left="5" bottom="10" right="5"/>
+ </border>
<children>
<grid id="b7b2b" layout-manager="BorderLayout" hgap="0" vgap="0">
<constraints border-constraint="North"/>
@@ -66,14 +68,14 @@
<properties/>
<border type="none"/>
<children>
- <component id="5de69" class="com.intellij.ui.components.JBLabel">
+ <component id="5de69" class="com.intellij.ui.components.JBLabel" binding="myMessage">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<alignmentX value="0.5"/>
<componentStyle value="SMALL"/>
- <text value="Red means Sample does not match RegExp"/>
+ <text value="Red means I can't hear you!"/>
</properties>
</component>
<hspacer id="c8c90">
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/intention/CheckRegExpForm.java b/RegExpSupport/src/org/intellij/lang/regexp/intention/CheckRegExpForm.java
index ce1047eebc5c..f8269dcd498b 100644
--- a/RegExpSupport/src/org/intellij/lang/regexp/intention/CheckRegExpForm.java
+++ b/RegExpSupport/src/org/intellij/lang/regexp/intention/CheckRegExpForm.java
@@ -16,33 +16,30 @@
package org.intellij.lang.regexp.intention;
import com.intellij.ide.util.PropertiesComponent;
+import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
-import com.intellij.openapi.actionSystem.CommonShortcuts;
import com.intellij.openapi.actionSystem.CustomShortcutSet;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.event.DocumentAdapter;
import com.intellij.openapi.editor.event.DocumentEvent;
import com.intellij.openapi.fileTypes.PlainTextFileType;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.popup.Balloon;
-import com.intellij.openapi.ui.popup.JBPopupAdapter;
-import com.intellij.openapi.ui.popup.LightweightWindowEvent;
-import com.intellij.openapi.util.Pair;
-import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.psi.PsiDocumentManager;
-import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
-import com.intellij.psi.impl.source.resolve.FileContextUtil;
-import com.intellij.ui.BalloonImpl;
+import com.intellij.psi.PsiLanguageInjectionHost;
+import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
import com.intellij.ui.EditorTextField;
import com.intellij.ui.Gray;
import com.intellij.ui.JBColor;
+import com.intellij.ui.components.JBLabel;
import com.intellij.util.Alarm;
import com.intellij.util.ui.UIUtil;
import org.intellij.lang.regexp.RegExpLanguage;
import org.intellij.lang.regexp.RegExpModifierProvider;
+import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.border.CompoundBorder;
@@ -56,52 +53,40 @@ import java.util.regex.Pattern;
*/
public class CheckRegExpForm {
private static final String LAST_EDITED_REGEXP = "last.edited.regexp";
- private Pair<PsiFile, Ref<Balloon>> myParams;
+ private final PsiFile myRegexpFile;
private EditorTextField mySampleText; //TODO[kb]: make it multiline
private EditorTextField myRegExp;
private JPanel myRootPanel;
- private Ref<Balloon> myRef;
+ private JBLabel myMessage;
private Project myProject;
- public CheckRegExpForm(Pair<PsiFile, Ref<Balloon>> params) {
- myParams = params;
+ public CheckRegExpForm(@NotNull PsiFile regexpFile) {
+ myRegexpFile = regexpFile;
}
private void createUIComponents() {
- PsiFile file = myParams.first;
- myProject = file.getProject();
- myRef = myParams.second;
- Document document = PsiDocumentManager.getInstance(myProject).getDocument(file);
+ myProject = myRegexpFile.getProject();
+ Document document = PsiDocumentManager.getInstance(myProject).getDocument(myRegexpFile);
myRegExp = new EditorTextField(document, myProject, RegExpLanguage.INSTANCE.getAssociatedFileType());
+ myRegExp.setPreferredWidth(Math.max(300, myRegExp.getPreferredSize().width));
final String sampleText = PropertiesComponent.getInstance(myProject).getValue(LAST_EDITED_REGEXP, "Sample Text");
mySampleText = new EditorTextField(sampleText, myProject, PlainTextFileType.INSTANCE);
mySampleText.setBorder(
- new CompoundBorder(new EmptyBorder(2, 2, 2, 4), new LineBorder(UIUtil.isUnderDarcula() ? Gray._100 : UIUtil.getBorderColor())));
+ new CompoundBorder(new EmptyBorder(2, 2, 2, 4), new LineBorder(UIUtil.isUnderDarcula() ? Gray._100 : JBColor.border())));
mySampleText.setOneLineMode(false);
- mySampleText.addDocumentListener(new DocumentAdapter() {
- @Override
- public void documentChanged(DocumentEvent e) {
- //noinspection SSBasedInspection
- SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- myRootPanel.revalidate();
- final Balloon balloon = myRef.get();
- if (balloon != null) {
- balloon.revalidate();
- }
- }
- });
- }
- });
myRootPanel = new JPanel(new BorderLayout()) {
+ Disposable disposable;
+
@Override
public void addNotify() {
super.addNotify();
+ disposable = Disposer.newDisposable();
+
IdeFocusManager.getGlobalInstance().requestFocus(mySampleText, true);
new AnAction(){
@@ -109,26 +94,10 @@ public class CheckRegExpForm {
public void actionPerformed(AnActionEvent e) {
IdeFocusManager.findInstance().requestFocus(myRegExp.getFocusTarget(), true);
}
- }.registerCustomShortcutSet(CustomShortcutSet.fromString("shift TAB"), mySampleText, myRef.get());
- final AnAction escaper = new AnAction() {
- @Override
- public void actionPerformed(AnActionEvent e) {
- myRef.get().hide();
- }
- };
- escaper.registerCustomShortcutSet(CommonShortcuts.ESCAPE, myRegExp.getFocusTarget(), myRef.get());
- escaper.registerCustomShortcutSet(CommonShortcuts.ESCAPE, mySampleText.getFocusTarget(), myRef.get());
-
-
- myRef.get().addListener(new JBPopupAdapter() {
- @Override
- public void onClosed(LightweightWindowEvent event) {
- PropertiesComponent.getInstance(myProject).setValue(LAST_EDITED_REGEXP, mySampleText.getText());
- }
- });
+ }.registerCustomShortcutSet(CustomShortcutSet.fromString("shift TAB"), mySampleText);
- final Alarm updater = new Alarm(Alarm.ThreadToUse.SWING_THREAD, myRef.get());
- final DocumentAdapter documentListener = new DocumentAdapter() {
+ final Alarm updater = new Alarm(Alarm.ThreadToUse.SWING_THREAD, disposable);
+ DocumentAdapter documentListener = new DocumentAdapter() {
@Override
public void documentChanged(DocumentEvent e) {
updater.cancelAllRequests();
@@ -148,48 +117,44 @@ public class CheckRegExpForm {
updateBalloon();
mySampleText.selectAll();
}
+
+ @Override
+ public void removeNotify() {
+ super.removeNotify();
+ Disposer.dispose(disposable);
+ PropertiesComponent.getInstance(myProject).setValue(LAST_EDITED_REGEXP, mySampleText.getText());
+ }
};
}
+ @NotNull
+ public JComponent getPreferredFocusedComponent() {
+ return mySampleText;
+ }
+ @NotNull
public JPanel getRootPanel() {
return myRootPanel;
}
private void updateBalloon() {
boolean correct = false;
- try {
- final PsiFile file = myParams.first;
- //todo: unfortunately there is no way to access host element representing regexp
- int offset = -1;
- try {
- final String name = file.getName();
- offset = Integer.parseInt(name.substring(name.lastIndexOf(':') + 1, name.lastIndexOf(')')));
- } catch (Exception ignore) {}
-
- int flags = 0;
- if (offset != -1) {
- final PsiFile host = FileContextUtil.getContextFile(file);
- if (host != null) {
- final PsiElement regexpInHost = host.findElementAt(offset);
- if (regexpInHost != null) {
- for (RegExpModifierProvider provider : RegExpModifierProvider.EP.getExtensions()) {
- final int modifiers = provider.getFlags(regexpInHost, file);
- if (modifiers > 0) {
- flags = modifiers;
- break;
- }
- }
- }
- }
+ PsiLanguageInjectionHost host = InjectedLanguageUtil.findInjectionHost(myRegexpFile);
+ int flags = 0;
+ if (host != null) {
+ for (RegExpModifierProvider provider : RegExpModifierProvider.EP.getExtensions()) {
+ flags = provider.getFlags(host, myRegexpFile);
+ if (flags > 0) break;
}
+ }
+ try {
correct = Pattern.compile(myRegExp.getText(), flags).matcher(mySampleText.getText()).matches();
} catch (Exception ignore) {}
- mySampleText.setBackground(correct ? new JBColor(new Color(231, 250, 219), new Color(68, 85, 66)) : new JBColor(new Color(255, 177, 160), new Color(110, 43, 40)));
- BalloonImpl balloon = (BalloonImpl)myRef.get();
- if (balloon != null && balloon.isDisposed()) {
- balloon.revalidate();
- }
+ JBColor color1 = new JBColor(new Color(231, 250, 219), new Color(68, 85, 66));
+ JBColor color2 = new JBColor(new Color(255, 177, 160), new Color(110, 43, 40));
+ mySampleText.setBackground(correct ? color1 : color2);
+ myMessage.setText(correct ? "Matches!" : "no match");
+ myRootPanel.revalidate();
}
}
diff --git a/RegExpSupport/src/org/intellij/lang/regexp/intention/CheckRegExpIntentionAction.java b/RegExpSupport/src/org/intellij/lang/regexp/intention/CheckRegExpIntentionAction.java
index 6c052461c5b8..6da84caa56ec 100644
--- a/RegExpSupport/src/org/intellij/lang/regexp/intention/CheckRegExpIntentionAction.java
+++ b/RegExpSupport/src/org/intellij/lang/regexp/intention/CheckRegExpIntentionAction.java
@@ -20,10 +20,8 @@ import com.intellij.lang.Language;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.popup.Balloon;
import com.intellij.openapi.util.Iconable;
import com.intellij.openapi.util.Pair;
-import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
@@ -41,12 +39,10 @@ public class CheckRegExpIntentionAction extends QuickEditAction implements Icona
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
- final Pair<PsiElement, TextRange> pair = getRangePair(file, editor);
- /*super.isAvailable(project, editor, file) && */
+ Pair<PsiElement, TextRange> pair = getRangePair(file, editor);
if (pair != null && pair.first != null) {
Language language = pair.first.getLanguage();
- Language baseLanguage = language.getBaseLanguage();
- return language == RegExpLanguage.INSTANCE || baseLanguage == RegExpLanguage.INSTANCE;
+ return language.isKindOf(RegExpLanguage.INSTANCE);
}
return false;
}
@@ -57,11 +53,11 @@ public class CheckRegExpIntentionAction extends QuickEditAction implements Icona
}
@Override
- protected JComponent createBalloonComponent(PsiFile file, final Ref<Balloon> ref) {
+ protected JComponent createBalloonComponent(@NotNull PsiFile file) {
final Project project = file.getProject();
final Document document = PsiDocumentManager.getInstance(project).getDocument(file);
if (document != null) {
- return new CheckRegExpForm(Pair.create(file, ref)).getRootPanel();
+ return new CheckRegExpForm(file).getRootPanel();
}
return null;
}
diff --git a/build/scripts/layouts.gant b/build/scripts/layouts.gant
index f91ac85d7449..e33f920fe146 100644
--- a/build/scripts/layouts.gant
+++ b/build/scripts/layouts.gant
@@ -519,6 +519,12 @@ public def layoutCommunityPlugins(String home) {
}
}
+ layoutPlugin("editorconfig") {
+ fileset(dir: "$home/plugins/editorconfig/lib") {
+ include(name: "**/*.jar")
+ }
+ }
+
pluginDir("coverage") {
dir("lib") {
jar("coverage.jar") {
diff --git a/build/scripts/libLicenses.gant b/build/scripts/libLicenses.gant
index d495f952b7a8..872cc5f6e9fe 100644
--- a/build/scripts/libLicenses.gant
+++ b/build/scripts/libLicenses.gant
@@ -278,6 +278,7 @@ libraryLicense(name: "ANTLR 4 Runtime", libraryName: "antlr-runtime-4.1.jar", ve
libraryLicense(name: "minlog", libraryName: "minlog-1.2.jar", version: "1.2", license: "BSD", url: "https://github.com/EsotericSoftware/minlog", licenseUrl: "http://opensource.org/licenses/BSD-3-Clause")
libraryLicense(name: "ReflectASM", libraryName: "reflectasm-1.0.7.jar", version: "1.0.7", license: "BSD", url: "https://github.com/EsotericSoftware/reflectasm", licenseUrl: "http://opensource.org/licenses/BSD-3-Clause")
libraryLicense(name: "Objenesis", libraryName: "objenesis-1.2.jar", version: "1.2", license: "Apache 2.0", url: "http://objenesis.org/", licenseUrl: "http://apache.org/licenses/LICENSE-2.0")
+libraryLicense(name: "EditorConfig Java Core", libraryName: "editorconfig-core-java.jar", version: "1.0", license: "Apache 2.0", url: "https://github.com/editorconfig/editorconfig-core-java/", licenseUrl: "https://github.com/editorconfig/editorconfig-core-java/blob/master/LICENSE")
jetbrainsLibrary("Coverage")
jetbrainsLibrary("CoverageReport")
jetbrainsLibrary("JPS")
diff --git a/build/scripts/utils.gant b/build/scripts/utils.gant
index ae07104045b3..b090f7a84dd5 100644
--- a/build/scripts/utils.gant
+++ b/build/scripts/utils.gant
@@ -250,6 +250,7 @@ binding.setVariable("classPathLibs", [
binding.setVariable("platformApiModules", [
"analysis-api",
"core-api",
+ "dvcs-api",
"editor-ui-api",
"external-system-api",
"indexing-api",
@@ -261,6 +262,7 @@ binding.setVariable("platformApiModules", [
"structure-view-api",
"usageView",
"vcs-api",
+ "vcs-api-core",
"vcs-log-api",
"vcs-log-graph-api",
"xdebugger-api",
@@ -276,7 +278,7 @@ binding.setVariable("platformApiModules", [
binding.setVariable("platformImplementationModules", [
"analysis-impl",
"core-impl",
- "dvcs",
+ "dvcs-impl",
"editor-ui-ex",
"images",
"indexing-impl",
diff --git a/community-resources/src/plugins/OtherTools.png b/community-resources/src/plugins/OtherTools.png
deleted file mode 100644
index 5fb7ae56774c..000000000000
--- a/community-resources/src/plugins/OtherTools.png
+++ /dev/null
Binary files differ
diff --git a/java/compiler/impl/src/com/intellij/compiler/options/AnnotationProcessorsConfigurable.java b/java/compiler/impl/src/com/intellij/compiler/options/AnnotationProcessorsConfigurable.java
index 74ed9e1ae075..934f83db31ea 100644
--- a/java/compiler/impl/src/com/intellij/compiler/options/AnnotationProcessorsConfigurable.java
+++ b/java/compiler/impl/src/com/intellij/compiler/options/AnnotationProcessorsConfigurable.java
@@ -100,6 +100,7 @@ public class AnnotationProcessorsConfigurable implements SearchableConfigurable,
}
public void disposeUIResources() {
+ myMainPanel = null;
}
}
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 01da3bc62541..c40135db7c5f 100644
--- a/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java
+++ b/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java
@@ -25,7 +25,6 @@ import com.intellij.execution.ExecutionManager;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.configurations.RunProfile;
import com.intellij.execution.process.*;
-import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.ide.DataManager;
import com.intellij.ide.PowerSaveMode;
import com.intellij.ide.file.BatchFileChangeListener;
@@ -101,8 +100,7 @@ import org.jetbrains.jps.cmdline.ClasspathBootstrap;
import org.jetbrains.jps.incremental.Utils;
import org.jetbrains.jps.model.serialization.JpsGlobalLoader;
-import javax.tools.JavaCompiler;
-import javax.tools.ToolProvider;
+import javax.tools.*;
import java.awt.*;
import java.io.File;
import java.io.IOException;
@@ -516,9 +514,8 @@ public class BuildManager implements ApplicationComponent{
}
private static boolean hasRunningProcess(Project project) {
- for (RunContentDescriptor descriptor : ExecutionManager.getInstance(project).getContentManager().getAllDescriptors()) {
- final ProcessHandler handler = descriptor.getProcessHandler();
- if (handler != null && !handler.isProcessTerminated() && !ALLOW_AUTOMAKE.get(handler, Boolean.FALSE)) { // active process
+ for (ProcessHandler handler : ExecutionManager.getInstance(project).getRunningProcesses()) {
+ if (!handler.isProcessTerminated() && !ALLOW_AUTOMAKE.get(handler, Boolean.FALSE)) { // active process
return true;
}
}
diff --git a/java/debugger/impl/src/com/intellij/debugger/DebuggerManagerEx.java b/java/debugger/impl/src/com/intellij/debugger/DebuggerManagerEx.java
index 59faecb2a6f9..d14e554fd99e 100644
--- a/java/debugger/impl/src/com/intellij/debugger/DebuggerManagerEx.java
+++ b/java/debugger/impl/src/com/intellij/debugger/DebuggerManagerEx.java
@@ -22,12 +22,9 @@ import com.intellij.debugger.impl.DebuggerSession;
import com.intellij.debugger.impl.DebuggerStateManager;
import com.intellij.debugger.ui.breakpoints.BreakpointManager;
import com.intellij.execution.ExecutionException;
-import com.intellij.execution.Executor;
-import com.intellij.execution.configurations.ModuleRunProfile;
-import com.intellij.execution.configurations.RemoteConnection;
-import com.intellij.execution.configurations.RunProfileState;
-import com.intellij.execution.runners.ProgramRunner;
import com.intellij.openapi.project.Project;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.util.Collection;
@@ -46,13 +43,6 @@ public abstract class DebuggerManagerEx extends DebuggerManager {
public abstract void addDebuggerManagerListener(DebuggerManagerListener debuggerManagerListener);
public abstract void removeDebuggerManagerListener(DebuggerManagerListener debuggerManagerListener);
- public abstract DebuggerSession attachVirtualMachine(Executor executor,
- ProgramRunner runner,
- ModuleRunProfile profile,
- RunProfileState state,
- RemoteConnection connection,
- boolean pollConnection
- ) throws ExecutionException;
-
- public abstract DebuggerSession attachVirtualMachine(DebugEnvironment environment) throws ExecutionException;
+ @Nullable
+ public abstract DebuggerSession attachVirtualMachine(@NotNull DebugEnvironment environment) throws ExecutionException;
}
diff --git a/java/debugger/impl/src/com/intellij/debugger/DefaultDebugEnvironment.java b/java/debugger/impl/src/com/intellij/debugger/DefaultDebugEnvironment.java
index 76515d8fddfe..5a7ae496853d 100644
--- a/java/debugger/impl/src/com/intellij/debugger/DefaultDebugEnvironment.java
+++ b/java/debugger/impl/src/com/intellij/debugger/DefaultDebugEnvironment.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,46 +17,33 @@ package com.intellij.debugger;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.ExecutionResult;
-import com.intellij.execution.Executor;
-import com.intellij.execution.configurations.*;
-import com.intellij.execution.runners.ProgramRunner;
-import com.intellij.openapi.project.Project;
+import com.intellij.execution.configurations.RemoteConnection;
+import com.intellij.execution.configurations.RemoteState;
+import com.intellij.execution.configurations.RunProfileState;
+import com.intellij.execution.configurations.SearchScopeProvider;
+import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.psi.search.GlobalSearchScope;
+import org.jetbrains.annotations.NotNull;
-/**
- * Created by IntelliJ IDEA.
- * User: michael.golubev
- */
public class DefaultDebugEnvironment implements DebugEnvironment {
-
private final GlobalSearchScope mySearchScope;
- private final Executor myExecutor;
- private final ProgramRunner myRunner;
- private RunProfileState myState;
private final RemoteConnection myRemoteConnection;
private final boolean myPollConnection;
- private final RunProfile myRunProfile;
+ private final ExecutionEnvironment environment;
+ private final RunProfileState state;
- public DefaultDebugEnvironment(Project project,
- Executor executor,
- ProgramRunner runner,
- RunProfile runProfile,
- RunProfileState state,
- RemoteConnection remoteConnection,
- boolean pollConnection) {
- myExecutor = executor;
- myRunner = runner;
- myRunProfile = runProfile;
- myState = state;
+ public DefaultDebugEnvironment(@NotNull ExecutionEnvironment environment, @NotNull RunProfileState state, RemoteConnection remoteConnection, boolean pollConnection) {
+ this.environment = environment;
+ this.state = state;
myRemoteConnection = remoteConnection;
myPollConnection = pollConnection;
- mySearchScope = SearchScopeProvider.createSearchScope(project, runProfile);
+ mySearchScope = SearchScopeProvider.createSearchScope(environment.getProject(), environment.getRunProfile());
}
@Override
public ExecutionResult createExecutionResult() throws ExecutionException {
- return myState.execute(myExecutor, myRunner);
+ return state.execute(environment.getExecutor(), environment.getRunner());
}
@Override
@@ -66,7 +53,7 @@ public class DefaultDebugEnvironment implements DebugEnvironment {
@Override
public boolean isRemote() {
- return myState instanceof RemoteState;
+ return environment.getRunProfile() instanceof RemoteState;
}
@Override
@@ -81,6 +68,6 @@ public class DefaultDebugEnvironment implements DebugEnvironment {
@Override
public String getSessionName() {
- return myRunProfile.getName();
+ return environment.getRunProfile().getName();
}
}
diff --git a/java/debugger/impl/src/com/intellij/debugger/DefaultDebugUIEnvironment.java b/java/debugger/impl/src/com/intellij/debugger/DefaultDebugUIEnvironment.java
index bc7915f62a47..f29f3bfe572d 100644
--- a/java/debugger/impl/src/com/intellij/debugger/DefaultDebugUIEnvironment.java
+++ b/java/debugger/impl/src/com/intellij/debugger/DefaultDebugUIEnvironment.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.
@@ -24,63 +24,27 @@ import com.intellij.execution.configurations.RunProfile;
import com.intellij.execution.configurations.RunProfileState;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.runners.ExecutionEnvironment;
-import com.intellij.execution.runners.ProgramRunner;
import com.intellij.execution.runners.RestartAction;
import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.execution.ui.actions.CloseAction;
import com.intellij.ide.actions.ContextHelpAction;
-import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.Constraints;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Disposer;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
-/**
- * Created by IntelliJ IDEA.
- * User: michael.golubev
- */
public class DefaultDebugUIEnvironment implements DebugUIEnvironment {
-
- private final Project myProject;
- private final Executor myExecutor;
- private final ProgramRunner myRunner;
private final ExecutionEnvironment myExecutionEnvironment;
- @Nullable private RunContentDescriptor myReuseContent;
- private final RunProfile myRunProfile;
private final DebugEnvironment myModelEnvironment;
- public DefaultDebugUIEnvironment(Project project,
- Executor executor,
- ProgramRunner runner,
- ExecutionEnvironment environment,
+ public DefaultDebugUIEnvironment(@NotNull ExecutionEnvironment environment,
RunProfileState state,
- @Nullable RunContentDescriptor reuseContent,
RemoteConnection remoteConnection,
boolean pollConnection) {
- myProject = project;
- myExecutor = executor;
- myRunner = runner;
myExecutionEnvironment = environment;
- myRunProfile = environment.getRunProfile();
- myModelEnvironment = new DefaultDebugEnvironment(project,
- executor,
- runner,
- myRunProfile,
- state,
- remoteConnection,
- pollConnection);
- myReuseContent = reuseContent;
- if (myReuseContent != null) {
- Disposer.register(myReuseContent, new Disposable() {
- @Override
- public void dispose() {
- myReuseContent = null;
- }
- });
- }
+ myModelEnvironment = new DefaultDebugEnvironment(environment, state, remoteConnection, pollConnection);
}
@Override
@@ -91,42 +55,43 @@ public class DefaultDebugUIEnvironment implements DebugUIEnvironment {
@Nullable
@Override
public RunContentDescriptor getReuseContent() {
- return myReuseContent;
+ return myExecutionEnvironment.getContentToReuse();
}
@Override
public Icon getIcon() {
- return myRunProfile.getIcon();
+ return getRunProfile().getIcon();
}
@Override
public void initLogs(RunContentDescriptor content, LogFilesManager logFilesManager) {
ProcessHandler processHandler = content.getProcessHandler();
- if (myRunProfile instanceof RunConfigurationBase) {
- RunConfigurationBase runConfiguration = (RunConfigurationBase)myRunProfile;
+ if (getRunProfile() instanceof RunConfigurationBase) {
+ RunConfigurationBase runConfiguration = (RunConfigurationBase)getRunProfile();
logFilesManager.registerFileMatcher(runConfiguration);
- logFilesManager.initLogConsoles(runConfiguration, processHandler);
- OutputFileUtil.attachDumpListener(runConfiguration, processHandler, content.getExecutionConsole());
+ if (processHandler != null) {
+ logFilesManager.initLogConsoles(runConfiguration, processHandler);
+ OutputFileUtil.attachDumpListener(runConfiguration, processHandler, content.getExecutionConsole());
+ }
}
}
@Override
public void initActions(RunContentDescriptor content, DefaultActionGroup actionGroup) {
- RestartAction restartAction = new RestartAction(myExecutor,
- myRunner,
- content,
- myExecutionEnvironment);
+ Executor executor = myExecutionEnvironment.getExecutor();
+ RestartAction restartAction = new RestartAction(content, myExecutionEnvironment);
actionGroup.add(restartAction, Constraints.FIRST);
restartAction.registerShortcut(content.getComponent());
- actionGroup.add(new CloseAction(myExecutor, content, myProject));
- actionGroup.add(new ContextHelpAction(myExecutor.getHelpId()));
+ actionGroup.add(new CloseAction(executor, content, myExecutionEnvironment.getProject()));
+ actionGroup.add(new ContextHelpAction(executor.getHelpId()));
}
@Override
+ @NotNull
public RunProfile getRunProfile() {
- return myRunProfile;
+ return myExecutionEnvironment.getRunProfile();
}
}
diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/ShowReferringObjectsAction.java b/java/debugger/impl/src/com/intellij/debugger/actions/ShowReferringObjectsAction.java
new file mode 100644
index 000000000000..68275af275c4
--- /dev/null
+++ b/java/debugger/impl/src/com/intellij/debugger/actions/ShowReferringObjectsAction.java
@@ -0,0 +1,131 @@
+/*
+ * 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.debugger.actions;
+
+import com.intellij.debugger.DebuggerContext;
+import com.intellij.debugger.engine.JavaValue;
+import com.intellij.debugger.engine.evaluation.EvaluateException;
+import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
+import com.intellij.debugger.engine.events.SuspendContextCommandImpl;
+import com.intellij.debugger.ui.impl.watch.ValueDescriptorImpl;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.psi.PsiExpression;
+import com.intellij.xdebugger.frame.*;
+import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree;
+import com.intellij.xdebugger.impl.ui.tree.XInspectDialog;
+import com.intellij.xdebugger.impl.ui.tree.actions.XDebuggerTreeActionBase;
+import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl;
+import com.sun.jdi.ObjectReference;
+import com.sun.jdi.Value;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+/**
+ * @author egor
+ */
+public class ShowReferringObjectsAction extends XDebuggerTreeActionBase {
+ private static final long MAX_REFERRING = 100;
+
+ @Override
+ public void update(AnActionEvent e) {
+ super.update(e);
+ }
+
+ @Override
+ protected void perform(XValueNodeImpl node, @NotNull String nodeName, AnActionEvent e) {
+ XValue container = node.getValueContainer();
+ JavaValue javaValue = null;
+ if (container instanceof ReferringObjectsValue) {
+ javaValue = ((ReferringObjectsValue)container).myJavaValue;
+ }
+ else if (container instanceof JavaValue) {
+ javaValue = ((JavaValue)container);
+ }
+ if (javaValue != null) {
+ XDebuggerTree tree = XDebuggerTree.getTree(e.getDataContext());
+ XInspectDialog dialog = new XInspectDialog(tree.getProject(),
+ tree.getEditorsProvider(),
+ tree.getSourcePosition(),
+ nodeName,
+ new ReferringObjectsValue(javaValue),
+ tree.getValueMarkers());
+ dialog.setTitle("Referring objects for " + nodeName);
+ dialog.show();
+ }
+ }
+
+ private static class ReferringObjectsValue extends XValue {
+ private final JavaValue myJavaValue;
+
+ public ReferringObjectsValue(JavaValue javaValue) {
+ myJavaValue = javaValue;
+ }
+
+ @Override
+ public void computePresentation(@NotNull XValueNode node, @NotNull XValuePlace place) {
+ myJavaValue.computePresentation(node, place);
+ }
+
+ @Override
+ public void computeChildren(@NotNull final XCompositeNode node) {
+ myJavaValue.getEvaluationContext().getDebugProcess().getManagerThread().schedule(
+ new SuspendContextCommandImpl(myJavaValue.getEvaluationContext().getSuspendContext()) {
+ @Override
+ public Priority getPriority() {
+ return Priority.NORMAL;
+ }
+
+ @Override
+ public void contextAction() throws Exception {
+ final XValueChildrenList children = new XValueChildrenList();
+
+ Value value = myJavaValue.getDescriptor().getValue();
+ List<ObjectReference> references = ((ObjectReference)value).referringObjects(MAX_REFERRING);
+ int i = 1;
+ for (final ObjectReference reference : references) {
+ ValueDescriptorImpl descriptor = new ValueDescriptorImpl(myJavaValue.getProject(), reference) {
+ @Override
+ public Value calcValue(EvaluationContextImpl evaluationContext) throws EvaluateException {
+ return reference;
+ }
+
+ @Override
+ public String getName() {
+ return "Ref";
+ }
+
+ @Override
+ public String calcValueName() {
+ return "Ref";
+ }
+
+ @Override
+ public PsiExpression getDescriptorEvaluation(DebuggerContext context) throws EvaluateException {
+ return null;
+ }
+ };
+ JavaValue jValue = JavaValue.create(descriptor, myJavaValue.getEvaluationContext(), null);
+ children.add("Referrer " + i++ ,new ReferringObjectsValue(jValue));
+ }
+
+ node.addChildren(children, true);
+ }
+ }
+ );
+ }
+ }
+}
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 db28c4bf34a7..3f649e2b1dab 100644
--- a/java/debugger/impl/src/com/intellij/debugger/engine/JavaStackFrame.java
+++ b/java/debugger/impl/src/com/intellij/debugger/engine/JavaStackFrame.java
@@ -38,13 +38,11 @@ import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.ColoredTextContainer;
-import com.intellij.ui.SimpleTextAttributes;
import com.intellij.xdebugger.XDebugSession;
import com.intellij.xdebugger.XSourcePosition;
import com.intellij.xdebugger.evaluation.XDebuggerEvaluator;
-import com.intellij.xdebugger.frame.XCompositeNode;
-import com.intellij.xdebugger.frame.XStackFrame;
-import com.intellij.xdebugger.frame.XValueChildrenList;
+import com.intellij.xdebugger.frame.*;
+import com.intellij.xdebugger.frame.presentation.XValuePresentation;
import com.intellij.xdebugger.impl.ui.XDebuggerUIConstants;
import com.intellij.xdebugger.settings.XDebuggerSettingsManager;
import com.sun.jdi.*;
@@ -53,6 +51,7 @@ import com.sun.jdi.event.ExceptionEvent;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import javax.swing.*;
import java.util.Collection;
import java.util.List;
import java.util.Map;
@@ -316,7 +315,8 @@ public class JavaStackFrame extends XStackFrame {
for (Value argValue : argValues) {
children.add(createArgumentValue(index++, argValue, null, evaluationContext));
}
- node.setMessage(MessageDescriptor.LOCAL_VARIABLES_INFO_UNAVAILABLE.getLabel(), XDebuggerUIConstants.INFORMATION_MESSAGE_ICON, SimpleTextAttributes.REGULAR_ATTRIBUTES, null);
+ //node.setMessage(MessageDescriptor.LOCAL_VARIABLES_INFO_UNAVAILABLE.getLabel(), XDebuggerUIConstants.INFORMATION_MESSAGE_ICON, SimpleTextAttributes.REGULAR_ATTRIBUTES, null);
+ children.add(new DummyMessageValueNode(MessageDescriptor.LOCAL_VARIABLES_INFO_UNAVAILABLE.getLabel(), XDebuggerUIConstants.INFORMATION_MESSAGE_ICON));
//myChildren.add(myNodeManager.createMessageNode(MessageDescriptor.LOCAL_VARIABLES_INFO_UNAVAILABLE));
// trying to collect values from variable slots
@@ -339,6 +339,33 @@ public class JavaStackFrame extends XStackFrame {
}
}
+ static class DummyMessageValueNode extends XNamedValue {
+ private final String myMessage;
+ private final Icon myIcon;
+
+ public DummyMessageValueNode(String message, Icon icon) {
+ super("");
+ myMessage = message;
+ myIcon = icon;
+ }
+
+ @Override
+ public void computePresentation(@NotNull XValueNode node, @NotNull XValuePlace place) {
+ node.setPresentation(myIcon, new XValuePresentation() {
+ @NotNull
+ @Override
+ public String getSeparator() {
+ return "";
+ }
+
+ @Override
+ public void renderValue(@NotNull XValueTextRenderer renderer) {
+ renderer.renderValue(myMessage);
+ }
+ }, false);
+ }
+ }
+
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
diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/JavaValue.java b/java/debugger/impl/src/com/intellij/debugger/engine/JavaValue.java
index 0a691d332207..9cfb2bfde84e 100644
--- a/java/debugger/impl/src/com/intellij/debugger/engine/JavaValue.java
+++ b/java/debugger/impl/src/com/intellij/debugger/engine/JavaValue.java
@@ -36,21 +36,30 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.CommonClassNames;
import com.intellij.psi.PsiExpression;
+import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.xdebugger.frame.*;
import com.intellij.xdebugger.frame.presentation.XRegularValuePresentation;
import com.intellij.xdebugger.frame.presentation.XStringValuePresentation;
import com.intellij.xdebugger.frame.presentation.XValuePresentation;
+import com.intellij.xdebugger.impl.evaluate.XValueCompactPresentation;
+import com.intellij.xdebugger.impl.ui.XValueTextProvider;
+import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl;
+import com.sun.jdi.ArrayReference;
+import com.sun.jdi.ArrayType;
+import com.sun.jdi.Value;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
+import java.util.ArrayList;
import java.util.List;
/**
* @author egor
*/
-public class JavaValue extends XNamedValue implements NodeDescriptorProvider {
+public class JavaValue extends XNamedValue implements NodeDescriptorProvider, XValueTextProvider {
private static final Logger LOG = Logger.getInstance(JavaValue.class);
private final JavaValue myParent;
@@ -74,7 +83,7 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider {
return new JavaValue(parent, valueDescriptor, evaluationContext, nodeManager);
}
- static JavaValue create(@NotNull ValueDescriptorImpl valueDescriptor,
+ public static JavaValue create(@NotNull ValueDescriptorImpl valueDescriptor,
EvaluationContextImpl evaluationContext,
NodeManagerImpl nodeManager) {
return create(null, valueDescriptor, evaluationContext, nodeManager, true);
@@ -156,7 +165,7 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider {
});
}
- private static class JavaValuePresentation extends XValuePresentation {
+ private static class JavaValuePresentation extends XValuePresentation implements XValueCompactPresentation {
private final String myValue;
private final String myType;
private final String myError;
@@ -175,6 +184,12 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider {
@Override
public void renderValue(@NotNull XValueTextRenderer renderer) {
+ renderValue(renderer, null);
+ }
+
+ @Override
+ public void renderValue(@NotNull XValueTextRenderer renderer, @Nullable XValueNodeImpl node) {
+ boolean compact = node != null;
if (myError != null) {
if (myValue.endsWith(myError)) {
renderer.renderValue(myValue.substring(0, myValue.length() - myError.length()));
@@ -182,6 +197,34 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider {
renderer.renderError(myError);
}
else {
+ if (compact && node.getValueContainer() instanceof JavaValue) {
+ final JavaValue container = (JavaValue)node.getValueContainer();
+
+ if (container.getDescriptor().isArray()) {
+ final ArrayReference value = (ArrayReference)container.getDescriptor().getValue();
+ final ArrayType type = (ArrayType)container.getDescriptor().getType();
+ if (type != null) {
+ final String typeName = type.componentTypeName();
+ if (TypeConversionUtil.isPrimitive(typeName) || CommonClassNames.JAVA_LANG_STRING.equals(typeName)) {
+ int max = CommonClassNames.JAVA_LANG_STRING.equals(typeName) ? 5 : 10;
+ final List<Value> values = value.getValues();
+ int i = 0;
+ final List<String> vals = new ArrayList<String>(max);
+ while (i < values.size() && i <= max) {
+ vals.add(StringUtil.first(values.get(i).toString(), 15, true));
+ i++;
+ }
+ String more = "";
+ if (vals.size() < values.size()) {
+ more = ", + " + (values.size() - vals.size()) + " more";
+ }
+
+ renderer.renderValue("{" + StringUtil.join(vals, ", ") + more + "}");
+ return;
+ }
+ }
+ }
+ }
renderer.renderValue(myValue);
}
}
@@ -269,23 +312,7 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider {
children.add(create(JavaValue.this, (ValueDescriptorImpl)descriptor, myEvaluationContext, myNodeManager, false));
}
else if (descriptor instanceof MessageDescriptor) {
- children.add("", new XValue() {
- @Override
- public void computePresentation(@NotNull XValueNode node, @NotNull XValuePlace place) {
- node.setPresentation(null, new XValuePresentation() {
- @NotNull
- @Override
- public String getSeparator() {
- return "";
- }
-
- @Override
- public void renderValue(@NotNull XValueTextRenderer renderer) {
- renderer.renderValue(descriptor.getLabel());
- }
- }, false);
- }
- });
+ children.add(new JavaStackFrame.DummyMessageValueNode(descriptor.getLabel(), null));
}
}
}
@@ -299,19 +326,36 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider {
}
@Override
- public void computeSourcePosition(@NotNull XNavigatable navigatable) {
- if (myValueDescriptor instanceof FieldDescriptorImpl) {
- SourcePosition position = ((FieldDescriptorImpl)myValueDescriptor).getSourcePosition(getProject(), getDebuggerContext());
- if (position != null) {
- navigatable.setSourcePosition(DebuggerUtilsEx.toXSourcePosition(position));
+ public void computeSourcePosition(@NotNull final XNavigatable navigatable) {
+ if (myEvaluationContext.getSuspendContext().isResumed()) return;
+ myEvaluationContext.getDebugProcess().getManagerThread().schedule(new SuspendContextCommandImpl(myEvaluationContext.getSuspendContext()) {
+ @Override
+ public Priority getPriority() {
+ return Priority.NORMAL;
}
- }
- if (myValueDescriptor instanceof LocalVariableDescriptorImpl) {
- SourcePosition position = ((LocalVariableDescriptorImpl)myValueDescriptor).getSourcePosition(getProject(), getDebuggerContext());
- if (position != null) {
- navigatable.setSourcePosition(DebuggerUtilsEx.toXSourcePosition(position));
+
+ @Override
+ public void contextAction() throws Exception {
+ ApplicationManager.getApplication().runReadAction(new Runnable() {
+ @Override
+ public void run() {
+ if (myValueDescriptor instanceof FieldDescriptorImpl) {
+ SourcePosition position = ((FieldDescriptorImpl)myValueDescriptor).getSourcePosition(getProject(), getDebuggerContext());
+ if (position != null) {
+ navigatable.setSourcePosition(DebuggerUtilsEx.toXSourcePosition(position));
+ }
+ }
+ if (myValueDescriptor instanceof LocalVariableDescriptorImpl) {
+ SourcePosition position =
+ ((LocalVariableDescriptorImpl)myValueDescriptor).getSourcePosition(getProject(), getDebuggerContext());
+ if (position != null) {
+ navigatable.setSourcePosition(DebuggerUtilsEx.toXSourcePosition(position));
+ }
+ }
+ }
+ });
}
- }
+ });
}
private DebuggerContextImpl getDebuggerContext() {
@@ -393,4 +437,9 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider {
}
return evaluationExpression;
}
+
+ @Override
+ public String getValueText() {
+ return myValueDescriptor.getValueText();
+ }
}
diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/PositionManagerImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/PositionManagerImpl.java
index 2c31e75cc521..016b01ed6f96 100644
--- a/java/debugger/impl/src/com/intellij/debugger/engine/PositionManagerImpl.java
+++ b/java/debugger/impl/src/com/intellij/debugger/engine/PositionManagerImpl.java
@@ -27,6 +27,7 @@ import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.NullableComputable;
import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.search.FilenameIndex;
import com.intellij.psi.search.GlobalSearchScope;
@@ -194,12 +195,17 @@ public class PositionManagerImpl implements PositionManager {
return element.getContainingFile();
}
else {
- // for now just take the first file with the required name
- // TODO: if there are more than one, we can try matching package name and sourcePath if available
+ // try to search by filename
try {
PsiFile[] files = FilenameIndex.getFilesByName(project, refType.sourceName(), GlobalSearchScope.allScope(project));
- if (files.length > 0) {
- return files[0];
+ for (PsiFile file : files) {
+ if (file instanceof PsiJavaFile) {
+ for (PsiClass cls : ((PsiJavaFile)file).getClasses()) {
+ if (StringUtil.equals(originalQName, cls.getQualifiedName())) {
+ return file;
+ }
+ }
+ }
}
}
catch (AbsentInformationException ignore) {
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 79c1db31db3c..60c0d2dded3d 100644
--- a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerManagerImpl.java
+++ b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerManagerImpl.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.
@@ -23,16 +23,13 @@ import com.intellij.debugger.ui.GetJPDADialog;
import com.intellij.debugger.ui.breakpoints.BreakpointManager;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.ExecutionResult;
-import com.intellij.execution.Executor;
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;
-import com.intellij.execution.runners.ProgramRunner;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.PersistentStateComponent;
import com.intellij.openapi.components.State;
@@ -208,24 +205,8 @@ public class DebuggerManagerImpl extends DebuggerManagerEx implements Persistent
}
@Override
- public DebuggerSession attachVirtualMachine(Executor executor,
- ProgramRunner runner,
- ModuleRunProfile profile,
- RunProfileState state,
- RemoteConnection remoteConnection,
- boolean pollConnection
- ) throws ExecutionException {
- return attachVirtualMachine(new DefaultDebugEnvironment(myProject,
- executor,
- runner,
- profile,
- state,
- remoteConnection,
- pollConnection));
- }
-
- @Override
- public DebuggerSession attachVirtualMachine(DebugEnvironment environment) throws ExecutionException {
+ @Nullable
+ public DebuggerSession attachVirtualMachine(@NotNull DebugEnvironment environment) throws ExecutionException {
ApplicationManager.getApplication().assertIsDispatchThread();
final DebugProcessEvents debugProcess = new DebugProcessEvents(myProject);
debugProcess.addDebugProcessListener(new DebugProcessAdapter() {
@@ -258,8 +239,7 @@ public class DebuggerManagerImpl extends DebuggerManagerEx implements Persistent
debugProcess.removeDebugProcessListener(this);
}
});
- final DebuggerSession session = new DebuggerSession(environment.getSessionName(), debugProcess);
-
+ DebuggerSession session = new DebuggerSession(environment.getSessionName(), debugProcess);
final ExecutionResult executionResult = session.attach(environment);
if (executionResult == null) {
return null;
@@ -303,7 +283,6 @@ public class DebuggerManagerImpl extends DebuggerManagerEx implements Persistent
return session;
}
-
@Override
public DebugProcessImpl getDebugProcess(final ProcessHandler processHandler) {
synchronized (mySessions) {
diff --git a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerSession.java b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerSession.java
index 344406bb141c..0a5210f16c36 100644
--- a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerSession.java
+++ b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerSession.java
@@ -35,6 +35,7 @@ import com.intellij.execution.configurations.RemoteConnection;
import com.intellij.execution.configurations.RemoteState;
import com.intellij.execution.configurations.RunProfileState;
import com.intellij.execution.process.ProcessOutputTypes;
+import com.intellij.execution.runners.ExecutionEnvironmentBuilder;
import com.intellij.execution.runners.ProgramRunner;
import com.intellij.idea.ActionsBundle;
import com.intellij.openapi.application.ApplicationManager;
@@ -379,16 +380,13 @@ public class DebuggerSession implements AbstractDebuggerSession {
}
@Nullable
- protected ExecutionResult attach(@NotNull final Executor executor,
- @NotNull final ProgramRunner runner,
- final ModuleRunProfile profile,
- final RunProfileState state,
- final RemoteConnection remoteConnection,
- final boolean pollConnection) throws ExecutionException {
- return attach(new DefaultDebugEnvironment(myDebugProcess.getProject(),
- executor,
- runner,
- profile,
+ protected ExecutionResult attach(@NotNull Executor executor,
+ @NotNull ProgramRunner runner,
+ @NotNull ModuleRunProfile profile,
+ @NotNull RunProfileState state,
+ RemoteConnection remoteConnection,
+ boolean pollConnection) throws ExecutionException {
+ return attach(new DefaultDebugEnvironment(new ExecutionEnvironmentBuilder(myDebugProcess.getProject(), executor).runProfile(profile).runner(runner).build(),
state,
remoteConnection,
pollConnection));
diff --git a/java/debugger/impl/src/com/intellij/debugger/impl/GenericDebuggerRunner.java b/java/debugger/impl/src/com/intellij/debugger/impl/GenericDebuggerRunner.java
index 50f525dc5185..c6491a2b8a3f 100644
--- a/java/debugger/impl/src/com/intellij/debugger/impl/GenericDebuggerRunner.java
+++ b/java/debugger/impl/src/com/intellij/debugger/impl/GenericDebuggerRunner.java
@@ -30,6 +30,7 @@ import com.intellij.execution.Executor;
import com.intellij.execution.configurations.*;
import com.intellij.execution.executors.DefaultDebugExecutor;
import com.intellij.execution.runners.ExecutionEnvironment;
+import com.intellij.execution.runners.ExecutionEnvironmentBuilder;
import com.intellij.execution.runners.JavaPatchableProgramRunner;
import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.openapi.fileEditor.FileDocumentManager;
@@ -58,51 +59,43 @@ public class GenericDebuggerRunner extends JavaPatchableProgramRunner<GenericDeb
}
@Override
- protected RunContentDescriptor doExecute(@NotNull final Project project,
- @NotNull final RunProfileState state,
- final RunContentDescriptor contentToReuse,
- @NotNull final ExecutionEnvironment env) throws ExecutionException {
+ protected RunContentDescriptor doExecute(@NotNull Project project,
+ @NotNull RunProfileState state,
+ @Nullable RunContentDescriptor contentToReuse,
+ @NotNull ExecutionEnvironment env) throws ExecutionException {
FileDocumentManager.getInstance().saveAllDocuments();
- return createContentDescriptor(project, state, contentToReuse, env);
+ return createContentDescriptor(state, contentToReuse == null || env.getContentToReuse() == contentToReuse
+ ? env
+ : new ExecutionEnvironmentBuilder(env).contentToReuse(contentToReuse).build());
}
@Nullable
- protected RunContentDescriptor createContentDescriptor(Project project, RunProfileState state,
- RunContentDescriptor contentToReuse,
- ExecutionEnvironment env) throws ExecutionException {
+ protected RunContentDescriptor createContentDescriptor(@NotNull RunProfileState state, @NotNull ExecutionEnvironment environment) throws ExecutionException {
if (state instanceof JavaCommandLine) {
final JavaParameters parameters = ((JavaCommandLine)state).getJavaParameters();
- runCustomPatchers(parameters, env.getExecutor(), env.getRunProfile());
+ runCustomPatchers(parameters, environment.getExecutor(), environment.getRunProfile());
RemoteConnection connection = DebuggerManagerImpl.createDebugParameters(parameters, true, DebuggerSettings.getInstance().DEBUGGER_TRANSPORT, "", false);
- return attachVirtualMachine(project, state, contentToReuse, env, connection, true);
+ return attachVirtualMachine(state, environment, connection, true);
}
if (state instanceof PatchedRunnableState) {
- final RemoteConnection connection = doPatch(new JavaParameters(), env.getRunnerSettings());
- return attachVirtualMachine(project, state, contentToReuse, env, connection, true);
+ final RemoteConnection connection = doPatch(new JavaParameters(), environment.getRunnerSettings());
+ return attachVirtualMachine(state, environment, connection, true);
}
if (state instanceof RemoteState) {
- final RemoteConnection connection = createRemoteDebugConnection((RemoteState)state, env.getRunnerSettings());
- return attachVirtualMachine(project, state, contentToReuse, env, connection, false);
+ final RemoteConnection connection = createRemoteDebugConnection((RemoteState)state, environment.getRunnerSettings());
+ return attachVirtualMachine(state, environment, connection, false);
}
return null;
}
@Nullable
- protected RunContentDescriptor attachVirtualMachine(final Project project, RunProfileState state,
- RunContentDescriptor contentToReuse,
- ExecutionEnvironment env, RemoteConnection connection, boolean pollConnection)
- throws ExecutionException {
- DefaultDebugUIEnvironment debugEnvironment = new DefaultDebugUIEnvironment(project,
- env.getExecutor(),
- this,
- env,
- state,
- contentToReuse,
- connection,
- pollConnection);
- DebugEnvironment environment = debugEnvironment.getEnvironment();
- final DebuggerSession debuggerSession = DebuggerManagerEx.getInstanceEx(project).attachVirtualMachine(environment);
+ protected RunContentDescriptor attachVirtualMachine(RunProfileState state,
+ @NotNull ExecutionEnvironment env,
+ RemoteConnection connection,
+ boolean pollConnection) throws ExecutionException {
+ DebugEnvironment environment = new DefaultDebugUIEnvironment(env, state, connection, pollConnection).getEnvironment();
+ final DebuggerSession debuggerSession = DebuggerManagerEx.getInstanceEx(env.getProject()).attachVirtualMachine(environment);
if (debuggerSession == null) {
return null;
}
@@ -118,22 +111,20 @@ public class GenericDebuggerRunner extends JavaPatchableProgramRunner<GenericDeb
debugProcess.putUserData(BatchEvaluator.REMOTE_SESSION_KEY, Boolean.TRUE);
}
- XDebugSession debugSession =
- XDebuggerManager.getInstance(project).startSession(this, env, contentToReuse, new XDebugProcessStarter() {
- @Override
- @NotNull
- public XDebugProcess start(@NotNull XDebugSession session) {
- XDebugSessionImpl sessionImpl = (XDebugSessionImpl)session;
- ExecutionResult executionResult = debugProcess.getExecutionResult();
- sessionImpl.addExtraActions(executionResult.getActions());
- if (executionResult instanceof DefaultExecutionResult) {
- sessionImpl.addRestartActions(((DefaultExecutionResult)executionResult).getRestartActions());
- sessionImpl.addExtraStopActions(((DefaultExecutionResult)executionResult).getAdditionalStopActions());
- }
- return new JavaDebugProcess(session, debuggerSession);
+ return XDebuggerManager.getInstance(env.getProject()).startSession(env, new XDebugProcessStarter() {
+ @Override
+ @NotNull
+ public XDebugProcess start(@NotNull XDebugSession session) {
+ XDebugSessionImpl sessionImpl = (XDebugSessionImpl)session;
+ ExecutionResult executionResult = debugProcess.getExecutionResult();
+ sessionImpl.addExtraActions(executionResult.getActions());
+ if (executionResult instanceof DefaultExecutionResult) {
+ sessionImpl.addRestartActions(((DefaultExecutionResult)executionResult).getRestartActions());
+ sessionImpl.addExtraStopActions(((DefaultExecutionResult)executionResult).getAdditionalStopActions());
}
- });
- return debugSession.getRunContentDescriptor();
+ return new JavaDebugProcess(session, debuggerSession);
+ }
+ }).getRunContentDescriptor();
}
private static RemoteConnection createRemoteDebugConnection(RemoteState connection, final RunnerSettings settings) {
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 3a8505c7dfe8..dd9c01a4aff8 100644
--- a/java/debugger/impl/src/com/intellij/debugger/settings/UserRenderersConfigurable.java
+++ b/java/debugger/impl/src/com/intellij/debugger/settings/UserRenderersConfigurable.java
@@ -44,16 +44,19 @@ public final class UserRenderersConfigurable extends JPanel implements Configura
private final JPanel myNameFieldPanel;
private final JTextField myNameField;
- private ElementsChooser<NodeRenderer> myRendererChooser;
+ private final ElementsChooser<NodeRenderer> myRendererChooser;
private NodeRenderer myCurrentRenderer = null;
private final CompoundRendererConfigurable myRendererDataConfigurable = new CompoundRendererConfigurable();
public UserRenderersConfigurable() {
super(new BorderLayout(4, 0));
+ myRendererChooser = new ElementsChooser<NodeRenderer>(true);
+ setupRenderersList();
+
JPanel left = new JPanel(new BorderLayout());
left.add(createToolbar(), BorderLayout.NORTH);
- left.add(createRenderersList(), BorderLayout.CENTER);
+ left.add(myRendererChooser, BorderLayout.CENTER);
myNameField = new JTextField();
myNameFieldPanel = new JPanel(new BorderLayout());
@@ -85,8 +88,7 @@ public final class UserRenderersConfigurable extends JPanel implements Configura
return this;
}
- private JComponent createRenderersList() {
- myRendererChooser = new ElementsChooser<NodeRenderer>(true);
+ private void setupRenderersList() {
myRendererChooser.getEmptyText().setText(DebuggerBundle.message("text.user.renderers.configurable.no.renderers"));
myRendererChooser.addElementsMarkListener(new ElementsChooser.ElementsMarkListener<NodeRenderer>() {
@@ -103,7 +105,6 @@ public final class UserRenderersConfigurable extends JPanel implements Configura
}
}
});
- return myRendererChooser;
}
private void updateCurrentRenderer(List<NodeRenderer> selectedElements) {
@@ -135,6 +136,7 @@ public final class UserRenderersConfigurable extends JPanel implements Configura
myRendererDataConfigurable.setRenderer(renderer);
}
+ @NotNull
private JComponent createToolbar() {
final DefaultActionGroup group = new DefaultActionGroup();
group.add(new AddAction());
@@ -142,8 +144,7 @@ public final class UserRenderersConfigurable extends JPanel implements Configura
group.add(new CopyAction());
group.add(new MoveAction(true));
group.add(new MoveAction(false));
- final ActionToolbar toolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, group, true);
- return toolbar.getComponent();
+ return ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, group, true).getComponent();
}
@Override
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 13336358620b..14077c698284 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerPanelsManager.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerPanelsManager.java
@@ -15,11 +15,13 @@
*/
package com.intellij.debugger.ui;
-import com.intellij.debugger.*;
+import com.intellij.debugger.DebugEnvironment;
+import com.intellij.debugger.DebugUIEnvironment;
+import com.intellij.debugger.DebuggerManagerEx;
+import com.intellij.debugger.DefaultDebugUIEnvironment;
import com.intellij.debugger.engine.DebugProcessImpl;
import com.intellij.debugger.engine.JavaDebugProcess;
import com.intellij.debugger.impl.DebuggerContextImpl;
-import com.intellij.debugger.impl.DebuggerContextListener;
import com.intellij.debugger.impl.DebuggerSession;
import com.intellij.debugger.impl.DebuggerStateManager;
import com.intellij.debugger.ui.impl.MainWatchPanel;
@@ -31,19 +33,13 @@ import com.intellij.execution.configurations.RemoteConnection;
import com.intellij.execution.configurations.RunProfileState;
import com.intellij.execution.executors.DefaultDebugExecutor;
import com.intellij.execution.runners.ExecutionEnvironment;
+import com.intellij.execution.runners.ExecutionEnvironmentBuilder;
import com.intellij.execution.runners.ProgramRunner;
-import com.intellij.execution.ui.ExecutionConsole;
-import com.intellij.execution.ui.RunContentDescriptor;
-import com.intellij.execution.ui.RunContentListener;
-import com.intellij.execution.ui.RunContentManager;
-import com.intellij.openapi.Disposable;
+import com.intellij.execution.ui.*;
import com.intellij.openapi.components.ProjectComponent;
import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.editor.colors.EditorColorsListener;
import com.intellij.openapi.editor.colors.EditorColorsManager;
-import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Disposer;
import com.intellij.xdebugger.XDebugProcess;
import com.intellij.xdebugger.XDebugProcessStarter;
import com.intellij.xdebugger.XDebugSession;
@@ -96,21 +92,30 @@ public class DebuggerPanelsManager implements ProjectComponent {
}
@Nullable
+ @Deprecated
+ /**
+ * @deprecated to remove in IDEA 15
+ */
public RunContentDescriptor attachVirtualMachine(Executor executor,
- ProgramRunner runner,
- ExecutionEnvironment environment,
+ @NotNull ProgramRunner runner,
+ @NotNull ExecutionEnvironment environment,
RunProfileState state,
RunContentDescriptor reuseContent,
RemoteConnection remoteConnection,
boolean pollConnection) throws ExecutionException {
- return attachVirtualMachine(new DefaultDebugUIEnvironment(myProject,
- executor,
- runner,
- environment,
- state,
- reuseContent,
- remoteConnection,
- pollConnection));
+ return attachVirtualMachine(new ExecutionEnvironmentBuilder(environment)
+ .executor(executor)
+ .runner(runner)
+ .contentToReuse(reuseContent)
+ .build(), state, remoteConnection, pollConnection);
+ }
+
+ @Nullable
+ public RunContentDescriptor attachVirtualMachine(@NotNull ExecutionEnvironment environment,
+ RunProfileState state,
+ RemoteConnection remoteConnection,
+ boolean pollConnection) throws ExecutionException {
+ return attachVirtualMachine(new DefaultDebugUIEnvironment(environment, state, remoteConnection, pollConnection));
}
@Nullable
@@ -144,47 +149,43 @@ public class DebuggerPanelsManager implements ProjectComponent {
}
+ @Override
public void projectOpened() {
- final RunContentManager contentManager = myExecutionManager.getContentManager();
- LOG.assertTrue(contentManager != null, "Content manager is null");
-
- final RunContentListener myContentListener = new RunContentListener() {
- public void contentSelected(RunContentDescriptor descriptor) {
- DebuggerSession session = getSession(myProject, descriptor.getExecutionConsole());
-
- if (session != null) {
- getContextManager()
- .setState(session.getContextManager().getContext(), session.getState(), DebuggerSession.EVENT_CONTEXT, null);
- }
- else {
- getContextManager()
- .setState(DebuggerContextImpl.EMPTY_CONTEXT, DebuggerSession.STATE_DISPOSED, DebuggerSession.EVENT_CONTEXT, null);
+ myProject.getMessageBus().connect(myProject).subscribe(RunContentManager.TOPIC, new RunContentWithExecutorListener() {
+ @Override
+ public void contentSelected(@Nullable RunContentDescriptor descriptor, @NotNull Executor executor) {
+ if (executor == DefaultDebugExecutor.getDebugExecutorInstance()) {
+ DebuggerSession session = descriptor == null ? null : getSession(myProject, descriptor.getExecutionConsole());
+ if (session != null) {
+ getContextManager().setState(session.getContextManager().getContext(), session.getState(), DebuggerSession.EVENT_CONTEXT, null);
+ }
+ else {
+ getContextManager().setState(DebuggerContextImpl.EMPTY_CONTEXT, DebuggerSession.STATE_DISPOSED, DebuggerSession.EVENT_CONTEXT, null);
+ }
}
}
- public void contentRemoved(RunContentDescriptor descriptor) {
- }
- };
-
- contentManager.addRunContentListener(myContentListener, DefaultDebugExecutor.getDebugExecutorInstance());
- Disposer.register(myProject, new Disposable() {
- public void dispose() {
- contentManager.removeRunContentListener(myContentListener);
+ @Override
+ public void contentRemoved(@Nullable RunContentDescriptor descriptor, @NotNull Executor executor) {
}
});
}
+ @Override
public void projectClosed() {
}
+ @Override
@NotNull
public String getComponentName() {
return "DebuggerPanelsManager";
}
+ @Override
public void initComponent() {
}
+ @Override
public void disposeComponent() {
}
@@ -218,7 +219,7 @@ public class DebuggerPanelsManager implements ProjectComponent {
}
}
- private DebuggerSession getSession(Project project, ExecutionConsole console) {
+ private static DebuggerSession getSession(Project project, ExecutionConsole console) {
XDebugSession session = XDebuggerManager.getInstance(project).getDebugSession(console);
if (session != null) {
XDebugProcess process = session.getDebugProcess();
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerSessionTab.java b/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerSessionTab.java
index 600efd834e56..47fc217751a4 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerSessionTab.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerSessionTab.java
@@ -72,7 +72,7 @@ import javax.swing.tree.TreePath;
import java.util.List;
public class DebuggerSessionTab extends DebuggerSessionTabBase implements Disposable {
- private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.ui.DebuggerSessionTab");
+ private static final Logger LOG = Logger.getInstance(DebuggerSessionTab.class);
private final VariablesPanel myVariablesPanel;
private final MainWatchPanel myWatchPanel;
@@ -90,6 +90,7 @@ public class DebuggerSessionTab extends DebuggerSessionTabBase implements Dispos
public DebuggerSessionTab(final Project project, final String sessionName, @NotNull final DebugUIEnvironment environment,
@NotNull DebuggerSession debuggerSession) {
super(project, "JavaDebugger", sessionName, debuggerSession.getSearchScope());
+
myDebuggerSession = debuggerSession;
myDebugUIEnvironment = environment;
@@ -129,11 +130,9 @@ public class DebuggerSessionTab extends DebuggerSessionTabBase implements Dispos
topToolbar.add(Separator.getInstance(), new Constraints(Anchor.AFTER, DebuggerActions.POP_FRAME));
myUi.getOptions().setTopToolbar(topToolbar, ActionPlaces.DEBUGGER_TOOLBAR);
-
myWatchPanel = new MainWatchPanel(getProject(), getContextManager());
myFramesPanel = new FramesPanel(getProject(), getContextManager());
-
final AlertIcon breakpointAlert = new AlertIcon(AllIcons.Debugger.BreakpointAlert);
// watches
@@ -271,7 +270,7 @@ public class DebuggerSessionTab extends DebuggerSessionTabBase implements Dispos
}
console.setActions(consoleActions, ActionPlaces.DEBUGGER_TOOLBAR, myConsole.getPreferredFocusableComponent());
- myDebugUIEnvironment.initLogs(myRunContentDescriptor, getLogManager());
+ myDebugUIEnvironment.initLogs(myRunContentDescriptor, myManager);
DefaultActionGroup leftToolbar = new DefaultActionGroup();
@@ -348,7 +347,6 @@ public class DebuggerSessionTab extends DebuggerSessionTabBase implements Dispos
if (action != null) group.add(action);
}
-
@Override
public void dispose() {
disposeSession();
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/XBreakpointGroupingByClassRule.java b/java/debugger/impl/src/com/intellij/debugger/ui/XBreakpointGroupingByClassRule.java
index 437cd85bedf8..4f655274ebba 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/XBreakpointGroupingByClassRule.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/XBreakpointGroupingByClassRule.java
@@ -68,6 +68,6 @@ class XBreakpointGroupingByClassRule<B> extends XBreakpointGroupingRule<B, XBrea
@Nullable
@Override
public Icon getIcon() {
- return AllIcons.Nodes.Class;
+ return AllIcons.Actions.GroupByClass;
}
}
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/VariablesPanel.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/VariablesPanel.java
index 1bda597586e8..ead97cba1c63 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/VariablesPanel.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/VariablesPanel.java
@@ -147,5 +147,13 @@ public class VariablesPanel extends DebuggerTreePanel implements DataProvider {
buildTreeAndRestoreState(stackFrame);
}
}
+
+ @Override
+ protected void clear() {
+ }
+
+ @Override
+ public void processSessionEvent(@NotNull SessionEvent event) {
+ }
}
}
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 3190e19dcee4..27280b193c2c 100644
--- a/java/execution/impl/src/com/intellij/execution/impl/DefaultJavaProgramRunner.java
+++ b/java/execution/impl/src/com/intellij/execution/impl/DefaultJavaProgramRunner.java
@@ -99,24 +99,19 @@ public class DefaultJavaProgramRunner extends JavaPatchableProgramRunner {
onProcessStarted(env.getRunnerSettings(), executionResult);
- final RunContentBuilder contentBuilder = new RunContentBuilder(this, executionResult, env);
+ final RunContentBuilder contentBuilder = new RunContentBuilder(executionResult, env);
Disposer.register(project, contentBuilder);
if (shouldAddDefaultActions) {
addDefaultActions(contentBuilder);
}
-
- RunContentDescriptor runContent = contentBuilder.showRunContent(contentToReuse);
-
- AnAction[] actions = createActions(contentBuilder.getExecutionResult());
-
- for (AnAction action : actions) {
- contentBuilder.addAction(action);
- }
-
- return runContent;
+ return contentBuilder.showRunContent(contentToReuse);
}
- protected AnAction[] createActions(final ExecutionResult executionResult) {
+ @Deprecated
+ /**
+ * @deprecated to remove in IDEA 14
+ */
+ protected AnAction[] createActions(@SuppressWarnings("UnusedParameters") final ExecutionResult executionResult) {
return AnAction.EMPTY_ARRAY;
}
diff --git a/java/execution/openapi/src/com/intellij/execution/JavaExecutionUtil.java b/java/execution/openapi/src/com/intellij/execution/JavaExecutionUtil.java
index 53861de25c3c..4c59e267b209 100644
--- a/java/execution/openapi/src/com/intellij/execution/JavaExecutionUtil.java
+++ b/java/execution/openapi/src/com/intellij/execution/JavaExecutionUtil.java
@@ -21,7 +21,8 @@ import com.intellij.execution.filters.Filter;
import com.intellij.execution.filters.TextConsoleBuilder;
import com.intellij.execution.filters.TextConsoleBuilderFactory;
import com.intellij.execution.runners.ExecutionEnvironment;
-import com.intellij.execution.runners.ProgramRunner;
+import com.intellij.execution.runners.ExecutionEnvironmentBuilder;
+import com.intellij.execution.runners.ExecutionUtil;
import com.intellij.execution.util.ExecutionErrorDialog;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.module.Module;
@@ -56,13 +57,11 @@ public class JavaExecutionUtil {
public static boolean executeRun(@NotNull final Project project, String contentName, Icon icon, DataContext dataContext, Filter[] filters) throws ExecutionException {
final JavaParameters cmdLine = JavaParameters.JAVA_PARAMETERS.getData(dataContext);
final DefaultRunProfile profile = new DefaultRunProfile(project, cmdLine, contentName, icon, filters);
- final ProgramRunner runner = RunnerRegistry.getInstance().getRunner(DefaultRunExecutor.EXECUTOR_ID, profile);
- if (runner != null) {
- Executor executor = DefaultRunExecutor.getRunExecutorInstance();
- runner.execute(new ExecutionEnvironment(profile, executor, project, null));
+ ExecutionEnvironmentBuilder builder = ExecutionEnvironmentBuilder.createOrNull(project, DefaultRunExecutor.getRunExecutorInstance(), profile);
+ if (builder != null) {
+ builder.buildAndExecute();
return true;
}
-
return false;
}
@@ -114,7 +113,7 @@ public class JavaExecutionUtil {
}
@Override
- public RunProfileState getState(@NotNull final Executor executor, @NotNull final ExecutionEnvironment env) throws ExecutionException {
+ public RunProfileState getState(@NotNull final Executor executor, @NotNull final ExecutionEnvironment env) {
final JavaCommandLineState state = new JavaCommandLineState(env) {
@Override
protected JavaParameters createJavaParameters() {
@@ -146,7 +145,7 @@ public class JavaExecutionUtil {
}
/**
- * {@link JavaExecutionUtil#getPresentableClassName(java.lang.String)}
+ * {@link JavaExecutionUtil#getPresentableClassName(java.lang.String)}
*/
@Deprecated
@Nullable
diff --git a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/FacetLibrariesValidatorImpl.java b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/FacetLibrariesValidatorImpl.java
index 63ba7def99d5..bb5735d109e0 100644
--- a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/FacetLibrariesValidatorImpl.java
+++ b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/FacetLibrariesValidatorImpl.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.
@@ -72,6 +72,7 @@ public class FacetLibrariesValidatorImpl extends FacetLibrariesValidator {
onChange();
}
+ @NotNull
public ValidationResult check() {
if (myRequiredLibraries == null) {
return ValidationResult.OK;
diff --git a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/FrameworkLibraryValidatorImpl.java b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/FrameworkLibraryValidatorImpl.java
index be22534d2754..36a77fc7e18a 100644
--- a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/FrameworkLibraryValidatorImpl.java
+++ b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/FrameworkLibraryValidatorImpl.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.
@@ -27,6 +27,7 @@ import com.intellij.openapi.roots.ui.configuration.libraries.CustomLibraryDescri
import com.intellij.openapi.roots.ui.configuration.libraries.LibraryPresentationManager;
import com.intellij.openapi.util.Ref;
import com.intellij.util.Processor;
+import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.util.Set;
@@ -50,6 +51,7 @@ public class FrameworkLibraryValidatorImpl extends FrameworkLibraryValidator {
myLibraryCategoryName = libraryCategoryName;
}
+ @NotNull
@Override
public ValidationResult check() {
final Set<? extends LibraryKind> libraryKinds = myLibraryDescription.getSuitableLibraryKinds();
diff --git a/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTemplateList.java b/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTemplateList.java
index 57918b1843d1..be586661f0d3 100644
--- a/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTemplateList.java
+++ b/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTemplateList.java
@@ -17,7 +17,7 @@ package com.intellij.ide.projectWizard;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.openapi.ui.Messages;
-import com.intellij.openapi.ui.popup.ListItemDescriptor;
+import com.intellij.openapi.ui.popup.ListItemDescriptorAdapter;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.IconLoader;
@@ -57,7 +57,7 @@ public class ProjectTemplateList extends JPanel {
super(new BorderLayout());
add(myPanel, BorderLayout.CENTER);
- GroupedItemsListRenderer renderer = new GroupedItemsListRenderer(new ListItemDescriptor<ProjectTemplate>() {
+ GroupedItemsListRenderer renderer = new GroupedItemsListRenderer(new ListItemDescriptorAdapter<ProjectTemplate>() {
@Nullable
@Override
public String getTextFor(ProjectTemplate value) {
@@ -66,26 +66,9 @@ public class ProjectTemplateList extends JPanel {
@Nullable
@Override
- public String getTooltipFor(ProjectTemplate value) {
- return null;
- }
-
- @Nullable
- @Override
public Icon getIconFor(ProjectTemplate value) {
return value.getIcon();
}
-
- @Override
- public boolean hasSeparatorAboveOf(ProjectTemplate value) {
- return false;
- }
-
- @Nullable
- @Override
- public String getCaptionAboveOf(ProjectTemplate value) {
- return null;
- }
}) {
@Override
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 8fca04c7aa69..10e11f74077f 100644
--- a/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypeStep.java
+++ b/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypeStep.java
@@ -42,7 +42,7 @@ 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.ui.Messages;
-import com.intellij.openapi.ui.popup.ListItemDescriptor;
+import com.intellij.openapi.ui.popup.ListItemDescriptorAdapter;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Disposer;
@@ -143,7 +143,7 @@ public class ProjectTypeStep extends ModuleWizardStep implements SettingsStep, D
updateSelection();
}
});
- myProjectTypeList.setCellRenderer(new GroupedItemsListRenderer(new ListItemDescriptor<TemplatesGroup>() {
+ myProjectTypeList.setCellRenderer(new GroupedItemsListRenderer(new ListItemDescriptorAdapter<TemplatesGroup>() {
@Nullable
@Override
public String getTextFor(TemplatesGroup value) {
@@ -171,12 +171,6 @@ public class ProjectTypeStep extends ModuleWizardStep implements SettingsStep, D
return !Comparing.equal(upper.getParentGroup(), value.getParentGroup()) &&
!Comparing.equal(upper.getName(), value.getParentGroup());
}
-
- @Nullable
- @Override
- public String getCaptionAboveOf(TemplatesGroup value) {
- return null;
- }
}) {
@Override
protected JComponent createItemComponent() {
diff --git a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/FrameworkSupportNodeBase.java b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/FrameworkSupportNodeBase.java
index 72e793e53903..2fee50a4301b 100644
--- a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/FrameworkSupportNodeBase.java
+++ b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/FrameworkSupportNodeBase.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.ide.util.newProjectWizard;
import com.intellij.framework.FrameworkOrGroup;
@@ -47,7 +62,7 @@ public abstract class FrameworkSupportNodeBase<T extends FrameworkOrGroup> exten
}
});
for (FrameworkSupportNodeBase node : nodes) {
- sortByName(node.children, null);
+ sortByName((List)node.children, null);
}
}
@@ -68,7 +83,7 @@ public abstract class FrameworkSupportNodeBase<T extends FrameworkOrGroup> exten
@NotNull
public List<FrameworkSupportNodeBase> getChildren() {
- return children != null ? children : Collections.<FrameworkSupportNodeBase>emptyList();
+ return children != null ? (List)children : Collections.<FrameworkSupportNodeBase>emptyList();
}
public FrameworkSupportNodeBase getParentNode() {
diff --git a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/ProjectTypesList.java b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/ProjectTypesList.java
index 2872e0deff50..7a502443fcdb 100644
--- a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/ProjectTypesList.java
+++ b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/ProjectTypesList.java
@@ -23,7 +23,7 @@ import com.intellij.openapi.actionSystem.CustomShortcutSet;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
-import com.intellij.openapi.ui.popup.ListItemDescriptor;
+import com.intellij.openapi.ui.popup.ListItemDescriptorAdapter;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.platform.ProjectTemplate;
@@ -114,7 +114,7 @@ public class ProjectTypesList implements Disposable {
}
});
- myList.setCellRenderer(new GroupedItemsListRenderer(new ListItemDescriptor() {
+ myList.setCellRenderer(new GroupedItemsListRenderer(new ListItemDescriptorAdapter() {
@Nullable
@Override
public String getTextFor(Object value) {
@@ -123,12 +123,6 @@ public class ProjectTypesList implements Disposable {
@Nullable
@Override
- public String getTooltipFor(Object value) {
- return null;
- }
-
- @Nullable
- @Override
public Icon getIconFor(Object value) {
return ((TemplateItem)value).getIcon();
}
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 f24153739031..7554019e5473 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
@@ -64,6 +64,8 @@ public class ProjectJdksConfigurable extends MasterDetailsComponent {
myProject = project;
myProjectJdksModel = sdksModel;
initTree();
+ myToReInitWholePanel = true;
+ reInitWholePanelIfNeeded();
}
@Override
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 355888b02a42..abe085cca457 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,10 +20,7 @@ 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.Gray;
-import com.intellij.ui.JBColor;
-import com.intellij.ui.ScrollPaneFactory;
-import com.intellij.ui.SeparatorWithText;
+import com.intellij.ui.*;
import com.intellij.ui.components.JBList;
import com.intellij.ui.components.panels.NonOpaquePanel;
import com.intellij.ui.navigation.History;
@@ -118,9 +115,18 @@ public class SidePanel extends JPanel {
@Override
protected void paintComponent(Graphics g) {
if (Registry.is("ide.new.project.settings")) {
- g.setColor(new JBColor(POPUP_SEPARATOR_FOREGROUND, Gray._80));
+ final JBColor separatorColor = new JBColor(POPUP_SEPARATOR_FOREGROUND, Gray._80);
+ g.setColor(separatorColor);
if ("--".equals(getCaption())) {
- g.drawLine(0, getHeight()/ 2, getWidth(), getHeight() /2);
+ final GraphicsConfig config = GraphicsUtil.setupAAPainting(g);
+ final int h = getHeight() / 2;
+ g.drawLine(30, h, getWidth() - 30, h);
+ ((Graphics2D)g).setPaint(new GradientPaint(5, h, ColorUtil.toAlpha(separatorColor, 0), 30, h, separatorColor));
+ g.drawLine(5, h, 30, h);
+ ((Graphics2D)g).setPaint(
+ new GradientPaint(getWidth() - 5, h, ColorUtil.toAlpha(separatorColor, 0), getWidth() - 30, h, separatorColor));
+ g.drawLine(getWidth() - 5, h, getWidth() - 30, h);
+ config.restore();
return;
}
Rectangle viewR = new Rectangle(0, getVgap(), getWidth() - 1, getHeight() - getVgap() - 1);
diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java
index 7404d1fbfae3..b85fb167f6e3 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java
@@ -889,6 +889,11 @@ public class HighlightUtil extends HighlightUtilBase {
PsiModifier.STRICTFP.equals(modifier) || PsiModifier.SYNCHRONIZED.equals(modifier)) {
isAllowed &= modifierOwnerParent instanceof PsiClass && !((PsiClass)modifierOwnerParent).isInterface();
}
+
+ if (containingClass != null && containingClass.isAnnotationType()) {
+ isAllowed &= !PsiModifier.STATIC.equals(modifier);
+ isAllowed &= !PsiModifier.DEFAULT.equals(modifier);
+ }
}
else if (modifierOwner instanceof PsiField) {
if (PsiModifier.PRIVATE.equals(modifier) || PsiModifier.PROTECTED.equals(modifier) || PsiModifier.TRANSIENT.equals(modifier) ||
diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java
index cbfb5f4f5d65..095912a20094 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java
@@ -257,8 +257,13 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
}
myHolder.add(AnnotationsHighlightUtil.checkValidAnnotationType(method.getReturnTypeElement()));
- myHolder.add(AnnotationsHighlightUtil.checkCyclicMemberType(method.getReturnTypeElement(), method.getContainingClass()));
+ final PsiClass aClass = method.getContainingClass();
+ myHolder.add(AnnotationsHighlightUtil.checkCyclicMemberType(method.getReturnTypeElement(), aClass));
myHolder.add(AnnotationsHighlightUtil.checkClashesWithSuperMethods(method));
+
+ if (!myHolder.hasErrorResults() && aClass != null) {
+ myHolder.add(HighlightMethodUtil.checkDuplicateMethod(aClass, method, getDuplicateMethods(aClass)));
+ }
}
@Override
@@ -1213,6 +1218,13 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
final String accessProblem = HighlightUtil.buildProblemWithAccessDescription(expression, result);
HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(accessProblem).create();
myHolder.add(info);
+ } else {
+ final TextAttributesScheme colorsScheme = myHolder.getColorsScheme();
+ if (method instanceof PsiMethod) {
+ final PsiElement methodNameElement = expression.getReferenceNameElement();
+ myHolder.add(HighlightNamesUtil.highlightMethodName((PsiMethod)method, methodNameElement, false, colorsScheme));
+ }
+ myHolder.add(HighlightNamesUtil.highlightClassNameInQualifier(expression, colorsScheme));
}
if (!myHolder.hasErrorResults()) {
final PsiType functionalInterfaceType = expression.getFunctionalInterfaceType();
@@ -1222,11 +1234,6 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
myHolder.add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression)
.descriptionAndTooltip(functionalInterfaceType.getPresentableText() + " is not a functional interface").create());
}
- else if (LambdaUtil.dependsOnTypeParams(functionalInterfaceType, functionalInterfaceType, expression)) {
- HighlightInfo result1 =
- HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip("Cyclic inference").create();
- myHolder.add(result1); //todo[ann] append not inferred type params info
- }
}
if (!myHolder.hasErrorResults()) {
final PsiElement referenceNameElement = expression.getReferenceNameElement();
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/JavaSuppressionUtil.java b/java/java-analysis-impl/src/com/intellij/codeInspection/JavaSuppressionUtil.java
index 52cb18dc9131..1751468084dd 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/JavaSuppressionUtil.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/JavaSuppressionUtil.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.
@@ -35,6 +35,7 @@ import com.intellij.psi.javadoc.PsiDocTag;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.IncorrectOperationException;
+import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -42,14 +43,13 @@ import javax.annotation.Generated;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
-import java.util.HashSet;
import java.util.regex.Matcher;
public class JavaSuppressionUtil {
public static final String SUPPRESS_INSPECTIONS_ANNOTATION_NAME = "java.lang.SuppressWarnings";
public static boolean alreadyHas14Suppressions(@NotNull PsiDocCommentOwner commentOwner) {
final PsiDocComment docComment = commentOwner.getDocComment();
- return docComment != null && docComment.findTagByName(SuppressionUtil.SUPPRESS_INSPECTIONS_TAG_NAME) != null;
+ return docComment != null && docComment.findTagByName(SuppressionUtilCore.SUPPRESS_INSPECTIONS_TAG_NAME) != null;
}
@Nullable
@@ -63,7 +63,7 @@ public class JavaSuppressionUtil {
else if (element instanceof PsiReferenceExpression) {
final PsiElement psiElement = ((PsiReferenceExpression)element).resolve();
if (psiElement instanceof PsiVariableEx) {
- final Object val = ((PsiVariableEx)psiElement).computeConstantValue(new HashSet<PsiVariable>());
+ final Object val = ((PsiVariableEx)psiElement).computeConstantValue(new THashSet<PsiVariable>());
if (val instanceof String) {
return (String)val;
}
@@ -150,7 +150,7 @@ public class JavaSuppressionUtil {
}
}
if (docComment != null) {
- PsiDocTag inspectionTag = docComment.findTagByName(SuppressionUtil.SUPPRESS_INSPECTIONS_TAG_NAME);
+ PsiDocTag inspectionTag = docComment.findTagByName(SuppressionUtilCore.SUPPRESS_INSPECTIONS_TAG_NAME);
if (inspectionTag != null) {
final PsiElement[] dataElements = inspectionTag.getDataElements();
for (PsiElement dataElement : dataElements) {
@@ -181,7 +181,7 @@ public class JavaSuppressionUtil {
if (element instanceof PsiDocCommentOwner) {
PsiDocComment docComment = ((PsiDocCommentOwner)element).getDocComment();
if (docComment != null) {
- PsiDocTag inspectionTag = docComment.findTagByName(SuppressionUtil.SUPPRESS_INSPECTIONS_TAG_NAME);
+ PsiDocTag inspectionTag = docComment.findTagByName(SuppressionUtilCore.SUPPRESS_INSPECTIONS_TAG_NAME);
if (inspectionTag != null) {
String valueText = "";
for (PsiElement dataElement : inspectionTag.getDataElements()) {
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/StreamApiMigrationInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/StreamApiMigrationInspection.java
index d04ef1bbb295..d4beda08c875 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/StreamApiMigrationInspection.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/StreamApiMigrationInspection.java
@@ -275,10 +275,7 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
final PsiIfStatement ifStmt = extractIfStatement(body);
String foreEachText = wrapInBlock(body);
- String iterated = iteratedValue instanceof PsiCallExpression ||
- iteratedValue instanceof PsiReferenceExpression ||
- iteratedValue instanceof PsiQualifiedExpression ||
- iteratedValue instanceof PsiParenthesizedExpression ? iteratedValue.getText() : "(" + iteratedValue.getText() + ")";
+ String iterated = getIteratedValueText(iteratedValue);
if (ifStmt != null) {
final PsiExpression condition = ifStmt.getCondition();
if (condition != null) {
@@ -359,7 +356,7 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
final PsiIfStatement ifStatement = extractIfStatement(body);
final PsiMethodCallExpression methodCallExpression = extractAddCall(body);
- String iteration = iteratedValue.getText() + ".stream()";
+ String iteration = getIteratedValueText(iteratedValue) + ".stream()";
if (ifStatement != null) {
final PsiExpression condition = ifStatement.getCondition();
if (condition != null) {
@@ -443,6 +440,13 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
}
}
+ private static String getIteratedValueText(PsiExpression iteratedValue) {
+ return iteratedValue instanceof PsiCallExpression ||
+ iteratedValue instanceof PsiReferenceExpression ||
+ iteratedValue instanceof PsiQualifiedExpression ||
+ iteratedValue instanceof PsiParenthesizedExpression ? iteratedValue.getText() : "(" + iteratedValue.getText() + ")";
+ }
+
public static PsiIfStatement extractIfStatement(PsiStatement body) {
PsiIfStatement ifStmt = null;
if (body instanceof PsiIfStatement) {
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/canBeFinal/CanBeFinalInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/canBeFinal/CanBeFinalInspection.java
index 429bd6281eed..3582ce1a293c 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/canBeFinal/CanBeFinalInspection.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/canBeFinal/CanBeFinalInspection.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.
@@ -295,6 +295,7 @@ public class CanBeFinalInspection extends GlobalJavaBatchInspectionTool {
final PsiModifierList modifierList = psiElement.getModifierList();
LOG.assertTrue(modifierList != null);
modifierList.setModifierProperty(PsiModifier.FINAL, true);
+ modifierList.setModifierProperty(PsiModifier.VOLATILE, false);
}
catch (IncorrectOperationException e) {
LOG.error(e);
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/javaDoc/JavaDocLocalInspectionBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/javaDoc/JavaDocLocalInspectionBase.java
index 33cd0040462b..5d6c4bcb59a1 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/javaDoc/JavaDocLocalInspectionBase.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/javaDoc/JavaDocLocalInspectionBase.java
@@ -65,6 +65,7 @@ public class JavaDocLocalInspectionBase extends BaseJavaBatchLocalInspectionTool
}
@NonNls private static final String IGNORE_ACCESSORS_ATTR_NAME = "IGNORE_ACCESSORS";
+ @NonNls private static final String IGNORE_DUPLICATED_THROWS_TAGS_ATTR_NAME = "IGNORE_DUPLICATED_THROWS_TAGS";
public static class Options implements JDOMExternalizable {
@NonNls public String ACCESS_JAVADOC_REQUIRED_FOR = NONE;
@@ -95,7 +96,18 @@ public class JavaDocLocalInspectionBase extends BaseJavaBatchLocalInspectionTool
@NonNls public Options FIELD_OPTIONS = new Options("none", "");
public boolean IGNORE_DEPRECATED = false;
public boolean IGNORE_JAVADOC_PERIOD = true;
+ @Deprecated
public boolean IGNORE_DUPLICATED_THROWS = false;
+
+ private boolean myIgnoreDuplicatedThrows = true;
+ public boolean getIgnoreDuplicatedThrows() {
+ return myIgnoreDuplicatedThrows;
+ }
+
+ public void setIgnoreDuplicatedThrows(boolean ignoreDuplicatedThrows) {
+ myIgnoreDuplicatedThrows = ignoreDuplicatedThrows;
+ }
+
public boolean IGNORE_POINT_TO_ITSELF = false;
public String myAdditionalJavadocTags = "";
@@ -126,6 +138,9 @@ public class JavaDocLocalInspectionBase extends BaseJavaBatchLocalInspectionTool
option.setAttribute("value", String.valueOf(true));
node.addContent(option);
}
+ if (!myIgnoreDuplicatedThrows) {
+ node.addContent(new Element(IGNORE_DUPLICATED_THROWS_TAGS_ATTR_NAME).setAttribute("value", String.valueOf(false)));
+ }
if (!PACKAGE_OPTIONS.ACCESS_JAVADOC_REQUIRED_FOR.equals("none") || !PACKAGE_OPTIONS.REQUIRED_TAGS.isEmpty()) {
PACKAGE_OPTIONS.writeExternal(node);
}
@@ -138,6 +153,10 @@ public class JavaDocLocalInspectionBase extends BaseJavaBatchLocalInspectionTool
if (ignoreAccessorsTag != null) {
myIgnoreSimpleAccessors = Boolean.parseBoolean(ignoreAccessorsTag.getAttributeValue("value"));
}
+ Element ignoreDupThrowsTag = node.getChild(IGNORE_DUPLICATED_THROWS_TAGS_ATTR_NAME);
+ if (ignoreDupThrowsTag != null) {
+ myIgnoreDuplicatedThrows = Boolean.parseBoolean(ignoreDupThrowsTag.getAttributeValue("value"));
+ }
PACKAGE_OPTIONS.readExternal(node);
}
@@ -1000,7 +1019,7 @@ public class JavaDocLocalInspectionBase extends BaseJavaBatchLocalInspectionTool
}
}
}
- else if (!IGNORE_DUPLICATED_THROWS && ("throws".equals(tag.getName()) || "exception".equals(tag.getName()))) {
+ else if (!myIgnoreDuplicatedThrows && ("throws".equals(tag.getName()) || "exception".equals(tag.getName()))) {
PsiDocTagValue value = tag.getValueElement();
if (value != null) {
final PsiElement firstChild = value.getFirstChild();
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/unneededThrows/RedundantThrows.java b/java/java-analysis-impl/src/com/intellij/codeInspection/unneededThrows/RedundantThrows.java
index 6c611f707d6c..ff1f366c42e5 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/unneededThrows/RedundantThrows.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/unneededThrows/RedundantThrows.java
@@ -294,7 +294,10 @@ public class RedundantThrows extends GlobalJavaBatchInspectionTool {
if (refMethod != null) {
for (RefMethod refDerived : refMethod.getDerivedMethods()) {
- removeException(refDerived, exceptionType, refsToDelete, (PsiMethod)refDerived.getElement());
+ PsiModifierListOwner method = refDerived.getElement();
+ if (method != null) {
+ removeException(refDerived, exceptionType, refsToDelete, (PsiMethod)method);
+ }
}
} else {
final Query<Pair<PsiMethod,PsiMethod>> query = AllOverridingMethodsSearch.search(psiMethod.getContainingClass());
diff --git a/java/java-analysis-impl/src/com/intellij/refactoring/util/duplicates/DuplicatesFinder.java b/java/java-analysis-impl/src/com/intellij/refactoring/util/duplicates/DuplicatesFinder.java
index 66c4f9da2c4f..846e1fd5d0ee 100644
--- a/java/java-analysis-impl/src/com/intellij/refactoring/util/duplicates/DuplicatesFinder.java
+++ b/java/java-analysis-impl/src/com/intellij/refactoring/util/duplicates/DuplicatesFinder.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.
@@ -108,9 +108,9 @@ public class DuplicatesFinder {
}
@Nullable
- public Match isDuplicate(PsiElement element, boolean ignoreParameterTypes) {
+ public Match isDuplicate(PsiElement element, boolean ignoreParameterTypesAndPostVariableUsages) {
annotatePattern();
- Match match = isDuplicateFragment(element, ignoreParameterTypes);
+ Match match = isDuplicateFragment(element, ignoreParameterTypesAndPostVariableUsages);
deannotatePattern();
return match;
}
@@ -163,7 +163,7 @@ public class DuplicatesFinder {
@Nullable
- private Match isDuplicateFragment(PsiElement candidate, boolean ignoreParameterTypes) {
+ private Match isDuplicateFragment(PsiElement candidate, boolean ignoreParameterTypesAndPostVariableUsages) {
for (PsiElement pattern : myPattern) {
if (PsiTreeUtil.isAncestor(pattern, candidate, false)) return null;
}
@@ -196,12 +196,12 @@ public class DuplicatesFinder {
}
}
- final Match match = new Match(candidates.get(0), candidates.get(candidates.size() - 1), ignoreParameterTypes);
+ final Match match = new Match(candidates.get(0), candidates.get(candidates.size() - 1), ignoreParameterTypesAndPostVariableUsages);
for (int i = 0; i < myPattern.length; i++) {
if (!matchPattern(myPattern[i], candidates.get(i), candidates, match)) return null;
}
- if (checkPostVariableUsages(candidates, match)) return null;
+ if (!ignoreParameterTypesAndPostVariableUsages && checkPostVariableUsages(candidates, match)) return null;
return match;
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java
index 49379c2c4f3e..2a9fc2f4a79f 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java
@@ -19,6 +19,7 @@ import com.intellij.codeInsight.TailType;
import com.intellij.codeInsight.completion.scope.CompletionElement;
import com.intellij.codeInsight.completion.scope.JavaCompletionProcessor;
import com.intellij.codeInsight.editorActions.wordSelection.DocTagSelectioner;
+import com.intellij.codeInsight.javadoc.JavaDocUtil;
import com.intellij.codeInsight.lookup.*;
import com.intellij.codeInspection.InspectionProfile;
import com.intellij.codeInspection.SuppressionUtil;
@@ -391,16 +392,19 @@ public class JavaDocCompletionContributor extends CompletionContributor {
private static void shortenReferences(final Project project, final Editor editor, InsertionContext context, int offset) {
PsiDocumentManager.getInstance(project).commitDocument(editor.getDocument());
final PsiElement element = context.getFile().findElementAt(offset);
- final PsiDocTagValue tagValue = PsiTreeUtil.getParentOfType(element, PsiDocTagValue.class);
- if (tagValue != null) {
- try {
- JavaCodeStyleManager.getInstance(project).shortenClassReferences(tagValue);
- }
- catch (IncorrectOperationException e) {
- LOG.error(e);
+ final PsiDocComment docComment = PsiTreeUtil.getParentOfType(element, PsiDocComment.class);
+ if (!JavaDocUtil.isInsidePackageInfo(docComment)) {
+ final PsiDocTagValue tagValue = PsiTreeUtil.getParentOfType(element, PsiDocTagValue.class);
+ if (tagValue != null) {
+ try {
+ JavaCodeStyleManager.getInstance(project).shortenClassReferences(tagValue);
+ }
+ catch (IncorrectOperationException e) {
+ LOG.error(e);
+ }
}
+ PsiDocumentManager.getInstance(context.getProject()).commitAllDocuments();
}
- PsiDocumentManager.getInstance(context.getProject()).commitAllDocuments();
}
}
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaGenerateMemberCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaGenerateMemberCompletionContributor.java
index 7015004b7340..351eca4857fd 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaGenerateMemberCompletionContributor.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaGenerateMemberCompletionContributor.java
@@ -15,10 +15,7 @@
*/
package com.intellij.codeInsight.completion;
-import com.intellij.codeInsight.generation.GenerateMembersUtil;
-import com.intellij.codeInsight.generation.OverrideImplementExploreUtil;
-import com.intellij.codeInsight.generation.OverrideImplementUtil;
-import com.intellij.codeInsight.generation.PsiGenerationInfo;
+import com.intellij.codeInsight.generation.*;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.icons.AllIcons;
@@ -35,6 +32,7 @@ import com.intellij.util.containers.ContainerUtil;
import javax.swing.*;
import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
import java.util.Set;
@@ -70,8 +68,8 @@ public class JavaGenerateMemberCompletionContributor {
List<PsiMethod> prototypes = ContainerUtil.newArrayList();
for (PsiField field : parent.getFields()) {
if (!(field instanceof PsiEnumConstant)) {
- prototypes.add(GenerateMembersUtil.generateGetterPrototype(field));
- prototypes.add(GenerateMembersUtil.generateSetterPrototype(field));
+ Collections.addAll(prototypes, GetterSetterPrototypeProvider.generateGetterSetters(field, true));
+ Collections.addAll(prototypes, GetterSetterPrototypeProvider.generateGetterSetters(field, false));
}
}
for (final PsiMethod prototype : prototypes) {
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodCallElement.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodCallElement.java
index 29906bbde605..c0f82668f74a 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodCallElement.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodCallElement.java
@@ -39,7 +39,11 @@ public class JavaMethodCallElement extends LookupItem<PsiMethod> implements Type
private boolean myMayNeedExplicitTypeParameters;
public JavaMethodCallElement(@NotNull PsiMethod method) {
- super(method, method.getName());
+ this(method, method.getName());
+ }
+
+ public JavaMethodCallElement(@NotNull PsiMethod method, String methodName) {
+ super(method, methodName);
myMethod = method;
myHelper = null;
myContainingClass = method.getContainingClass();
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/LambdaCompletionProvider.java b/java/java-impl/src/com/intellij/codeInsight/completion/LambdaCompletionProvider.java
index f169ccd8aa56..4fd7df6c7e2e 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/LambdaCompletionProvider.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/LambdaCompletionProvider.java
@@ -25,6 +25,7 @@ import com.intellij.openapi.editor.EditorModificationUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
+import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.impl.source.resolve.graphInference.FunctionalInterfaceParameterizationUtil;
import com.intellij.psi.util.PsiUtil;
@@ -52,18 +53,25 @@ public class LambdaCompletionProvider extends CompletionProvider<CompletionParam
final Project project = method.getProject();
final PsiElement originalPosition = parameters.getOriginalPosition();
final JVMElementFactory jvmElementFactory = originalPosition != null ? JVMElementFactories.getFactory(originalPosition.getLanguage(), project) : null;
+ final JavaCodeStyleManager javaCodeStyleManager = JavaCodeStyleManager.getInstance(project);
if (jvmElementFactory != null) {
final PsiSubstitutor substitutor = LambdaUtil.getSubstitutor(method, PsiUtil.resolveGenericsClassInType(functionalInterfaceType));
- final JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(project);
- params = GenerateMembersUtil.overriddenParameters(params, jvmElementFactory, codeStyleManager, substitutor, originalPosition);
+ params = GenerateMembersUtil.overriddenParameters(params, jvmElementFactory, javaCodeStyleManager, substitutor, originalPosition);
}
- final String paramsString = params.length == 1 ? params[0].getName() : "(" + StringUtil.join(params, new Function<PsiParameter, String>() {
+ String paramsString =
+ params.length == 1 ? getParamName(params[0], javaCodeStyleManager, originalPosition) : "(" + StringUtil.join(params, new Function<PsiParameter, String>() {
@Override
public String fun(PsiParameter parameter) {
- return parameter.getName();
+ return getParamName(parameter, javaCodeStyleManager, originalPosition);
}
- }, ",") + ")";
+ }, ",") + ")";
+
+ final CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(project);
+ PsiLambdaExpression lambdaExpression = (PsiLambdaExpression)JavaPsiFacade.getElementFactory(project)
+ .createExpressionFromText(paramsString + " -> {}", null);
+ lambdaExpression = (PsiLambdaExpression)codeStyleManager.reformat(lambdaExpression);
+ paramsString = lambdaExpression.getParameterList().getText();
final LookupElementBuilder builder =
LookupElementBuilder.create(paramsString).withPresentableText(paramsString + " -> {}").withInsertHandler(new InsertHandler<LookupElement>() {
@Override
@@ -77,4 +85,8 @@ public class LambdaCompletionProvider extends CompletionProvider<CompletionParam
}
}
}
+
+ private static String getParamName(PsiParameter param, JavaCodeStyleManager javaCodeStyleManager, PsiElement originalPosition) {
+ return javaCodeStyleManager.suggestUniqueVariableName(param.getName(), originalPosition, true);
+ }
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/MethodReferenceCompletionProvider.java b/java/java-impl/src/com/intellij/codeInsight/completion/MethodReferenceCompletionProvider.java
index e83f0ef38c3c..494ed110b254 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/MethodReferenceCompletionProvider.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/MethodReferenceCompletionProvider.java
@@ -68,7 +68,7 @@ public class MethodReferenceCompletionProvider extends CompletionProvider<Comple
final PsiElement resolve = referenceExpression.resolve();
if (resolve != null && PsiEquivalenceUtil.areElementsEquivalent(element, resolve) &&
PsiMethodReferenceUtil.checkMethodReferenceContext(referenceExpression, resolve, functionalType) == null) {
- result.addElement(new JavaMethodReferenceElement((PsiMethod)element, refPlace, referenceExpression));
+ result.addElement(new JavaMethodReferenceElement((PsiMethod)element, refPlace));
}
}
finally {
@@ -80,19 +80,20 @@ public class MethodReferenceCompletionProvider extends CompletionProvider<Comple
}
private PsiMethodReferenceExpression createMethodReferenceExpression(PsiMethod method) {
+ PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(method.getProject());
if (refPlace instanceof PsiMethodReferenceExpression) {
final PsiMethodReferenceExpression referenceExpression = (PsiMethodReferenceExpression)refPlace.copy();
final PsiElement referenceNameElement = referenceExpression.getReferenceNameElement();
LOG.assertTrue(referenceNameElement != null, referenceExpression);
- referenceNameElement.replace(JavaPsiFacade.getElementFactory(method.getProject()).createIdentifier(method.getName()));
+ referenceNameElement.replace(method.isConstructor() ? elementFactory.createKeyword("new") : elementFactory.createIdentifier(method.getName()));
return referenceExpression;
}
else if (method.hasModifierProperty(PsiModifier.STATIC)) {
final PsiClass aClass = method.getContainingClass();
LOG.assertTrue(aClass != null);
final String qualifiedName = aClass.getQualifiedName();
- return (PsiMethodReferenceExpression)JavaPsiFacade.getElementFactory(method.getProject()).createExpressionFromText(
- qualifiedName + "::" + method.getName(), refPlace);
+ return (PsiMethodReferenceExpression)elementFactory.createExpressionFromText(
+ qualifiedName + "::" + (method.isConstructor() ? "new" : method.getName()), refPlace);
}
else {
return null;
@@ -113,13 +114,11 @@ public class MethodReferenceCompletionProvider extends CompletionProvider<Comple
private static class JavaMethodReferenceElement extends JavaMethodCallElement {
private final PsiMethod myMethod;
private final PsiElement myRefPlace;
- private PsiMethodReferenceExpression myReferenceExpression;
- public JavaMethodReferenceElement(PsiMethod method, PsiElement refPlace, PsiMethodReferenceExpression referenceExpression) {
- super(method);
+ public JavaMethodReferenceElement(PsiMethod method, PsiElement refPlace) {
+ super(method, method.isConstructor() ? "new" : method.getName());
myMethod = method;
myRefPlace = refPlace;
- myReferenceExpression = referenceExpression;
}
@Override
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 abe9368374e8..9e8684899939 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
@@ -475,7 +475,7 @@ public abstract class CreateFromUsageBaseFix extends BaseIntentionAction {
} else {
while (true) {
final String paramName = idx > 0 ? "T" + idx : "T";
- if (!typeParamNames.contains(paramName)) {
+ if (typeParamNames.add(paramName)) {
targetClass.getTypeParameterList().add(factory.createTypeParameterFromText(paramName, null));
break;
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateGetterOrSetterFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateGetterOrSetterFix.java
index 209dde6cf4ea..897c6f80a571 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateGetterOrSetterFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateGetterOrSetterFix.java
@@ -18,6 +18,7 @@ package com.intellij.codeInsight.daemon.impl.quickfix;
import com.intellij.codeInsight.FileModificationService;
import com.intellij.codeInsight.daemon.QuickFixBundle;
import com.intellij.codeInsight.generation.GenerateMembersUtil;
+import com.intellij.codeInsight.generation.GetterSetterPrototypeProvider;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInsight.intention.LowPriorityAction;
import com.intellij.openapi.editor.Editor;
@@ -29,6 +30,7 @@ import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
/**
@@ -115,10 +117,10 @@ public class CreateGetterOrSetterFix implements IntentionAction, LowPriorityActi
PsiClass aClass = myField.getContainingClass();
final List<PsiMethod> methods = new ArrayList<PsiMethod>();
if (myCreateGetter) {
- methods.add(GenerateMembersUtil.generateGetterPrototype(myField));
+ Collections.addAll(methods, GetterSetterPrototypeProvider.generateGetterSetters(myField, true));
}
if (myCreateSetter) {
- methods.add(GenerateMembersUtil.generateSetterPrototype(myField));
+ Collections.addAll(methods, GetterSetterPrototypeProvider.generateGetterSetters(myField, false));
}
for (PsiMethod method : methods) {
aClass.add(method);
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateInnerClassFromNewFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateInnerClassFromNewFix.java
index 55fe7664d0b0..333ca47b014c 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateInnerClassFromNewFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateInnerClassFromNewFix.java
@@ -67,9 +67,8 @@ public class CreateInnerClassFromNewFix extends CreateClassFromNewFix {
}
created = (PsiClass)targetClass.add(created);
- setupClassFromNewExpression(created, newExpression);
-
setupGenericParameters(created, ref);
+ setupClassFromNewExpression(created, newExpression);
}
private static boolean isInThisOrSuperCall(PsiNewExpression newExpression) {
diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/surroundWith/SurroundWithUtil.java b/java/java-impl/src/com/intellij/codeInsight/generation/surroundWith/SurroundWithUtil.java
index 046a9b7cea0a..2439aafc1e87 100644
--- a/java/java-impl/src/com/intellij/codeInsight/generation/surroundWith/SurroundWithUtil.java
+++ b/java/java-impl/src/com/intellij/codeInsight/generation/surroundWith/SurroundWithUtil.java
@@ -28,6 +28,7 @@ import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.PsiTypesUtil;
import com.intellij.psi.util.PsiUtilBase;
import com.intellij.psi.util.PsiUtilCore;
+import com.intellij.refactoring.util.RefactoringUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -59,7 +60,7 @@ public class SurroundWithUtil {
PsiExpressionStatement assignment = (PsiExpressionStatement)factory.createStatementFromText(name + "=x;", null);
assignment = (PsiExpressionStatement)CodeStyleManager.getInstance(psiManager.getProject()).reformat(assignment);
PsiAssignmentExpression expr = (PsiAssignmentExpression)assignment.getExpression();
- expr.getRExpression().replace(initializer);
+ expr.getRExpression().replace(RefactoringUtil.convertInitializerToNormalExpression(initializer, var.getType()));
assignment = (PsiExpressionStatement)block.addAfter(assignment, declaration);
array.add(assignment);
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/BaseMoveInitializerToMethodAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/BaseMoveInitializerToMethodAction.java
index 4756a5b25a47..5ccdc398684f 100644
--- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/BaseMoveInitializerToMethodAction.java
+++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/BaseMoveInitializerToMethodAction.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.
@@ -29,6 +29,7 @@ import com.intellij.psi.*;
import com.intellij.psi.javadoc.PsiDocComment;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.refactoring.util.RefactoringChangeUtil;
+import com.intellij.refactoring.util.RefactoringUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -126,9 +127,7 @@ public abstract class BaseMoveInitializerToMethodAction extends PsiElementBaseIn
final PsiExpressionStatement statement = (PsiExpressionStatement)factory.createStatementFromText(field.getName() + " = y;", codeBlock);
PsiExpression initializer = field.getInitializer();
- if (initializer instanceof PsiArrayInitializerExpression) {
- initializer = arrayInitializerToNewExpression((PsiArrayInitializerExpression)initializer, factory, codeBlock);
- }
+ initializer = RefactoringUtil.convertInitializerToNormalExpression(initializer, field.getType());
final PsiAssignmentExpression expression = (PsiAssignmentExpression)statement.getExpression();
expression.getRExpression().replace(initializer);
@@ -158,15 +157,6 @@ public abstract class BaseMoveInitializerToMethodAction extends PsiElementBaseIn
return false;
}
- private static PsiExpression arrayInitializerToNewExpression(@NotNull PsiArrayInitializerExpression initializer,
- @NotNull PsiElementFactory factory,
- @NotNull PsiElement context) {
- final PsiType type = initializer.getType();
- final PsiNewExpression newExpression = (PsiNewExpression)factory.createExpressionFromText("new " + type.getCanonicalText() + "{}", context);
- newExpression.getArrayInitializer().replace(initializer);
- return newExpression;
- }
-
private static boolean containsReference(final @NotNull PsiElement element,
final @NotNull PsiField field) {
final Ref<Boolean> result = new Ref<Boolean>(Boolean.FALSE);
diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/CopyAbstractMethodImplementationHandler.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/CopyAbstractMethodImplementationHandler.java
index ddddf94430f7..6f6dcf4d4d6f 100644
--- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/CopyAbstractMethodImplementationHandler.java
+++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/CopyAbstractMethodImplementationHandler.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.
@@ -20,6 +20,7 @@ import com.intellij.codeInsight.CodeInsightBundle;
import com.intellij.codeInsight.generation.GenerateMembersUtil;
import com.intellij.codeInsight.generation.OverrideImplementUtil;
import com.intellij.ide.util.MethodCellRenderer;
+import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.diagnostic.Logger;
@@ -38,6 +39,7 @@ import com.intellij.psi.util.PsiUtilCore;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.ui.components.JBList;
import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.util.*;
@@ -66,7 +68,12 @@ public class CopyAbstractMethodImplementationHandler {
ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
@Override
public void run() {
- searchExistingImplementations();
+ ApplicationManager.getApplication().runReadAction(new Runnable() {
+ @Override
+ public void run() {
+ searchExistingImplementations();
+ }
+ });
}
}, CodeInsightBundle.message("searching.for.implementations"), false, myProject);
if (mySourceMethods.isEmpty()) {
@@ -152,7 +159,7 @@ public class CopyAbstractMethodImplementationHandler {
final List<PsiMethod> generatedMethods = new ArrayList<PsiMethod>();
new WriteCommandAction(myProject, getTargetFiles()) {
@Override
- protected void run(final Result result) throws Throwable {
+ protected void run(@NotNull final Result result) throws Throwable {
for (PsiEnumConstant enumConstant : myTargetEnumConstants) {
PsiClass initializingClass = enumConstant.getOrCreateInitializingClass();
myTargetClasses.add(initializingClass);
@@ -186,7 +193,7 @@ public class CopyAbstractMethodImplementationHandler {
}
}
}.execute();
- if (generatedMethods.size() > 0) {
+ if (!generatedMethods.isEmpty()) {
PsiMethod target = generatedMethods.get(0);
PsiFile psiFile = target.getContainingFile();
FileEditorManager fileEditorManager = FileEditorManager.getInstance(psiFile.getProject());
diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/SplitDeclarationAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/SplitDeclarationAction.java
index 8c1da6252efb..9ea64d81463b 100644
--- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/SplitDeclarationAction.java
+++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/SplitDeclarationAction.java
@@ -25,6 +25,7 @@ import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.javadoc.PsiDocComment;
import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.refactoring.util.RefactoringUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
@@ -119,12 +120,7 @@ public class SplitDeclarationAction extends PsiElementBaseIntentionAction {
statement = (PsiExpressionStatement)CodeStyleManager.getInstance(project).reformat(statement);
PsiAssignmentExpression assignment = (PsiAssignmentExpression)statement.getExpression();
PsiExpression initializer = var.getInitializer();
- PsiExpression rExpression = initializer;
- if (initializer instanceof PsiArrayInitializerExpression && var.getType() instanceof PsiArrayType) {
- rExpression = JavaPsiFacade.getInstance(psiManager.getProject()).getElementFactory().createExpressionFromText(
- "new " + var.getTypeElement().getText() + " " + initializer.getText(), null
- );
- }
+ PsiExpression rExpression = RefactoringUtil.convertInitializerToNormalExpression(initializer, var.getType());
assignment.getRExpression().replace(rExpression);
initializer.delete();
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 2142c8fd33da..7e168e23dd1e 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
@@ -106,21 +106,21 @@ public abstract class JavaPostfixTemplatesUtils {
public static Condition<PsiElement> IS_THROWABLE = new Condition<PsiElement>() {
@Override
public boolean value(PsiElement element) {
- return element instanceof PsiExpression && isThrowable((((PsiExpression)element).getType()));
+ return element instanceof PsiExpression && isThrowable(((PsiExpression)element).getType());
}
};
public static Condition<PsiElement> IS_NON_VOID = new Condition<PsiElement>() {
@Override
public boolean value(PsiElement element) {
- return element instanceof PsiExpression && isNonVoid((((PsiExpression)element).getType()));
+ return element instanceof PsiExpression && isNonVoid(((PsiExpression)element).getType());
}
};
public static Condition<PsiElement> IS_NOT_PRIMITIVE = new Condition<PsiElement>() {
@Override
public boolean value(PsiElement element) {
- return element instanceof PsiExpression && isNotPrimitiveTypeExpression(((PsiExpression)element));
+ return element instanceof PsiExpression && isNotPrimitiveTypeExpression((PsiExpression)element);
}
};
@@ -130,7 +130,7 @@ public abstract class JavaPostfixTemplatesUtils {
if (!(element instanceof PsiExpression)) return false;
PsiType type = ((PsiExpression)element).getType();
- return (isArray(type) || isIterable(type));
+ return isArray(type) || isIterable(type);
}
};
diff --git a/java/java-impl/src/com/intellij/codeInspection/actions/ReplaceImplementsWithStaticImportAction.java b/java/java-impl/src/com/intellij/codeInspection/actions/ReplaceImplementsWithStaticImportAction.java
index ce12094e74a3..5ced0c4fb766 100644
--- a/java/java-impl/src/com/intellij/codeInspection/actions/ReplaceImplementsWithStaticImportAction.java
+++ b/java/java-impl/src/com/intellij/codeInspection/actions/ReplaceImplementsWithStaticImportAction.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.
@@ -96,7 +96,7 @@ public class ReplaceImplementsWithStaticImportAction extends BaseIntentionAction
JavaPsiFacade.getInstance(project).findClass(CommonClassNames.JAVA_LANG_OBJECT, GlobalSearchScope.allScope(project));
if (objectClass == null) return false;
methods.removeAll(Arrays.asList(objectClass.getMethods()));
- if (methods.size() > 0) return false;
+ if (!methods.isEmpty()) return false;
}
else if (targetClass.getMethods().length > 0) {
return false;
@@ -122,7 +122,7 @@ public class ReplaceImplementsWithStaticImportAction extends BaseIntentionAction
final PsiClass targetClass = (PsiClass)target;
new WriteCommandAction(project, getText()) {
@Override
- protected void run(Result result) throws Throwable {
+ protected void run(@NotNull Result result) throws Throwable {
for (PsiField constField : targetClass.getAllFields()) {
final String fieldName = constField.getName();
final PsiClass containingClass = constField.getContainingClass();
@@ -159,30 +159,35 @@ public class ReplaceImplementsWithStaticImportAction extends BaseIntentionAction
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
@Override
public void run() {
- for (PsiField field : targetClass.getAllFields()) {
- final PsiClass containingClass = field.getContainingClass();
- for (PsiReference reference : ReferencesSearch.search(field)) {
- if (reference == null) {
- continue;
- }
- final PsiElement refElement = reference.getElement();
- if (encodeQualifier(containingClass, reference, targetClass)) continue;
- final PsiFile psiFile = refElement.getContainingFile();
- if (psiFile instanceof PsiJavaFile) {
- Map<PsiField, Set<PsiReference>> references = refs.get(psiFile);
- if (references == null) {
- references = new HashMap<PsiField, Set<PsiReference>>();
- refs.put(psiFile, references);
- }
- Set<PsiReference> fieldsRefs = references.get(field);
- if (fieldsRefs == null) {
- fieldsRefs = new HashSet<PsiReference>();
- references.put(field, fieldsRefs);
+ ApplicationManager.getApplication().runReadAction(new Runnable() {
+ @Override
+ public void run() {
+ for (PsiField field : targetClass.getAllFields()) {
+ final PsiClass containingClass = field.getContainingClass();
+ for (PsiReference reference : ReferencesSearch.search(field)) {
+ if (reference == null) {
+ continue;
+ }
+ final PsiElement refElement = reference.getElement();
+ if (encodeQualifier(containingClass, reference, targetClass)) continue;
+ final PsiFile psiFile = refElement.getContainingFile();
+ if (psiFile instanceof PsiJavaFile) {
+ Map<PsiField, Set<PsiReference>> references = refs.get(psiFile);
+ if (references == null) {
+ references = new HashMap<PsiField, Set<PsiReference>>();
+ refs.put(psiFile, references);
+ }
+ Set<PsiReference> fieldsRefs = references.get(field);
+ if (fieldsRefs == null) {
+ fieldsRefs = new HashSet<PsiReference>();
+ references.put(field, fieldsRefs);
+ }
+ fieldsRefs.add(reference);
+ }
}
- fieldsRefs.add(reference);
}
}
- }
+ });
}
}, FIND_CONSTANT_FIELD_USAGES, true, project)) {
return;
@@ -192,14 +197,19 @@ public class ReplaceImplementsWithStaticImportAction extends BaseIntentionAction
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
@Override
public void run() {
- for (PsiClass psiClass : DirectClassInheritorsSearch.search(targetClass)) {
- PsiFile containingFile = psiClass.getContainingFile();
- if (!refs.containsKey(containingFile)) {
- refs.put(containingFile, new HashMap<PsiField, Set<PsiReference>>());
+ ApplicationManager.getApplication().runReadAction(new Runnable() {
+ @Override
+ public void run() {
+ for (PsiClass psiClass : DirectClassInheritorsSearch.search(targetClass)) {
+ PsiFile containingFile = psiClass.getContainingFile();
+ if (!refs.containsKey(containingFile)) {
+ refs.put(containingFile, new HashMap<PsiField, Set<PsiReference>>());
+ }
+ if (collectExtendsImplements(targetClass, psiClass.getExtendsList(), refs2Unimplement)) continue;
+ collectExtendsImplements(targetClass, psiClass.getImplementsList(), refs2Unimplement);
+ }
}
- if (collectExtendsImplements(targetClass, psiClass.getExtendsList(), refs2Unimplement)) continue;
- collectExtendsImplements(targetClass, psiClass.getImplementsList(), refs2Unimplement);
- }
+ });
}
}, "Find references in implement/extends lists...", true, project)) {
return;
@@ -232,14 +242,19 @@ public class ReplaceImplementsWithStaticImportAction extends BaseIntentionAction
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable(){
@Override
public void run() {
- for (PsiFile psiFile : refs.keySet()) {
- final Collection<PsiImportStatementBase> red = codeStyleManager.findRedundantImports((PsiJavaFile)psiFile);
- if (red != null) {
- for (PsiImportStatementBase statementBase : red) {
- redundant.add(pointerManager.createSmartPsiElementPointer(statementBase));
+ ApplicationManager.getApplication().runReadAction(new Runnable() {
+ @Override
+ public void run() {
+ for (PsiFile psiFile : refs.keySet()) {
+ final Collection<PsiImportStatementBase> red = codeStyleManager.findRedundantImports((PsiJavaFile)psiFile);
+ if (red != null) {
+ for (PsiImportStatementBase statementBase : red) {
+ redundant.add(pointerManager.createSmartPsiElementPointer(statementBase));
+ }
+ }
}
}
- }
+ });
}
}, "Collect redundant imports...", true, project)) return;
ApplicationManager.getApplication().runWriteAction(new Runnable() {
diff --git a/java/java-impl/src/com/intellij/codeInspection/javaDoc/JavaDocLocalInspection.java b/java/java-impl/src/com/intellij/codeInspection/javaDoc/JavaDocLocalInspection.java
index ba5b40120a32..df37ce2a7267 100644
--- a/java/java-impl/src/com/intellij/codeInspection/javaDoc/JavaDocLocalInspection.java
+++ b/java/java-impl/src/com/intellij/codeInspection/javaDoc/JavaDocLocalInspection.java
@@ -100,7 +100,7 @@ public class JavaDocLocalInspection extends JavaDocLocalInspectionBase {
InspectionsBundle.message("inspection.scope.for.title"), true),
BorderFactory.createEmptyBorder(0, 3, 3, 3)));
- final Hashtable<Integer, JLabel> sliderLabels = new Hashtable<Integer, JLabel>();
+ final Hashtable<Integer, JComponent> sliderLabels = new Hashtable<Integer, JComponent>();
for (int i = 0; i < modifiers.length; i++) {
sliderLabels.put(i + 1, new JLabel(modifiers[i]));
}
@@ -184,11 +184,11 @@ public class JavaDocLocalInspection extends JavaDocLocalInspectionBase {
add(periodCheckBox, gc);
final JCheckBox ignoreDuplicateThrowsCheckBox = new JCheckBox("Ignore duplicate throws tag",
- IGNORE_DUPLICATED_THROWS);
+ getIgnoreDuplicatedThrows());
ignoreDuplicateThrowsCheckBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
- IGNORE_DUPLICATED_THROWS = ignoreDuplicateThrowsCheckBox.isSelected();
+ setIgnoreDuplicatedThrows(ignoreDuplicateThrowsCheckBox.isSelected());
}
});
add(ignoreDuplicateThrowsCheckBox, gc);
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 73fcc83df646..b68b68b8b195 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
@@ -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.
@@ -136,6 +136,7 @@ public final class PackageViewPane extends AbstractProjectViewPSIPane {
return result;
}
+ @NotNull
@Override
public PsiDirectory[] getSelectedDirectories() {
List<PsiDirectory> directories = ContainerUtil.newArrayList();
@@ -194,6 +195,7 @@ public final class PackageViewPane extends AbstractProjectViewPSIPane {
@Override
public void addToolbarActions(DefaultActionGroup actionGroup) {
actionGroup.addAction(new ShowModulesAction(myProject){
+ @NotNull
@Override
protected String getId() {
return PackageViewPane.this.getId();
diff --git a/java/java-impl/src/com/intellij/javadoc/JavadocGenerationManager.java b/java/java-impl/src/com/intellij/javadoc/JavadocGenerationManager.java
index e34cafbbb10c..3589918fe4a1 100644
--- a/java/java-impl/src/com/intellij/javadoc/JavadocGenerationManager.java
+++ b/java/java-impl/src/com/intellij/javadoc/JavadocGenerationManager.java
@@ -18,11 +18,9 @@ package com.intellij.javadoc;
import com.intellij.CommonBundle;
import com.intellij.analysis.AnalysisScope;
import com.intellij.execution.ExecutionException;
-import com.intellij.execution.Executor;
-import com.intellij.execution.RunnerRegistry;
import com.intellij.execution.executors.DefaultRunExecutor;
-import com.intellij.execution.runners.ExecutionEnvironment;
-import com.intellij.execution.runners.ProgramRunner;
+import com.intellij.execution.runners.ExecutionEnvironmentBuilder;
+import com.intellij.execution.runners.ExecutionUtil;
import com.intellij.execution.util.ExecutionErrorDialog;
import com.intellij.openapi.components.*;
import com.intellij.openapi.diagnostic.Logger;
@@ -82,10 +80,7 @@ public final class JavadocGenerationManager implements PersistentStateComponent<
public void generateJavadoc(AnalysisScope scope) {
myConfiguration.setGenerationScope(scope);
try {
- final ProgramRunner runner = RunnerRegistry.getInstance().getRunner(DefaultRunExecutor.EXECUTOR_ID, myConfiguration);
- assert runner != null;
- Executor executor = DefaultRunExecutor.getRunExecutorInstance();
- runner.execute(new ExecutionEnvironment(myConfiguration ,executor, myProject, null));
+ ExecutionEnvironmentBuilder.create(myProject, DefaultRunExecutor.getRunExecutorInstance(), myConfiguration).buildAndExecute();
}
catch (ExecutionException e) {
ExecutionErrorDialog.show(e, CommonBundle.getErrorTitle(), myProject);
diff --git a/java/java-impl/src/com/intellij/javadoc/JavadocGenerationPanel.java b/java/java-impl/src/com/intellij/javadoc/JavadocGenerationPanel.java
index 5cc096016683..d15ce5804170 100644
--- a/java/java-impl/src/com/intellij/javadoc/JavadocGenerationPanel.java
+++ b/java/java-impl/src/com/intellij/javadoc/JavadocGenerationPanel.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.
@@ -69,7 +69,7 @@ final class JavadocGenerationPanel extends JPanel {
);
//noinspection UseOfObsoleteCollectionType
- Hashtable<Integer, JLabel> labelTable = new Hashtable<Integer, JLabel>();
+ Hashtable<Integer, JComponent> labelTable = new Hashtable<Integer, JComponent>();
labelTable.put(new Integer(1), new JLabel(PsiKeyword.PUBLIC));
labelTable.put(new Integer(2), new JLabel(PsiKeyword.PROTECTED));
labelTable.put(new Integer(3), new JLabel(PsiKeyword.PACKAGE));
diff --git a/java/java-impl/src/com/intellij/psi/RefQueueIndex.java b/java/java-impl/src/com/intellij/psi/RefQueueIndex.java
new file mode 100644
index 000000000000..d65fa4473c2f
--- /dev/null
+++ b/java/java-impl/src/com/intellij/psi/RefQueueIndex.java
@@ -0,0 +1,119 @@
+/*
+ * 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.psi;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.impl.file.impl.ResolveScopeManagerImpl;
+import com.intellij.util.indexing.*;
+import com.intellij.util.io.DataExternalizer;
+import com.intellij.util.io.KeyDescriptor;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.util.Collections;
+import java.util.Map;
+
+// all it does is take files it was fed and queue them to the resolve
+public class RefQueueIndex extends FileBasedIndexExtension<Void,Void> {
+ private static final ID<Void, Void> ID = com.intellij.util.indexing.ID.create("RefQueueIndex");
+
+ @NotNull
+ @Override
+ public ID<Void, Void> getName() {
+ return ID;
+ }
+
+ @NotNull
+ @Override
+ public DataIndexer<Void, Void, FileContent> getIndexer() {
+ return new DataIndexer<Void, Void, FileContent>() {
+ @NotNull
+ @Override
+ public Map<Void, Void> map(@NotNull FileContent inputData) {
+ if (ResolveScopeManagerImpl.ENABLED_REF_BACK) {
+ Project project = inputData.getProject();
+ RefResolveService.getInstance(project).queue(Collections.singletonList(inputData.getFile()), "Cache updater");
+ }
+ return Collections.emptyMap();
+ }
+ };
+ }
+
+ @NotNull
+ @Override
+ public KeyDescriptor<Void> getKeyDescriptor() {
+ return new KeyDescriptor<Void>() {
+ @Override
+ public void save(@NotNull DataOutput out, Void value) {
+
+ }
+
+ @Override
+ public Void read(@NotNull DataInput in) {
+ return null;
+ }
+
+ @Override
+ public int getHashCode(Void value) {
+ return 0;
+ }
+
+ @Override
+ public boolean isEqual(Void val1, Void val2) {
+ return false;
+ }
+ };
+ }
+
+ @NotNull
+ @Override
+ public DataExternalizer<Void> getValueExternalizer() {
+ return new DataExternalizer<Void>() {
+ @Override
+ public void save(@NotNull DataOutput out, Void value) {
+
+ }
+
+ @Override
+ public Void read(@NotNull DataInput in) {
+ return null;
+ }
+ };
+ }
+
+ @NotNull
+ @Override
+ public FileBasedIndex.InputFilter getInputFilter() {
+ return new FileBasedIndex.InputFilter() {
+ @Override
+ public boolean acceptInput(@NotNull VirtualFile file) {
+ return !file.isDirectory();
+ }
+ };
+ }
+
+ @Override
+ public boolean dependsOnFileContent() {
+ return true;
+ }
+
+ @Override
+ public int getVersion() {
+ return 0;
+ }
+}
diff --git a/java/java-impl/src/com/intellij/psi/RefResolveServiceImpl.java b/java/java-impl/src/com/intellij/psi/RefResolveServiceImpl.java
new file mode 100644
index 000000000000..3655942f97b7
--- /dev/null
+++ b/java/java-impl/src/com/intellij/psi/RefResolveServiceImpl.java
@@ -0,0 +1,773 @@
+/*
+ * 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.psi;
+
+import com.intellij.concurrency.JobLauncher;
+import com.intellij.openapi.Disposable;
+import com.intellij.openapi.application.ApplicationAdapter;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.PathManager;
+import com.intellij.openapi.application.ex.ApplicationEx;
+import com.intellij.openapi.application.ex.ApplicationUtil;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.fileTypes.StdFileTypes;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.progress.ProcessCanceledException;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.Task;
+import com.intellij.openapi.progress.util.ProgressIndicatorUtils;
+import com.intellij.openapi.project.DumbService;
+import com.intellij.openapi.project.IndexNotReadyException;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.project.ProjectCoreUtil;
+import com.intellij.openapi.roots.ProjectFileIndex;
+import com.intellij.openapi.startup.StartupManager;
+import com.intellij.openapi.util.Computable;
+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.*;
+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.openapi.vfs.newvfs.persistent.FSRecords;
+import com.intellij.openapi.vfs.newvfs.persistent.PersistentFS;
+import com.intellij.psi.impl.PersistentIntList;
+import com.intellij.psi.impl.file.impl.ResolveScopeManagerImpl;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.util.PsiUtilCore;
+import com.intellij.psi.xml.XmlElement;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.ExceptionUtil;
+import com.intellij.util.Function;
+import com.intellij.util.Processor;
+import com.intellij.util.containers.ConcurrentBitSet;
+import com.intellij.util.containers.ConcurrentIntObjectMap;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.StripedLockIntObjectConcurrentHashMap;
+import com.intellij.util.io.storage.HeavyProcessLatch;
+import com.intellij.util.messages.MessageBus;
+import gnu.trove.*;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.java.JavaSourceRootType;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.text.DateFormat;
+import java.util.*;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+
+public class RefResolveServiceImpl extends RefResolveService implements Runnable, Disposable {
+ private static final Logger LOG = Logger.getInstance("#com.intellij.psi.RefResolveService");
+ private final AtomicInteger fileCount = new AtomicInteger();
+ private final AtomicLong bytesSize = new AtomicLong();
+ private final AtomicLong refCount = new AtomicLong();
+ private final PersistentIntList storage;
+ private final Deque<VirtualFile> filesToResolve = new ArrayDeque<VirtualFile>();
+ private final ConcurrentBitSet fileIsInQueue = new ConcurrentBitSet();
+ private final ConcurrentBitSet fileIsResolved;
+ private final ApplicationEx myApplication;
+ private volatile boolean myDisposed;
+ private volatile boolean upToDate;
+ private volatile boolean enabled = true;
+ private final FileWriter log;
+ private final ProjectFileIndex myProjectFileIndex;
+
+
+ public RefResolveServiceImpl(final Project project,
+ final MessageBus messageBus,
+ final PsiManager psiManager,
+ StartupManager startupManager,
+ ApplicationEx application,
+ ProjectFileIndex projectFileIndex) throws IOException {
+ super(project);
+ myApplication = application;
+ myProjectFileIndex = projectFileIndex;
+ if (ResolveScopeManagerImpl.ENABLED_REF_BACK) {
+ File indexFile = new File(getStorageDirectory(), "index");
+ File dataFile = new File(getStorageDirectory(), "data");
+ fileIsResolved = ConcurrentBitSet.readFrom(new File(getStorageDirectory(), "bitSet"));
+
+ final boolean initial = !indexFile.exists() || !dataFile.exists();
+ storage = new PersistentIntList(indexFile, dataFile, initial);
+ Disposer.register(this, storage);
+ if (!application.isUnitTestMode()) {
+ startupManager.runWhenProjectIsInitialized(new Runnable() {
+ @Override
+ public void run() {
+ init(messageBus, psiManager);
+ }
+ });
+ }
+ log = new FileWriter(new File(getStorageDirectory(), "log.txt"));
+ Disposer.register(this, new Disposable() {
+ @Override
+ public void dispose() {
+ try {
+ save();
+ log.close();
+ }
+ catch (IOException e) {
+ LOG.error(e);
+ }
+ }
+ });
+ }
+ else {
+ log = null;
+ fileIsResolved = null;
+ storage = null;
+ }
+ }
+
+ public static List<VirtualFile> toVf(@NotNull int[] ids) {
+ List<VirtualFile> res = new ArrayList<VirtualFile>();
+ for (int id : ids) {
+ VirtualFile file = PersistentFS.getInstance().findFileById(id);
+ if (file != null) {
+ res.add(file);
+ }
+ }
+ return res;
+ }
+
+ public static String toVfString(@NotNull int[] backIds) {
+ List<VirtualFile> list = toVf(backIds);
+ return toVfString(list);
+ }
+
+ private static String toVfString(@NotNull List<VirtualFile> list) {
+ List<VirtualFile> sub = list.subList(0, Math.min(list.size(), 100));
+ return list.size() + " files: " + StringUtil.join(sub, new Function<VirtualFile, String>() {
+ @Override
+ public String fun(VirtualFile file) {
+ return file.getName();
+ }
+ }, ", ")+(list.size()==sub.size() ? "" : "...");
+ }
+
+ private void init(@NotNull MessageBus messageBus, @NotNull PsiManager psiManager) {
+ messageBus.connect().subscribe(VirtualFileManager.VFS_CHANGES, new BulkFileListener.Adapter(){
+ @Override
+ public void after(@NotNull List<? extends VFileEvent> events) {
+ fileCount.set(0);
+ List<VirtualFile> files = ContainerUtil.mapNotNull(events, new Function<VFileEvent, VirtualFile>() {
+ @Override
+ public VirtualFile fun(VFileEvent event) {
+ return event.getFile();
+ }
+ });
+ queue(files, "VFS events " + events.size());
+ }
+ });
+ psiManager.addPsiTreeChangeListener(new PsiTreeChangeAdapter() {
+ @Override
+ public void childrenChanged(@NotNull PsiTreeChangeEvent event) {
+ PsiFile file = event.getFile();
+ VirtualFile virtualFile = PsiUtilCore.getVirtualFile(file);
+ if (virtualFile != null) {
+ queue(Collections.singletonList(virtualFile), event);
+ }
+ }
+
+ @Override
+ public void propertyChanged(@NotNull PsiTreeChangeEvent event) {
+ childrenChanged(event);
+ }
+ });
+
+ messageBus.connect().subscribe(DumbService.DUMB_MODE, new DumbService.DumbModeListener() {
+ @Override
+ public void enteredDumbMode() {
+ disable();
+ }
+
+ @Override
+ public void exitDumbMode() {
+ enable();
+ }
+ });
+ myApplication.addApplicationListener(new ApplicationAdapter() {
+ @Override
+ public void beforeWriteActionStart(Object action) {
+ disable();
+ }
+
+ @Override
+ public void writeActionFinished(Object action) {
+ enable();
+ }
+
+ @Override
+ public void applicationExiting() {
+ disable();
+ }
+ }, this);
+ VirtualFileManager.getInstance().addVirtualFileManagerListener(new VirtualFileManagerListener() {
+ @Override
+ public void beforeRefreshStart(boolean asynchronous) {
+ disable();
+ }
+
+ @Override
+ public void afterRefreshFinish(boolean asynchronous) {
+ enable();
+ }
+ }, this);
+ Disposer.register(this, HeavyProcessLatch.INSTANCE.addListener(new HeavyProcessLatch.HeavyProcessListener() {
+ @Override
+ public void processStarted() {
+ disable();
+ }
+
+ @Override
+ public void processFinished() {
+ enable();
+ }
+ }));
+
+ startThread();
+ }
+
+ // return true if file was added to queue
+ private boolean queueIfNeeded(VirtualFile virtualFile, @NotNull Project project) {
+ return toResolve(virtualFile, project) && queueUpdate(virtualFile);
+ }
+
+ private boolean toResolve(VirtualFile virtualFile, @NotNull Project project) {
+ if (virtualFile != null &&
+ virtualFile.isValid() &&
+ project.isInitialized() &&
+ myProjectFileIndex.isInContent(virtualFile)) {
+ if (virtualFile.isDirectory()) return true;
+ if (virtualFile.getFileType() == StdFileTypes.JAVA) return true;
+ if (virtualFile.getFileType() == StdFileTypes.XML && !ProjectCoreUtil.isProjectOrWorkspaceFile(virtualFile)) return true;
+ }
+
+ // else mark it as resolved so we will not have to check it again
+ if (virtualFile instanceof VirtualFileWithId) {
+ int id = getAbsId(virtualFile);
+ fileIsResolved.set(id);
+ }
+
+ return false;
+ }
+
+ @NotNull
+ private File getStorageDirectory() {
+ String dirName = myProject.getName() + "."+Integer.toHexString(myProject.getPresentableUrl().hashCode());
+ File dir = new File(PathManager.getSystemPath(), "refs/" + dirName);
+ FileUtil.createDirectory(dir);
+ return dir;
+ }
+
+
+ private void log(String m) {
+ //System.out.println(m);
+ logf(m);
+ }
+
+ private void logf(String m) {
+ try {
+ log.write(DateFormat.getDateTimeInstance().format(new Date()) + " "+m+" ; gap="+storage.gap+"\n");
+ }
+ catch (IOException e) {
+ LOG.error(e);
+ }
+ }
+
+ private void flushLog() {
+ try {
+ log.flush();
+ }
+ catch (IOException e) {
+ LOG.error(e);
+ }
+ }
+
+ // return true if file was added to queue
+ private boolean queueUpdate(@NotNull VirtualFile file) {
+ synchronized (filesToResolve) {
+ if (!(file instanceof VirtualFileWithId)) return false;
+ int fileId = getAbsId(file);
+ countAndMarkUnresolved(file, new THashSet<VirtualFile>(), true);
+ boolean alreadyAdded = fileIsInQueue.set(fileId);
+ if (!alreadyAdded) {
+ filesToResolve.add(file);
+ }
+ upToDate = false;
+ wakeUpUnderLock();
+ return !alreadyAdded;
+ }
+ }
+
+ private void wakeUp() {
+ synchronized (filesToResolve) {
+ wakeUpUnderLock();
+ }
+ }
+
+ private void wakeUpUnderLock() {
+ filesToResolve.notifyAll();
+ }
+
+ private void waitForQueue() throws InterruptedException {
+ synchronized (filesToResolve) {
+ filesToResolve.wait(1000);
+ }
+ }
+
+ private void startThread() {
+ new Thread(this, "Ref resolve service").start();
+ upToDate = true;
+ queueUnresolvedFilesSinceLastRestart();
+ }
+
+ private void queueUnresolvedFilesSinceLastRestart() {
+ PersistentFS fs = PersistentFS.getInstance();
+ int maxId = FSRecords.getMaxId();
+ TIntArrayList list = new TIntArrayList();
+ for (int id= fileIsResolved.nextClearBit(1); id >= 0 && id < maxId; id = fileIsResolved.nextClearBit(id + 1)) {
+ int nextSetBit = fileIsResolved.nextSetBit(id);
+ int endOfRun = Math.min(maxId, nextSetBit == -1 ? maxId : nextSetBit);
+ do {
+ VirtualFile virtualFile = fs.findFileById(id);
+ if (queueIfNeeded(virtualFile, myProject)) {
+ list.add(id);
+ }
+ }
+ while (++id < endOfRun);
+ }
+ log("Initially added to resolve " + toVfString(list.toNativeArray()));
+ }
+
+ @Override
+ public void dispose() {
+ myDisposed = true;
+ }
+
+ private void save() throws IOException {
+ fileIsResolved.writeTo(new File(getStorageDirectory(), "bitSet"));
+ }
+
+ @Override
+ public void run() {
+ while (!myDisposed) {
+ boolean isEmpty;
+ synchronized (filesToResolve) {
+ isEmpty = filesToResolve.isEmpty();
+ }
+ if (!enabled || isEmpty) {
+ try {
+ waitForQueue();
+ }
+ catch (InterruptedException e) {
+ break;
+ }
+ continue;
+ }
+ upToDate = false;
+ final CountDownLatch batchProcessedLatch = new CountDownLatch(1);
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ new Task.Backgroundable(myProject, "Resolving files...", true) {
+ @Override
+ public void run(@NotNull final ProgressIndicator indicator) {
+ if (ApplicationManager.getApplication().isDisposed()) return;
+ try {
+ processBatch(indicator);
+ }
+ finally {
+ batchProcessedLatch.countDown();
+ }
+ }
+ }.queue();
+ }
+ }, myProject.getDisposed());
+
+ try {
+ batchProcessedLatch.await();
+ }
+ catch (InterruptedException e) {
+ break;
+ }
+
+ synchronized (filesToResolve) {
+ upToDate = filesToResolve.isEmpty();
+ log("upToDate = " + upToDate);
+ }
+ flushLog();
+ }
+ }
+
+ private void processBatch(@NotNull final ProgressIndicator indicator) {
+ Set<VirtualFile> set;
+ int queuedSize;
+ synchronized (filesToResolve) {
+ queuedSize = filesToResolve.size();
+ set = new THashSet<VirtualFile>(queuedSize);
+ // someone might have cleared this bit to mark file as processed
+ for (VirtualFile file : filesToResolve) {
+ if (fileIsInQueue.clear(getAbsId(file))) {
+ set.add(file);
+ }
+ }
+ filesToResolve.clear();
+ }
+ final ConcurrentIntObjectMap<int[]> fileToForwardIds = new StripedLockIntObjectConcurrentHashMap<int[]>();
+ Set<VirtualFile> files = countAndMarkUnresolved(set, false);
+ if (files.isEmpty()) return;
+ final int size = files.size();
+ final Set<VirtualFile> toProcess = Collections.synchronizedSet(files);
+ log("Started to resolve "+ size + " files (was queued "+queuedSize+")");
+
+ indicator.setIndeterminate(false);
+ ProgressIndicatorUtils.forceWriteActionPriority(indicator, (Disposable)indicator);
+ long start = System.currentTimeMillis();
+ Processor<VirtualFile> processor = new Processor<VirtualFile>() {
+ @Override
+ public boolean process(VirtualFile file) {
+ double fraction = 1 - toProcess.size() * 1.0 / size;
+ indicator.setFraction(fraction);
+ try {
+ if (file.isDirectory() || !toResolve(file, myProject)) {
+ return true;
+ }
+ int fileId = getAbsId(file);
+ int i = size - toProcess.size();
+ indicator.setText(i + "/" + size + ": Resolving " + file.getPresentableUrl());
+ int[] forwardIds = processFile(file, fileId, indicator);
+ if (forwardIds == null) {
+ //queueUpdate(file);
+ return false;
+ }
+ toProcess.remove(file);
+ fileToForwardIds.put(fileId, forwardIds);
+ }
+ catch (RuntimeException e) {
+ indicator.checkCanceled();
+ }
+ return true;
+ }
+ };
+ boolean success = true;
+ try {
+ success = JobLauncher
+ .getInstance().invokeConcurrentlyUnderProgress(new ArrayList<VirtualFile>(files), indicator, false, false, processor);
+ }
+ finally {
+ queue(toProcess, "re-added after fail. success=" + success);
+ storeIds(fileToForwardIds);
+
+ long end = System.currentTimeMillis();
+ log("Resolved batch of " + (size - toProcess.size()) + " from " + size + " files in " + ((end - start) / 1000) + "sec. (Gap: " + storage.gap+")");
+ }
+ }
+
+ private static int getAbsId(@NotNull VirtualFile file) {
+ return Math.abs(((VirtualFileWithId)file).getId());
+ }
+
+ @NotNull
+ private Set<VirtualFile> countAndMarkUnresolved(@NotNull Collection<VirtualFile> files, boolean inDbOnly) {
+ Set<VirtualFile> result = new THashSet<VirtualFile>();
+ for (VirtualFile file : files) {
+ countAndMarkUnresolved(file, result, inDbOnly);
+ }
+ return result;
+ }
+
+ private void countAndMarkUnresolved(@NotNull VirtualFile file, @NotNull final Set<VirtualFile> result, final boolean inDbOnly) {
+ if (file.isDirectory()) {
+ VfsUtilCore.visitChildrenRecursively(file, new VirtualFileVisitor() {
+ @Override
+ public boolean visitFile(@NotNull VirtualFile file) {
+ doCountAndMarkUnresolved(file, result);
+ return true;
+ }
+
+ @Nullable
+ @Override
+ public Iterable<VirtualFile> getChildrenIterable(@NotNull VirtualFile file) {
+ return inDbOnly ? ((NewVirtualFile)file).iterInDbChildren() : null;
+ }
+ });
+ }
+ else {
+ doCountAndMarkUnresolved(file, result);
+ }
+ }
+
+ private void doCountAndMarkUnresolved(@NotNull VirtualFile file, @NotNull Set<VirtualFile> result) {
+ if (file.isDirectory()) {
+ fileIsResolved.set(getAbsId(file));
+ }
+ else if (toResolve(file, myProject)) {
+ result.add(file);
+ fileIsResolved.clear(getAbsId(file));
+ }
+ }
+
+ private void enable() {
+ enabled = true;
+ wakeUp();
+ }
+
+ private void disable() {
+ enabled = false;
+ wakeUp();
+ }
+
+ // returns list of resolved files if updated successfully, or null if write action or dumb mode started
+ private int[] processFile(@NotNull final VirtualFile file,
+ int fileId,
+ @NotNull final ProgressIndicator indicator) {
+ final TIntHashSet forward;
+ try {
+ forward = calcForwardRefs(file, indicator);
+ }
+ catch (IndexNotReadyException e) {
+ return null;
+ }
+ catch (ApplicationUtil.CannotRunReadActionException e) {
+ return null;
+ }
+ catch (ProcessCanceledException e) {
+ throw e;
+ }
+ catch (Exception e) {
+ log(ExceptionUtil.getThrowableText(e));
+ flushLog();
+ return null;
+ }
+
+ int[] forwardIds = forward.toArray();
+ fileIsResolved.set(fileId);
+ logf(" ---- "+file.getPresentableUrl() + " processed. forwardIds: "+ toVfString(forwardIds));
+ return forwardIds;
+ }
+
+ private void storeIds(@NotNull ConcurrentIntObjectMap<int[]> fileToForwardIds) {
+ int forwardSize = 0;
+ int backwardSize = 0;
+ final TIntObjectHashMap<TIntArrayList> fileToBackwardIds = new TIntObjectHashMap<TIntArrayList>(fileToForwardIds.size());
+ for (StripedLockIntObjectConcurrentHashMap.IntEntry<int[]> entry : fileToForwardIds.entries()) {
+ int fileId = entry.getKey();
+ int[] forwardIds = entry.getValue();
+ forwardSize += forwardIds.length;
+ for (int forwardId : forwardIds) {
+ TIntArrayList backIds = fileToBackwardIds.get(forwardId);
+ if (backIds == null) {
+ backIds = new TIntArrayList();
+ fileToBackwardIds.put(forwardId, backIds);
+ }
+ backIds.add(fileId);
+ backwardSize++;
+ }
+ }
+ log("backwardSize = " + backwardSize);
+ log("forwardSize = " + forwardSize);
+ log("fileToForwardIds.size() = "+fileToForwardIds.size());
+ log("fileToBackwardIds.size() = "+fileToBackwardIds.size());
+ assert forwardSize == backwardSize;
+
+ // wrap in read action so that sudden quit (in write action) would not interrupt us
+ ApplicationManager.getApplication().runReadAction(new Runnable() {
+ @Override
+ public void run() {
+ fileToBackwardIds.forEachEntry(new TIntObjectProcedure<TIntArrayList>() {
+ @Override
+ public boolean execute(int fileId, TIntArrayList backIds) {
+ storage.addAll(fileId, backIds.toNativeArray());
+ return true;
+ }
+ });
+ }
+ });
+ }
+
+
+ @NotNull
+ private TIntHashSet calcForwardRefs(@NotNull final VirtualFile virtualFile, @NotNull final ProgressIndicator indicator)
+ throws IndexNotReadyException, ApplicationUtil.CannotRunReadActionException {
+ if (myProject.isDisposed()) throw new ProcessCanceledException();
+ if (fileCount.incrementAndGet() % 100 == 0) {
+ PsiManager.getInstance(myProject).dropResolveCaches();
+ synchronized (storage) {
+ storage.flush();
+ }
+ try {
+ log.flush();
+ }
+ catch (IOException e) {
+ LOG.error(e);
+ }
+ }
+
+ final TIntHashSet forward = new TIntHashSet();
+
+ final PsiFile psiFile = ApplicationUtil.tryRunReadAction(new Computable<PsiFile>() {
+ @Override
+ public PsiFile compute() {
+ return PsiManager.getInstance(myProject).findFile(virtualFile);
+ }
+ });
+ final int fileId = getAbsId(virtualFile);
+ if (psiFile != null) {
+ bytesSize.addAndGet(virtualFile.getLength());
+ final Set<PsiElement> resolved = new THashSet<PsiElement>();
+ ApplicationUtil.tryRunReadAction(new Runnable() {
+ @Override
+ public void run() {
+ indicator.checkCanceled();
+
+ if (psiFile instanceof PsiJavaFile) {
+ psiFile.accept(new JavaRecursiveElementWalkingVisitor() {
+ @Override
+ public void visitReferenceElement(PsiJavaCodeReferenceElement reference) {
+ resolveReference(reference, indicator, resolved);
+
+ super.visitReferenceElement(reference);
+ }
+ });
+ }
+ else if (psiFile instanceof XmlFile) {
+ psiFile.accept(new XmlRecursiveElementWalkingVisitor() {
+ @Override
+ public void visitXmlElement(XmlElement element) {
+ for (PsiReference reference : element.getReferences()) {
+ resolveReference(reference, indicator, resolved);
+ }
+ super.visitXmlElement(element);
+ }
+ });
+ }
+
+ indicator.checkCanceled();
+ for (PsiElement element : resolved) {
+ PsiFile file = element.getContainingFile();
+ addIdAndSuperClasses(file, forward);
+ }
+ }
+ });
+ }
+
+ forward.remove(fileId);
+ return forward;
+ }
+
+ private void resolveReference(@NotNull PsiReference reference, @NotNull ProgressIndicator indicator, @NotNull Set<PsiElement> resolved) {
+ indicator.checkCanceled();
+ PsiElement element = reference.resolve();
+ if (element != null) {
+ resolved.add(element);
+ }
+ refCount.incrementAndGet();
+ }
+
+ private static void addIdAndSuperClasses(PsiFile file, @NotNull TIntHashSet forward) {
+ if (file instanceof PsiJavaFile && file.getName().equals("Object.class") && ((PsiJavaFile)file).getPackageName().equals("java.lang")) {
+ return;
+ }
+ VirtualFile virtualFile = PsiUtilCore.getVirtualFile(file);
+ if (virtualFile instanceof VirtualFileWithId && forward.add(getAbsId(virtualFile)) && file instanceof PsiClassOwner) {
+ for (PsiClass aClass : ((PsiClassOwner)file).getClasses()) {
+ for (PsiClass superClass : aClass.getSupers()) {
+ addIdAndSuperClasses(superClass.getContainingFile(), forward);
+ }
+ }
+ }
+ }
+
+ @Override
+ @Nullable
+ public int[] getBackwardIds(@NotNull VirtualFileWithId file) {
+ if (!upToDate) return null;
+ int fileId = getAbsId((VirtualFile)file);
+ return storage.get(fileId);
+ }
+
+ private String prevLog = "";
+ private static final Set<JavaSourceRootType> SOURCE_ROOTS = ContainerUtil.newTroveSet(JavaSourceRootType.SOURCE, JavaSourceRootType.TEST_SOURCE);
+
+ @NotNull
+ @Override
+ public GlobalSearchScope restrictByBackwardIds(@NotNull final VirtualFile virtualFile, @NotNull GlobalSearchScope scope) {
+ final int[] backIds = RefResolveService.getInstance(myProject).getBackwardIds((VirtualFileWithId)virtualFile);
+ if (backIds == null) {
+ return scope;
+ }
+ String files = toVfString(backIds);
+ String log = "Restricting scope of " + virtualFile.getName() + " to " + files;
+ if (!log.equals(prevLog)) {
+ log(log);
+ flushLog();
+ prevLog = log;
+ }
+ GlobalSearchScope restrictedByBackwardIds = new GlobalSearchScope() {
+ @Override
+ public boolean contains(@NotNull VirtualFile file) {
+ if (!(file instanceof VirtualFileWithId)
+ || file.equals(virtualFile)
+ || ArrayUtil.indexOf(backIds, getAbsId(file)) != -1) return true;
+ return false & !myProjectFileIndex.isUnderSourceRootOfType(file, SOURCE_ROOTS); // filter out source file which we know for sure does not reference the element
+ }
+
+ @Override
+ public int compare(@NotNull VirtualFile file1, @NotNull VirtualFile file2) {
+ return 0;
+ }
+
+ @Override
+ public boolean isSearchInModuleContent(@NotNull Module aModule) {
+ return true;
+ }
+
+ @Override
+ public boolean isSearchInLibraries() {
+ return false;
+ }
+ };
+ return scope.intersectWith(restrictedByBackwardIds);
+ }
+
+ @Override
+ public boolean queue(@NotNull Collection<VirtualFile> files, Object reason) {
+ if (files.isEmpty()) {
+ return false;
+ }
+ boolean queued = false;
+ List<VirtualFile> added = new ArrayList<VirtualFile>(files.size());
+ for (VirtualFile file : files) {
+ boolean wasAdded = queueIfNeeded(file, myProject);
+ if (wasAdded) {
+ added.add(file);
+ }
+ queued |= wasAdded;
+ }
+ if (queued) {
+ log("Queued to resolve (from " + reason + "): " + toVfString(added));
+ flushLog();
+ }
+ return queued;
+ }
+}
diff --git a/java/java-impl/src/com/intellij/psi/filters/FilterUtil.java b/java/java-impl/src/com/intellij/psi/filters/FilterUtil.java
index 89033fae439f..061e0bf18916 100644
--- a/java/java-impl/src/com/intellij/psi/filters/FilterUtil.java
+++ b/java/java-impl/src/com/intellij/psi/filters/FilterUtil.java
@@ -40,6 +40,12 @@ public class FilterUtil{
return JavaPsiFacade.getInstance(element.getProject()).getElementFactory().createType((PsiClass)element);
}
if(element instanceof PsiMethod){
+ if (((PsiMethod)element).isConstructor()) {
+ final PsiClass containingClass = ((PsiMethod)element).getContainingClass();
+ if (containingClass != null) {
+ return JavaPsiFacade.getInstance(element.getProject()).getElementFactory().createType(containingClass);
+ }
+ }
return ((PsiMethod)element).getReturnType();
}
if(element instanceof PsiVariable){
diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java b/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java
index 28748028c246..4d225e65d88b 100644
--- a/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java
+++ b/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java
@@ -222,13 +222,7 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor {
return;
}
if (myRole2 == ChildRole.LBRACE) {
- PsiIdentifier nameIdentifier = aClass.getNameIdentifier();
- int dependanceStart = nameIdentifier == null ? myParent.getTextRange().getStartOffset() : nameIdentifier.getTextRange().getStartOffset();
- ASTNode next = FormatterUtil.getNextNonWhitespaceSibling(myChild2);
- boolean keepOneLine = mySettings.KEEP_SIMPLE_CLASSES_IN_ONE_LINE && next != null && next.getElementType() == JavaTokenType.RBRACE;
- myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_CLASS_LBRACE, mySettings.CLASS_BRACE_STYLE,
- new TextRange(dependanceStart, myChild1.getTextRange().getEndOffset()),
- keepOneLine, true);
+ myResult = getSpaceBeforeClassLBrace(aClass);
}
else if (myRole1 == ChildRole.LBRACE || isEndOfLineCommentAfterLBrace(myChild1)) {
if (aClass.isEnum()) {
@@ -276,10 +270,131 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor {
}
}
- private boolean isEndOfLineCommentAfterLBrace(@NotNull ASTNode node) {
+ @NotNull
+ private Spacing getSpaceBeforeMethodLBrace(@NotNull PsiMethod method) {
+ final int space = mySettings.SPACE_BEFORE_METHOD_LBRACE ? 1 : 0;
+ final int methodBraceStyle = mySettings.METHOD_BRACE_STYLE;
+
+ if (methodBraceStyle == CommonCodeStyleSettings.END_OF_LINE) {
+ return createNonLFSpace(space, null, false);
+ }
+ else if (methodBraceStyle == CommonCodeStyleSettings.NEXT_LINE_IF_WRAPPED) {
+ TextRange headerRange = new TextRange(getMethodHeaderStartOffset(method), getMethodHeaderEndOffset(method));
+ return createNonLFSpace(space, headerRange, false);
+ }
+ else if (shouldHandleAsSimpleMethod(method)) {
+ TextRange rangeWithoutAnnotations = new TextRange(getMethodHeaderStartOffset(method), method.getTextRange().getEndOffset());
+ return createNonLFSpace(space, rangeWithoutAnnotations, false);
+ }
+
+ return Spacing.createSpacing(space, space, 1, false, mySettings.KEEP_BLANK_LINES_IN_CODE);
+ }
+
+ private static int getMethodHeaderEndOffset(@NotNull PsiMethod method) {
+ PsiElement headerEnd = method.getBody() != null ? method.getBody().getPrevSibling() : null;
+ if (headerEnd != null) {
+ return headerEnd.getTextRange().getEndOffset();
+ }
+ return method.getTextRange().getEndOffset();
+ }
+
+ @NotNull
+ private Spacing getSpaceBeforeClassLBrace(@NotNull PsiClass aClass) {
+ final int space = mySettings.SPACE_BEFORE_CLASS_LBRACE ? 1 : 0;
+ final int classBraceStyle = mySettings.CLASS_BRACE_STYLE;
+
+ if (classBraceStyle == CommonCodeStyleSettings.END_OF_LINE || shouldHandleAsSimpleClass(aClass)) {
+ return createNonLFSpace(space, null, false);
+ }
+ else if (classBraceStyle == CommonCodeStyleSettings.NEXT_LINE_IF_WRAPPED) {
+ final PsiIdentifier nameIdentifier = aClass.getNameIdentifier();
+ final int startOffset = nameIdentifier == null ? myParent.getTextRange().getStartOffset() : nameIdentifier.getTextRange().getStartOffset();
+ TextRange range = new TextRange(startOffset, myChild1.getTextRange().getEndOffset());
+ return createNonLFSpace(space, range, false);
+ }
+
+ return Spacing.createSpacing(space, space, 1, false, mySettings.KEEP_BLANK_LINES_IN_CODE);
+ }
+
+ private Spacing getSpaceBeforeLBrace(@NotNull ASTNode lBraceBlock, boolean spaceBeforeLbrace, @Nullable TextRange nextLineIfWrappedOptionRange) {
+ int space = spaceBeforeLbrace ? 1 : 0;
+
+ if (mySettings.BRACE_STYLE == CommonCodeStyleSettings.END_OF_LINE) {
+ return createNonLFSpace(space, null, false);
+ }
+ else if (mySettings.BRACE_STYLE == CommonCodeStyleSettings.NEXT_LINE_IF_WRAPPED) {
+ return createNonLFSpace(space, nextLineIfWrappedOptionRange, false);
+ }
+ else if (shouldHandleAsSimpleBlock(lBraceBlock)) {
+ return createNonLFSpace(space, lBraceBlock.getTextRange(), false);
+ }
+
+ return Spacing.createSpacing(space, space, 1, false, mySettings.KEEP_BLANK_LINES_IN_CODE);
+ }
+
+ private boolean shouldHandleAsSimpleClass(@NotNull PsiClass aClass) {
+ if (!mySettings.KEEP_SIMPLE_CLASSES_IN_ONE_LINE) return false;
+
+ final PsiElement lBrace = aClass.getLBrace();
+ final PsiElement rBrace = aClass.getRBrace();
+ if (lBrace != null && rBrace != null) {
+ PsiElement beforeLBrace = lBrace.getPrevSibling();
+ if (beforeLBrace instanceof PsiWhiteSpace && beforeLBrace.textContains('\n')) {
+ return false;
+ }
+
+ PsiElement betweenBraces = lBrace.getNextSibling();
+ if (betweenBraces == rBrace || isWhiteSpaceWithoutLinefeeds(betweenBraces) && betweenBraces.getNextSibling() == rBrace) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private static boolean isWhiteSpaceWithoutLinefeeds(@Nullable PsiElement betweenBraces) {
+ return betweenBraces instanceof PsiWhiteSpace && !betweenBraces.textContains('\n');
+ }
+
+ private boolean shouldHandleAsSimpleBlock(@NotNull ASTNode node) {
+ if (!mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE) return false;
+
+ PsiElement prev = node.getPsi().getPrevSibling();
+ if (prev instanceof PsiWhiteSpace && prev.textContains('\n')) {
+ return false;
+ }
+ return !node.textContains('\n');
+ }
+
+ private boolean shouldHandleAsSimpleMethod(@NotNull PsiMethod method) {
+ if (!mySettings.KEEP_SIMPLE_METHODS_IN_ONE_LINE) return false;
+
+ boolean skipElement = true;
+ for (PsiElement element : method.getChildren()) {
+ if (element instanceof PsiTypeElement) skipElement = false;
+ if (skipElement) continue;
+
+ if (element.textContains('\n')) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private static int getMethodHeaderStartOffset(@NotNull PsiMethod method) {
+ for (PsiElement element : method.getChildren()) {
+ if (element instanceof PsiTypeElement) {
+ return element.getTextRange().getStartOffset();
+ }
+ }
+ return method.getTextRange().getStartOffset();
+ }
+
+ private static boolean isEndOfLineCommentAfterLBrace(@NotNull ASTNode node) {
if (node.getPsi() instanceof PsiComment) {
PsiElement ws = node.getPsi().getPrevSibling();
- if (ws instanceof PsiWhiteSpace && !ws.textContains('\n')) {
+ if (isWhiteSpaceWithoutLinefeeds(ws)) {
PsiElement beforeWs = ws.getPrevSibling();
if (beforeWs instanceof PsiJavaToken && ((PsiJavaToken)beforeWs).getTokenType() == JavaTokenType.LBRACE) {
return true;
@@ -580,14 +695,11 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor {
}
else if (myRole2 == ChildRole.LOOP_BODY || myChild2.getElementType() == JavaElementType.CODE_BLOCK) {
if (myChild2.getElementType() == JavaElementType.BLOCK_STATEMENT) {
- myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_WHILE_LBRACE, mySettings.BRACE_STYLE,
- new TextRange(myParent.getTextRange().getStartOffset(), myChild1.getTextRange().getEndOffset()),
- mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE, true);
+ myResult = getSpaceBeforeLBrace(myChild2, mySettings.SPACE_BEFORE_WHILE_LBRACE, null);
} else {
createSpacingBeforeElementInsideControlStatement();
}
}
-
}
@Override
@@ -600,8 +712,7 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor {
}
else if (myRole2 == ChildRole.LOOP_BODY) {
if (myChild2.getElementType() == JavaElementType.BLOCK_STATEMENT) {
- myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_DO_LBRACE, mySettings.BRACE_STYLE, null,
- mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE, true);
+ myResult = getSpaceBeforeLBrace(myChild2, mySettings.SPACE_BEFORE_DO_LBRACE, null);
} else {
createSpacingBeforeElementInsideControlStatement();
}
@@ -652,25 +763,16 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor {
}
if (myRole2 == ChildRole.TRY_BLOCK) {
- TextRange dependantRange = getDependencyRangeForLBraceWhiteSpace(statement.getTryBlock());
- myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_TRY_LBRACE, mySettings.BRACE_STYLE, dependantRange, mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE, false);
+ myResult = getSpaceBeforeLBrace(myChild2, mySettings.SPACE_BEFORE_TRY_LBRACE, null);
}
else if (myRole2 == ChildRole.FINALLY_BLOCK) {
- TextRange dependantRange = getDependencyRangeForLBraceWhiteSpace(statement.getFinallyBlock());
- myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_FINALLY_LBRACE, mySettings.BRACE_STYLE, dependantRange, mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE, false);
+ myResult = getSpaceBeforeLBrace(myChild2, mySettings.SPACE_BEFORE_FINALLY_LBRACE, null);
}
else if (myType2 == JavaElementType.RESOURCE_LIST) {
createSpaceInCode(mySettings.SPACE_BEFORE_TRY_PARENTHESES);
}
}
- @Nullable
- private TextRange getDependencyRangeForLBraceWhiteSpace(PsiElement element) {
- return mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE && element != null
- ? element.getTextRange()
- : null;
- }
-
@Override
public void visitForeachStatement(PsiForeachStatement statement) {
if (myRole1 == ChildRole.FOR_KEYWORD && myRole2 == ChildRole.LPARENTH) {
@@ -686,9 +788,7 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor {
}
else if (myRole2 == ChildRole.LOOP_BODY) {
if (myChild2.getElementType() == JavaElementType.BLOCK_STATEMENT) {
- myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_FOR_LBRACE, mySettings.BRACE_STYLE,
- new TextRange(myParent.getTextRange().getStartOffset(), myChild1.getTextRange().getEndOffset()),
- mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE, true);
+ myResult = getSpaceBeforeLBrace(myChild2, mySettings.SPACE_BEFORE_FOR_LBRACE, null);
}
else if (mySettings.KEEP_CONTROL_STATEMENT_IN_ONE_LINE) {
myResult = Spacing.createDependentLFSpacing(1, 1, myParent.getTextRange(), false, mySettings.KEEP_BLANK_LINES_IN_CODE);
@@ -782,8 +882,7 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor {
else if (myChild1.getElementType() == JavaElementType.SWITCH_LABEL_STATEMENT
&& myChild2.getElementType() == JavaElementType.BLOCK_STATEMENT)
{
- myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_SWITCH_LBRACE, mySettings.BRACE_STYLE, null, false, true);
-
+ myResult = getSpaceBeforeLBrace(myChild2, mySettings.SPACE_BEFORE_SWITCH_LBRACE, null);
}
else if (lhsStatement && rhsStatement) {
int minSpaces = 0;
@@ -813,11 +912,11 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor {
private boolean keepInOneLine(final PsiCodeBlock block) {
if (block.getParent() instanceof PsiMethod) {
- return mySettings.KEEP_SIMPLE_METHODS_IN_ONE_LINE;
+ return shouldHandleAsSimpleMethod((PsiMethod)block.getParent());
}
else {
- return mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE;
- }
+ return shouldHandleAsSimpleBlock(block.getNode());
+ }
}
@Override
@@ -846,10 +945,7 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor {
}
else {
if (myChild2.getElementType() == JavaElementType.BLOCK_STATEMENT || myChild2.getElementType() == JavaElementType.CODE_BLOCK) {
- TextRange dependantRange = getDependencyRangeForLBraceWhiteSpace(statement.getElseBranch());
- myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_ELSE_LBRACE,
- mySettings.BRACE_STYLE,
- dependantRange, mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE, false);
+ myResult = getSpaceBeforeLBrace(myChild2, mySettings.SPACE_BEFORE_ELSE_LBRACE, null);
}
else {
createSpacingBeforeElementInsideControlStatement();
@@ -859,17 +955,13 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor {
else if (myChild2.getElementType() == JavaElementType.BLOCK_STATEMENT || myChild2.getElementType() == JavaElementType.CODE_BLOCK) {
boolean space = myRole2 == ChildRole.ELSE_BRANCH ? mySettings.SPACE_BEFORE_ELSE_LBRACE
: mySettings.SPACE_BEFORE_IF_LBRACE;
-
- PsiElement branch = myRole2 == ChildRole.ELSE_BRANCH ? statement.getElseBranch()
- : statement.getThenBranch();
-
- TextRange dependantRange = mySettings.BRACE_STYLE == CommonCodeStyleSettings.NEXT_LINE_IF_WRAPPED || branch == null
- ? new TextRange(myParent.getTextRange().getStartOffset(), myChild1.getTextRange().getEndOffset())
- : branch.getTextRange();
-
- myResult = getSpaceBeforeLBrace(space, mySettings.BRACE_STYLE,
- dependantRange,
- mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE, false);
+
+ TextRange dependentRange = null;
+ if (myRole2 == ChildRole.THEN_BRANCH) {
+ PsiExpression condition = statement.getCondition();
+ if (condition != null) dependentRange = condition.getTextRange();
+ }
+ myResult = getSpaceBeforeLBrace(myChild2, space, dependentRange);
}
else if (myRole2 == ChildRole.LPARENTH) {
createSpaceInCode(mySettings.SPACE_BEFORE_IF_PARENTHESES);
@@ -911,29 +1003,6 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor {
return FormatterUtil.getPreviousNonWhitespaceLeaf(child);
}
- private Spacing getSpaceBeforeLBrace(final boolean spaceBeforeLbrace,
- @CommonCodeStyleSettings.BraceStyleConstant int braceStyle,
- @Nullable TextRange dependantRange,
- boolean keepOneLine,
- boolean useParentBlockAsDependencyAllTheTime)
- {
- int space = spaceBeforeLbrace ? 1 : 0;
- if (dependantRange != null && braceStyle == CommonCodeStyleSettings.NEXT_LINE_IF_WRAPPED) {
- return createNonLFSpace(space, dependantRange, false);
- }
- else if (braceStyle == CommonCodeStyleSettings.END_OF_LINE || braceStyle == CommonCodeStyleSettings.NEXT_LINE_IF_WRAPPED) {
- return createNonLFSpace(space, null, false);
- }
- else if (keepOneLine) {
- TextRange dependencyRangeToUse = dependantRange == null || useParentBlockAsDependencyAllTheTime
- ? myParent.getTextRange() : dependantRange;
-
- return Spacing.createDependentLFSpacing(space, space, dependencyRangeToUse, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
- }
- else {
- return Spacing.createSpacing(0, 0, 1, false, mySettings.KEEP_BLANK_LINES_IN_CODE);
- }
- }
@Override
public void visitPolyadicExpression(PsiPolyadicExpression expression) {
@@ -1029,37 +1098,7 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor {
createSpaceInCode(true);
}
else if (myRole2 == ChildRole.METHOD_BODY) {
- PsiElement methodName = method.getNameIdentifier();
- int dependencyStart = methodName == null ? myParent.getTextRange().getStartOffset() : methodName.getTextRange().getStartOffset();
- PsiModifierList modifierList = method.getModifierList();
- PsiAnnotation[] annotations = modifierList.getAnnotations();
- boolean useParentBlockAsDependencyAllTheTime = true;
- if (annotations.length > 0) {
- useParentBlockAsDependencyAllTheTime = false;
- PsiAnnotation annotation = annotations[annotations.length - 1];
- ASTNode nextModifier = FormatterUtil.getNextNonWhitespaceSibling(annotation.getNode());
- if (nextModifier == null) {
- PsiElement element = modifierList.getNextSibling();
- if (element != null) {
- ASTNode node = element.getNode();
- if (node != null && node.getTextLength() > 0) {
- dependencyStart = element.getTextRange().getStartOffset();
- }
- }
- } else {
- dependencyStart = nextModifier.getStartOffset();
- }
- }
-
- ASTNode dependencyEndAnchor = mySettings.METHOD_BRACE_STYLE == CommonCodeStyleSettings.NEXT_LINE ? myChild2 : myChild1;
- int dependencyEnd = dependencyEndAnchor.getTextRange().getEndOffset();
- boolean keepInOneLine = mySettings.KEEP_SIMPLE_METHODS_IN_ONE_LINE
- && method.getBody() != null
- && !method.getBody().textContains('\n');
-
- myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_METHOD_LBRACE, mySettings.METHOD_BRACE_STYLE,
- new TextRange(dependencyStart, dependencyEnd), keepInOneLine,
- useParentBlockAsDependencyAllTheTime);
+ myResult = getSpaceBeforeMethodLBrace(method);
}
else if (myRole1 == ChildRole.MODIFIER_LIST) {
processModifierList();
@@ -1176,8 +1215,7 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor {
createSpaceInCode(mySettings.SPACE_WITHIN_SYNCHRONIZED_PARENTHESES);
}
else if (myRole2 == ChildRole.BLOCK) {
- myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_SYNCHRONIZED_LBRACE, mySettings.BRACE_STYLE, null,
- mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE, true);
+ myResult = getSpaceBeforeLBrace(myChild2, mySettings.SPACE_BEFORE_SYNCHRONIZED_LBRACE, null);
}
}
@@ -1197,10 +1235,8 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor {
createSpaceInCode(mySettings.SPACE_WITHIN_SWITCH_PARENTHESES);
}
else if (myRole2 == ChildRole.SWITCH_BODY) {
- myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_SWITCH_LBRACE, mySettings.BRACE_STYLE, null,
- mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE, true);
+ myResult = getSpaceBeforeLBrace(myChild2, mySettings.SPACE_BEFORE_SWITCH_LBRACE, null);
}
-
}
@Override
@@ -1265,9 +1301,7 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor {
}
else if (myRole2 == ChildRole.LOOP_BODY || myChild2.getElementType() == JavaElementType.CODE_BLOCK) {
if (myChild2.getElementType() == JavaElementType.BLOCK_STATEMENT) {
- myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_FOR_LBRACE, mySettings.BRACE_STYLE,
- new TextRange(myParent.getTextRange().getStartOffset(), myChild1.getTextRange().getEndOffset()),
- mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE, true);
+ myResult = getSpaceBeforeLBrace(myChild2, mySettings.SPACE_BEFORE_FOR_LBRACE, null);
}
else if (mySettings.KEEP_CONTROL_STATEMENT_IN_ONE_LINE) {
myResult = Spacing.createDependentLFSpacing(1, 1, myParent.getTextRange(), false, mySettings.KEEP_BLANK_LINES_IN_CODE);
@@ -1290,9 +1324,7 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor {
@Override
public void visitCatchSection(PsiCatchSection section) {
if (myRole2 == ChildRole.CATCH_BLOCK) {
- TextRange dependantRange = mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE ? section.getTextRange() : null;
- myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_CATCH_LBRACE, mySettings.BRACE_STYLE, dependantRange,
- mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE, true);
+ myResult = getSpaceBeforeLBrace(myChild2, mySettings.SPACE_BEFORE_CATCH_LBRACE, null);
}
else if (myRole2 == ChildRole.CATCH_BLOCK_PARAMETER_LPARENTH) {
createSpaceInCode(mySettings.SPACE_BEFORE_CATCH_PARENTHESES);
@@ -1512,7 +1544,7 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor {
@Override
public void visitClassInitializer(PsiClassInitializer initializer) {
if (myChild2.getElementType() == JavaElementType.CODE_BLOCK) {
- myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_METHOD_LBRACE, mySettings.BRACE_STYLE, null, false, true);
+ myResult = getSpaceBeforeLBrace(myChild2, mySettings.SPACE_BEFORE_METHOD_LBRACE, null);
}
}
@@ -1588,8 +1620,7 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor {
createSpaceInCode(mySettings.SPACE_BEFORE_METHOD_CALL_PARENTHESES);
}
else if (myRole2 == ChildRole.ANONYMOUS_CLASS) {
- myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_CLASS_LBRACE, mySettings.METHOD_BRACE_STYLE, enumConstant.getTextRange(),
- mySettings.KEEP_SIMPLE_METHODS_IN_ONE_LINE, true);
+ myResult = getSpaceBeforeLBrace(myChild2, mySettings.SPACE_BEFORE_CLASS_LBRACE, null);
}
}
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaCodeStyleManagerImpl.java b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaCodeStyleManagerImpl.java
index a35b6e36e756..d7028b99fcff 100644
--- a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaCodeStyleManagerImpl.java
+++ b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaCodeStyleManagerImpl.java
@@ -1064,7 +1064,7 @@ public class JavaCodeStyleManagerImpl extends JavaCodeStyleManager {
public static boolean isStringPsiLiteral(PsiElement element) {
if (element instanceof PsiLiteralExpression) {
final String text = element.getText();
- return text.length() > 1 && StringUtil.isQuotedString(text);
+ return StringUtil.isQuotedString(text);
}
return false;
}
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/JavaLangClassMemberReference.java b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/JavaLangClassMemberReference.java
index 13644930d88e..776f68bd2cfe 100644
--- a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/JavaLangClassMemberReference.java
+++ b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/JavaLangClassMemberReference.java
@@ -26,6 +26,7 @@ import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.impl.source.PsiClassReferenceType;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.*;
+import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -44,6 +45,11 @@ public class JavaLangClassMemberReference extends PsiReferenceBase<PsiLiteralExp
}
@Override
+ public PsiElement bindToElement(@NotNull PsiElement element) throws IncorrectOperationException {
+ return element;
+ }
+
+ @Override
public PsiElement resolve() {
final String name = (String)getElement().getValue();
final Type type = getType();
diff --git a/java/java-impl/src/com/intellij/refactoring/copy/CopyClassesHandler.java b/java/java-impl/src/com/intellij/refactoring/copy/CopyClassesHandler.java
index b551616c93dc..49064514be38 100644
--- a/java/java-impl/src/com/intellij/refactoring/copy/CopyClassesHandler.java
+++ b/java/java-impl/src/com/intellij/refactoring/copy/CopyClassesHandler.java
@@ -332,7 +332,7 @@ public class CopyClassesHandler extends CopyHandlerDelegateBase {
for (final PsiClass[] psiClasses : fileToClasses.values()) {
if (psiClasses != null) {
for (PsiClass aClass : psiClasses) {
- if (aClass instanceof SyntheticElement) {
+ if (isSynthetic(aClass)) {
continue;
}
oldToNewMap.put(aClass, null);
@@ -349,7 +349,7 @@ public class CopyClassesHandler extends CopyHandlerDelegateBase {
final PsiFile createdFile = copy(psiFile, targetDirectory, copyClassName, map == null ? null : map.get(psiFile), choice);
if (createdFile == null) return null;
for (final PsiClass destination : ((PsiClassOwner)createdFile).getClasses()) {
- if (destination instanceof SyntheticElement) {
+ if (isSynthetic(destination)) {
continue;
}
PsiClass source = findByName(sources, destination.getName());
@@ -408,6 +408,10 @@ public class CopyClassesHandler extends CopyHandlerDelegateBase {
return newElement != null ? newElement : createdFiles.size() > 0 ? createdFiles.get(0) : null;
}
+ protected static boolean isSynthetic(PsiClass aClass) {
+ return aClass instanceof SyntheticElement || !aClass.isPhysical();
+ }
+
private static PsiFile copy(@NotNull PsiFile file, PsiDirectory directory, String name, String relativePath, int[] choice) {
final String fileName = getNewFileName(file, name);
if (relativePath != null && !relativePath.isEmpty()) {
@@ -420,9 +424,10 @@ public class CopyClassesHandler extends CopyHandlerDelegateBase {
private static String getNewFileName(PsiFile file, String name) {
if (name != null) {
if (file instanceof PsiClassOwner) {
- final PsiClass[] classes = ((PsiClassOwner)file).getClasses();
- if (classes.length > 0 && !(classes[0] instanceof SyntheticElement)) {
- return name + "." + file.getViewProvider().getVirtualFile().getExtension();
+ for (final PsiClass psiClass : ((PsiClassOwner)file).getClasses()) {
+ if (!isSynthetic(psiClass)) {
+ return name + "." + file.getViewProvider().getVirtualFile().getExtension();
+ }
}
}
return name;
@@ -530,15 +535,14 @@ public class CopyClassesHandler extends CopyHandlerDelegateBase {
if (element instanceof PsiCompiledElement) return null;
if (element instanceof PsiClassOwner) {
PsiClass[] classes = ((PsiClassOwner)element).getClasses();
- if (classes.length > 0) {
- for (final PsiClass aClass : classes) {
- if (aClass instanceof SyntheticElement) {
- return null;
- }
+ ArrayList<PsiClass> buffer = new ArrayList<PsiClass>();
+ for (final PsiClass aClass : classes) {
+ if (isSynthetic(aClass)) {
+ return null;
}
-
- return classes;
+ buffer.add(aClass);
}
+ return buffer.toArray(new PsiClass[buffer.size()]);
}
return element instanceof PsiClass ? new PsiClass[]{(PsiClass)element} : null;
}
diff --git a/java/java-impl/src/com/intellij/refactoring/extractSuperclass/ExtractSuperclassHandler.java b/java/java-impl/src/com/intellij/refactoring/extractSuperclass/ExtractSuperclassHandler.java
index b8f24bc16f1f..b3e43eb93938 100644
--- a/java/java-impl/src/com/intellij/refactoring/extractSuperclass/ExtractSuperclassHandler.java
+++ b/java/java-impl/src/com/intellij/refactoring/extractSuperclass/ExtractSuperclassHandler.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.
@@ -59,6 +59,7 @@ public class ExtractSuperclassHandler implements RefactoringActionHandler, Extra
private Project myProject;
+ @Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file, DataContext dataContext) {
editor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
int offset = editor.getCaretModel().getOffset();
@@ -77,6 +78,7 @@ public class ExtractSuperclassHandler implements RefactoringActionHandler, Extra
}
}
+ @Override
public void invoke(@NotNull final Project project, @NotNull PsiElement[] elements, DataContext dataContext) {
if (elements.length != 1) return;
@@ -101,6 +103,7 @@ public class ExtractSuperclassHandler implements RefactoringActionHandler, Extra
final List<MemberInfo> memberInfos = MemberInfo.extractClassMembers(mySubclass, new MemberInfo.Filter<PsiMember>() {
+ @Override
public boolean includeMember(PsiMember element) {
return true;
}
@@ -112,8 +115,10 @@ public class ExtractSuperclassHandler implements RefactoringActionHandler, Extra
if (!dialog.isOK() || !dialog.isExtractSuperclass()) return;
CommandProcessor.getInstance().executeCommand(myProject, new Runnable() {
+ @Override
public void run() {
final Runnable action = new Runnable() {
+ @Override
public void run() {
doRefactoring(project, mySubclass, dialog);
}
@@ -124,6 +129,7 @@ public class ExtractSuperclassHandler implements RefactoringActionHandler, Extra
}
+ @Override
public boolean checkConflicts(final ExtractSuperclassDialog dialog) {
final MemberInfo[] infos = ArrayUtil.toObjectArray(dialog.getSelectedMemberInfos(), MemberInfo.class);
final PsiDirectory targetDirectory = dialog.getTargetDirectory();
@@ -136,9 +142,17 @@ public class ExtractSuperclassHandler implements RefactoringActionHandler, Extra
}
final MultiMap<PsiElement,String> conflicts = new MultiMap<PsiElement, String>();
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
+ @Override
public void run() {
- final PsiClass superClass = mySubclass.getExtendsListTypes().length > 0 || mySubclass instanceof PsiAnonymousClass ? mySubclass.getSuperClass() : null;
- conflicts.putAllValues(PullUpConflictsUtil.checkConflicts(infos, mySubclass, superClass, targetPackage, targetDirectory, dialog.getContainmentVerifier(), false));
+ ApplicationManager.getApplication().runReadAction(new Runnable() {
+ @Override
+ public void run() {
+ final PsiClass superClass =
+ mySubclass.getExtendsListTypes().length > 0 || mySubclass instanceof PsiAnonymousClass ? mySubclass.getSuperClass() : null;
+ conflicts.putAllValues(PullUpConflictsUtil.checkConflicts(infos, mySubclass, superClass, targetPackage, targetDirectory,
+ dialog.getContainmentVerifier(), false));
+ }
+ });
}
}, RefactoringBundle.message("detecting.possible.conflicts"), true, myProject)) return false;
ExtractSuperClassUtil.checkSuperAccessible(targetDirectory, conflicts, mySubclass);
@@ -168,6 +182,7 @@ public class ExtractSuperclassHandler implements RefactoringActionHandler, Extra
final SmartPsiElementPointer<PsiClass> classPointer = SmartPointerManager.getInstance(project).createSmartPsiElementPointer(subclass);
final SmartPsiElementPointer<PsiClass> interfacePointer = SmartPointerManager.getInstance(project).createSmartPsiElementPointer(superclass);
final Runnable turnRefsToSuperRunnable = new Runnable() {
+ @Override
public void run() {
ExtractClassUtil.askAndTurnRefsToSuper(project, classPointer, interfacePointer);
}
@@ -185,6 +200,7 @@ public class ExtractSuperclassHandler implements RefactoringActionHandler, Extra
return RefactoringBundle.message("extract.superclass.command.name", newName, DescriptiveNameUtil.getDescriptiveName(subclass));
}
+ @Override
public boolean isEnabledOnElements(PsiElement[] elements) {
return elements.length == 1 && elements[0] instanceof PsiClass && !((PsiClass) elements[0]).isInterface()
&&!((PsiClass)elements[0]).isEnum();
diff --git a/java/java-impl/src/com/intellij/refactoring/inline/InlineConstantFieldHandler.java b/java/java-impl/src/com/intellij/refactoring/inline/InlineConstantFieldHandler.java
index b82953534b8c..ddfb057460ab 100644
--- a/java/java-impl/src/com/intellij/refactoring/inline/InlineConstantFieldHandler.java
+++ b/java/java-impl/src/com/intellij/refactoring/inline/InlineConstantFieldHandler.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.refactoring.inline;
import com.intellij.codeInsight.TargetElementUtilBase;
import com.intellij.lang.StdLanguages;
+import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
@@ -35,10 +36,12 @@ import com.intellij.refactoring.util.CommonRefactoringUtil;
public class InlineConstantFieldHandler extends JavaInlineActionHandler {
private static final String REFACTORING_NAME = RefactoringBundle.message("inline.field.title");
+ @Override
public boolean canInlineElement(PsiElement element) {
return element instanceof PsiField && StdLanguages.JAVA.equals(element.getLanguage());
}
+ @Override
public void inlineElement(Project project, Editor editor, PsiElement element) {
final PsiElement navigationElement = element.getNavigationElement();
final PsiField field = (PsiField)(navigationElement instanceof PsiField ? navigationElement : element);
@@ -66,13 +69,18 @@ public class InlineConstantFieldHandler extends JavaInlineActionHandler {
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
@Override
public void run() {
- for (PsiReference reference : ReferencesSearch.search(field)) {
- final PsiElement referenceElement = reference.getElement();
- if (!(referenceElement instanceof PsiExpression && PsiUtil.isAccessedForReading((PsiExpression)referenceElement))) {
- hasWriteUsages.set(true);
- break;
+ ApplicationManager.getApplication().runReadAction(new Runnable() {
+ @Override
+ public void run() {
+ for (PsiReference reference : ReferencesSearch.search(field)) {
+ final PsiElement referenceElement = reference.getElement();
+ if (!(referenceElement instanceof PsiExpression && PsiUtil.isAccessedForReading((PsiExpression)referenceElement))) {
+ hasWriteUsages.set(true);
+ break;
+ }
+ }
}
- }
+ });
}
}, "Check if inline is possible...", true, project)) {
return;
diff --git a/java/java-impl/src/com/intellij/refactoring/inline/InlineParameterHandler.java b/java/java-impl/src/com/intellij/refactoring/inline/InlineParameterHandler.java
index 2b285553bc24..b8097d7376f6 100644
--- a/java/java-impl/src/com/intellij/refactoring/inline/InlineParameterHandler.java
+++ b/java/java-impl/src/com/intellij/refactoring/inline/InlineParameterHandler.java
@@ -200,7 +200,7 @@ public class InlineParameterHandler extends JavaInlineActionHandler {
}
if (!ApplicationManager.getApplication().isUnitTestMode()) {
- String occurencesString = RefactoringBundle.message("occurences.string", occurrences.size());
+ String occurencesString = RefactoringBundle.message("occurrences.string", occurrences.size());
String question = RefactoringBundle.message("inline.parameter.confirmation", psiParameter.getName(),
constantExpression.getText()) + " " + occurencesString;
RefactoringMessageDialog dialog = new RefactoringMessageDialog(
diff --git a/java/java-impl/src/com/intellij/refactoring/inline/InlineToAnonymousClassHandler.java b/java/java-impl/src/com/intellij/refactoring/inline/InlineToAnonymousClassHandler.java
index e17326844249..8d7995fbf1b0 100644
--- a/java/java-impl/src/com/intellij/refactoring/inline/InlineToAnonymousClassHandler.java
+++ b/java/java-impl/src/com/intellij/refactoring/inline/InlineToAnonymousClassHandler.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.
@@ -91,7 +91,7 @@ public class InlineToAnonymousClassHandler extends JavaInlineActionHandler {
});
}
}, "Searching for class \"" + element.getQualifiedName() + "\" inheritors ...", true, element.getProject())) return false;
- return inheritors.size() == 0;
+ return inheritors.isEmpty();
}
@Override
@@ -124,7 +124,12 @@ public class InlineToAnonymousClassHandler extends JavaInlineActionHandler {
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable(){
@Override
public void run() {
- errorMessage.set(getCannotInlineMessage(psiClass));
+ ApplicationManager.getApplication().runReadAction(new Runnable() {
+ @Override
+ public void run() {
+ errorMessage.set(getCannotInlineMessage(psiClass));
+ }
+ });
}
}, "Check if inline is possible...", true, project)) return;
if (errorMessage.get() != null) {
diff --git a/java/java-impl/src/com/intellij/refactoring/makeStatic/MakeMethodStaticProcessor.java b/java/java-impl/src/com/intellij/refactoring/makeStatic/MakeMethodStaticProcessor.java
index de5efa573d8a..64afbfa17e84 100644
--- a/java/java-impl/src/com/intellij/refactoring/makeStatic/MakeMethodStaticProcessor.java
+++ b/java/java-impl/src/com/intellij/refactoring/makeStatic/MakeMethodStaticProcessor.java
@@ -27,6 +27,7 @@ import com.intellij.refactoring.util.RefactoringUtil;
import com.intellij.refactoring.util.javadoc.MethodJavaDocHelper;
import com.intellij.usageView.UsageInfo;
import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.containers.MultiMap;
import java.util.ArrayList;
import java.util.List;
@@ -41,6 +42,20 @@ public class MakeMethodStaticProcessor extends MakeMethodOrClassStaticProcessor<
super(project, method, settings);
}
+ @Override
+ protected MultiMap<PsiElement, String> getConflictDescriptions(UsageInfo[] usages) {
+ MultiMap<PsiElement, String> descriptions = super.getConflictDescriptions(usages);
+ if (mySettings.isMakeClassParameter()) {
+ for (UsageInfo usage : usages) {
+ PsiElement element = usage.getElement();
+ if (element instanceof PsiMethodReferenceExpression) {
+ descriptions.putValue(element, "Method reference will be corrupted");
+ }
+ }
+ }
+ return descriptions;
+ }
+
protected void changeSelfUsage(SelfUsageInfo usageInfo) throws IncorrectOperationException {
PsiElement parent = usageInfo.getElement().getParent();
LOG.assertTrue(parent instanceof PsiMethodCallExpression);
diff --git a/java/java-impl/src/com/intellij/refactoring/memberPullUp/JavaPullUpHandler.java b/java/java-impl/src/com/intellij/refactoring/memberPullUp/JavaPullUpHandler.java
index 2cbf7a0adcee..5a21d945fd79 100644
--- a/java/java-impl/src/com/intellij/refactoring/memberPullUp/JavaPullUpHandler.java
+++ b/java/java-impl/src/com/intellij/refactoring/memberPullUp/JavaPullUpHandler.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.
@@ -26,6 +26,7 @@ package com.intellij.refactoring.memberPullUp;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ScrollType;
@@ -55,6 +56,7 @@ public class JavaPullUpHandler implements RefactoringActionHandler, PullUpDialog
private PsiClass mySubclass;
private Project myProject;
+ @Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file, DataContext dataContext) {
int offset = editor.getCaretModel().getOffset();
editor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
@@ -78,6 +80,7 @@ public class JavaPullUpHandler implements RefactoringActionHandler, PullUpDialog
}
}
+ @Override
public void invoke(@NotNull final Project project, @NotNull PsiElement[] elements, DataContext dataContext) {
if (elements.length != 1) return;
myProject = project;
@@ -130,6 +133,7 @@ public class JavaPullUpHandler implements RefactoringActionHandler, PullUpDialog
mySubclass = aClass;
MemberInfoStorage memberInfoStorage = new MemberInfoStorage(mySubclass, new MemberInfo.Filter<PsiMember>() {
+ @Override
public boolean includeMember(PsiMember element) {
return true;
}
@@ -152,6 +156,7 @@ public class JavaPullUpHandler implements RefactoringActionHandler, PullUpDialog
+ @Override
public boolean checkConflicts(final PullUpDialog dialog) {
final List<MemberInfo> infos = dialog.getSelectedMemberInfos();
final MemberInfo[] memberInfos = infos.toArray(new MemberInfo[infos.size()]);
@@ -159,11 +164,18 @@ public class JavaPullUpHandler implements RefactoringActionHandler, PullUpDialog
if (!checkWritable(superClass, memberInfos)) return false;
final MultiMap<PsiElement, String> conflicts = new MultiMap<PsiElement, String>();
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
+ @Override
public void run() {
- final PsiDirectory targetDirectory = superClass.getContainingFile().getContainingDirectory();
- final PsiPackage targetPackage = targetDirectory != null ? JavaDirectoryService.getInstance().getPackage(targetDirectory) : null;
- conflicts
- .putAllValues(PullUpConflictsUtil.checkConflicts(memberInfos, mySubclass, superClass, targetPackage, targetDirectory, dialog.getContainmentVerifier()));
+ ApplicationManager.getApplication().runReadAction(new Runnable() {
+ @Override
+ public void run() {
+ final PsiDirectory targetDirectory = superClass.getContainingFile().getContainingDirectory();
+ final PsiPackage targetPackage = targetDirectory != null ? JavaDirectoryService.getInstance().getPackage(targetDirectory) : null;
+ conflicts
+ .putAllValues(PullUpConflictsUtil.checkConflicts(memberInfos, mySubclass, superClass, targetPackage, targetDirectory, dialog.getContainmentVerifier()));
+ }
+ });
+
}
}, RefactoringBundle.message("detecting.possible.conflicts"), true, myProject)) return false;
if (!conflicts.isEmpty()) {
@@ -185,6 +197,7 @@ public class JavaPullUpHandler implements RefactoringActionHandler, PullUpDialog
return true;
}
+ @Override
public boolean isEnabledOnElements(PsiElement[] elements) {
/*
if (elements.length == 1) {
diff --git a/java/java-impl/src/com/intellij/refactoring/memberPullUp/PullUpProcessor.java b/java/java-impl/src/com/intellij/refactoring/memberPullUp/PullUpProcessor.java
index 4531e391f838..353898cafe51 100644
--- a/java/java-impl/src/com/intellij/refactoring/memberPullUp/PullUpProcessor.java
+++ b/java/java-impl/src/com/intellij/refactoring/memberPullUp/PullUpProcessor.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.
@@ -68,7 +68,7 @@ public class PullUpProcessor extends BaseRefactoringProcessor implements PullUpD
private final DocCommentPolicy myJavaDocPolicy;
private Set<PsiMember> myMembersAfterMove = null;
private Set<PsiMember> myMovedMembers = null;
- private Map<Language, PullUpHelper<MemberInfo>> myProcessors = ContainerUtil.newHashMap();
+ private final Map<Language, PullUpHelper<MemberInfo>> myProcessors = ContainerUtil.newHashMap();
public PullUpProcessor(PsiClass sourceClass, PsiClass targetSuperClass, MemberInfo[] membersToMove, DocCommentPolicy javaDocPolicy) {
super(sourceClass.getProject());
@@ -78,11 +78,13 @@ public class PullUpProcessor extends BaseRefactoringProcessor implements PullUpD
myJavaDocPolicy = javaDocPolicy;
}
+ @Override
@NotNull
protected UsageViewDescriptor createUsageViewDescriptor(UsageInfo[] usages) {
return new PullUpUsageViewDescriptor();
}
+ @Override
@NotNull
protected UsageInfo[] findUsages() {
final List<UsageInfo> result = new ArrayList<UsageInfo>();
@@ -125,6 +127,7 @@ public class PullUpProcessor extends BaseRefactoringProcessor implements PullUpD
return data;
}
+ @Override
protected void performRefactoring(UsageInfo[] usages) {
moveMembersToBase();
moveFieldInitializations();
@@ -148,29 +151,35 @@ public class PullUpProcessor extends BaseRefactoringProcessor implements PullUpD
ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
@Override
public void run() {
- final Query<PsiClass> search = ClassInheritorsSearch.search(myTargetSuperClass);
- final Set<VirtualFile> hierarchyFiles = new HashSet<VirtualFile>();
- for (PsiClass aClass : search) {
- final PsiFile containingFile = aClass.getContainingFile();
- if (containingFile != null) {
- final VirtualFile virtualFile = containingFile.getVirtualFile();
- if (virtualFile != null) {
- hierarchyFiles.add(virtualFile);
+ ApplicationManager.getApplication().runReadAction(new Runnable() {
+ @Override
+ public void run() {
+ final Query<PsiClass> search = ClassInheritorsSearch.search(myTargetSuperClass);
+ final Set<VirtualFile> hierarchyFiles = new HashSet<VirtualFile>();
+ for (PsiClass aClass : search) {
+ final PsiFile containingFile = aClass.getContainingFile();
+ if (containingFile != null) {
+ final VirtualFile virtualFile = containingFile.getVirtualFile();
+ if (virtualFile != null) {
+ hierarchyFiles.add(virtualFile);
+ }
+ }
+ }
+ final Set<PsiMember> methodsToSearchDuplicates = new HashSet<PsiMember>();
+ for (PsiMember psiMember : myMembersAfterMove) {
+ if (psiMember instanceof PsiMethod && psiMember.isValid() && ((PsiMethod)psiMember).getBody() != null) {
+ methodsToSearchDuplicates.add(psiMember);
+ }
}
- }
- }
- final Set<PsiMember> methodsToSearchDuplicates = new HashSet<PsiMember>();
- for (PsiMember psiMember : myMembersAfterMove) {
- if (psiMember instanceof PsiMethod && psiMember.isValid() && ((PsiMethod)psiMember).getBody() != null) {
- methodsToSearchDuplicates.add(psiMember);
- }
- }
- MethodDuplicatesHandler.invokeOnScope(myProject, methodsToSearchDuplicates, new AnalysisScope(myProject, hierarchyFiles), true);
+ MethodDuplicatesHandler.invokeOnScope(myProject, methodsToSearchDuplicates, new AnalysisScope(myProject, hierarchyFiles), true);
+ }
+ });
}
}, MethodDuplicatesHandler.REFACTORING_NAME, true, myProject);
}
+ @Override
protected String getCommandName() {
return RefactoringBundle.message("pullUp.command", DescriptiveNameUtil.getDescriptiveName(mySourceClass));
}
@@ -303,19 +312,23 @@ public class PullUpProcessor extends BaseRefactoringProcessor implements PullUpD
}
private class PullUpUsageViewDescriptor implements UsageViewDescriptor {
+ @Override
public String getProcessedElementsHeader() {
return "Pull up members from";
}
+ @Override
@NotNull
public PsiElement[] getElements() {
return new PsiElement[]{mySourceClass};
}
+ @Override
public String getCodeReferencesText(int usagesCount, int filesCount) {
return "Class to pull up members to \"" + RefactoringUIUtil.getDescription(myTargetSuperClass, true) + "\"";
}
+ @Override
public String getCommentReferencesText(int usagesCount, int filesCount) {
return null;
}
diff --git a/java/java-impl/src/com/intellij/refactoring/memberPushDown/PushDownProcessor.java b/java/java-impl/src/com/intellij/refactoring/memberPushDown/PushDownProcessor.java
index ca3298bc97b2..bb09c69c9fcc 100644
--- a/java/java-impl/src/com/intellij/refactoring/memberPushDown/PushDownProcessor.java
+++ b/java/java-impl/src/com/intellij/refactoring/memberPushDown/PushDownProcessor.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,6 +19,7 @@ import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInsight.ChangeContextUtil;
import com.intellij.codeInsight.intention.impl.CreateClassDialog;
import com.intellij.codeInsight.intention.impl.CreateSubclassAction;
+import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
@@ -72,10 +73,12 @@ public class PushDownProcessor extends BaseRefactoringProcessor {
myJavaDocPolicy = javaDocPolicy;
}
+ @Override
protected String getCommandName() {
return JavaPushDownHandler.REFACTORING_NAME;
}
+ @Override
@NotNull
protected UsageViewDescriptor createUsageViewDescriptor(UsageInfo[] usages) {
return new PushDownUsageViewDescriptor(myClass);
@@ -116,6 +119,7 @@ public class PushDownProcessor extends BaseRefactoringProcessor {
return data;
}
+ @Override
@NotNull
protected UsageInfo[] findUsages() {
final PsiClass[] inheritors = ClassInheritorsSearch.search(myClass, false).toArray(PsiClass.EMPTY_ARRAY);
@@ -147,6 +151,7 @@ public class PushDownProcessor extends BaseRefactoringProcessor {
return false;
}
+ @Override
protected boolean preprocessUsages(final Ref<UsageInfo[]> refUsages) {
final UsageInfo[] usagesIn = refUsages.get();
final PushDownConflicts pushDownConflicts = new PushDownConflicts(myClass, myMemberInfos);
@@ -177,13 +182,19 @@ public class PushDownProcessor extends BaseRefactoringProcessor {
}
}
Runnable runnable = new Runnable() {
+ @Override
public void run() {
- for (UsageInfo usage : usagesIn) {
- final PsiElement element = usage.getElement();
- if (element instanceof PsiClass) {
- pushDownConflicts.checkTargetClassConflicts((PsiClass)element, usagesIn.length > 1, element);
+ ApplicationManager.getApplication().runReadAction(new Runnable() {
+ @Override
+ public void run() {
+ for (UsageInfo usage : usagesIn) {
+ final PsiElement element = usage.getElement();
+ if (element instanceof PsiClass) {
+ pushDownConflicts.checkTargetClassConflicts((PsiClass)element, usagesIn.length > 1, element);
+ }
+ }
}
- }
+ });
}
};
@@ -204,6 +215,7 @@ public class PushDownProcessor extends BaseRefactoringProcessor {
return showConflicts(pushDownConflicts.getConflicts(), usagesIn);
}
+ @Override
protected void refreshElements(PsiElement[] elements) {
if(elements.length == 1 && elements[0] instanceof PsiClass) {
myClass = (PsiClass) elements[0];
@@ -213,6 +225,7 @@ public class PushDownProcessor extends BaseRefactoringProcessor {
}
}
+ @Override
protected void performRefactoring(UsageInfo[] usages) {
try {
encodeRefs();
@@ -509,6 +522,7 @@ public class PushDownProcessor extends BaseRefactoringProcessor {
decodeRefs(newMember, targetClass);
//rebind imports first
Collections.sort(refsToRebind, new Comparator<PsiReference>() {
+ @Override
public int compare(PsiReference o1, PsiReference o2) {
return PsiUtil.BY_POSITION.compare(o1.getElement(), o2.getElement());
}
diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesImpl.java b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesImpl.java
index 3e92a19373ab..844eb2dc0611 100644
--- a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesImpl.java
+++ b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesImpl.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.
@@ -88,7 +88,7 @@ public class MoveClassesOrPackagesImpl {
if (element instanceof PsiDirectory) {
PsiPackage aPackage = JavaDirectoryService.getInstance().getPackage((PsiDirectory)element);
LOG.assertTrue(aPackage != null);
- if (aPackage.getQualifiedName().length() == 0) { //is default package
+ if (aPackage.getQualifiedName().isEmpty()) { //is default package
String message = RefactoringBundle.message("move.package.refactoring.cannot.be.applied.to.default.package");
CommonRefactoringUtil.showErrorMessage(RefactoringBundle.message("move.title"), message, HelpID.getMoveHelpID(element), project);
return null;
@@ -167,7 +167,7 @@ public class MoveClassesOrPackagesImpl {
message.append(RefactoringBundle.message("do.you.wish.to.continue"));
int ret =
Messages.showYesNoDialog(project, message.toString(), RefactoringBundle.message("warning.title"), Messages.getWarningIcon());
- if (ret != 0) {
+ if (ret != Messages.YES) {
return false;
}
}
@@ -323,8 +323,15 @@ public class MoveClassesOrPackagesImpl {
if (selectedTarget == null) return;
final MultiMap<PsiElement, String> conflicts = new MultiMap<PsiElement, String>();
final Runnable analyzeConflicts = new Runnable() {
+ @Override
public void run() {
- RefactoringConflictsUtil.analyzeModuleConflicts(project, Arrays.asList(directories), UsageInfo.EMPTY_ARRAY, selectedTarget, conflicts);
+ ApplicationManager.getApplication().runReadAction(new Runnable() {
+ @Override
+ public void run() {
+ RefactoringConflictsUtil
+ .analyzeModuleConflicts(project, Arrays.asList(directories), UsageInfo.EMPTY_ARRAY, selectedTarget, conflicts);
+ }
+ });
}
};
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(analyzeConflicts, "Analyze Module Conflicts...", true, project)) {
@@ -345,8 +352,10 @@ public class MoveClassesOrPackagesImpl {
final Ref<IncorrectOperationException> ex = Ref.create(null);
final String commandDescription = RefactoringBundle.message("moving.directories.command");
Runnable runnable = new Runnable() {
+ @Override
public void run() {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ @Override
public void run() {
LocalHistoryAction a = LocalHistory.getInstance().startAction(commandDescription);
try {
diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesProcessor.java b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesProcessor.java
index f398dfdd115a..0e02b8f94e28 100644
--- a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesProcessor.java
+++ b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesProcessor.java
@@ -23,7 +23,6 @@ import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.openapi.wm.WindowManager;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.PackageScope;
@@ -48,7 +47,6 @@ import com.intellij.refactoring.util.classRefs.ClassReferenceScanner;
import com.intellij.usageView.UsageInfo;
import com.intellij.usageView.UsageViewDescriptor;
import com.intellij.usageView.UsageViewUtil;
-import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.Processor;
import com.intellij.util.VisibilityUtil;
@@ -472,9 +470,7 @@ public class MoveClassesOrPackagesProcessor extends BaseRefactoringProcessor {
}
protected boolean isPreviewUsages(UsageInfo[] usages) {
- if (UsageViewUtil.hasNonCodeUsages(usages)) {
- WindowManager.getInstance().getStatusBar(myProject).setInfo(
- RefactoringBundle.message("occurrences.found.in.comments.strings.and.non.java.files"));
+ if (UsageViewUtil.reportNonRegularUsages(usages, myProject)) {
return true;
}
else {
diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveInner/MoveInnerClassJavaUsagesHandler.java b/java/java-impl/src/com/intellij/refactoring/move/moveInner/MoveInnerClassJavaUsagesHandler.java
new file mode 100644
index 000000000000..0589e6d8e187
--- /dev/null
+++ b/java/java-impl/src/com/intellij/refactoring/move/moveInner/MoveInnerClassJavaUsagesHandler.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.refactoring.move.moveInner;
+
+import com.intellij.psi.*;
+import com.intellij.refactoring.util.RefactoringChangeUtil;
+import com.intellij.usageView.UsageInfo;
+import org.jetbrains.annotations.NotNull;
+
+public class MoveInnerClassJavaUsagesHandler implements MoveInnerClassUsagesHandler {
+ @Override
+ public void correctInnerClassUsage(@NotNull UsageInfo usage, @NotNull PsiClass outerClass) {
+ PsiElement refElement = usage.getElement();
+ if (refElement == null) return;
+
+ PsiManager manager = refElement.getManager();
+
+ PsiElement refParent = refElement.getParent();
+ if (refParent instanceof PsiNewExpression || refParent instanceof PsiAnonymousClass) {
+ PsiNewExpression newExpr = refParent instanceof PsiNewExpression
+ ? (PsiNewExpression)refParent
+ : (PsiNewExpression)refParent.getParent();
+
+ PsiExpressionList argList = newExpr.getArgumentList();
+
+ if (argList != null) { // can happen in incomplete code
+ if (newExpr.getQualifier() == null) {
+ PsiThisExpression thisExpr;
+ PsiClass parentClass = RefactoringChangeUtil.getThisClass(newExpr);
+ if (outerClass.equals(parentClass)) {
+ thisExpr = RefactoringChangeUtil.createThisExpression(manager, null);
+ }
+ else {
+ thisExpr = RefactoringChangeUtil.createThisExpression(manager, outerClass);
+ }
+ argList.addAfter(thisExpr, null);
+ }
+ else {
+ argList.addAfter(newExpr.getQualifier(), null);
+ newExpr.getQualifier().delete();
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveInner/MoveInnerClassUsagesHandler.java b/java/java-impl/src/com/intellij/refactoring/move/moveInner/MoveInnerClassUsagesHandler.java
new file mode 100644
index 000000000000..97946456d6fb
--- /dev/null
+++ b/java/java-impl/src/com/intellij/refactoring/move/moveInner/MoveInnerClassUsagesHandler.java
@@ -0,0 +1,28 @@
+/*
+ * 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.refactoring.move.moveInner;
+
+import com.intellij.lang.LanguageExtension;
+import com.intellij.psi.PsiClass;
+import com.intellij.usageView.UsageInfo;
+import org.jetbrains.annotations.NotNull;
+
+public interface MoveInnerClassUsagesHandler {
+ LanguageExtension<MoveInnerClassUsagesHandler> EP_NAME =
+ new LanguageExtension<MoveInnerClassUsagesHandler>("com.intellij.refactoring.moveInnerClassUsagesHandler");
+
+ void correctInnerClassUsage(@NotNull UsageInfo usage, @NotNull PsiClass outerClass);
+} \ No newline at end of file
diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveInner/MoveInnerProcessor.java b/java/java-impl/src/com/intellij/refactoring/move/moveInner/MoveInnerProcessor.java
index d4239e578016..d56b8c02844e 100644
--- a/java/java-impl/src/com/intellij/refactoring/move/moveInner/MoveInnerProcessor.java
+++ b/java/java-impl/src/com/intellij/refactoring/move/moveInner/MoveInnerProcessor.java
@@ -214,35 +214,11 @@ public class MoveInnerProcessor extends BaseRefactoringProcessor {
// correct references in usages
for (UsageInfo usage : usages) {
- if (usage.isNonCodeUsage) continue;
- PsiElement refElement = usage.getElement();
- if (myParameterNameOuterClass != null) { // should pass outer as parameter
- PsiElement refParent = refElement.getParent();
- if (refParent instanceof PsiNewExpression || refParent instanceof PsiAnonymousClass) {
- PsiNewExpression newExpr = refParent instanceof PsiNewExpression
- ? (PsiNewExpression)refParent
- : (PsiNewExpression)refParent.getParent();
-
- PsiExpressionList argList = newExpr.getArgumentList();
-
- if (argList != null) { // can happen in incomplete code
- if (newExpr.getQualifier() == null) {
- PsiThisExpression thisExpr;
- PsiClass parentClass = RefactoringChangeUtil.getThisClass(newExpr);
- if (myOuterClass.equals(parentClass)) {
- thisExpr = RefactoringChangeUtil.createThisExpression(manager, null);
- }
- else {
- thisExpr = RefactoringChangeUtil.createThisExpression(manager, myOuterClass);
- }
- argList.addAfter(thisExpr, null);
- }
- else {
- argList.addAfter(newExpr.getQualifier(), null);
- newExpr.getQualifier().delete();
- }
- }
- }
+ if (usage.isNonCodeUsage || myParameterNameOuterClass == null) continue; // should pass outer as parameter
+
+ MoveInnerClassUsagesHandler usagesHandler = MoveInnerClassUsagesHandler.EP_NAME.forLanguage(usage.getElement().getLanguage());
+ if (usagesHandler != null) {
+ usagesHandler.correctInnerClassUsage(usage, myOuterClass);
}
}
@@ -554,4 +530,4 @@ public class MoveInnerProcessor extends BaseRefactoringProcessor {
public String getParameterName() {
return myParameterNameOuterClass;
}
-}
+} \ No newline at end of file
diff --git a/java/java-impl/src/com/intellij/refactoring/turnRefsToSuper/TurnRefsToSuperProcessorBase.java b/java/java-impl/src/com/intellij/refactoring/turnRefsToSuper/TurnRefsToSuperProcessorBase.java
index 1ed6de9ced09..b4142228f01f 100644
--- a/java/java-impl/src/com/intellij/refactoring/turnRefsToSuper/TurnRefsToSuperProcessorBase.java
+++ b/java/java-impl/src/com/intellij/refactoring/turnRefsToSuper/TurnRefsToSuperProcessorBase.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.
@@ -69,6 +69,7 @@ public abstract class TurnRefsToSuperProcessorBase extends BaseRefactoringProces
private final String mySuperClassName;
private final List<UsageInfo> myVariablesUsages = new ArrayList<UsageInfo>();
+ @Override
protected boolean preprocessUsages(Ref<UsageInfo[]> refUsages) {
UsageInfo[] usages = refUsages.get();
List<UsageInfo> filtered = new ArrayList<UsageInfo>();
@@ -93,8 +94,14 @@ public abstract class TurnRefsToSuperProcessorBase extends BaseRefactoringProces
}
Runnable runnable = new Runnable() {
+ @Override
public void run() {
- myVariableRenamer.findUsages(myVariablesUsages, false, false);
+ ApplicationManager.getApplication().runReadAction(new Runnable() {
+ @Override
+ public void run() {
+ myVariableRenamer.findUsages(myVariablesUsages, false, false);
+ }
+ });
}
};
@@ -338,6 +345,7 @@ public abstract class TurnRefsToSuperProcessorBase extends BaseRefactoringProces
if (substitutor == null) return;
final LocalSearchScope baseScope = new LocalSearchScope(ownerClass);
ReferencesSearch.search(typeParameter, baseScope).forEach(new Processor<PsiReference>() {
+ @Override
public boolean process(final PsiReference ref) {
final PsiElement element = ref.getElement();
final PsiElement parent = element.getParent();
@@ -708,6 +716,7 @@ public abstract class TurnRefsToSuperProcessorBase extends BaseRefactoringProces
}
class Colorer implements OneEndFunctor {
+ @Override
public Mark compute(Mark from, Mark edge, Mark to) {
VisitMark mark = new VisitMark((VisitMark)to);
@@ -737,6 +746,7 @@ public abstract class TurnRefsToSuperProcessorBase extends BaseRefactoringProces
private boolean myVisited;
private final PsiElement myElement;
+ @Override
public boolean coincidesWith(Mark x) {
return ((VisitMark)x).myVisited == myVisited;
}
@@ -773,10 +783,12 @@ public abstract class TurnRefsToSuperProcessorBase extends BaseRefactoringProces
myMark = new VisitMark(x);
}
+ @Override
public Mark getMark() {
return myMark;
}
+ @Override
public void setMark(Mark x) {
myMark = (VisitMark)x;
}
diff --git a/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationProcessor.java b/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationProcessor.java
index 609a981b7bf4..2998ec6b0f07 100644
--- a/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationProcessor.java
+++ b/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationProcessor.java
@@ -88,28 +88,32 @@ public class TypeMigrationProcessor extends BaseRefactoringProcessor {
final Editor editor,
final TypeMigrationRules rules,
final PsiElement root) {
+ final PsiFile containingFile = root.getContainingFile();
final TypeMigrationProcessor processor = new TypeMigrationProcessor(project, root, rules) {
@Override
public void performRefactoring(final UsageInfo[] usages) {
super.performRefactoring(usages);
- ApplicationManager.getApplication().invokeLater(new Runnable() {
- public void run() {
- final List<PsiElement> result = new ArrayList<PsiElement>();
- for (UsageInfo usage : usages) {
- final PsiElement element = usage.getElement();
- if (element instanceof PsiMethod) {
- result.add(((PsiMethod)element).getReturnTypeElement());
- }
- else if (element instanceof PsiVariable) {
- result.add(((PsiVariable)element).getTypeElement());
- }
- else if (element != null) {
- result.add(element);
+ if (editor != null) {
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ public void run() {
+ final List<PsiElement> result = new ArrayList<PsiElement>();
+ for (UsageInfo usage : usages) {
+ final PsiElement element = usage.getElement();
+ if (element == null || containingFile != element.getContainingFile()) continue;
+ if (element instanceof PsiMethod) {
+ result.add(((PsiMethod)element).getReturnTypeElement());
+ }
+ else if (element instanceof PsiVariable) {
+ result.add(((PsiVariable)element).getTypeElement());
+ }
+ else {
+ result.add(element);
+ }
}
+ RefactoringUtil.highlightAllOccurrences(project, PsiUtilCore.toPsiElementArray(result), editor);
}
- if (editor != null) RefactoringUtil.highlightAllOccurrences(project, PsiUtilCore.toPsiElementArray(result), editor);
- }
- });
+ });
+ }
}
};
processor.run();
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 ca01331d3e94..ed08349519a7 100644
--- a/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java
+++ b/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java
@@ -677,7 +677,7 @@ public class RefactoringUtil {
public static PsiExpression convertInitializerToNormalExpression(PsiExpression expression, PsiType forcedReturnType)
throws IncorrectOperationException {
- if (expression instanceof PsiArrayInitializerExpression) {
+ if (expression instanceof PsiArrayInitializerExpression && (forcedReturnType == null || forcedReturnType instanceof PsiArrayType)) {
return createNewExpressionFromArrayInitializer((PsiArrayInitializerExpression)expression, forcedReturnType);
}
return expression;
diff --git a/java/java-impl/src/com/intellij/slicer/SliceNullnessAnalyzer.java b/java/java-impl/src/com/intellij/slicer/SliceNullnessAnalyzer.java
index c75c30dfb470..b65932aeaa81 100644
--- a/java/java-impl/src/com/intellij/slicer/SliceNullnessAnalyzer.java
+++ b/java/java-impl/src/com/intellij/slicer/SliceNullnessAnalyzer.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.
@@ -178,8 +178,13 @@ public class SliceNullnessAnalyzer {
node(element, map).add(node(duplicate, map));
}
else {
- SliceUsage sliceUsage = element.getValue();
- final PsiElement value = sliceUsage.getElement();
+ final SliceUsage sliceUsage = element.getValue();
+ final PsiElement value = ApplicationManager.getApplication().runReadAction(new Computable<PsiElement>() {
+ @Override
+ public PsiElement compute() {
+ return sliceUsage.getElement();
+ }
+ });
Nullness nullness = ApplicationManager.getApplication().runReadAction(new Computable<Nullness>() {
@Override
public Nullness compute() {
diff --git a/java/java-impl/src/com/intellij/slicer/SliceUtil.java b/java/java-impl/src/com/intellij/slicer/SliceUtil.java
index 6d556b5f9681..014bbdd0ce71 100644
--- a/java/java-impl/src/com/intellij/slicer/SliceUtil.java
+++ b/java/java-impl/src/com/intellij/slicer/SliceUtil.java
@@ -138,7 +138,8 @@ public class SliceUtil {
}
}
if (expression instanceof PsiMethodCallExpression) { // ctr call can't return value or be container get, so don't use PsiCall here
- Flow anno = isMethodFlowAnnotated(((PsiMethodCallExpression)expression).resolveMethod());
+ PsiMethod method = ((PsiMethodCallExpression)expression).resolveMethod();
+ Flow anno = isMethodFlowAnnotated(method);
if (anno != null) {
String target = anno.target();
if (target.equals(Flow.DEFAULT_TARGET)) target = Flow.RETURN_METHOD_TARGET;
diff --git a/java/java-impl/src/com/intellij/testIntegration/JavaTestFinder.java b/java/java-impl/src/com/intellij/testIntegration/JavaTestFinder.java
index 92fe17ad085e..f75fb83cf54e 100644
--- a/java/java-impl/src/com/intellij/testIntegration/JavaTestFinder.java
+++ b/java/java-impl/src/com/intellij/testIntegration/JavaTestFinder.java
@@ -47,14 +47,7 @@ public class JavaTestFinder implements TestFinder {
PsiClass klass = findSourceElement(element);
if (klass == null) return Collections.emptySet();
- GlobalSearchScope scope;
- Module module = getModule(element);
- if (module != null) {
- scope = GlobalSearchScope.moduleWithDependenciesScope(module);
- }
- else {
- scope = GlobalSearchScope.projectScope(element.getProject());
- }
+ GlobalSearchScope scope = getSearchScope(element);
PsiShortNamesCache cache = PsiShortNamesCache.getInstance(element.getProject());
@@ -70,6 +63,16 @@ public class JavaTestFinder implements TestFinder {
return TestFinderHelper.getSortedElements(classesWithWeights, false);
}
+ protected GlobalSearchScope getSearchScope(PsiElement element) {
+ final Module module = getModule(element);
+ if (module != null) {
+ return GlobalSearchScope.moduleWithDependenciesScope(module);
+ }
+ else {
+ return GlobalSearchScope.projectScope(element.getProject());
+ }
+ }
+
private static boolean isTestSubjectClass(PsiClass klass) {
if (klass.isAnnotationType() || TestFrameworks.getInstance().isTestClass(klass)) {
return false;
@@ -90,15 +93,8 @@ public class JavaTestFinder implements TestFinder {
return TestFinderHelper.getSortedElements(classesWithProximities, true);
}
- private static boolean collectTests(PsiClass klass, Processor<Pair<? extends PsiNamedElement, Integer>> processor) {
- GlobalSearchScope scope;
- Module module = getModule(klass);
- if (module != null) {
- scope = GlobalSearchScope.moduleWithDependentsScope(module);
- }
- else {
- scope = GlobalSearchScope.projectScope(klass.getProject());
- }
+ private boolean collectTests(PsiClass klass, Processor<Pair<? extends PsiNamedElement, Integer>> processor) {
+ GlobalSearchScope scope = getSearchScope(klass);
PsiShortNamesCache cache = PsiShortNamesCache.getInstance(klass.getProject());
@@ -131,13 +127,4 @@ public class JavaTestFinder implements TestFinder {
public boolean isTest(@NotNull PsiElement element) {
return TestIntegrationUtils.isTest(element);
}
-
- public static boolean hasTestsForClass(PsiClass aClass) {
- return collectTests(aClass, new CommonProcessors.FindProcessor<Pair<? extends PsiNamedElement, Integer>>() {
- @Override
- protected boolean accept(Pair<? extends PsiNamedElement, Integer> pair) {
- return true;
- }
- });
- }
}
diff --git a/java/java-impl/src/com/intellij/testIntegration/createTest/CreateTestAction.java b/java/java-impl/src/com/intellij/testIntegration/createTest/CreateTestAction.java
index d32864676c55..cceceb24c826 100644
--- a/java/java-impl/src/com/intellij/testIntegration/createTest/CreateTestAction.java
+++ b/java/java-impl/src/com/intellij/testIntegration/createTest/CreateTestAction.java
@@ -109,11 +109,7 @@ public class CreateTestAction extends PsiElementBaseIntentionAction {
propertiesComponent.setValue(CREATE_TEST_IN_THE_SAME_ROOT, String.valueOf(true));
}
- final CreateTestDialog d = new CreateTestDialog(project,
- getText(),
- srcClass,
- srcPackage,
- srcModule);
+ final CreateTestDialog d = createTestDialog(project, srcModule, srcClass, srcPackage);
d.show();
if (!d.isOK()) return;
@@ -127,6 +123,10 @@ public class CreateTestAction extends PsiElementBaseIntentionAction {
}, CodeInsightBundle.message("intention.create.test"), this);
}
+ protected CreateTestDialog createTestDialog(Project project, Module srcModule, PsiClass srcClass, PsiPackage srcPackage) {
+ return new CreateTestDialog(project, getText(), srcClass, srcPackage, srcModule);
+ }
+
protected static void checkForTestRoots(Module srcModule, Set<VirtualFile> testFolders) {
checkForTestRoots(srcModule, testFolders, new HashSet<Module>());
}
diff --git a/java/java-impl/src/com/intellij/testIntegration/createTest/CreateTestDialog.java b/java/java-impl/src/com/intellij/testIntegration/createTest/CreateTestDialog.java
index cf4c67911208..5be9ce379705 100644
--- a/java/java-impl/src/com/intellij/testIntegration/createTest/CreateTestDialog.java
+++ b/java/java-impl/src/com/intellij/testIntegration/createTest/CreateTestDialog.java
@@ -181,7 +181,7 @@ public class CreateTestDialog extends DialogWrapper {
}
});
- myTargetClassNameField = new EditorTextField(targetClass.getName() + "Test");
+ myTargetClassNameField = new EditorTextField(suggestTestClassName(targetClass));
myTargetClassNameField.getDocument().addDocumentListener(new DocumentAdapter() {
@Override
public void documentChanged(DocumentEvent e) {
@@ -217,6 +217,10 @@ public class CreateTestDialog extends DialogWrapper {
updateMethodsTable();
}
+ protected String suggestTestClassName(PsiClass targetClass) {
+ return targetClass.getName() + "Test";
+ }
+
private boolean isSuperclassSelectedManually() {
String superClass = mySuperClassField.getText();
if (StringUtil.isEmptyOrSpaces(superClass)) {
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 25034e9ab7ba..78f29c4c8488 100644
--- a/java/java-psi-api/src/com/intellij/codeInsight/AnnotationUtil.java
+++ b/java/java-psi-api/src/com/intellij/codeInsight/AnnotationUtil.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.
@@ -95,7 +95,7 @@ public class AnnotationUtil {
}
@Nullable
- public static PsiAnnotation findAnnotation(@Nullable PsiModifierListOwner listOwner, Collection<String> annotationNames) {
+ public static PsiAnnotation findAnnotation(@Nullable PsiModifierListOwner listOwner, @NotNull Collection<String> annotationNames) {
return findAnnotation(listOwner, annotationNames, false);
}
@@ -133,7 +133,7 @@ public class AnnotationUtil {
}
@NotNull
- public static PsiAnnotation[] findAnnotations(final PsiModifierListOwner modifierListOwner, @NotNull Collection<String> annotationNames) {
+ public static PsiAnnotation[] findAnnotations(@Nullable PsiModifierListOwner modifierListOwner, @NotNull Collection<String> annotationNames) {
if (modifierListOwner == null) return PsiAnnotation.EMPTY_ARRAY;
final PsiModifierList modifierList = modifierListOwner.getModifierList();
if (modifierList == null) return PsiAnnotation.EMPTY_ARRAY;
@@ -171,8 +171,8 @@ public class AnnotationUtil {
}
@Nullable
- private static PsiAnnotation doFindAnnotationInHierarchy(PsiParameter parameter,
- Set<String> annotationNames,
+ private static PsiAnnotation doFindAnnotationInHierarchy(@NotNull PsiParameter parameter,
+ @NotNull Set<String> annotationNames,
@Nullable Set<PsiModifierListOwner> visited) {
PsiAnnotation annotation = findAnnotation(parameter, annotationNames);
if (annotation != null) return annotation;
@@ -206,7 +206,7 @@ public class AnnotationUtil {
}
@Nullable
- private static PsiAnnotation findAnnotationInHierarchy(@NotNull final PsiClass psiClass, final Set<String> annotationNames, @Nullable Set<PsiClass> processed) {
+ private static PsiAnnotation findAnnotationInHierarchy(@NotNull final PsiClass psiClass, @NotNull Set<String> annotationNames, @Nullable Set<PsiClass> processed) {
final PsiClass[] superClasses = psiClass.getSupers();
for (final PsiClass superClass : superClasses) {
if (processed == null) processed = new THashSet<PsiClass>();
@@ -240,18 +240,18 @@ public class AnnotationUtil {
return null;
}
- public static boolean isAnnotated(@NotNull PsiModifierListOwner listOwner, Collection<String> annotations) {
+ public static boolean isAnnotated(@NotNull PsiModifierListOwner listOwner, @NotNull Collection<String> annotations) {
return isAnnotated(listOwner, annotations, false);
}
public static boolean isAnnotated(@NotNull PsiModifierListOwner listOwner,
- Collection<String> annotations,
+ @NotNull Collection<String> annotations,
final boolean checkHierarchy) {
return isAnnotated(listOwner, annotations, checkHierarchy, true);
}
public static boolean isAnnotated(@NotNull PsiModifierListOwner listOwner,
- Collection<String> annotations,
+ @NotNull Collection<String> annotations,
final boolean checkHierarchy,
boolean skipExternal) {
for (String annotation : annotations) {
@@ -260,17 +260,17 @@ public class AnnotationUtil {
return false;
}
- public static boolean isAnnotated(@NotNull PsiModifierListOwner listOwner, @NonNls String annotationFQN, boolean checkHierarchy) {
+ public static boolean isAnnotated(@NotNull PsiModifierListOwner listOwner, @NonNls @NotNull String annotationFQN, boolean checkHierarchy) {
return isAnnotated(listOwner, annotationFQN, checkHierarchy, true, null);
}
- public static boolean isAnnotated(@NotNull PsiModifierListOwner listOwner, @NonNls String annotationFQN, boolean checkHierarchy,
+ public static boolean isAnnotated(@NotNull PsiModifierListOwner listOwner, @NonNls @NotNull String annotationFQN, boolean checkHierarchy,
boolean skipExternal) {
return isAnnotated(listOwner, annotationFQN, checkHierarchy, skipExternal, null);
}
private static boolean isAnnotated(@NotNull PsiModifierListOwner listOwner,
- @NonNls String annotationFQN,
+ @NonNls @NotNull String annotationFQN,
boolean checkHierarchy, final boolean skipExternal, @Nullable Set<PsiMember> processed) {
if (!listOwner.isValid()) return false;
final PsiModifierList modifierList = listOwner.getModifierList();
@@ -310,13 +310,13 @@ public class AnnotationUtil {
return isAnnotatingApplicable(elt, NullableNotNullManager.getInstance(elt.getProject()).getDefaultNullable());
}
- public static boolean isAnnotatingApplicable(@NotNull PsiElement elt, final String annotationFQN) {
+ public static boolean isAnnotatingApplicable(@NotNull PsiElement elt, @NotNull String annotationFQN) {
final Project project = elt.getProject();
return PsiUtil.isLanguageLevel5OrHigher(elt) &&
JavaPsiFacade.getInstance(project).findClass(annotationFQN, elt.getResolveScope()) != null;
}
- public static boolean isJetbrainsAnnotation(@NonNls final String simpleName) {
+ public static boolean isJetbrainsAnnotation(@NonNls @NotNull String simpleName) {
return ArrayUtil.find(SIMPLE_NAMES, simpleName) != -1;
}
@@ -328,7 +328,7 @@ public class AnnotationUtil {
* @param annotations annotations qualified names or patterns. Patterns can have '*' at the end
* @return <code>true</code> if annotated of at least one annotation from the annotations list
*/
- public static boolean checkAnnotatedUsingPatterns(PsiModifierListOwner owner, Collection<String> annotations) {
+ public static boolean checkAnnotatedUsingPatterns(@Nullable PsiModifierListOwner owner, @NotNull Collection<String> annotations) {
final PsiModifierList modList;
if (owner == null || (modList = owner.getModifierList()) == null) return false;
@@ -361,7 +361,7 @@ public class AnnotationUtil {
}
@Nullable
- public static PsiMethod getAnnotationMethod(PsiNameValuePair pair) {
+ public static PsiMethod getAnnotationMethod(@NotNull PsiNameValuePair pair) {
final PsiAnnotation annotation = PsiTreeUtil.getParentOfType(pair.getParent(), PsiAnnotation.class);
assert annotation != 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 2210e02a080a..0f19a245ff18 100644
--- a/java/java-psi-api/src/com/intellij/codeInsight/NullableNotNullManager.java
+++ b/java/java-psi-api/src/com/intellij/codeInsight/NullableNotNullManager.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.
@@ -70,7 +70,7 @@ public class NullableNotNullManager implements PersistentStateComponent<Element>
return isNullable(owner, false) || isNotNull(owner, false);
}
- private static void addAllIfNotPresent(Collection<String> collection, String... annotations) {
+ private static void addAllIfNotPresent(@NotNull Collection<String> collection, @NotNull String... annotations) {
for (String annotation : annotations) {
LOG.assertTrue(annotation != null);
if (!collection.contains(annotation)) {
@@ -79,30 +79,31 @@ public class NullableNotNullManager implements PersistentStateComponent<Element>
}
}
- public void setNotNulls(String... annotations) {
+ public void setNotNulls(@NotNull String... annotations) {
myNotNulls.clear();
addAllIfNotPresent(myNotNulls, DEFAULT_NOT_NULLS);
addAllIfNotPresent(myNotNulls, annotations);
}
- public void setNullables(String... annotations) {
+ public void setNullables(@NotNull String... annotations) {
myNullables.clear();
addAllIfNotPresent(myNullables, DEFAULT_NULLABLES);
addAllIfNotPresent(myNullables, annotations);
}
+ @NotNull
public String getDefaultNullable() {
return myDefaultNullable;
}
@Nullable
- public String getNullable(PsiModifierListOwner owner) {
+ public String getNullable(@NotNull PsiModifierListOwner owner) {
PsiAnnotation annotation = getNullableAnnotation(owner, false);
return annotation == null ? null : annotation.getQualifiedName();
}
@Nullable
- public PsiAnnotation getNullableAnnotation(PsiModifierListOwner owner, boolean checkBases) {
+ public PsiAnnotation getNullableAnnotation(@NotNull PsiModifierListOwner owner, boolean checkBases) {
return findNullabilityAnnotation(owner, checkBases, true);
}
@@ -116,17 +117,18 @@ public class NullableNotNullManager implements PersistentStateComponent<Element>
myDefaultNullable = defaultNullable;
}
+ @NotNull
public String getDefaultNotNull() {
return myDefaultNotNull;
}
@Nullable
- public PsiAnnotation getNotNullAnnotation(PsiModifierListOwner owner, boolean checkBases) {
+ public PsiAnnotation getNotNullAnnotation(@NotNull PsiModifierListOwner owner, boolean checkBases) {
return findNullabilityAnnotation(owner, checkBases, false);
}
@Nullable
- public String getNotNull(PsiModifierListOwner owner) {
+ public String getNotNull(@NotNull PsiModifierListOwner owner) {
PsiAnnotation annotation = getNotNullAnnotation(owner, false);
return annotation == null ? null : annotation.getQualifiedName();
}
@@ -226,10 +228,12 @@ public class NullableNotNullManager implements PersistentStateComponent<Element>
return required.isEmpty() || ContainerUtil.intersects(required, Arrays.asList(placeTargetTypes));
}
+ @NotNull
public List<String> getNullables() {
return myNullables;
}
+ @NotNull
public List<String> getNotNulls() {
return myNotNulls;
}
diff --git a/java/java-psi-api/src/com/intellij/psi/JavaRecursiveElementWalkingVisitor.java b/java/java-psi-api/src/com/intellij/psi/JavaRecursiveElementWalkingVisitor.java
index a707a296b0cb..d5ed67d3525c 100644
--- a/java/java-psi-api/src/com/intellij/psi/JavaRecursiveElementWalkingVisitor.java
+++ b/java/java-psi-api/src/com/intellij/psi/JavaRecursiveElementWalkingVisitor.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.
@@ -34,8 +34,7 @@ public abstract class JavaRecursiveElementWalkingVisitor extends JavaElementVisi
myWalkingState.elementStarted(element);
}
- @SuppressWarnings({"UnusedDeclaration"})
- protected void elementFinished(PsiElement element) {
+ protected void elementFinished(@NotNull PsiElement element) {
}
@Override
diff --git a/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceUtil.java b/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceUtil.java
index 87afd3d4f8e4..0b0e09684128 100644
--- a/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceUtil.java
+++ b/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceUtil.java
@@ -75,20 +75,22 @@ public class PsiMethodReferenceUtil {
return null;
}
- public static boolean isCorrectAssignment(PsiType[] signatureParameterTypes2,
- PsiType[] parameterTypes,
+ public static boolean isCorrectAssignment(PsiType[] parameterTypes,
+ PsiType[] argTypes,
boolean varargs,
int offset) {
- final int min = Math.min(signatureParameterTypes2.length, parameterTypes.length - offset);
+ final int min = Math.min(parameterTypes.length, argTypes.length - offset);
for (int i = 0; i < min; i++) {
- final PsiType type1 = parameterTypes[i + offset];
- final PsiType type2 = signatureParameterTypes2[i];
- if (varargs && i == signatureParameterTypes2.length - 1) {
- if (!TypeConversionUtil.isAssignable(type2, type1) && !TypeConversionUtil.isAssignable(((PsiArrayType)type2).getComponentType(), type1)) {
+ final PsiType argType = argTypes[i + offset];
+ PsiType parameterType = parameterTypes[i];
+ parameterType = GenericsUtil.getVariableTypeByExpressionType(parameterType, true);
+ if (varargs && i == parameterTypes.length - 1) {
+ if (!TypeConversionUtil.isAssignable(parameterType, argType) &&
+ !TypeConversionUtil.isAssignable(((PsiArrayType)parameterType).getComponentType(), argType)) {
return false;
}
}
- else if (!TypeConversionUtil.isAssignable(type2, type1)) {
+ else if (!TypeConversionUtil.isAssignable(parameterType, argType)) {
return false;
}
}
@@ -324,7 +326,8 @@ public class PsiMethodReferenceUtil {
LOG.assertTrue(signature != null);
final PsiType[] parameterTypes = signature.getParameterTypes();
final QualifierResolveResult qualifierResolveResult = getQualifierResolveResult(methodRef);
- return (method.getParameterList().getParametersCount() + 1 == parameterTypes.length || method.isVarArgs() && parameterTypes.length > 0)&&
+ return (method.getParameterList().getParametersCount() + 1 == parameterTypes.length ||
+ method.isVarArgs() && parameterTypes.length > 0 && !method.hasModifierProperty(PsiModifier.STATIC)) &&
hasReceiver(parameterTypes, qualifierResolveResult, methodRef);
}
diff --git a/java/java-psi-api/src/com/intellij/psi/PsiType.java b/java/java-psi-api/src/com/intellij/psi/PsiType.java
index 1dd67fb31a7f..6834e39b2ff6 100644
--- a/java/java-psi-api/src/com/intellij/psi/PsiType.java
+++ b/java/java-psi-api/src/com/intellij/psi/PsiType.java
@@ -15,6 +15,7 @@
*/
package com.intellij.psi;
+import com.intellij.openapi.project.Project;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.ArrayFactory;
@@ -134,6 +135,19 @@ public abstract class PsiType implements PsiAnnotationOwner {
public abstract boolean equalsToText(@NotNull @NonNls String text);
/**
+ * Returns the class type for qualified class name.
+ *
+ * @param qName qualified class name.
+ * @param project
+ * @param resolveScope the scope in which the class is searched.
+ * @return the class instance.
+ */
+ public static PsiClassType getTypeByName(String qName, Project project, GlobalSearchScope resolveScope) {
+ PsiElementFactory factory = JavaPsiFacade.getInstance(project).getElementFactory();
+ return factory.createTypeByFQClassName(qName, resolveScope);
+ }
+
+ /**
* Returns the class type for the java.lang.Object class.
*
* @param manager the PSI manager used to create the class type.
@@ -142,8 +156,7 @@ public abstract class PsiType implements PsiAnnotationOwner {
*/
@NotNull
public static PsiClassType getJavaLangObject(@NotNull PsiManager manager, @NotNull GlobalSearchScope resolveScope) {
- PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();
- return factory.createTypeByFQClassName(CommonClassNames.JAVA_LANG_OBJECT, resolveScope);
+ return getTypeByName(CommonClassNames.JAVA_LANG_OBJECT, manager.getProject(), resolveScope);
}
/**
@@ -155,8 +168,7 @@ public abstract class PsiType implements PsiAnnotationOwner {
*/
@NotNull
public static PsiClassType getJavaLangClass(@NotNull PsiManager manager, @NotNull GlobalSearchScope resolveScope) {
- PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();
- return factory.createTypeByFQClassName(CommonClassNames.JAVA_LANG_CLASS, resolveScope);
+ return getTypeByName(CommonClassNames.JAVA_LANG_CLASS, manager.getProject(), resolveScope);
}
/**
@@ -168,8 +180,7 @@ public abstract class PsiType implements PsiAnnotationOwner {
*/
@NotNull
public static PsiClassType getJavaLangThrowable(@NotNull PsiManager manager, @NotNull GlobalSearchScope resolveScope) {
- PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();
- return factory.createTypeByFQClassName(CommonClassNames.JAVA_LANG_THROWABLE, resolveScope);
+ return getTypeByName(CommonClassNames.JAVA_LANG_THROWABLE, manager.getProject(), resolveScope);
}
/**
@@ -181,8 +192,7 @@ public abstract class PsiType implements PsiAnnotationOwner {
*/
@NotNull
public static PsiClassType getJavaLangString(@NotNull PsiManager manager, @NotNull GlobalSearchScope resolveScope) {
- PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();
- return factory.createTypeByFQClassName(CommonClassNames.JAVA_LANG_STRING, resolveScope);
+ return getTypeByName(CommonClassNames.JAVA_LANG_STRING, manager.getProject(), resolveScope);
}
/**
@@ -194,8 +204,7 @@ public abstract class PsiType implements PsiAnnotationOwner {
*/
@NotNull
public static PsiClassType getJavaLangError(@NotNull PsiManager manager, @NotNull GlobalSearchScope resolveScope) {
- PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();
- return factory.createTypeByFQClassName(CommonClassNames.JAVA_LANG_ERROR, resolveScope);
+ return getTypeByName(CommonClassNames.JAVA_LANG_ERROR, manager.getProject(), resolveScope);
}
/**
@@ -207,8 +216,7 @@ public abstract class PsiType implements PsiAnnotationOwner {
*/
@NotNull
public static PsiClassType getJavaLangRuntimeException(@NotNull PsiManager manager, @NotNull GlobalSearchScope resolveScope) {
- PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();
- return factory.createTypeByFQClassName(CommonClassNames.JAVA_LANG_RUNTIME_EXCEPTION, resolveScope);
+ return getTypeByName(CommonClassNames.JAVA_LANG_RUNTIME_EXCEPTION, manager.getProject(), resolveScope);
}
/**
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 f43358007eab..f05df7dab9c1 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
@@ -130,7 +130,6 @@ public class MethodCandidateInfo extends CandidateInfo{
final CurrentCandidateProperties properties = new CurrentCandidateProperties(method, substitutor, isVarargs(), true);
final CurrentCandidateProperties alreadyThere = map.put(getMarkerList(), properties);
try {
- properties.setSubstitutor(substitutor);
PsiType[] argumentTypes = getArgumentTypes();
if (argumentTypes == null) {
return ApplicabilityLevel.NOT_APPLICABLE;
@@ -143,7 +142,11 @@ public class MethodCandidateInfo extends CandidateInfo{
return applicabilityLevel;
}
finally {
- if (alreadyThere == null) map.remove(getMarkerList());
+ if (alreadyThere == null) {
+ map.remove(getMarkerList());
+ } else {
+ map.put(getMarkerList(), alreadyThere);
+ }
}
}
return getApplicabilityLevelInner();
@@ -269,10 +272,8 @@ public class MethodCandidateInfo extends CandidateInfo{
CURRENT_CANDIDATE.set(map);
}
final PsiMethod method = getElement();
- final CurrentCandidateProperties alreadyThere = map.get(getMarkerList());
- if (alreadyThere == null) {
+ final CurrentCandidateProperties alreadyThere =
map.put(getMarkerList(), new CurrentCandidateProperties(method, super.getSubstitutor(), isVarargs(), !includeReturnConstraint));
- }
try {
PsiTypeParameter[] typeParameters = method.getTypeParameters();
@@ -293,7 +294,11 @@ public class MethodCandidateInfo extends CandidateInfo{
.inferTypeArguments(typeParameters, method.getParameterList().getParameters(), arguments, mySubstitutor, parent, policy, myLanguageLevel);
}
finally {
- if (alreadyThere == null) map.remove(getMarkerList());
+ if (alreadyThere == null) {
+ map.remove(getMarkerList());
+ } else {
+ map.put(getMarkerList(), alreadyThere);
+ }
}
}
diff --git a/java/java-psi-api/src/com/intellij/psi/util/RedundantCastUtil.java b/java/java-psi-api/src/com/intellij/psi/util/RedundantCastUtil.java
index d4382b40db7a..ccb606d51376 100644
--- a/java/java-psi-api/src/com/intellij/psi/util/RedundantCastUtil.java
+++ b/java/java-psi-api/src/com/intellij/psi/util/RedundantCastUtil.java
@@ -541,8 +541,17 @@ public class RedundantCastUtil {
}
}
}
- if (parent instanceof PsiInstanceOfExpression || (TypeConversionUtil.isAssignable(castTo, opType, false) &&
- (expectedTypeByParent == null || TypeConversionUtil.isAssignable(expectedTypeByParent, opType, false)))) {
+ if (parent instanceof PsiInstanceOfExpression) {
+ //15.20.2. Type Comparison Operator instanceof:
+ //If a cast (§15.16) of the RelationalExpression to the ReferenceType would be rejected as a compile-time error,
+ //then the instanceof relational expression likewise produces a compile-time error.
+ final PsiTypeElement checkTypeElement = ((PsiInstanceOfExpression)parent).getCheckType();
+ if (checkTypeElement != null && TypeConversionUtil.areTypesConvertible(opType, checkTypeElement.getType())) {
+ addToResults(typeCast);
+ }
+ }
+ else if (TypeConversionUtil.isAssignable(castTo, opType, false) &&
+ (expectedTypeByParent == null || TypeConversionUtil.isAssignable(expectedTypeByParent, opType, false))) {
addToResults(typeCast);
}
}
diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocUtil.java b/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocUtil.java
index 8a686f834958..2228b2628fa0 100644
--- a/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocUtil.java
+++ b/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocUtil.java
@@ -19,6 +19,7 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
+import com.intellij.psi.javadoc.PsiDocComment;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.IncorrectOperationException;
@@ -363,4 +364,8 @@ public class JavaDocUtil {
return list == null ? PsiClassType.EMPTY_ARRAY : list.getReferencedTypes();
}
+ public static boolean isInsidePackageInfo(@Nullable PsiDocComment containingComment) {
+ return containingComment != null && containingComment.getOwner() == null && containingComment.getParent() instanceof PsiJavaFile;
+ }
+
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowAnalyzer.java b/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowAnalyzer.java
index a7b7e290b42c..da32b64ea092 100644
--- a/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowAnalyzer.java
+++ b/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowAnalyzer.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.
@@ -1505,12 +1505,14 @@ class ControlFlowAnalyzer extends JavaElementVisitor {
IElementType op = expression.getOperationTokenType();
PsiExpression operand = PsiUtil.skipParenthesizedExprDown(expression.getOperand());
- operand.accept(this);
- if (op == JavaTokenType.PLUSPLUS || op == JavaTokenType.MINUSMINUS) {
- if (operand instanceof PsiReferenceExpression) {
- PsiVariable variable = getUsedVariable((PsiReferenceExpression)operand);
- if (variable != null) {
- generateWriteInstruction(variable);
+ if (operand != null) {
+ operand.accept(this);
+ if (op == JavaTokenType.PLUSPLUS || op == JavaTokenType.MINUSMINUS) {
+ if (operand instanceof PsiReferenceExpression) {
+ PsiVariable variable = getUsedVariable((PsiReferenceExpression)operand);
+ if (variable != null) {
+ generateWriteInstruction(variable);
+ }
}
}
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/JavaConstantExpressionEvaluator.java b/java/java-psi-impl/src/com/intellij/psi/impl/JavaConstantExpressionEvaluator.java
index 19da149c99b8..3c84456a0a28 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/JavaConstantExpressionEvaluator.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/JavaConstantExpressionEvaluator.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.
@@ -41,27 +41,29 @@ public class JavaConstantExpressionEvaluator extends JavaRecursiveElementWalking
private static final Object NO_VALUE = ObjectUtils.NULL;
private final ConstantExpressionVisitor myConstantExpressionVisitor;
- private JavaConstantExpressionEvaluator(Set<PsiVariable> visitedVars, final boolean throwExceptionOnOverflow, final Project project, final PsiConstantEvaluationHelper.AuxEvaluator auxEvaluator) {
- myMapFactory = auxEvaluator != null ? new Factory<ConcurrentMap<PsiElement, Object>>() {
+ private JavaConstantExpressionEvaluator(Set<PsiVariable> visitedVars,
+ final boolean throwExceptionOnOverflow,
+ @NotNull Project project,
+ final PsiConstantEvaluationHelper.AuxEvaluator auxEvaluator) {
+ myMapFactory = auxEvaluator == null ? new Factory<ConcurrentMap<PsiElement, Object>>() {
@Override
public ConcurrentMap<PsiElement, Object> create() {
- return auxEvaluator.getCacheMap(throwExceptionOnOverflow);
+ final Key<CachedValue<ConcurrentMap<PsiElement, Object>>> key =
+ throwExceptionOnOverflow ? CONSTANT_VALUE_WITH_OVERFLOW_MAP_KEY : CONSTANT_VALUE_WO_OVERFLOW_MAP_KEY;
+ return CachedValuesManager.getManager(myProject).getCachedValue(myProject, key, PROVIDER, false);
}
} : new Factory<ConcurrentMap<PsiElement, Object>>() {
@Override
public ConcurrentMap<PsiElement, Object> create() {
- final Key<CachedValue<ConcurrentMap<PsiElement, Object>>> key =
- throwExceptionOnOverflow ? CONSTANT_VALUE_WITH_OVERFLOW_MAP_KEY : CONSTANT_VALUE_WO_OVERFLOW_MAP_KEY;
- return CachedValuesManager.getManager(myProject).getCachedValue(myProject, key, PROVIDER, false);
+ return auxEvaluator.getCacheMap(throwExceptionOnOverflow);
}
};
myProject = project;
myConstantExpressionVisitor = new ConstantExpressionVisitor(visitedVars, throwExceptionOnOverflow, auxEvaluator);
-
}
@Override
- protected void elementFinished(PsiElement element) {
+ protected void elementFinished(@NotNull PsiElement element) {
Object value = getCached(element);
if (value == null) {
Object result = myConstantExpressionVisitor.handle(element);
@@ -109,7 +111,9 @@ public class JavaConstantExpressionEvaluator extends JavaRecursiveElementWalking
return computeConstantExpression(expression, visitedVars, throwExceptionOnOverflow, null);
}
- public static Object computeConstantExpression(@Nullable PsiExpression expression, @Nullable Set<PsiVariable> visitedVars, boolean throwExceptionOnOverflow,
+ public static Object computeConstantExpression(@Nullable PsiExpression expression,
+ @Nullable Set<PsiVariable> visitedVars,
+ boolean throwExceptionOnOverflow,
final PsiConstantEvaluationHelper.AuxEvaluator auxEvaluator) {
if (expression == null) return null;
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 938b40f51bb8..19e77db037e2 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
@@ -97,9 +97,9 @@ public class PsiImplUtil {
if (referenceElement != null) {
PsiElement resolved = referenceElement.resolve();
if (resolved != null) {
- PsiMethod[] methods = ((PsiClass)resolved).getMethods();
+ PsiMethod[] methods = ((PsiClass)resolved).findMethodsByName(attributeName, false);
for (PsiMethod method : methods) {
- if (PsiUtil.isAnnotationMethod(method) && Comparing.equal(method.getName(), attributeName)) {
+ if (PsiUtil.isAnnotationMethod(method)) {
return ((PsiAnnotationMethod)method).getDefaultValue();
}
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiAnnotationMethodImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiAnnotationMethodImpl.java
index def3bb307a14..abff53174f68 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiAnnotationMethodImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiAnnotationMethodImpl.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.
@@ -30,7 +30,7 @@ import org.jetbrains.annotations.NotNull;
* @author ven
*/
public class PsiAnnotationMethodImpl extends PsiMethodImpl implements PsiAnnotationMethod {
- private SoftReference<PsiAnnotationMemberValue> myCachedDefaultValue = null;
+ private SoftReference<PsiAnnotationMemberValue> myCachedDefaultValue;
public PsiAnnotationMethodImpl(final PsiMethodStub stub) {
super(stub, JavaStubElementTypes.ANNOTATION_METHOD);
@@ -62,7 +62,7 @@ public class PsiAnnotationMethodImpl extends PsiMethodImpl implements PsiAnnotat
return value;
}
- @NonNls final String annoText = "@interface _Dummy_ { Class foo() default " + text + "; }";
+ @NonNls final String annoText = "@interface _Dummy_ { " + getReturnType() + " " + getName() + "() default " + text + "; }";
final PsiFileFactory factory = PsiFileFactory.getInstance(getProject());
final PsiJavaFile file = (PsiJavaFile)factory.createFileFromText("a.java", JavaFileType.INSTANCE, annoText);
value = ((PsiAnnotationMethod)file.getClasses()[0].getMethods()[0]).getDefaultValue();
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiFieldImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiFieldImpl.java
index 367a8bb6e014..78c5c2d8fdc8 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiFieldImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiFieldImpl.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.
@@ -250,7 +250,7 @@ public class PsiFieldImpl extends JavaStubPsiElement<PsiFieldStub> implements Ps
private static final OurConstValueComputer INSTANCE = new OurConstValueComputer();
@Override
- public Object execute(PsiVariable variable, Set<PsiVariable> visitedVars) {
+ public Object execute(@NotNull PsiVariable variable, Set<PsiVariable> visitedVars) {
return ((PsiFieldImpl)variable)._computeConstantValue(visitedVars);
}
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java
index 807b42d60383..c1893da7162e 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java
@@ -15,6 +15,7 @@
*/
package com.intellij.psi.impl.source;
+import com.intellij.codeInsight.javadoc.JavaDocUtil;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
@@ -162,7 +163,7 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
i == JavaDocElementType.DOC_REFERENCE_HOLDER ||
i == JavaDocElementType.DOC_TYPE_HOLDER) {
PsiDocComment docComment = PsiTreeUtil.getParentOfType(this, PsiDocComment.class);
- if (docComment != null && docComment.getOwner() == null && docComment.getParent() instanceof PsiJavaFile) {
+ if (JavaDocUtil.isInsidePackageInfo(docComment)) {
return CLASS_FQ_OR_PACKAGE_NAME_KIND;
}
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 b2c934ef9783..14764b25b4ee 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
@@ -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.
@@ -144,6 +144,6 @@ public class JavaResolveCache {
}
public interface ConstValueComputer{
- Object execute(PsiVariable variable, Set<PsiVariable> visitedVars);
+ Object execute(@NotNull PsiVariable variable, Set<PsiVariable> visitedVars);
}
}
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 7d6166a7f95a..27e34f00a25f 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
@@ -20,6 +20,7 @@ import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.*;
+import com.intellij.psi.impl.PsiImplUtil;
import com.intellij.psi.impl.source.resolve.graphInference.constraints.*;
import com.intellij.psi.infos.MethodCandidateInfo;
import com.intellij.psi.search.GlobalSearchScope;
@@ -27,6 +28,7 @@ import com.intellij.psi.util.*;
import com.intellij.util.ArrayUtilRt;
import com.intellij.util.Function;
import com.intellij.util.Processor;
+import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -220,8 +222,9 @@ public class InferenceSession {
return prepareSubstitution();
}
- if (parameters != null && args != null) {
- final Set<ConstraintFormula> additionalConstraints = new HashSet<ConstraintFormula>();
+ if (parameters != null && args != null &&
+ !MethodCandidateInfo.ourOverloadGuard.currentStack().contains(PsiUtil.skipParenthesizedExprUp(parent.getParent()))) {
+ final Set<ConstraintFormula> additionalConstraints = new LinkedHashSet<ConstraintFormula>();
if (parameters.length > 0) {
collectAdditionalConstraints(parameters, args, properties.getMethod(), PsiSubstitutor.EMPTY, additionalConstraints, properties.isVarargs(), true);
}
@@ -782,6 +785,7 @@ public class InferenceSession {
PsiSubstitutor substitutor) {
final List<PsiType> lowerBounds = variable.getBounds(boundType);
PsiType lub = PsiType.NULL;
+ List<PsiType> dTypes = new ArrayList<PsiType>();
for (PsiType lowerBound : lowerBounds) {
lowerBound = substituteNonProperBound(lowerBound, substitutor);
final HashSet<InferenceVariable> dependencies = new HashSet<InferenceVariable>();
@@ -830,35 +834,21 @@ public class InferenceSession {
}
private boolean proceedWithAdditionalConstraints(Set<ConstraintFormula> additionalConstraints) {
- final Set<InferenceVariable> mentionedVars = new HashSet<InferenceVariable>();
- for (ConstraintFormula constraint : additionalConstraints) {
- if (constraint instanceof InputOutputConstraintFormula) {
- final Set<InferenceVariable> inputVariables = ((InputOutputConstraintFormula)constraint).getInputVariables(this);
- if (inputVariables != null) {
- mentionedVars.addAll(inputVariables);
- }
- final Set<InferenceVariable> outputVariables = ((InputOutputConstraintFormula)constraint).getOutputVariables(inputVariables, this);
- if (outputVariables != null) {
- mentionedVars.addAll(outputVariables);
- }
- }
- }
-
- final Set<InferenceVariable> readyVariables = new LinkedHashSet<InferenceVariable>(myInferenceVariables.values());
- readyVariables.removeAll(mentionedVars);
-
- final PsiSubstitutor siteSubstitutor = resolveBounds(readyVariables, mySiteSubstitutor);
+ final PsiSubstitutor siteSubstitutor = mySiteSubstitutor;
while (!additionalConstraints.isEmpty()) {
//extract subset of constraints
final Set<ConstraintFormula> subset = buildSubset(additionalConstraints);
//collect all input variables of selection
- final Set<InferenceVariable> varsToResolve = new HashSet<InferenceVariable>();
+ final Set<InferenceVariable> varsToResolve = new LinkedHashSet<InferenceVariable>();
for (ConstraintFormula formula : subset) {
if (formula instanceof InputOutputConstraintFormula) {
final Set<InferenceVariable> inputVariables = ((InputOutputConstraintFormula)formula).getInputVariables(this);
if (inputVariables != null) {
+ for (InferenceVariable inputVariable : inputVariables) {
+ varsToResolve.addAll(inputVariable.getDependencies(this));
+ }
varsToResolve.addAll(inputVariables);
}
}
@@ -895,7 +885,7 @@ public class InferenceSession {
private Set<ConstraintFormula> buildSubset(final Set<ConstraintFormula> additionalConstraints) {
- final Set<ConstraintFormula> subset = new HashSet<ConstraintFormula>();
+ final Set<ConstraintFormula> subset = new LinkedHashSet<ConstraintFormula>();
final Set<InferenceVariable> outputVariables = new HashSet<InferenceVariable>();
for (ConstraintFormula constraint : additionalConstraints) {
if (constraint instanceof InputOutputConstraintFormula) {
@@ -913,8 +903,19 @@ public class InferenceSession {
if (inputVariables != null) {
boolean dependsOnOutput = false;
for (InferenceVariable inputVariable : inputVariables) {
+ if (dependsOnOutput) break;
+ if (inputVariable.hasInstantiation(this)) continue;
final Set<InferenceVariable> dependencies = inputVariable.getDependencies(this);
dependencies.add(inputVariable);
+ if (!hasCapture(inputVariable)) {
+ for (InferenceVariable outputVariable : outputVariables) {
+ if (ContainerUtil.intersects(outputVariable.getDependencies(this), dependencies)) {
+ dependsOnOutput = true;
+ break;
+ }
+ }
+ }
+
dependencies.retainAll(outputVariables);
if (!dependencies.isEmpty()) {
dependsOnOutput = true;
@@ -971,7 +972,8 @@ public class InferenceSession {
for (int i = 0; i < functionalMethodParameters.length; i++) {
final PsiType pType = signature.getParameterTypes()[i];
- addConstraint(new TypeCompatibilityConstraint(getParameterType(parameters, i, PsiSubstitutor.EMPTY, varargs), pType));
+ addConstraint(new TypeCompatibilityConstraint(getParameterType(parameters, i, PsiSubstitutor.EMPTY, varargs),
+ PsiImplUtil.normalizeWildcardTypeByPosition(pType, reference)));
}
}
else if (parameters.length + 1 == functionalMethodParameters.length && !varargs ||
@@ -1005,7 +1007,8 @@ public class InferenceSession {
for (int i = 0; i < signature.getParameterTypes().length - 1; i++) {
final PsiType interfaceParamType = signature.getParameterTypes()[i + 1];
- addConstraint(new TypeCompatibilityConstraint(getParameterType(parameters, i, PsiSubstitutor.EMPTY, varargs), interfaceParamType));
+ addConstraint(new TypeCompatibilityConstraint(getParameterType(parameters, i, PsiSubstitutor.EMPTY, varargs),
+ PsiImplUtil.normalizeWildcardTypeByPosition(interfaceParamType, reference)));
}
}
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 a19961f4c3a9..6bc9e0b89871 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
@@ -115,6 +115,16 @@ public class InferenceVariable extends LightTypeParameter {
return dependencies;
}
+ public boolean hasInstantiation(InferenceSession session) {
+ List<PsiType> bounds = getBounds(InferenceBound.EQ);
+ if (bounds != null) {
+ for (PsiType bound : bounds) {
+ if (session.isProperType(bound)) return true;
+ }
+ }
+ return false;
+ }
+
public boolean isThrownBound() {
return myThrownBound;
}
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 9516265a8cb5..eefd040b2a99 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
@@ -63,7 +63,6 @@ public class PsiMethodReferenceCompatibilityConstraint implements ConstraintForm
final PsiType[] typeParameters = myExpression.getTypeParameters();
final PsiMethodReferenceUtil.QualifierResolveResult qualifierResolveResult = PsiMethodReferenceUtil.getQualifierResolveResult(myExpression);
- PsiSubstitutor psiSubstitutor = qualifierResolveResult.getSubstitutor();
if (!myExpression.isExact()) {
for (PsiParameter parameter : targetParameters) {
@@ -78,6 +77,7 @@ public class PsiMethodReferenceCompatibilityConstraint implements ConstraintForm
final PsiClass applicableMemberContainingClass = applicableMember.getContainingClass();
final PsiClass containingClass = qualifierResolveResult.getContainingClass();
+ PsiSubstitutor psiSubstitutor = qualifierResolveResult.getSubstitutor();
psiSubstitutor = applicableMemberContainingClass == null || containingClass == null || myExpression.isConstructor()
? psiSubstitutor
: TypeConversionUtil.getSuperClassSubstitutor(applicableMemberContainingClass, containingClass, psiSubstitutor);
@@ -146,11 +146,16 @@ public class PsiMethodReferenceCompatibilityConstraint implements ConstraintForm
final PsiType referencedMethodReturnType;
final PsiClass containingClass = method.getContainingClass();
LOG.assertTrue(containingClass != null, method);
-
PsiClass qContainingClass = qualifierResolveResult.getContainingClass();
- if (qContainingClass != null && InheritanceUtil.isInheritorOrSelf(qContainingClass, containingClass, true)) {
- psiSubstitutor = TypeConversionUtil.getClassSubstitutor(containingClass, qContainingClass, PsiSubstitutor.EMPTY);
- LOG.assertTrue(psiSubstitutor != null);
+ PsiSubstitutor psiSubstitutor = qualifierResolveResult.getSubstitutor();
+ if (qContainingClass != null) {
+ if ( PsiUtil.isRawSubstitutor(qContainingClass, psiSubstitutor)) {
+ psiSubstitutor = PsiSubstitutor.EMPTY;
+ }
+ if (qContainingClass.isInheritor(containingClass, true)) {
+ psiSubstitutor = TypeConversionUtil.getClassSubstitutor(containingClass, qContainingClass, PsiSubstitutor.EMPTY);
+ LOG.assertTrue(psiSubstitutor != null);
+ }
}
if (method.isConstructor()) {
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/MethodReferenceResolver.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/MethodReferenceResolver.java
index 4066c6cc4a78..29525add1549 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/MethodReferenceResolver.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/MethodReferenceResolver.java
@@ -231,8 +231,8 @@ public class MethodReferenceResolver implements ResolveCache.PolyVariantContextR
checkSameSignatures(conflicts);
checkAccessStaticLevels(conflicts, true);
- final PsiType[] parameterTypes = mySignature.getParameterTypes();
- boolean hasReceiver = PsiMethodReferenceUtil.hasReceiver(parameterTypes, myQualifierResolveResult, myReferenceExpression);
+ final PsiType[] argTypes = mySignature.getParameterTypes();
+ boolean hasReceiver = PsiMethodReferenceUtil.hasReceiver(argTypes, myQualifierResolveResult, myReferenceExpression);
final List<CandidateInfo> firstCandidates = new ArrayList<CandidateInfo>();
final List<CandidateInfo> secondCandidates = new ArrayList<CandidateInfo>();
@@ -242,19 +242,19 @@ public class MethodReferenceResolver implements ResolveCache.PolyVariantContextR
final PsiMethod psiMethod = ((MethodCandidateInfo)conflict).getElement();
final PsiSubstitutor substitutor = conflict.getSubstitutor();
- final PsiType[] signatureParameterTypes2 = psiMethod.getSignature(substitutor).getParameterTypes();
+ final PsiType[] parameterTypes = psiMethod.getSignature(substitutor).getParameterTypes();
final boolean varargs = ((MethodCandidateInfo)conflict).isVarargs();
if (varargs && (!psiMethod.isVarArgs() || myFunctionalMethodVarArgs)) continue;
- if ((varargs || parameterTypes.length == signatureParameterTypes2.length) &&
- PsiMethodReferenceUtil.isCorrectAssignment(signatureParameterTypes2, parameterTypes, varargs, 0)) {
+ if ((varargs || argTypes.length == parameterTypes.length) &&
+ PsiMethodReferenceUtil.isCorrectAssignment(parameterTypes, argTypes, varargs, 0)) {
firstCandidates.add(conflict);
}
if (hasReceiver &&
- (varargs || parameterTypes.length == signatureParameterTypes2.length + 1) &&
- PsiMethodReferenceUtil.isCorrectAssignment(signatureParameterTypes2, parameterTypes, varargs, 1)) {
+ (varargs || argTypes.length == parameterTypes.length + 1) &&
+ PsiMethodReferenceUtil.isCorrectAssignment(parameterTypes, argTypes, varargs, 1)) {
secondCandidates.add(conflict);
}
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiConditionalExpressionImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiConditionalExpressionImpl.java
index 73639b26c945..5bf3addded5f 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiConditionalExpressionImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiConditionalExpressionImpl.java
@@ -92,7 +92,7 @@ public class PsiConditionalExpressionImpl extends ExpressionPsiElement implement
if (PsiUtil.isLanguageLevel8OrHigher(this) &&
PsiPolyExpressionUtil.isPolyExpression(this) &&
- !MethodCandidateInfo.ourOverloadGuard.currentStack().contains(this.getParent())) {
+ !MethodCandidateInfo.ourOverloadGuard.currentStack().contains(PsiUtil.skipParenthesizedExprUp(this.getParent()))) {
//15.25.3 Reference Conditional Expressions
// The type of a poly reference conditional expression is the same as its target type.
return InferenceSession.getTargetType(this);
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiKeywordImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiKeywordImpl.java
index f39a88e8b35c..cdc2fa881c0b 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiKeywordImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiKeywordImpl.java
@@ -25,6 +25,7 @@ import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Field;
+import java.util.Locale;
public class PsiKeywordImpl extends LeafPsiElement implements PsiKeyword, PsiJavaToken {
public PsiKeywordImpl(@NotNull IElementType type, CharSequence text) {
@@ -52,7 +53,7 @@ public class PsiKeywordImpl extends LeafPsiElement implements PsiKeyword, PsiJav
static {
for(Field field: PsiKeyword.class.getFields()) {
- CharTableImpl.staticIntern(field.getName().toLowerCase());
+ CharTableImpl.staticIntern(field.getName().toLowerCase(Locale.ENGLISH));
}
}
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiLiteralExpressionImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiLiteralExpressionImpl.java
index e5892be2fb4d..ce38729027d9 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiLiteralExpressionImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiLiteralExpressionImpl.java
@@ -31,6 +31,8 @@ import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.util.Locale;
+
public class PsiLiteralExpressionImpl
extends ExpressionPsiElement
implements PsiLiteralExpression, PsiLanguageInjectionHost, ContributedReferenceHost {
@@ -93,7 +95,7 @@ public class PsiLiteralExpressionImpl
@Override
public Object getValue() {
final IElementType type = getLiteralElementType();
- String text = NUMERIC_LITERALS.contains(type) ? getCanonicalText().toLowerCase() : getCanonicalText();
+ String text = NUMERIC_LITERALS.contains(type) ? getCanonicalText().toLowerCase(Locale.ENGLISH) : getCanonicalText();
final int textLength = text.length();
if (type == JavaTokenType.INTEGER_LITERAL) {
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiReferenceExpressionImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiReferenceExpressionImpl.java
index 8dd43933c660..8b10b6326df9 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiReferenceExpressionImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiReferenceExpressionImpl.java
@@ -234,7 +234,7 @@ public class PsiReferenceExpressionImpl extends PsiReferenceExpressionBase imple
}
@Override
- protected void elementFinished(PsiElement element) {
+ protected void elementFinished(@NotNull PsiElement element) {
if (!(element instanceof PsiReferenceExpressionImpl)) return;
PsiReferenceExpressionImpl expression = (PsiReferenceExpressionImpl)element;
resolveCache.resolveWithCaching(expression, INSTANCE, false, false, containingFile);
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 669080107623..58a04db8f32b 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
@@ -31,10 +31,7 @@ import com.intellij.util.Function;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashSet;
+import java.util.*;
import static com.intellij.psi.util.PsiFormatUtilBase.*;
@@ -47,20 +44,22 @@ public class PsiMethodTreeElement extends JavaClassTreeElementBase<PsiMethod> im
@Override
@NotNull
public Collection<StructureViewTreeElement> getChildrenBase() {
- final ArrayList<StructureViewTreeElement> result = new ArrayList<StructureViewTreeElement>();
+ final List<StructureViewTreeElement> emptyResult = Collections.emptyList();
final PsiMethod element = getElement();
- if (element == null || element instanceof SyntheticElement) return result;
+ if (element == null || element instanceof SyntheticElement) return emptyResult;
final PsiFile psiFile = element.getContainingFile();
- if (psiFile == null || psiFile instanceof PsiCompiledElement) return result;
+ if (psiFile == null || psiFile instanceof PsiCompiledElement) return emptyResult;
final TextRange range = element.getTextRange();
- if (range == null) return result;
+ if (range == null) return emptyResult;
final String fileText = psiFile.getText();
- if (fileText == null) return result;
+ if (fileText == null) return emptyResult;
+
+ if (!range.substring(fileText).contains(PsiKeyword.CLASS)) return emptyResult;
- if (!range.substring(fileText).contains(PsiKeyword.CLASS)) return result;
+ final ArrayList<StructureViewTreeElement> result = new ArrayList<StructureViewTreeElement>();
element.accept(new JavaRecursiveElementWalkingVisitor(){
@Override public void visitClass(PsiClass aClass) {
diff --git a/java/java-tests/testData/codeInsight/completion/smartType/ConstructorRef-out.java b/java/java-tests/testData/codeInsight/completion/smartType/ConstructorRef-out.java
new file mode 100644
index 000000000000..19decec183b0
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/smartType/ConstructorRef-out.java
@@ -0,0 +1,14 @@
+@FunctionalInterface
+interface Foo9 {
+ Bar test(int p);
+}
+
+class Bar {
+ public Bar(int p) {}
+}
+
+class Test88 {
+ void foo(Foo9 foo) {
+ foo(Bar::new<caret>);
+ }
+} \ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/completion/smartType/ConstructorRef.java b/java/java-tests/testData/codeInsight/completion/smartType/ConstructorRef.java
new file mode 100644
index 000000000000..7f7af003b377
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/smartType/ConstructorRef.java
@@ -0,0 +1,14 @@
+@FunctionalInterface
+interface Foo9 {
+ Bar test(int p);
+}
+
+class Bar {
+ public Bar(int p) {}
+}
+
+class Test88 {
+ void foo(Foo9 foo) {
+ foo(Bar::<caret>);
+ }
+} \ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/completion/smartType/InLambdaPositionSameNames-out.java b/java/java-tests/testData/codeInsight/completion/smartType/InLambdaPositionSameNames-out.java
new file mode 100644
index 000000000000..48157c4ded2a
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/smartType/InLambdaPositionSameNames-out.java
@@ -0,0 +1,10 @@
+interface I<T> {
+ void m(T t, String s);
+}
+
+class Test {
+ public static void main(String[] args) {
+ String s = "";
+ I<String> i = (s1, s2) -> <caret>
+ }
+} \ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/completion/smartType/InLambdaPositionSameNames.java b/java/java-tests/testData/codeInsight/completion/smartType/InLambdaPositionSameNames.java
new file mode 100644
index 000000000000..e7adb2ffb758
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/smartType/InLambdaPositionSameNames.java
@@ -0,0 +1,10 @@
+interface I<T> {
+ void m(T t, String s);
+}
+
+class Test {
+ public static void main(String[] args) {
+ String s = "";
+ I<String> i = <caret>
+ }
+} \ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/createSubclass/innerClassImplement/after/Test.java b/java/java-tests/testData/codeInsight/createSubclass/innerClassImplement/after/Test.java
index 38024980a233..4c765169c38f 100644
--- a/java/java-tests/testData/codeInsight/createSubclass/innerClassImplement/after/Test.java
+++ b/java/java-tests/testData/codeInsight/createSubclass/innerClassImplement/after/Test.java
@@ -11,7 +11,7 @@ public class Test {
@Override
void bar() {
-
+
}
}
} \ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/AssignToFinal.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/AssignToFinal.java
index 171b63a8f06f..de5212a4bf87 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/AssignToFinal.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/AssignToFinal.java
@@ -90,5 +90,6 @@ class T1 {
++(<error descr="Variable 'i2' might not have been initialized">i2</error>);
<error descr="Variable 'i3' might not have been initialized">i3</error> += 1;
(i4) = 1;
+ (<error descr="Expression expected">)</error>++;
}
} \ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/TypeCastInInstanceof.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/TypeCastInInstanceof.java
new file mode 100644
index 000000000000..cbbffdf44291
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/TypeCastInInstanceof.java
@@ -0,0 +1,13 @@
+@SuppressWarnings({"UnusedDeclaration"})
+class C {
+ boolean foo(final ConfigurableField<String> nameField) {
+ return (Formatter<?>)nameField.getFormatter() instanceof DefaultFormatter;
+ }
+}
+
+@SuppressWarnings({"UnusedDeclaration"})
+interface Formatter<V>{}
+class DefaultFormatter implements Formatter<Object>{}
+interface ConfigurableField<V> {
+ Formatter<V> getFormatter();
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/annotations/dupMethods.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/annotations/dupMethods.java
new file mode 100644
index 000000000000..94744fa9be03
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/annotations/dupMethods.java
@@ -0,0 +1,4 @@
+@interface Example {
+ <error descr="'myMethod()' is already defined in 'Example'">public String myMethod()</error>;
+ <error descr="'myMethod()' is already defined in 'Example'">public int myMethod()</error>;
+} \ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/annotations/privateInaccessibleConstant.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/annotations/privateInaccessibleConstant.java
new file mode 100644
index 000000000000..435810d00b44
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/annotations/privateInaccessibleConstant.java
@@ -0,0 +1,8 @@
+@FooAnnotation(<error descr="'Foo.BAR' has private access in 'Foo'">Foo.BAR</error>)
+class Foo {
+ private static final String BAR = "bar";
+}
+
+@interface FooAnnotation {
+ String value();
+} \ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA55510.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA55510.java
index 5776db03ae4b..2db53078fce5 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA55510.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA55510.java
@@ -34,3 +34,20 @@ class Records {
}
}
}
+//---------------------------------------------
+class Parent<T extends Parent.NestedParent>
+{
+ protected static interface NestedParent
+ {
+ }
+}
+
+class Test
+{
+ public final static class Child extends Parent<<error descr="NestedChild is not accessible in current context">Child.NestedChild</error>>
+ {
+ private static interface NestedChild extends NestedParent
+ {
+ }
+ }
+} \ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA78402.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA78402.java
new file mode 100644
index 000000000000..ed8d259ab462
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA78402.java
@@ -0,0 +1,18 @@
+import java.util.Collection;
+import java.util.List;
+
+class Reference<T> {}
+
+class Bug {
+ private static <T> void foo(List<T> x, Reference<String> y) {
+ System.out.println(x);
+ }
+
+ private static <T> void foo(Collection<T> x, Reference<T> y) {
+ System.out.println(x);
+ }
+
+ public static void bazz(List<String> bar) {
+ foo<error descr="Ambiguous method call: both 'Bug.foo(List<String>, Reference<String>)' and 'Bug.foo(Collection<String>, Reference<String>)' match">(bar, null)</error>;
+ }
+} \ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA78402.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA78402.java
new file mode 100644
index 000000000000..ed8d259ab462
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA78402.java
@@ -0,0 +1,18 @@
+import java.util.Collection;
+import java.util.List;
+
+class Reference<T> {}
+
+class Bug {
+ private static <T> void foo(List<T> x, Reference<String> y) {
+ System.out.println(x);
+ }
+
+ private static <T> void foo(Collection<T> x, Reference<T> y) {
+ System.out.println(x);
+ }
+
+ public static void bazz(List<String> bar) {
+ foo<error descr="Ambiguous method call: both 'Bug.foo(List<String>, Reference<String>)' and 'Bug.foo(Collection<String>, Reference<String>)' match">(bar, null)</error>;
+ }
+} \ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/IDEA127928.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/IDEA127928.java
new file mode 100644
index 000000000000..d0c118198599
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/IDEA127928.java
@@ -0,0 +1,21 @@
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Function;
+
+class CastLambdaParameter {
+
+ void main(final Map<Integer, String> map) {
+ Set<Function<Object, String>> property2formatter = foo(bar((joint) -> map.get((Integer)joint)));
+ }
+
+ public static <B> Set<B> foo(List<B> property2name) {return property2name != null ? null : null;}
+ public static <B> Set<B> foo(List<B>... property2name) {return property2name != null ? null : null;}
+ public static <B> Set<B> foo(Set<B> property2name) {return property2name != null ? null : null;}
+
+ public static <TB> List<TB> bar(TB b) {
+ return null;
+ }
+
+}
+
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/OuterCallOverloads.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/OuterCallOverloads.java
new file mode 100644
index 000000000000..6506a7a48464
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/OuterCallOverloads.java
@@ -0,0 +1,16 @@
+import java.util.List;
+import java.util.Set;
+
+abstract class Overloadsss {
+ abstract <T> List<T> foo(List<T> l);
+ abstract <T> Set<T> foo(Set<T> s);
+
+ abstract <K> List<K> bar(List<K> l);
+ abstract <K> List<K> bar1(List<K> l);
+ abstract <K> Set<K> bar1(Set<K> s);
+
+ {
+ List<String> l = foo(bar (null));
+ List<String> l1 = foo(bar1<error descr="Ambiguous method call: both 'Overloadsss.bar1(List<Object>)' and 'Overloadsss.bar1(Set<Object>)' match">(null)</error>);
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/interfaceMethods/AnnotationTypeExtensionsNotSupported.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/interfaceMethods/AnnotationTypeExtensionsNotSupported.java
new file mode 100644
index 000000000000..258bf1132d5b
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/interfaceMethods/AnnotationTypeExtensionsNotSupported.java
@@ -0,0 +1,9 @@
+@interface Example {
+
+ public <error descr="Modifier 'static' not allowed here">static</error> String myMethod() {
+ return "";
+ }
+ public <error descr="Modifier 'default' not allowed here">default</error> String myMethod1() {
+ return "";
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/IDEA123951.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/IDEA123951.java
new file mode 100644
index 000000000000..c5bdecf7c43e
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/IDEA123951.java
@@ -0,0 +1,8 @@
+
+import java.util.stream.Collectors;
+
+class Test {
+ {
+ Collectors.mapping(i -> 1, Collectors.summingInt(s -> s.intValue()));
+ }
+} \ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/IDEA124190.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/IDEA124190.java
new file mode 100644
index 000000000000..9885b03ffaa9
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/IDEA124190.java
@@ -0,0 +1,12 @@
+import java.util.*;
+import java.util.stream.Stream;
+
+class Test {
+
+ void foo(final Stream<String> stream){
+ stream.collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
+ stream.collect(ArrayList<String>::new, ArrayList::add, ArrayList::addAll);
+ stream.collect(ArrayList::new, Collection::add, Collection::addAll);
+ }
+
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/IDEA124424.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/IDEA124424.java
new file mode 100644
index 000000000000..369804623026
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/IDEA124424.java
@@ -0,0 +1,12 @@
+import java.util.stream.Stream;
+
+import static java.util.stream.Collectors.toList;
+
+class Main {
+ void bar(final Stream<Object> objectStream) {
+ foo(objectStream.map(o -> "str").collect(toList()));
+ }
+
+ void foo(Iterable<?> k){}
+ void foo(String s){}
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/IDEA124983.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/IDEA124983.java
new file mode 100644
index 000000000000..2a92ebe2accf
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/IDEA124983.java
@@ -0,0 +1,9 @@
+
+import java.util.stream.IntStream;
+
+class Test {
+ private void foo(final IntStream range) {
+ range.mapToObj(i -> range.mapToObj(j -> 1))
+ .flatMap(s -> s);
+ }
+} \ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/IDEA125674.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/IDEA125674.java
new file mode 100644
index 000000000000..92d8de505e95
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/IDEA125674.java
@@ -0,0 +1,8 @@
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+class Test {
+ void foo(final Stream<String> stream){
+ stream.collect(Collectors.toMap(s -> s, s -> s, (a, b) -> a.length() > b. length() ? a : b));
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/IDEA127124comment.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/IDEA127124comment.java
new file mode 100644
index 000000000000..cb8442e59d12
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/IDEA127124comment.java
@@ -0,0 +1,30 @@
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+class Test {
+ private static class Thing {
+ final String val;
+ public Thing(String val) {
+ this.val = val;
+ }
+ }
+
+ public static Optional<List<String>> highlights() {
+ return Optional.of(Collections.singletonList(new Thing("Hello")))
+ .map(l -> l
+ .stream()
+ .map(t -> t.val + " world!")
+ .collect(Collectors.toList()));
+ }
+
+ public static Optional<List<String>> works() {
+ return Optional.of(Collections.singletonList(new Thing("Hello")))
+ .map(l -> l
+ .stream()
+ .map(t -> t.val + " world!")
+ .collect(Collectors.toList()));
+ }
+} \ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/IDEA127275.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/IDEA127275.java
new file mode 100644
index 000000000000..6b3a6123fa09
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/IDEA127275.java
@@ -0,0 +1,18 @@
+import java.util.List;
+import java.util.Optional;
+import java.util.function.Function;
+
+class Main {
+ {
+ List<Optional<Function<String, String>>> list = asList(of(Main::identity));
+ }
+
+ static <T> List<T> asList(T... a) { return null;}
+
+ static <T> Optional<T> of(T value) { return null;}
+
+ public static String identity(final String s) {
+ return s;
+ }
+
+} \ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/IDEA127275_.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/IDEA127275_.java
new file mode 100644
index 000000000000..c002468c1b91
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/IDEA127275_.java
@@ -0,0 +1,19 @@
+import java.util.List;
+import java.util.Optional;
+import java.util.function.Function;
+
+class Main {
+ {
+ List<Optional<Function<String, String>>> list = asList(of(Main::identity));
+ }
+
+ static <T> List<T> asList(T a) { return null;}
+ static <T> List<T> asList(Optional a) { return null;}
+
+ static <T> Optional<T> of(T value) { return null;}
+
+ public static String identity(final String s) {
+ return s;
+ }
+
+} \ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/IDEA128534.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/IDEA128534.java
new file mode 100644
index 000000000000..74b4322196b8
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/IDEA128534.java
@@ -0,0 +1,10 @@
+import java.util.Set;
+
+class Test {
+
+ public static void foo(String[] args, final Set<Test> singleton) {
+ singleton.forEach(Test::m);
+ }
+
+ public static void m(Test... others) {}
+} \ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/IDEA128712.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/IDEA128712.java
new file mode 100644
index 000000000000..3a812195b86f
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/IDEA128712.java
@@ -0,0 +1,19 @@
+import java.util.Collection;
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+abstract class Foo {
+ {
+ map(Foo::bar);
+ map(a -> Foo.bar(a));
+ }
+
+ <R> Stream<R> map(Function<Class<?>, ? extends R> mapper) {
+ return null;
+ }
+
+
+ private static <T> Collection<T> bar(Class<T> baseClass) {
+ return null;
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/UnresolvedMethodReference.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/UnresolvedMethodReference.java
new file mode 100644
index 000000000000..cee3a33a1230
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/UnresolvedMethodReference.java
@@ -0,0 +1,9 @@
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+
+class Main {
+ public void test() {
+ Collections.sort(new ArrayList<>(), Comparator::<error descr="Cannot resolve method 'reversed'">reversed</error>);
+ }
+} \ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createInnerClassFromNew/afterTypeParamSetup.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createInnerClassFromNew/afterTypeParamSetup.java
new file mode 100644
index 000000000000..9d516996894c
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createInnerClassFromNew/afterTypeParamSetup.java
@@ -0,0 +1,11 @@
+// "Create Inner Class 'AInner'" "true"
+class Test {
+ {
+ AInner aInner = new AInner<String>(42);
+ }
+
+ private class AInner<T> {
+ public AInner(int i) {
+ }
+ }
+} \ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createInnerClassFromNew/afterTypeParamSetup1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createInnerClassFromNew/afterTypeParamSetup1.java
new file mode 100644
index 000000000000..aac015e28360
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createInnerClassFromNew/afterTypeParamSetup1.java
@@ -0,0 +1,11 @@
+// "Create Inner Class 'AInner'" "true"
+class Test {
+ {
+ AInner aInner = new AInner<String, String>(42);
+ }
+
+ private class AInner<T, T1> {
+ public AInner(int i) {
+ }
+ }
+} \ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createInnerClassFromNew/beforeTypeParamSetup.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createInnerClassFromNew/beforeTypeParamSetup.java
new file mode 100644
index 000000000000..1d26d9d55357
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createInnerClassFromNew/beforeTypeParamSetup.java
@@ -0,0 +1,6 @@
+// "Create Inner Class 'AInner'" "true"
+class Test {
+ {
+ AInner aInner = new AIn<caret>ner<String>(42);
+ }
+} \ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createInnerClassFromNew/beforeTypeParamSetup1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createInnerClassFromNew/beforeTypeParamSetup1.java
new file mode 100644
index 000000000000..bf0997aed99e
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createInnerClassFromNew/beforeTypeParamSetup1.java
@@ -0,0 +1,6 @@
+// "Create Inner Class 'AInner'" "true"
+class Test {
+ {
+ AInner aInner = new AIn<caret>ner<String, String>(42);
+ }
+} \ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/fixAll/after1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/fixAll/after1.java
index f90b3db33828..a144d82ac59c 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/fixAll/after1.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/fixAll/after1.java
@@ -1,4 +1,4 @@
-// "Fix all 'Constant conditions & exceptions' problems" "true"
+// "Fix all 'Constant conditions & exceptions' problems in file" "true"
public class Test {
void foo() {
int k = 0;
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/fixAll/after2.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/fixAll/after2.java
index 877810ea9ade..a43c160b6d38 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/fixAll/after2.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/fixAll/after2.java
@@ -1,4 +1,4 @@
-// "Fix all 'Constant conditions & exceptions' problems" "true"
+// "Fix all 'Constant conditions & exceptions' problems in file" "true"
public class Test {
void foo1() {
int k = 0;
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/fixAll/afterAssertFalse.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/fixAll/afterAssertFalse.java
index 5aba2e1bc320..b16797331be1 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/fixAll/afterAssertFalse.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/fixAll/afterAssertFalse.java
@@ -1,4 +1,4 @@
-// "Fix all 'Constant conditions & exceptions' problems" "true"
+// "Fix all 'Constant conditions & exceptions' problems in file" "true"
public class Test {
void foo2() {
int k = 0;
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/fixAll/afterAssertTrue.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/fixAll/afterAssertTrue.java
index b251f0387f29..a5ded0b7ba07 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/fixAll/afterAssertTrue.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/fixAll/afterAssertTrue.java
@@ -1,4 +1,4 @@
-// "Fix all 'Constant conditions & exceptions' problems" "true"
+// "Fix all 'Constant conditions & exceptions' problems in file" "true"
public class Test {
void foo2() {
int k = 0;
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/fixAll/before1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/fixAll/before1.java
index b012f43a1c52..698897914e67 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/fixAll/before1.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/fixAll/before1.java
@@ -1,4 +1,4 @@
-// "Fix all 'Constant conditions & exceptions' problems" "true"
+// "Fix all 'Constant conditions & exceptions' problems in file" "true"
public class Test {
void foo() {
int k = 0;
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/fixAll/before2.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/fixAll/before2.java
index e7d9398ae3e8..768ea463ff1c 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/fixAll/before2.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/fixAll/before2.java
@@ -1,4 +1,4 @@
-// "Fix all 'Constant conditions & exceptions' problems" "true"
+// "Fix all 'Constant conditions & exceptions' problems in file" "true"
public class Test {
void foo1() {
int k = 0;
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/fixAll/beforeAssertFalse.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/fixAll/beforeAssertFalse.java
index 8ddc67b7ac1e..49786029f303 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/fixAll/beforeAssertFalse.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/fixAll/beforeAssertFalse.java
@@ -1,4 +1,4 @@
-// "Fix all 'Constant conditions & exceptions' problems" "true"
+// "Fix all 'Constant conditions & exceptions' problems in file" "true"
public class Test {
void foo2() {
int k = 0;
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/fixAll/beforeAssertTrue.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/fixAll/beforeAssertTrue.java
index 98611528fce5..4aa5316be779 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/fixAll/beforeAssertTrue.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/fixAll/beforeAssertTrue.java
@@ -1,4 +1,4 @@
-// "Fix all 'Constant conditions & exceptions' problems" "true"
+// "Fix all 'Constant conditions & exceptions' problems in file" "true"
public class Test {
void foo2() {
int k = 0;
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/fixAllAnnotator/after1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/fixAllAnnotator/after1.java
index 1a0aba5d40ef..1297d5d7fac5 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/fixAllAnnotator/after1.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/fixAllAnnotator/after1.java
@@ -1,4 +1,4 @@
-// "Fix all 'Annotator' problems" "true"
+// "Fix all 'Annotator' problems in file" "true"
public class Test {
void fooF() {
}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/fixAllAnnotator/before1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/fixAllAnnotator/before1.java
index 8006731dbe32..8805559ebe8e 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/fixAllAnnotator/before1.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/fixAllAnnotator/before1.java
@@ -1,4 +1,4 @@
-// "Fix all 'Annotator' problems" "true"
+// "Fix all 'Annotator' problems in file" "true"
public class Test {
void f<caret>oo() {
}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/moveInitializerToConstructor/afterArrayInitializer.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/moveInitializerToConstructor/afterArrayInitializer.java
new file mode 100644
index 000000000000..c063aef37715
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/moveInitializerToConstructor/afterArrayInitializer.java
@@ -0,0 +1,8 @@
+// "Move initializer to constructor" "true"
+class X {
+ final String s;
+
+ X() {
+ s = {};
+ }
+} \ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/moveInitializerToConstructor/beforeArrayInitializer.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/moveInitializerToConstructor/beforeArrayInitializer.java
new file mode 100644
index 000000000000..fdc8c7b3e22f
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/moveInitializerToConstructor/beforeArrayInitializer.java
@@ -0,0 +1,7 @@
+// "Move initializer to constructor" "true"
+class X {
+ final String <caret>s = {};
+
+ X() {
+ }
+} \ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/surroundWithTry/afterArrayInitializer.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/surroundWithTry/afterArrayInitializer.java
new file mode 100644
index 000000000000..fda3c915e4da
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/surroundWithTry/afterArrayInitializer.java
@@ -0,0 +1,22 @@
+// "Surround with try/catch" "true"
+public class ExTest {
+ public static String maybeThrow(String data) throws Ex {
+ throw new Ex(data);
+ }
+
+ {
+ String[] a = new String[0];
+ try {
+ a = new String[]{maybeThrow("")};
+ } catch (Ex ex) {
+ ex.printStackTrace();
+ }
+ System.out.println(a);
+ }
+
+
+ private static class Ex extends Exception {
+ public Ex(String s) {
+ }
+ }
+} \ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/surroundWithTry/beforeArrayInitializer.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/surroundWithTry/beforeArrayInitializer.java
new file mode 100644
index 000000000000..60e76c1781a3
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/surroundWithTry/beforeArrayInitializer.java
@@ -0,0 +1,17 @@
+// "Surround with try/catch" "true"
+public class ExTest {
+ public static String maybeThrow(String data) throws Ex {
+ throw new Ex(data);
+ }
+
+ {
+ String[] a = {mayb<caret>eThrow("")};
+ System.out.println(a);
+ }
+
+
+ private static class Ex extends Exception {
+ public Ex(String s) {
+ }
+ }
+} \ No newline at end of file
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/OverrideImplementTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/OverrideImplementTest.java
index f9f70d655310..f35df4d389f9 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/OverrideImplementTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/OverrideImplementTest.java
@@ -81,7 +81,7 @@ public class OverrideImplementTest extends LightCodeInsightTestCase {
CodeStyleSettings codeStyleSettings = CodeStyleSettingsManager.getSettings(getProject()).clone();
try {
CommonCodeStyleSettings javaSettings = codeStyleSettings.getCommonSettings(JavaLanguage.INSTANCE);
- codeStyleSettings.RIGHT_MARGIN = 80;
+ javaSettings.RIGHT_MARGIN = 80;
javaSettings.KEEP_LINE_BREAKS = true;
codeStyleSettings.GENERATE_FINAL_PARAMETERS = true;
javaSettings.METHOD_PARAMETERS_WRAP = CommonCodeStyleSettings.WRAP_ON_EVERY_ITEM;
@@ -97,7 +97,7 @@ public class OverrideImplementTest extends LightCodeInsightTestCase {
CodeStyleSettings codeStyleSettings = CodeStyleSettingsManager.getSettings(getProject()).clone();
try {
CommonCodeStyleSettings javaSettings = codeStyleSettings.getCommonSettings(JavaLanguage.INSTANCE);
- codeStyleSettings.RIGHT_MARGIN = 80;
+ javaSettings.RIGHT_MARGIN = 80;
javaSettings.KEEP_LINE_BREAKS = false;
codeStyleSettings.GENERATE_FINAL_PARAMETERS = false;
javaSettings.METHOD_PARAMETERS_WRAP = CommonCodeStyleSettings.WRAP_ON_EVERY_ITEM;
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavadocCompletionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavadocCompletionTest.groovy
index b966d5205776..2b4d4af70554 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavadocCompletionTest.groovy
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavadocCompletionTest.groovy
@@ -229,6 +229,20 @@ class Foo {
myFixture.assertPreferredCompletionItems 0, 'param', 'param param2'
}
+ public void "test fqns in package info"() {
+ myFixture.configureByText "package-info.java", '''
+/**
+ * {@link java.util.Map#putA<caret>}
+ */
+'''
+ myFixture.complete(CompletionType.BASIC)
+ myFixture.checkResult '''
+/**
+ * {@link java.util.Map#putAll(java.util.Map)}
+ */
+'''
+ }
+
public void "test suggest same param descriptions"() {
myFixture.configureByText "a.java", '''
class Foo {
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartType18CompletionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartType18CompletionTest.java
index 8aee494012cb..eb3c4c4577b6 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartType18CompletionTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartType18CompletionTest.java
@@ -80,6 +80,13 @@ public class SmartType18CompletionTest extends LightFixtureCompletionTestCase {
public void testInLambdaPositionNameSubstitution() throws Exception {
doTest();
}
+ public void testInLambdaPositionSameNames() throws Exception {
+ doTest();
+ }
+
+ public void testConstructorRef() throws Exception {
+ doTest(false);
+ }
public void testFilteredMethodReference() throws Exception {
doTest(false);
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AnnotationsHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AnnotationsHighlightingTest.java
index 964566fcf5ff..43e90b84257b 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AnnotationsHighlightingTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AnnotationsHighlightingTest.java
@@ -41,6 +41,8 @@ public class AnnotationsHighlightingTest extends LightDaemonAnalyzerTestCase {
public void testDuplicateTarget() { doTest(false); }
public void testPingPongAnnotationTypesDependencies() { doTest(false);}
public void testClashMethods() { doTest(false);}
+ public void testDupMethods() { doTest(false);}
+ public void testPrivateInaccessibleConstant() { doTest(false);}
public void testInvalidPackageAnnotationTarget() { doTest(BASE_PATH + "/" + getTestName(true) + "/package-info.java", false, false); }
public void testPackageAnnotationNotInPackageInfo() { doTest(BASE_PATH + "/" + getTestName(true) + "/notPackageInfo.java", false, false); }
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java
index f6be0686d239..688e83b5b198 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java
@@ -371,6 +371,7 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase {
public void testIDEA126697() { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, true); }
public void testIDEA126633() { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); }
public void testIDEA124363() { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); }
+ public void testIDEA78402() { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); }
//jdk should propagate LL 1.4 but actually it provides LL 1.7?!
public void testCastObjectToIntJdk14() { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_4, false); }
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/JavadocHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/JavadocHighlightingTest.java
index 0c561dfdace5..10d5bc064dcd 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/JavadocHighlightingTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/JavadocHighlightingTest.java
@@ -21,8 +21,10 @@ public class JavadocHighlightingTest extends LightDaemonAnalyzerTestCase {
@NotNull
@Override
protected LocalInspectionTool[] configureLocalInspectionTools() {
+ JavaDocLocalInspection localInspection = new JavaDocLocalInspection();
+ localInspection.setIgnoreDuplicatedThrows(false);
return new LocalInspectionTool[]{
- new JavaDocLocalInspection(),
+ localInspection,
new JavaDocReferenceInspection()
};
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk7Test.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk7Test.java
index d6831d4a2d4a..c24366b3d513 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk7Test.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk7Test.java
@@ -145,6 +145,7 @@ public class LightAdvHighlightingJdk7Test extends LightDaemonAnalyzerTestCase {
public void testPreciseRethrow() { doTest(false, false); }
public void testImprovedCatchAnalysis() { doTest(true, false); }
public void testPolymorphicTypeCast() { doTest(true, false); }
+ public void testTypeCastInInstanceof() { doTest(true, false); }
public void testErasureClashConfusion() { doTest(true, false, UnusedDeclarationInspection.class); }
public void testUnused() { doTest(true, false, UnusedDeclarationInspection.class); }
public void testSuperBound() { doTest(false, false); }
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GenericsHighlighting8Test.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GenericsHighlighting8Test.java
index 8f9167d83a21..d23dfea6daf0 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GenericsHighlighting8Test.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GenericsHighlighting8Test.java
@@ -759,6 +759,8 @@ public class GenericsHighlighting8Test extends LightDaemonAnalyzerTestCase {
doTest();
}
+ public void testIDEA78402() { doTest(); }
+
private void doTest() {
doTest(false);
}
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 6ccefa35ae51..c2ab020f09f3 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
@@ -16,11 +16,14 @@
package com.intellij.codeInsight.daemon.lambda;
import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase;
+import com.intellij.idea.Bombed;
import com.intellij.openapi.projectRoots.JavaSdkVersion;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.testFramework.IdeaTestUtil;
import org.jetbrains.annotations.NonNls;
+import java.util.Calendar;
+
public class GraphInferenceHighlightingTest extends LightDaemonAnalyzerTestCase {
@NonNls static final String BASE_PATH = "/codeInsight/daemonCodeAnalyzer/lambda/graphInference";
@@ -44,10 +47,12 @@ public class GraphInferenceHighlightingTest extends LightDaemonAnalyzerTestCase
doTest();
}
+ @Bombed(day = 20, month = Calendar.AUGUST)
public void testInferenceFromSiblings() throws Exception {
doTest();
}
+ @Bombed(day = 20, month = Calendar.AUGUST)
public void testChainedInferenceTypeParamsOrderIndependent() throws Exception {
doTest();
}
@@ -204,6 +209,14 @@ public class GraphInferenceHighlightingTest extends LightDaemonAnalyzerTestCase
doTest();
}
+ public void testOuterCallOverloads() throws Exception {
+ doTest();
+ }
+
+ public void testIDEA127928() throws Exception {
+ doTest();
+ }
+
private void doTest() throws Exception {
doTest(false);
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Interface8MethodsHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Interface8MethodsHighlightingTest.java
index 95b3bfb7395d..2162b96db138 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Interface8MethodsHighlightingTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Interface8MethodsHighlightingTest.java
@@ -43,6 +43,9 @@ public class Interface8MethodsHighlightingTest extends LightCodeInsightFixtureTe
public void testDefaultSupersInStaticContext() {
doTest(false, false);
}
+ public void testAnnotationTypeExtensionsNotSupported() {
+ doTest(false, false);
+ }
public void testSuperProtectedCalls() throws Exception {
myFixture.addClass("package p; public class Foo {" +
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java
index ea9ada93ca77..1411249b3dcc 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java
@@ -18,12 +18,15 @@ package com.intellij.codeInsight.daemon.lambda;
import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspection;
+import com.intellij.idea.Bombed;
import com.intellij.openapi.projectRoots.JavaSdkVersion;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.testFramework.IdeaTestUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
+import java.util.Calendar;
+
public class NewLambdaHighlightingTest extends LightDaemonAnalyzerTestCase {
@NonNls static final String BASE_PATH = "/codeInsight/daemonCodeAnalyzer/lambda/newLambda";
@@ -60,6 +63,7 @@ public class NewLambdaHighlightingTest extends LightDaemonAnalyzerTestCase {
public void testTargetTypeConflictResolverShouldNotTryToEvaluateCurrentArgumentType() { doTest(); }
public void testIDEA119535() { doTest(); }
public void testIDEA119003() { doTest(); }
+ public void testIDEA125674() { doTest(); }
public void testIDEA117124() { doTest(); }
public void testWildcardParameterization() { doTest(); }
public void testDiamondInLambdaReturn() { doTest(); }
@@ -73,6 +77,7 @@ public class NewLambdaHighlightingTest extends LightDaemonAnalyzerTestCase {
public void testIDEA122700() { doTest(); }
public void testIDEA122406() { doTest(); }
public void testNestedCallsInsideLambdaReturnExpression() { doTest(); }
+ @Bombed(day = 20, month = Calendar.AUGUST)
public void testIDEA123731() { doTest(); }
public void testIDEA123869() { doTest(); }
public void testIDEA123848() { doTest(); }
@@ -87,11 +92,28 @@ public class NewLambdaHighlightingTest extends LightDaemonAnalyzerTestCase {
public void testIDEA124961() { doTest(); }
public void testIDEA126109() { doTest(); }
public void testIDEA126809() { doTest(); }
+ public void testIDEA124424() { doTest(); }
public void testIDEA127596() throws Exception {
doTest();
}
+ @Bombed(day = 20, month = Calendar.AUGUST)
+ public void testIDEA124983() throws Exception {
+ doTest();
+ }
+
+ public void testIDEA123951() throws Exception {
+ doTest();
+ }
+
+ public void testIDEA124190() throws Exception {
+ doTest();
+ }
+ public void testIDEA127124comment() throws Exception {
+ doTest();
+ }
+
private void doTest() {
doTest(false);
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java
index dd7ceb566139..c48ef71d92d4 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java
@@ -19,12 +19,15 @@ import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.uncheckedWarnings.UncheckedWarningLocalInspection;
import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspection;
+import com.intellij.idea.Bombed;
import com.intellij.openapi.projectRoots.JavaSdkVersion;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.testFramework.IdeaTestUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
+import java.util.Calendar;
+
public class NewMethodRefHighlightingTest extends LightDaemonAnalyzerTestCase {
@NonNls static final String BASE_PATH = "/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef";
@@ -281,6 +284,27 @@ public class NewMethodRefHighlightingTest extends LightDaemonAnalyzerTestCase {
doTest();
}
+ public void testIDEA127275() throws Exception {
+ doTest();
+ }
+
+ @Bombed(day = 20, month = Calendar.AUGUST)
+ public void testIDEA127275_() throws Exception {
+ doTest();
+ }
+
+ public void testUnresolvedMethodReference() throws Exception {
+ doTest();
+ }
+
+ public void testIDEA128534() throws Exception {
+ doTest();
+ }
+
+ public void testIDEA128712() throws Exception {
+ doTest();
+ }
+
private void doTest() {
doTest(false);
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/I18nizeTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/I18nizeTest.java
index 099a7f4d3f0e..03693ce742c3 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/I18nizeTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/I18nizeTest.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,6 +20,7 @@ import com.intellij.codeInspection.i18n.I18nizeAction;
import com.intellij.codeInspection.i18n.JavaI18nUtil;
import com.intellij.ide.DataManager;
import com.intellij.lang.properties.psi.PropertiesFile;
+import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.application.ex.PathManagerEx;
@@ -43,7 +44,7 @@ public class I18nizeTest extends LightCodeInsightTestCase {
configureByFile(getBasePath() + "/before"+getTestName(false)+"."+ext);
I18nizeAction action = new I18nizeAction();
DataContext dataContext = DataManager.getInstance().getDataContext(myEditor.getComponent());
- AnActionEvent event = new AnActionEvent(null, dataContext, "place", action.getTemplatePresentation(), null, 0);
+ AnActionEvent event = new AnActionEvent(null, dataContext, "place", action.getTemplatePresentation(), ActionManager.getInstance(), 0);
action.update(event);
@NonNls String afterFile = getBasePath() + "/after" + getTestName(false) + "." + ext;
boolean afterFileExists = new File(PathManagerEx.getTestDataPath() + afterFile).exists();
diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/JavaDocInspectionTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/JavaDocInspectionTest.java
index 0f4644a84a26..30802e8a6da3 100644
--- a/java/java-tests/testSrc/com/intellij/codeInspection/JavaDocInspectionTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInspection/JavaDocInspectionTest.java
@@ -33,7 +33,9 @@ public class JavaDocInspectionTest extends InspectionTestCase {
}
public void testDuplicateThrows() throws Exception {
- doTest();
+ JavaDocLocalInspection tool = new JavaDocLocalInspection();
+ tool.setIgnoreDuplicatedThrows(false);
+ doTest("javaDocInspection/" + getTestName(true), tool);
}
//inherited javadoc
@@ -67,7 +69,6 @@ public class JavaDocInspectionTest extends InspectionTestCase {
public void testIgnoreDuplicateThrows() throws Exception {
final JavaDocLocalInspection inspection = new JavaDocLocalInspection();
- inspection.IGNORE_DUPLICATED_THROWS = true;
doTest("javaDocInspection/" + getTestName(true), inspection);
}
diff --git a/java/java-tests/testSrc/com/intellij/execution/ConfigurationsTest.java b/java/java-tests/testSrc/com/intellij/execution/ConfigurationsTest.java
index 7a8c5727c8eb..ac9844c4ced8 100644
--- a/java/java-tests/testSrc/com/intellij/execution/ConfigurationsTest.java
+++ b/java/java-tests/testSrc/com/intellij/execution/ConfigurationsTest.java
@@ -8,7 +8,7 @@ import com.intellij.execution.executors.DefaultRunExecutor;
import com.intellij.execution.junit.*;
import com.intellij.execution.junit2.configuration.JUnitConfigurable;
import com.intellij.execution.junit2.configuration.JUnitConfigurationModel;
-import com.intellij.execution.runners.ExecutionEnvironment;
+import com.intellij.execution.runners.ExecutionEnvironmentBuilder;
import com.intellij.execution.testframework.TestSearchScope;
import com.intellij.execution.ui.CommonJavaParametersPanel;
import com.intellij.openapi.module.Module;
@@ -21,7 +21,10 @@ import com.intellij.openapi.roots.ContentEntry;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.ModuleRootModificationUtil;
import com.intellij.openapi.ui.LabeledComponent;
-import com.intellij.openapi.util.*;
+import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.Disposer;
+import com.intellij.openapi.util.InvalidDataException;
+import com.intellij.openapi.util.WriteExternalException;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.JarFileSystem;
import com.intellij.openapi.vfs.LocalFileSystem;
@@ -30,20 +33,23 @@ import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.rt.execution.junit.JUnitStarter;
import com.intellij.rt.execution.junit.segments.SegmentedOutputStream;
-import com.intellij.testFramework.IdeaTestUtil;
import com.intellij.testFramework.MapDataContext;
+import com.intellij.testFramework.PlatformTestUtil;
import com.intellij.testFramework.PsiTestUtil;
import com.intellij.ui.EditorTextFieldWithBrowseButton;
import com.intellij.util.Assertion;
import com.intellij.util.PathUtil;
import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.ContainerUtilRt;
import junit.framework.TestCase;
import org.jdom.Element;
-import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.io.*;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.StringTokenizer;
public class ConfigurationsTest extends BaseConfigurationTestCase {
private final Assertion CHECK = new Assertion();
@@ -51,13 +57,6 @@ public class ConfigurationsTest extends BaseConfigurationTestCase {
private Sdk myJdk;
private static final String INNER_TEST_NAME = "test1.InnerTest.Inner";
private static final String RT_INNER_TEST_NAME = "test1.InnerTest$Inner";
- private static final Executor MOCK_EXECUTOR = new DefaultRunExecutor() {
- @NotNull
- @Override
- public String getId() {
- return "mock";
- }
- };
@Override
protected void setUp() throws Exception {
@@ -72,12 +71,12 @@ public class ConfigurationsTest extends BaseConfigurationTestCase {
Module module1 = getModule1();
PsiClass psiClass = findTestA(module1);
JUnitConfiguration configuration = createConfiguration(psiClass);
- assertEquals(Collections.singleton(module1), new HashSet(Arrays.asList(configuration.getModules())));
+ assertEquals(Collections.singleton(module1), ContainerUtilRt.newHashSet(configuration.getModules()));
checkClassName(psiClass.getQualifiedName(), configuration);
assertEquals(psiClass.getName(), configuration.getName());
checkTestObject(JUnitConfiguration.TEST_CLASS, configuration);
Module module2 = getModule2();
- CHECK.compareUnordered(new Module[]{module1, module2}, configuration.getValidModules());
+ Assertion.compareUnordered(new Module[]{module1, module2}, configuration.getValidModules());
PsiClass innerTest = findClass(module1, INNER_TEST_NAME);
configuration = createJUnitConfiguration(innerTest, TestClassConfigurationProducer.class, new MapDataContext());
@@ -99,7 +98,7 @@ public class ConfigurationsTest extends BaseConfigurationTestCase {
}
public void testModulesSelector() throws ConfigurationException {
- if (IdeaTestUtil.COVERAGE_ENABLED_BUILD) return;
+ if (PlatformTestUtil.COVERAGE_ENABLED_BUILD) return;
Module module1 = getModule1();
Module module2 = getModule2();
@@ -117,7 +116,7 @@ public class ConfigurationsTest extends BaseConfigurationTestCase {
assertTrue(configurable.isModified());
configurable.apply();
assertFalse(configurable.isModified());
- assertEquals(Collections.singleton(module1), new HashSet(Arrays.asList(configuration.getModules())));
+ assertEquals(Collections.singleton(module1), ContainerUtilRt.newHashSet(configuration.getModules()));
}
finally {
Disposer.dispose(editor);
@@ -163,7 +162,7 @@ public class ConfigurationsTest extends BaseConfigurationTestCase {
JUnitConfiguration configuration = createConfiguration(psiPackage, module1);
JavaParameters parameters = checkCanRun(configuration);
List<String> lines = extractAllInPackageTests(parameters, psiPackage);
- CHECK.compareUnordered(
+ Assertion.compareUnordered(
new Object[]{"", psiClass.getQualifiedName(), psiClass2.getQualifiedName(), derivedTest.getQualifiedName(), RT_INNER_TEST_NAME,
testB.getQualifiedName()},
lines);
@@ -246,7 +245,7 @@ public class ConfigurationsTest extends BaseConfigurationTestCase {
newCfg.readExternal(element);
checkTestObject(configuration.getPersistentData().TEST_OBJECT, newCfg);
- assertEquals(Collections.singleton(getModule1()), new HashSet(Arrays.asList(newCfg.getModules())));
+ assertEquals(Collections.singleton(getModule1()), ContainerUtilRt.newHashSet(newCfg.getModules()));
checkClassName(configuration.getPersistentData().getMainClassName(), newCfg);
}
@@ -297,7 +296,7 @@ public class ConfigurationsTest extends BaseConfigurationTestCase {
}
public void testCreatingApplicationConfiguration() throws ConfigurationException {
- if (IdeaTestUtil.COVERAGE_ENABLED_BUILD) return;
+ if (PlatformTestUtil.COVERAGE_ENABLED_BUILD) return;
ApplicationConfiguration configuration = new ApplicationConfiguration(null, myProject, ApplicationConfigurationType.getInstance());
ApplicationConfigurable editor = new ApplicationConfigurable(myProject);
@@ -329,7 +328,7 @@ public class ConfigurationsTest extends BaseConfigurationTestCase {
}
public void testEditJUnitConfiguration() throws ConfigurationException {
- if (IdeaTestUtil.COVERAGE_ENABLED_BUILD) return;
+ if (PlatformTestUtil.COVERAGE_ENABLED_BUILD) return;
PsiClass testA = findTestA(getModule2());
JUnitConfiguration configuration = createConfiguration(testA);
@@ -357,11 +356,11 @@ public class ConfigurationsTest extends BaseConfigurationTestCase {
}
}
- public void testRunThridPartyApplication() throws ExecutionException {
+ public void testRunThirdPartyApplication() throws ExecutionException {
ApplicationConfiguration configuration =
- new ApplicationConfiguration("Thrid party", myProject, ApplicationConfigurationType.getInstance());
+ new ApplicationConfiguration("Third party", myProject, ApplicationConfigurationType.getInstance());
configuration.setModule(getModule1());
- configuration.MAIN_CLASS_NAME = "thrid.party.Main";
+ configuration.MAIN_CLASS_NAME = "third.party.Main";
checkCanRun(configuration);
}
@@ -407,7 +406,7 @@ public class ConfigurationsTest extends BaseConfigurationTestCase {
return PathUtil.getLocalPath(output);
}
- private String[] addOutputs(Module module, int index) {
+ private static String[] addOutputs(Module module, int index) {
String[] outputs = new String[2];
String prefix = "outputs" + File.separatorChar;
VirtualFile generalOutput = findFile(prefix + "general " + index);
@@ -419,12 +418,13 @@ public class ConfigurationsTest extends BaseConfigurationTestCase {
return outputs;
}
- private JavaParameters checkCanRun(RunConfiguration configuration) throws ExecutionException {
+ private static JavaParameters checkCanRun(RunConfiguration configuration) throws ExecutionException {
final RunProfileState state;
- state = configuration.getState(MOCK_EXECUTOR, new ExecutionEnvironment(new MockProfile(), MOCK_EXECUTOR, myProject, null));
+ state = ExecutionEnvironmentBuilder.create(DefaultRunExecutor.getRunExecutorInstance(), configuration).build().getState();
assertNotNull(state);
assertTrue(state instanceof JavaCommandLine);
if (state instanceof TestPackage) {
+ @SuppressWarnings("UnusedDeclaration")
final JavaParameters parameters = ((TestPackage)state).getJavaParameters();
((TestPackage)state).findTests();
}
@@ -440,7 +440,7 @@ public class ConfigurationsTest extends BaseConfigurationTestCase {
return ((JavaCommandLine)state).getJavaParameters();
}
- private void checkCantRun(RunConfiguration configuration, String reasonBegining) throws ExecutionException {
+ private void checkCantRun(RunConfiguration configuration, String reasonBeginning) throws ExecutionException {
//MockRunRequest request = new MockRunRequest(myProject);
//CantRunException rejectReason;
//try {
@@ -451,28 +451,27 @@ public class ConfigurationsTest extends BaseConfigurationTestCase {
// rejectReason = e;
//}
//if (rejectReason == null) fail("Should not run");
- //rejectReason.getMessage().startsWith(reasonBegining);
+ //rejectReason.getMessage().startsWith(reasonBeginning);
try {
configuration.checkConfiguration();
}
catch (RuntimeConfigurationError e) {
- assertTrue(e.getLocalizedMessage().startsWith(reasonBegining));
+ assertTrue(e.getLocalizedMessage().startsWith(reasonBeginning));
return;
}
- catch (RuntimeConfigurationException e) {
+ catch (RuntimeConfigurationException ignored) {
}
- final RunProfileState state = configuration
- .getState(MOCK_EXECUTOR, new ExecutionEnvironment(new MockProfile(), MOCK_EXECUTOR, myProject, null));
+ RunProfileState state = configuration.getState(DefaultRunExecutor.getRunExecutorInstance(), new ExecutionEnvironmentBuilder(myProject, DefaultRunExecutor.getRunExecutorInstance()).runProfile(configuration).build());
assertTrue(state instanceof JavaCommandLine);
try {
((JavaCommandLine)state).getJavaParameters();
}
catch (Throwable e) {
- assertTrue(e.getLocalizedMessage().startsWith(reasonBegining));
+ assertTrue(e.getLocalizedMessage().startsWith(reasonBeginning));
return;
}
@@ -537,11 +536,11 @@ public class ConfigurationsTest extends BaseConfigurationTestCase {
}
private static void checkContains(String string, String fragment) {
- assertTrue(fragment + " in " + string, string.indexOf(fragment) >= 0);
+ assertTrue(fragment + " in " + string, string.contains(fragment));
}
private static void checkDoesNotContain(String string, String fragment) {
- assertFalse(fragment + " in " + string, string.indexOf(fragment) >= 0);
+ assertFalse(fragment + " in " + string, string.contains(fragment));
}
@Override
@@ -549,21 +548,4 @@ public class ConfigurationsTest extends BaseConfigurationTestCase {
myJdk = null;
super.tearDown();
}
-
- private static class MockProfile implements RunProfile {
- @Override
- public RunProfileState getState(@NotNull final Executor executor, @NotNull final ExecutionEnvironment env) throws ExecutionException {
- return null;
- }
-
- @Override
- public Icon getIcon() {
- return null;
- }
-
- @Override
- public String getName() {
- return null;
- }
- }
}
diff --git a/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java b/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java
index f83d836bb55a..e40e2c160822 100644
--- a/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java
+++ b/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java
@@ -670,6 +670,18 @@ public class FindManagerTest extends DaemonAnalyzerTestCase {
assertTrue(findResult.getStartOffset() > prefix.length());
}
+ public void testFindExceptComments2() {
+ FindModel findModel = FindManagerTestUtils.configureFindModel("oo");
+
+ String text = "//oooo";
+
+ findModel.setSearchContext(FindModel.SearchContext.EXCEPT_COMMENTS);
+ LightVirtualFile file = new LightVirtualFile("A.java", text);
+
+ FindResult findResult = myFindManager.findString(text, 0, findModel, file);
+ assertFalse(findResult.isStringFound());
+ }
+
public void testFindExceptLiterals() {
FindModel findModel = FindManagerTestUtils.configureFindModel("done");
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 56624594bb0e..d74f7a3d0bff 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
@@ -378,6 +378,8 @@ public class DirectoryIndexTest extends IdeaTestCase {
assertTrue(info.isIgnored());
assertTrue(myFileIndex.isExcluded(ignoredFile));
assertTrue(myFileIndex.isUnderIgnored(ignoredFile));
+ assertNull(myFileIndex.getContentRootForFile(ignoredFile, false));
+ assertNull(myFileIndex.getModuleForFile(ignoredFile, false));
}
public void testAddModule() throws Exception {
@@ -804,6 +806,10 @@ public class DirectoryIndexTest extends IdeaTestCase {
PsiTestUtil.addExcludedRoot(myModule, fileExcludeRoot);
assertFalse(myFileIndex.isInContent(fileExcludeRoot));
assertFalse(myFileIndex.isInSource(fileExcludeRoot));
+ assertNull(myFileIndex.getContentRootForFile(fileExcludeRoot));
+ assertEquals(myModule1Dir, myFileIndex.getContentRootForFile(fileExcludeRoot, false));
+ assertNull(myFileIndex.getModuleForFile(fileExcludeRoot));
+ assertEquals(myModule, myFileIndex.getModuleForFile(fileExcludeRoot, false));
assertExcluded(fileExcludeRoot, myModule);
assertIteratedContent(myFileIndex, null, Arrays.asList(fileExcludeRoot));
@@ -928,7 +934,7 @@ public class DirectoryIndexTest extends IdeaTestCase {
assertEquals(Arrays.toString(myIndex.getOrderEntries(info)), modulesOfOrderEntries.length, myIndex.getOrderEntries(info).length);
for (Module aModule : modulesOfOrderEntries) {
- OrderEntry found = myIndex.findOrderEntryWithOwnerModule(info, aModule);
+ OrderEntry found = ModuleFileIndexImpl.findOrderEntryWithOwnerModule(aModule, myIndex.getOrderEntries(info));
assertNotNull("not found: " + aModule + " in " + Arrays.toString(myIndex.getOrderEntries(info)), found);
}
}
diff --git a/java/java-tests/testSrc/com/intellij/projectView/ProjectViewSwitchingTest.java b/java/java-tests/testSrc/com/intellij/projectView/ProjectViewSwitchingTest.java
index 88641107057c..1f70167a1d8e 100644
--- a/java/java-tests/testSrc/com/intellij/projectView/ProjectViewSwitchingTest.java
+++ b/java/java-tests/testSrc/com/intellij/projectView/ProjectViewSwitchingTest.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.
@@ -18,7 +18,6 @@ package com.intellij.projectView;
import com.intellij.JavaTestUtil;
import com.intellij.ide.favoritesTreeView.FavoritesManager;
import com.intellij.ide.projectView.ProjectView;
-import com.intellij.ide.projectView.impl.ProjectViewImpl;
import com.intellij.ide.projectView.impl.ProjectViewPane;
import com.intellij.testFramework.TestSourceBasedTestCase;
@@ -29,12 +28,6 @@ public class ProjectViewSwitchingTest extends TestSourceBasedTestCase {
}
@Override
- protected void setUp() throws Exception {
- super.setUp();
- ((ProjectViewImpl)ProjectView.getInstance(getProject())).setupImpl(null);
- }
-
- @Override
protected void runStartupActivities() {
FavoritesManager.getInstance(getProject()).projectOpened();
super.runStartupActivities();
diff --git a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterAlignmentTest.java b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterAlignmentTest.java
index c0902414d277..ac4aaa2bda42 100644
--- a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterAlignmentTest.java
+++ b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterAlignmentTest.java
@@ -350,7 +350,7 @@ public class JavaFormatterAlignmentTest extends AbstractJavaFormatterTest {
public void testChainedMethodCalls_WithChopDownIfLongOption() throws Exception {
getSettings().ALIGN_MULTILINE_CHAINED_METHODS = true;
getSettings().METHOD_CALL_CHAIN_WRAP = CommonCodeStyleSettings.WRAP_ON_EVERY_ITEM; // it's equal to "Chop down if long"
- getSettings().getRootSettings().RIGHT_MARGIN = 50;
+ getSettings().RIGHT_MARGIN = 50;
String before = "a.current.current.getThis().getThis().getThis().getThis().getThis();";
doMethodTest(
@@ -362,14 +362,14 @@ public class JavaFormatterAlignmentTest extends AbstractJavaFormatterTest {
" .getThis();"
);
- getSettings().getRootSettings().RIGHT_MARGIN = 80;
+ getSettings().RIGHT_MARGIN = 80;
doMethodTest(before, before);
}
public void testChainedMethodCalls_WithWrapIfNeededOption() throws Exception {
getSettings().ALIGN_MULTILINE_CHAINED_METHODS = false;
getSettings().METHOD_CALL_CHAIN_WRAP = CommonCodeStyleSettings.WRAP_AS_NEEDED;
- getSettings().getRootSettings().RIGHT_MARGIN = 50;
+ getSettings().RIGHT_MARGIN = 50;
String before = "a.current.current.getThis().getThis().getThis().getThis();";
@@ -387,7 +387,7 @@ public class JavaFormatterAlignmentTest extends AbstractJavaFormatterTest {
" .getThis().getThis();"
);
- getSettings().getRootSettings().RIGHT_MARGIN = 75;
+ getSettings().RIGHT_MARGIN = 75;
doMethodTest(before, before);
}
}
diff --git a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterBracesTest.java b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterBracesTest.java
index 52dc555c981b..582fc3a81a6a 100644
--- a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterBracesTest.java
+++ b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterBracesTest.java
@@ -158,7 +158,7 @@ public class JavaFormatterBracesTest extends AbstractJavaFormatterTest {
public void testSimpleMethodsInOneLineEvenIfExceedsRightMargin() {
getSettings().KEEP_SIMPLE_METHODS_IN_ONE_LINE = true;
- getSettings().getRootSettings().RIGHT_MARGIN = 90;
+ getSettings().RIGHT_MARGIN = 90;
String text = "public class Repr2 {\n" +
" public void start() { System.out.println(\"kfjsdkfjsdkfjskdjfslkdjfklsdjfklsdjfksjdfkljsdkfjsd!\"); }\n" +
"}";
@@ -242,4 +242,51 @@ public class JavaFormatterBracesTest extends AbstractJavaFormatterTest {
doMethodTest(singleLine, multiLine);
doMethodTest(multiLine, multiLine);
}
+
+ public void testMethodBraceOnNextLineIfWrapped() {
+ getSettings().METHOD_BRACE_STYLE = CommonCodeStyleSettings.NEXT_LINE_IF_WRAPPED;
+ getSettings().METHOD_PARAMETERS_WRAP = CommonCodeStyleSettings.WRAP_AS_NEEDED;
+ getSettings().RIGHT_MARGIN = 50;
+ doClassTest(
+ "public static void main(int state, int column, int width, int rate) {\n" +
+ "}\n",
+ "public static void main(int state, int column,\n" +
+ " int width, int rate)\n" +
+ "{\n" +
+ "}\n"
+ );
+ }
+
+ public void testIDEA127110() {
+ getSettings().KEEP_SIMPLE_BLOCKS_IN_ONE_LINE = true;
+ getSettings().BRACE_STYLE = CommonCodeStyleSettings.NEXT_LINE_IF_WRAPPED;
+ doMethodTest(
+ "if ( 1 > 2) {\n" +
+ "\n" +
+ "} else {\n" +
+ "\n" +
+ "}\n" +
+ "\n" +
+ "try {\n" +
+ "\n" +
+ "} catch ( Exception e) {\n" +
+ "\n" +
+ "} finally {\n" +
+ "\n" +
+ "}",
+ "if (1 > 2) {\n" +
+ "\n" +
+ "} else {\n" +
+ "\n" +
+ "}\n" +
+ "\n" +
+ "try {\n" +
+ "\n" +
+ "} catch (Exception e) {\n" +
+ "\n" +
+ "} finally {\n" +
+ "\n" +
+ "}"
+ );
+ }
}
diff --git a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterInEditorTest.java b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterInEditorTest.java
index ed79f2f60bc6..5749fe80b549 100644
--- a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterInEditorTest.java
+++ b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterInEditorTest.java
@@ -17,6 +17,7 @@ package com.intellij.psi.formatter.java;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.psi.codeStyle.CodeStyleManager;
+import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import com.intellij.testFramework.LightPlatformCodeInsightTestCase;
import org.jetbrains.annotations.NotNull;
@@ -32,8 +33,9 @@ public class JavaFormatterInEditorTest extends LightPlatformCodeInsightTestCase
public void testCaretPositionOnLongLineWrapping() throws IOException {
// Inspired by IDEA-70242
- getCurrentCodeStyleSettings().getCommonSettings(JavaLanguage.INSTANCE).WRAP_LONG_LINES = true;
- getCurrentCodeStyleSettings().RIGHT_MARGIN = 40;
+ CommonCodeStyleSettings javaCommonSettings = getCurrentCodeStyleSettings().getCommonSettings(JavaLanguage.INSTANCE);
+ javaCommonSettings.WRAP_LONG_LINES = true;
+ javaCommonSettings.RIGHT_MARGIN = 40;
doTest(
"import static java.util.concurrent.atomic.AtomicInteger.*;\n" +
"\n" +
diff --git a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterTest.java b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterTest.java
index c00db0fc77ad..0831f555fa29 100644
--- a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterTest.java
+++ b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterTest.java
@@ -15,6 +15,7 @@
*/
package com.intellij.psi.formatter.java;
+import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.fileTypes.StdFileTypes;
@@ -664,7 +665,7 @@ public class JavaFormatterTest extends AbstractJavaFormatterTest {
public void testParametersAlignment() throws Exception {
final CommonCodeStyleSettings settings = getSettings();
settings.ALIGN_MULTILINE_PARAMETERS_IN_CALLS = true;
- settings.getRootSettings().RIGHT_MARGIN = 140;
+ settings.RIGHT_MARGIN = 140;
doTest();
}
@@ -903,7 +904,7 @@ public class JavaFormatterTest extends AbstractJavaFormatterTest {
public void testBraceOnNewLineIfWrapped() throws Exception {
getSettings().BINARY_OPERATION_WRAP = CommonCodeStyleSettings.WRAP_AS_NEEDED;
getSettings().BRACE_STYLE = CommonCodeStyleSettings.NEXT_LINE_IF_WRAPPED;
- getSettings().getRootSettings().RIGHT_MARGIN = 35;
+ getSettings().RIGHT_MARGIN = 35;
getSettings().ALIGN_MULTILINE_BINARY_OPERATION = true;
doTextTest("class Foo {\n" +
@@ -928,7 +929,7 @@ public class JavaFormatterTest extends AbstractJavaFormatterTest {
}
public void testFirstArgumentWrapping() throws Exception {
- getSettings().getRootSettings().RIGHT_MARGIN = 20;
+ getSettings().RIGHT_MARGIN = 20;
getSettings().CALL_PARAMETERS_WRAP = CommonCodeStyleSettings.WRAP_AS_NEEDED;
doTextTest("class Foo {\n" + " void foo() {\n" + " fooFooFooFoo(1);" + " }\n" + "}",
"class Foo {\n" + " void foo() {\n" + " fooFooFooFoo(\n" + " 1);\n" + " }\n" + "}");
@@ -956,7 +957,7 @@ public class JavaFormatterTest extends AbstractJavaFormatterTest {
public void testAssertStatementWrapping() throws Exception {
getSettings().ASSERT_STATEMENT_WRAP = CommonCodeStyleSettings.WRAP_AS_NEEDED;
getSettings().BINARY_OPERATION_WRAP = CommonCodeStyleSettings.DO_NOT_WRAP;
- getSettings().getRootSettings().RIGHT_MARGIN = 40;
+ getSettings().RIGHT_MARGIN = 40;
final JavaPsiFacade facade = getJavaFacade();
final LanguageLevel effectiveLanguageLevel = LanguageLevelProjectExtension.getInstance(facade.getProject()).getLanguageLevel();
try {
@@ -1001,7 +1002,7 @@ public class JavaFormatterTest extends AbstractJavaFormatterTest {
public void testAssertStatementWrapping2() throws Exception {
getSettings().BINARY_OPERATION_WRAP = CommonCodeStyleSettings.DO_NOT_WRAP;
getSettings().ASSERT_STATEMENT_WRAP = CommonCodeStyleSettings.WRAP_AS_NEEDED;
- getSettings().getRootSettings().RIGHT_MARGIN = 37;
+ getSettings().RIGHT_MARGIN = 37;
final CommonCodeStyleSettings.IndentOptions options = getSettings().getRootSettings().getIndentOptions(StdFileTypes.JAVA);
options.INDENT_SIZE = 2;
@@ -1044,7 +1045,7 @@ public class JavaFormatterTest extends AbstractJavaFormatterTest {
public void test() throws Exception {
getSettings().getRootSettings().getIndentOptions(StdFileTypes.JAVA).INDENT_SIZE = 2;
getSettings().getRootSettings().getIndentOptions(StdFileTypes.JAVA).CONTINUATION_INDENT_SIZE = 2;
- getSettings().getRootSettings().RIGHT_MARGIN = 37;
+ getSettings().RIGHT_MARGIN = 37;
getSettings().ALIGN_MULTILINE_EXTENDS_LIST = true;
getSettings().EXTENDS_KEYWORD_WRAP = CommonCodeStyleSettings.WRAP_AS_NEEDED;
@@ -1081,7 +1082,7 @@ public class JavaFormatterTest extends AbstractJavaFormatterTest {
public void testLBrace() throws Exception {
getSettings().METHOD_BRACE_STYLE = CommonCodeStyleSettings.END_OF_LINE;
- getSettings().getRootSettings().RIGHT_MARGIN = 14;
+ getSettings().RIGHT_MARGIN = 14;
doTextTest("class Foo {\n" + " void foo() {\n" + " \n" + " }\n" + "}",
"class Foo {\n" + " void foo() {\n" + "\n" + " }\n" + "}");
}
@@ -1194,7 +1195,7 @@ public class JavaFormatterTest extends AbstractJavaFormatterTest {
public void testArrayInitializerWrapping() throws Exception {
getSettings().ARRAY_INITIALIZER_WRAP = CommonCodeStyleSettings.WRAP_AS_NEEDED;
getSettings().ALIGN_MULTILINE_ARRAY_INITIALIZER_EXPRESSION = false;
- getSettings().getRootSettings().RIGHT_MARGIN = 37;
+ getSettings().RIGHT_MARGIN = 37;
doTextTest("class Foo{\n" +
" public int[] i = new int[]{1,2,3,4,5,6,7,8,9};\n" +
@@ -1537,7 +1538,7 @@ public class JavaFormatterTest extends AbstractJavaFormatterTest {
getSettings().KEEP_CONTROL_STATEMENT_IN_ONE_LINE = true;
getSettings().KEEP_SIMPLE_METHODS_IN_ONE_LINE = true;
getSettings().ELSE_ON_NEW_LINE = false;
- getSettings().getRootSettings().RIGHT_MARGIN = 110;
+ getSettings().RIGHT_MARGIN = 110;
getSettings().KEEP_LINE_BREAKS = false;
doTextTest("class Foo {\n" +
" void foo() {\n" +
@@ -1698,7 +1699,7 @@ public class JavaFormatterTest extends AbstractJavaFormatterTest {
public void testDoNotWrapLBrace() throws IncorrectOperationException {
getSettings().BRACE_STYLE = CommonCodeStyleSettings.END_OF_LINE;
- getSettings().getRootSettings().RIGHT_MARGIN = 66;
+ getSettings().RIGHT_MARGIN = 66;
doTextTest("public class Test {\n" +
" void foo(){\n" +
" if (veryLongIdentifier1 == 1 && veryLongIdentifier2 == 2) {\n" +
@@ -1718,7 +1719,7 @@ public class JavaFormatterTest extends AbstractJavaFormatterTest {
getSettings().ARRAY_INITIALIZER_WRAP = CommonCodeStyleSettings.WRAP_AS_NEEDED;
getSettings().ARRAY_INITIALIZER_LBRACE_ON_NEXT_LINE = true;
getSettings().ARRAY_INITIALIZER_RBRACE_ON_NEXT_LINE = true;
- getSettings().getRootSettings().RIGHT_MARGIN = 40;
+ getSettings().RIGHT_MARGIN = 40;
doTextTest("class Foo {\n" + " int[] a = new int[]{1,2,0x0052,0x0053,0x0054,0x0054,0x0054};\n" + "}", "class Foo {\n" +
" int[] a = new int[]{\n" +
" 1, 2, 0x0052, 0x0053,\n" +
@@ -1768,7 +1769,7 @@ public class JavaFormatterTest extends AbstractJavaFormatterTest {
}
public void testWrapExtendsList() throws Exception {
- getSettings().getRootSettings().RIGHT_MARGIN = 50;
+ getSettings().RIGHT_MARGIN = 50;
getSettings().EXTENDS_LIST_WRAP = CommonCodeStyleSettings.WRAP_ON_EVERY_ITEM;
getSettings().EXTENDS_KEYWORD_WRAP = CommonCodeStyleSettings.WRAP_AS_NEEDED;
@@ -1779,7 +1780,7 @@ public class JavaFormatterTest extends AbstractJavaFormatterTest {
}
public void testWrapLongExpression() throws Exception {
- getSettings().getRootSettings().RIGHT_MARGIN = 80;
+ getSettings().RIGHT_MARGIN = 80;
getSettings().BINARY_OPERATION_WRAP = CommonCodeStyleSettings.WRAP_AS_NEEDED;
getSettings().ALIGN_MULTILINE_BINARY_OPERATION = true;
doTextTest("class Foo {\n" +
@@ -1797,7 +1798,7 @@ public class JavaFormatterTest extends AbstractJavaFormatterTest {
}
public void testDoNotWrapCallChainIfParametersWrapped() throws Exception {
- getSettings().getRootSettings().RIGHT_MARGIN = 87;
+ getSettings().RIGHT_MARGIN = 87;
getSettings().CALL_PARAMETERS_WRAP = CommonCodeStyleSettings.WRAP_AS_NEEDED;
getSettings().METHOD_CALL_CHAIN_WRAP = CommonCodeStyleSettings.WRAP_AS_NEEDED;
getSettings().ALIGN_MULTILINE_PARAMETERS_IN_CALLS = true;
@@ -1831,7 +1832,7 @@ public class JavaFormatterTest extends AbstractJavaFormatterTest {
}
public void testRightMargin_2() throws Exception {
- getSettings().getRootSettings().RIGHT_MARGIN = 65;
+ getSettings().RIGHT_MARGIN = 65;
getSettings().ASSIGNMENT_WRAP = CommonCodeStyleSettings.WRAP_AS_NEEDED;
getSettings().PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE = true;
getSettings().KEEP_LINE_BREAKS = false;
@@ -1844,7 +1845,7 @@ public class JavaFormatterTest extends AbstractJavaFormatterTest {
}
public void testRightMargin_3() throws Exception {
- getSettings().getRootSettings().RIGHT_MARGIN = 65;
+ getSettings().RIGHT_MARGIN = 65;
getSettings().ASSIGNMENT_WRAP = CommonCodeStyleSettings.WRAP_AS_NEEDED;
getSettings().PLACE_ASSIGNMENT_SIGN_ON_NEXT_LINE = false;
getSettings().KEEP_LINE_BREAKS = false;
@@ -1902,12 +1903,12 @@ public class JavaFormatterTest extends AbstractJavaFormatterTest {
public void testWrapParamsOnEveryItem() throws Exception {
CodeStyleSettings codeStyleSettings = CodeStyleSettingsManager.getSettings(getProject());
- int oldMargin = codeStyleSettings.RIGHT_MARGIN;
+ int oldMargin = codeStyleSettings.getCommonSettings(JavaLanguage.INSTANCE).RIGHT_MARGIN;
boolean oldKeep = codeStyleSettings.KEEP_LINE_BREAKS;
int oldWrap = codeStyleSettings.METHOD_PARAMETERS_WRAP;
try {
- codeStyleSettings.RIGHT_MARGIN = 80;
+ codeStyleSettings.setRightMargin(JavaLanguage.INSTANCE, 80);
codeStyleSettings.KEEP_LINE_BREAKS = false;
codeStyleSettings.METHOD_PARAMETERS_WRAP = CommonCodeStyleSettings.WRAP_ON_EVERY_ITEM;
@@ -1932,7 +1933,7 @@ public class JavaFormatterTest extends AbstractJavaFormatterTest {
"}");
}
finally {
- codeStyleSettings.RIGHT_MARGIN = oldMargin;
+ codeStyleSettings.setRightMargin(JavaLanguage.INSTANCE, oldMargin);
codeStyleSettings.KEEP_LINE_BREAKS = oldKeep;
codeStyleSettings.METHOD_PARAMETERS_WRAP = oldWrap;
}
@@ -1942,10 +1943,10 @@ public class JavaFormatterTest extends AbstractJavaFormatterTest {
public void testCommentAfterDeclaration() throws Exception {
CodeStyleSettings codeStyleSettings = CodeStyleSettingsManager.getSettings(getProject());
- int oldMargin = codeStyleSettings.RIGHT_MARGIN;
+ int oldMargin = codeStyleSettings.getDefaultRightMargin();
try {
- codeStyleSettings.RIGHT_MARGIN = 20;
+ codeStyleSettings.setDefaultRightMargin(20);
codeStyleSettings.ASSIGNMENT_WRAP = CommonCodeStyleSettings.WRAP_AS_NEEDED;
doMethodTest(
"int i=0; //comment comment",
@@ -1955,7 +1956,7 @@ public class JavaFormatterTest extends AbstractJavaFormatterTest {
}
finally {
- codeStyleSettings.RIGHT_MARGIN = oldMargin;
+ codeStyleSettings.setDefaultRightMargin(oldMargin);
}
}
@@ -2106,7 +2107,7 @@ public void testSCR260() throws Exception {
public void testSCR479() throws Exception {
final CommonCodeStyleSettings settings = getSettings();
- settings.getRootSettings().RIGHT_MARGIN = 80;
+ settings.RIGHT_MARGIN = 80;
settings.TERNARY_OPERATION_WRAP = CommonCodeStyleSettings.WRAP_AS_NEEDED;
doTextTest("public class Foo {\n" +
" public static void main(String[] args) {\n" +
@@ -2190,7 +2191,7 @@ public void testSCR260() throws Exception {
}
public void test1607() throws Exception {
- getSettings().getRootSettings().RIGHT_MARGIN = 30;
+ getSettings().RIGHT_MARGIN = 30;
getSettings().METHOD_BRACE_STYLE = CommonCodeStyleSettings.NEXT_LINE;
getSettings().KEEP_SIMPLE_METHODS_IN_ONE_LINE = true;
getSettings().ALIGN_MULTILINE_PARAMETERS = true;
@@ -2271,7 +2272,7 @@ public void testSCR260() throws Exception {
getSettings().METHOD_CALL_CHAIN_WRAP = CommonCodeStyleSettings.WRAP_AS_NEEDED;
getSettings().CALL_PARAMETERS_WRAP = CommonCodeStyleSettings.WRAP_AS_NEEDED;
getSettings().ALIGN_MULTILINE_PARAMETERS_IN_CALLS = true;
- getSettings().getRootSettings().RIGHT_MARGIN = 80;
+ getSettings().RIGHT_MARGIN = 80;
getSettings().PREFER_PARAMETERS_WRAP = true;
@@ -2392,7 +2393,7 @@ public void testSCR260() throws Exception {
}
public void test1980() throws Exception {
- getSettings().getRootSettings().RIGHT_MARGIN = 144;
+ getSettings().RIGHT_MARGIN = 144;
getSettings().TERNARY_OPERATION_WRAP = CommonCodeStyleSettings.WRAP_ON_EVERY_ITEM;
getSettings().METHOD_CALL_CHAIN_WRAP = CommonCodeStyleSettings.WRAP_AS_NEEDED;
getSettings().ALIGN_MULTILINE_TERNARY_OPERATION = true;
@@ -2523,7 +2524,7 @@ public void testSCR260() throws Exception {
public void testSCRIDEA_4783() throws IncorrectOperationException {
getSettings().ASSIGNMENT_WRAP = CommonCodeStyleSettings.WRAP_AS_NEEDED;
getSettings().METHOD_CALL_CHAIN_WRAP = CommonCodeStyleSettings.WRAP_AS_NEEDED;
- getSettings().getRootSettings().RIGHT_MARGIN = 80;
+ getSettings().RIGHT_MARGIN = 80;
doTextTest("class Foo{\n" +
" void foo() {\n" +
@@ -2655,7 +2656,7 @@ public void testSCR260() throws Exception {
doTextTest("class Foo {\n" + " void foo() {\n" + " while(true) foo();\n" + " }\n" + "}",
"class Foo {\n" + " void foo() {\n" + " while (true) foo();\n" + " }\n" + "}");
- getSettings().getRootSettings().RIGHT_MARGIN = 17;
+ getSettings().RIGHT_MARGIN = 17;
doTextTest("class Foo {\n" + " void foo() {\n" + " if (a) foo();\n" + " else bar();\n" + " }\n" + "}",
"class Foo {\n" +
@@ -2667,7 +2668,7 @@ public void testSCR260() throws Exception {
" }\n" +
"}");
- getSettings().getRootSettings().RIGHT_MARGIN = 30;
+ getSettings().RIGHT_MARGIN = 30;
doTextTest("class Foo {\n" + " void foo() {\n" + " for (int i = 0; i < 10; i++) foo();\n" + " }\n" + "}",
"class Foo {\n" +
@@ -2677,12 +2678,12 @@ public void testSCR260() throws Exception {
" }\n" +
"}");
- getSettings().getRootSettings().RIGHT_MARGIN = 32;
+ getSettings().RIGHT_MARGIN = 32;
doTextTest("class Foo {\n" + " void foo() {\n" + " for (int var : vars) foo();\n" + " }\n" + "}",
"class Foo {\n" + " void foo() {\n" + " for (int var : vars)\n" + " foo();\n" + " }\n" + "}");
- getSettings().getRootSettings().RIGHT_MARGIN = 12;
+ getSettings().RIGHT_MARGIN = 12;
doTextTest("class Foo {\n" + " void foo() {\n" + " do foo(); while (true);\n" + " }\n" + "}", "class Foo {\n" +
" void foo() {\n" +
" do\n" +
@@ -2691,7 +2692,7 @@ public void testSCR260() throws Exception {
" }\n" +
"}");
- getSettings().getRootSettings().RIGHT_MARGIN = 23;
+ getSettings().RIGHT_MARGIN = 23;
doTextTest("class Foo {\n" + " void foo() {\n" + " while(true) foo();\n" + " }\n" + "}",
"class Foo {\n" + " void foo() {\n" + " while (true)\n" + " foo();\n" + " }\n" + "}");
@@ -2807,7 +2808,7 @@ public void testSCR260() throws Exception {
public void testIDEADEV_12836() throws IncorrectOperationException {
getSettings().SPECIAL_ELSE_IF_TREATMENT = true;
- getSettings().getRootSettings().RIGHT_MARGIN = 80;
+ getSettings().RIGHT_MARGIN = 80;
doTextTest("class Foo {\n" +
"void foo(){\n" +
"if (true){\n" +
@@ -2886,7 +2887,7 @@ public void testSCR260() throws Exception {
public void testIDEADEV_23551() throws IncorrectOperationException {
getSettings().BINARY_OPERATION_WRAP = CommonCodeStyleSettings.WRAP_ON_EVERY_ITEM;
- getSettings().getRootSettings().RIGHT_MARGIN = 60;
+ getSettings().RIGHT_MARGIN = 60;
doTextTest("public class Wrapping {\n" +
"public static void sample() {\n" +
"System.out.println(\".\" + File.separator + \"..\" + File.separator + \"some-directory-name\" + File.separator + \"more-file-name\");\n" +
diff --git a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterWrapTest.java b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterWrapTest.java
index 512a7ef3c158..c06370b06743 100644
--- a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterWrapTest.java
+++ b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterWrapTest.java
@@ -32,7 +32,7 @@ import java.util.Calendar;
public class JavaFormatterWrapTest extends AbstractJavaFormatterTest {
@SuppressWarnings("SpellCheckingInspection")
public void testWrappingAnnotationArrayParameters() {
- getSettings().getRootSettings().RIGHT_MARGIN = 80;
+ getSettings().RIGHT_MARGIN = 80;
getSettings().ARRAY_INITIALIZER_WRAP = CommonCodeStyleSettings.WRAP_AS_NEEDED;
doTextTest(
"@AttributeOverrides( { @AttributeOverride(name = \"id\", column = @Column(name = \"recovery_id\"))," +
@@ -64,7 +64,7 @@ public class JavaFormatterWrapTest extends AbstractJavaFormatterTest {
public void testAnnotationParamValueExceedingRightMargin() {
// Inspired by IDEA-18051
- getSettings().getRootSettings().RIGHT_MARGIN = 80;
+ getSettings().RIGHT_MARGIN = 80;
doTextTest(
"package formatting;\n" +
"\n" +
@@ -128,7 +128,7 @@ public class JavaFormatterWrapTest extends AbstractJavaFormatterTest {
public void testEnumConstantsWrapping() {
// Inspired by IDEA-54667
getSettings().ENUM_CONSTANTS_WRAP = CommonCodeStyleSettings.WRAP_AS_NEEDED;
- getSettings().getRootSettings().RIGHT_MARGIN = 80;
+ getSettings().RIGHT_MARGIN = 80;
// Don't expect the constants to be placed on new line.
doTextTest(
@@ -177,8 +177,8 @@ public class JavaFormatterWrapTest extends AbstractJavaFormatterTest {
public void testWrapCompoundStringLiteralThatEndsAtRightMargin() {
// Inspired by IDEA-82398
- getSettings().getRootSettings().RIGHT_MARGIN = 30;
- getSettings().getRootSettings().getCommonSettings(JavaLanguage.INSTANCE).WRAP_LONG_LINES = true;
+ getSettings().RIGHT_MARGIN = 30;
+ getSettings().WRAP_LONG_LINES = true;
final String text = "class Test {\n" +
" String s = \"first line \" +\n" +
@@ -189,8 +189,8 @@ public class JavaFormatterWrapTest extends AbstractJavaFormatterTest {
public void testWrapLongLine() {
// Inspired by IDEA-55782
- getSettings().getRootSettings().RIGHT_MARGIN = 50;
- getSettings().getRootSettings().getCommonSettings(JavaLanguage.INSTANCE).WRAP_LONG_LINES = true;
+ getSettings().RIGHT_MARGIN = 50;
+ getSettings().WRAP_LONG_LINES = true;
doTextTest(
"class TestClass {\n" +
@@ -218,8 +218,8 @@ public class JavaFormatterWrapTest extends AbstractJavaFormatterTest {
public void testWrapLongLineWithTabs() {
// Inspired by IDEA-55782
- getSettings().getRootSettings().RIGHT_MARGIN = 20;
- getSettings().getRootSettings().getCommonSettings(JavaLanguage.INSTANCE).WRAP_LONG_LINES = true;
+ getSettings().RIGHT_MARGIN = 20;
+ getSettings().WRAP_LONG_LINES = true;
getIndentOptions().USE_TAB_CHARACTER = true;
getIndentOptions().TAB_SIZE = 4;
@@ -236,8 +236,8 @@ public class JavaFormatterWrapTest extends AbstractJavaFormatterTest {
public void testWrapLongLineWithSelection() {
// Inspired by IDEA-55782
- getSettings().getRootSettings().RIGHT_MARGIN = 20;
- getSettings().getRootSettings().getCommonSettings(JavaLanguage.INSTANCE).WRAP_LONG_LINES = true;
+ getSettings().RIGHT_MARGIN = 20;
+ getSettings().WRAP_LONG_LINES = true;
String initial =
"class TestClass {\n" +
@@ -264,7 +264,7 @@ public class JavaFormatterWrapTest extends AbstractJavaFormatterTest {
@Bombed(user = "Roman Shevchenko", year = 2014, month = Calendar.MARCH, day = 14)
public void testWrapMethodAnnotationBeforeParams() {
// Inspired by IDEA-59536
- getSettings().getRootSettings().RIGHT_MARGIN = 90;
+ getSettings().RIGHT_MARGIN = 90;
getSettings().METHOD_ANNOTATION_WRAP = CommonCodeStyleSettings.WRAP_AS_NEEDED;
getSettings().METHOD_PARAMETERS_WRAP = CommonCodeStyleSettings.WRAP_AS_NEEDED;
@@ -304,7 +304,7 @@ public class JavaFormatterWrapTest extends AbstractJavaFormatterTest {
public void testResourceListWrap() {
getSettings().KEEP_SIMPLE_BLOCKS_IN_ONE_LINE = true;
- getSettings().getRootSettings().RIGHT_MARGIN = 40;
+ getSettings().RIGHT_MARGIN = 40;
getSettings().RESOURCE_LIST_WRAP = CommonCodeStyleSettings.WRAP_AS_NEEDED;
doMethodTest("try (MyResource r1 = null; MyResource r2 = null) { }",
"try (MyResource r1 = null;\n" +
@@ -323,7 +323,7 @@ public class JavaFormatterWrapTest extends AbstractJavaFormatterTest {
public void testLineLongEnoughToExceedAfterFirstWrapping() {
// Inspired by IDEA-103624
getSettings().WRAP_LONG_LINES = true;
- getSettings().getRootSettings().RIGHT_MARGIN = 40;
+ getSettings().RIGHT_MARGIN = 40;
getSettings().ALIGN_MULTILINE_PARAMETERS_IN_CALLS = true;
doMethodTest(
"test(1,\n" +
@@ -344,7 +344,7 @@ public class JavaFormatterWrapTest extends AbstractJavaFormatterTest {
public void testNoUnnecessaryWrappingIsPerformedForLongLine() {
// Inspired by IDEA-103624
getSettings().WRAP_LONG_LINES = true;
- getSettings().getRootSettings().RIGHT_MARGIN = 40;
+ getSettings().RIGHT_MARGIN = 40;
getSettings().ALIGN_MULTILINE_PARAMETERS_IN_CALLS = true;
String text =
"test(1,\n" +
@@ -359,7 +359,7 @@ public class JavaFormatterWrapTest extends AbstractJavaFormatterTest {
public void testEnforceIndentMethodCallParamWrap() {
getSettings().WRAP_LONG_LINES = true;
- getSettings().getRootSettings().RIGHT_MARGIN = 140;
+ getSettings().RIGHT_MARGIN = 140;
getSettings().PREFER_PARAMETERS_WRAP = true;
getSettings().CALL_PARAMETERS_WRAP = CommonCodeStyleSettings.WRAP_ON_EVERY_ITEM;
@@ -402,7 +402,7 @@ public class JavaFormatterWrapTest extends AbstractJavaFormatterTest {
@SuppressWarnings("SpellCheckingInspection")
public void testDoNotWrapMethodsWithMethodCallAsParameters() {
getSettings().WRAP_LONG_LINES = true;
- getSettings().getRootSettings().RIGHT_MARGIN = 140;
+ getSettings().RIGHT_MARGIN = 140;
getSettings().PREFER_PARAMETERS_WRAP = true;
getSettings().CALL_PARAMETERS_WRAP = CommonCodeStyleSettings.WRAP_ON_EVERY_ITEM;
getSettings().CALL_PARAMETERS_RPAREN_ON_NEXT_LINE = true;
diff --git a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavadocFormatterTest.java b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavadocFormatterTest.java
index a1819a263617..ad3ad822d83e 100644
--- a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavadocFormatterTest.java
+++ b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavadocFormatterTest.java
@@ -28,8 +28,8 @@ import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
public class JavadocFormatterTest extends AbstractJavaFormatterTest {
public void testRightMargin() throws Exception {
- getSettings().getRootSettings().getCommonSettings(JavaLanguage.INSTANCE).WRAP_LONG_LINES = true;
- getSettings().getRootSettings().RIGHT_MARGIN = 35;// |
+ getSettings().WRAP_LONG_LINES = true;
+ getSettings().RIGHT_MARGIN = 35;
doTextTest(
"/** Here is one-line java-doc comment */" +
"class Foo {\n" +
@@ -44,9 +44,9 @@ public class JavadocFormatterTest extends AbstractJavaFormatterTest {
}
public void testEA49739() throws Exception {
- getSettings().getRootSettings().getCommonSettings(JavaLanguage.INSTANCE).WRAP_LONG_LINES = true;
- getSettings().getRootSettings().RIGHT_MARGIN = 35;
- getSettings().getRootSettings().WRAP_COMMENTS = true;
+ getSettings().WRAP_LONG_LINES = true;
+ getSettings().RIGHT_MARGIN = 35;
+ getSettings().WRAP_COMMENTS = true;
doTextTest("class A {\n" +
" /**\n" +
" * @return a is one line javadoc\n" +
@@ -70,7 +70,7 @@ public class JavadocFormatterTest extends AbstractJavaFormatterTest {
getSettings().getRootSettings().WRAP_COMMENTS = true;
getSettings().getRootSettings().ENABLE_JAVADOC_FORMATTING = true;
getSettings().getRootSettings().JD_DO_NOT_WRAP_ONE_LINE_COMMENTS = true;
- getSettings().getRootSettings().RIGHT_MARGIN = 35;
+ getSettings().RIGHT_MARGIN = 35;
doTextTest(
"/** Here is one-line java-doc comment */" +
"class Foo {\n" +
@@ -87,7 +87,7 @@ public class JavadocFormatterTest extends AbstractJavaFormatterTest {
// Inspired by IDEA-61895
getSettings().getRootSettings().WRAP_COMMENTS = true;
getSettings().getRootSettings().JD_PRESERVE_LINE_FEEDS = true;
- getSettings().getRootSettings().RIGHT_MARGIN = 48;
+ getSettings().RIGHT_MARGIN = 48;
doTextTest(
"/**\n" +
@@ -108,7 +108,7 @@ public class JavadocFormatterTest extends AbstractJavaFormatterTest {
public void testSCR11296() throws Exception {
final CommonCodeStyleSettings settings = getSettings();
- settings.getRootSettings().RIGHT_MARGIN = 50;
+ settings.RIGHT_MARGIN = 50;
settings.getRootSettings().WRAP_COMMENTS = true;
settings.getRootSettings().ENABLE_JAVADOC_FORMATTING = true;
settings.getRootSettings().JD_P_AT_EMPTY_LINES = false;
@@ -119,7 +119,7 @@ public class JavadocFormatterTest extends AbstractJavaFormatterTest {
public void testSCR2632() throws Exception {
getSettings().getRootSettings().ENABLE_JAVADOC_FORMATTING = true;
getSettings().getRootSettings().WRAP_COMMENTS = true;
- getSettings().getRootSettings().RIGHT_MARGIN = 20;
+ getSettings().RIGHT_MARGIN = 20;
LanguageLevelProjectExtension.getInstance(getProject()).setLanguageLevel(LanguageLevel.JDK_1_7);
doTextTest("/**\n" + " * <p />\n" + " * Another paragraph of the description placed after blank line.\n" + " */\n" + "class A{}",
@@ -137,7 +137,7 @@ public class JavadocFormatterTest extends AbstractJavaFormatterTest {
public void testSCR2632_JDK8_LanguageLevel() throws Exception {
getSettings().getRootSettings().ENABLE_JAVADOC_FORMATTING = true;
getSettings().getRootSettings().WRAP_COMMENTS = true;
- getSettings().getRootSettings().RIGHT_MARGIN = 20;
+ getSettings().RIGHT_MARGIN = 20;
LanguageLevelProjectExtension.getInstance(getProject()).setLanguageLevel(LanguageLevel.JDK_1_8);
doTextTest("/**\n" + " * <p />\n" + " * Another paragraph of the description placed after blank line.\n" + " */\n" + "class A{}",
@@ -355,7 +355,7 @@ public class JavadocFormatterTest extends AbstractJavaFormatterTest {
public void testReturnTagAlignment() throws Exception {
getSettings().getRootSettings().ENABLE_JAVADOC_FORMATTING = true;
- getSettings().getRootSettings().RIGHT_MARGIN = 80;
+ getSettings().RIGHT_MARGIN = 80;
getSettings().getRootSettings().JD_LEADING_ASTERISKS_ARE_ENABLED = true;
getSettings().getRootSettings().WRAP_COMMENTS = true;
getSettings().getRootSettings().getCommonSettings(JavaLanguage.INSTANCE).WRAP_LONG_LINES = true;
@@ -383,7 +383,7 @@ public class JavadocFormatterTest extends AbstractJavaFormatterTest {
public void testReturnTagAlignmentWithPreTagOnFirstLine() throws Exception {
getSettings().getRootSettings().ENABLE_JAVADOC_FORMATTING = true;
- getSettings().getRootSettings().RIGHT_MARGIN = 80;
+ getSettings().RIGHT_MARGIN = 80;
getSettings().getRootSettings().JD_LEADING_ASTERISKS_ARE_ENABLED = true;
getSettings().getRootSettings().WRAP_COMMENTS = true;
getSettings().getRootSettings().getCommonSettings(JavaLanguage.INSTANCE).WRAP_LONG_LINES = true;
@@ -410,7 +410,7 @@ public class JavadocFormatterTest extends AbstractJavaFormatterTest {
public void testSeeTagAlignment() throws Exception {
getSettings().getRootSettings().ENABLE_JAVADOC_FORMATTING = true;
- getSettings().getRootSettings().RIGHT_MARGIN = 80;
+ getSettings().RIGHT_MARGIN = 80;
getSettings().getRootSettings().JD_LEADING_ASTERISKS_ARE_ENABLED = true;
getSettings().getRootSettings().WRAP_COMMENTS = true;
getSettings().getRootSettings().getCommonSettings(JavaLanguage.INSTANCE).WRAP_LONG_LINES = true;
@@ -437,7 +437,7 @@ public class JavadocFormatterTest extends AbstractJavaFormatterTest {
public void testDummySinceTagAlignment() throws Exception {
getSettings().getRootSettings().ENABLE_JAVADOC_FORMATTING = true;
- getSettings().getRootSettings().RIGHT_MARGIN = 80;
+ getSettings().RIGHT_MARGIN = 80;
getSettings().getRootSettings().JD_LEADING_ASTERISKS_ARE_ENABLED = true;
getSettings().getRootSettings().WRAP_COMMENTS = true;
getSettings().getRootSettings().getCommonSettings(JavaLanguage.INSTANCE).WRAP_LONG_LINES = true;
@@ -464,7 +464,7 @@ public class JavadocFormatterTest extends AbstractJavaFormatterTest {
public void testDummyDeprecatedTagAlignment() throws Exception {
getSettings().getRootSettings().ENABLE_JAVADOC_FORMATTING = true;
- getSettings().getRootSettings().RIGHT_MARGIN = 80;
+ getSettings().RIGHT_MARGIN = 80;
getSettings().getRootSettings().JD_LEADING_ASTERISKS_ARE_ENABLED = true;
getSettings().getRootSettings().WRAP_COMMENTS = true;
getSettings().getRootSettings().getCommonSettings(JavaLanguage.INSTANCE).WRAP_LONG_LINES = true;
@@ -490,7 +490,7 @@ public class JavadocFormatterTest extends AbstractJavaFormatterTest {
}
public void testJavadocFormattingIndependentOfMethodIndentation() {
- getCurrentCodeStyleSettings().RIGHT_MARGIN = 50;
+ getCurrentCodeStyleSettings().setRightMargin(JavaLanguage.INSTANCE, 50);
getCurrentCodeStyleSettings().ENABLE_JAVADOC_FORMATTING = true;
getCurrentCodeStyleSettings().WRAP_COMMENTS = true;
getCurrentCodeStyleSettings().JD_LEADING_ASTERISKS_ARE_ENABLED = true;
@@ -529,7 +529,7 @@ public class JavadocFormatterTest extends AbstractJavaFormatterTest {
}
public void testJavadocAlignmentForInnerClasses() {
- getCurrentCodeStyleSettings().RIGHT_MARGIN = 40;
+ getCurrentCodeStyleSettings().setRightMargin(JavaLanguage.INSTANCE, 40);
getCurrentCodeStyleSettings().ENABLE_JAVADOC_FORMATTING = true;
getCurrentCodeStyleSettings().WRAP_COMMENTS = true;
getCurrentCodeStyleSettings().JD_LEADING_ASTERISKS_ARE_ENABLED = true;
@@ -579,7 +579,7 @@ public class JavadocFormatterTest extends AbstractJavaFormatterTest {
}
public void testAlignmentWithNoTopClassMembersIndentation() {
- getCurrentCodeStyleSettings().RIGHT_MARGIN = 40;
+ getCurrentCodeStyleSettings().setRightMargin(JavaLanguage.INSTANCE, 40);
getCurrentCodeStyleSettings().WRAP_COMMENTS = true;
getCurrentCodeStyleSettings().JD_LEADING_ASTERISKS_ARE_ENABLED = true;
getCurrentCodeStyleSettings().getCommonSettings(JavaLanguage.INSTANCE).DO_NOT_INDENT_TOP_LEVEL_CLASS_MEMBERS = true;
@@ -655,7 +655,7 @@ public class JavadocFormatterTest extends AbstractJavaFormatterTest {
public void testDoNotWrapLongLineCommentWithSpaceInStart() throws Exception {
getSettings().KEEP_FIRST_COLUMN_COMMENT = true;
getSettings().WRAP_LONG_LINES = true;
- getSettings().getRootSettings().RIGHT_MARGIN = 200;
+ getSettings().RIGHT_MARGIN = 200;
String before = "public class JiraIssue {\n" +
"\n" +
" public static void main(String[] args) {\n" +
diff --git a/java/jdkAnnotations/java/awt/annotations.xml b/java/jdkAnnotations/java/awt/annotations.xml
index a1ea3a596052..50d1f16ca819 100644
--- a/java/jdkAnnotations/java/awt/annotations.xml
+++ b/java/jdkAnnotations/java/awt/annotations.xml
@@ -71,6 +71,9 @@
<item name="java.awt.CardLayout void show(java.awt.Container, java.lang.String) 1">
<annotation name="org.jetbrains.annotations.NonNls" />
</item>
+ <item name='java.awt.Component java.awt.Cursor getCursor()'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
<item name='java.awt.Component java.awt.Point getLocation()'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
@@ -99,6 +102,9 @@
<val name="valuesFromClass" val="java.awt.Cursor.class" />
</annotation>
</item>
+ <item name='java.awt.Cursor java.awt.Cursor getPredefinedCursor(int)'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
<item name="java.awt.Cursor java.awt.Cursor getPredefinedCursor(int) 0">
<annotation name="org.intellij.lang.annotations.MagicConstant">
<val name="valuesFromClass" val="java.awt.Cursor.class" />
diff --git a/java/jdkAnnotations/java/util/annotations.xml b/java/jdkAnnotations/java/util/annotations.xml
index 330f7a4d0e23..7e499f6ea9a2 100644
--- a/java/jdkAnnotations/java/util/annotations.xml
+++ b/java/jdkAnnotations/java/util/annotations.xml
@@ -1120,15 +1120,24 @@
<item name='java.util.ResourceBundle boolean containsKey(java.lang.String) 0'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
+ <item name='java.util.ResourceBundle java.lang.Object getObject(java.lang.String)'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
<item name='java.util.ResourceBundle java.lang.Object getObject(java.lang.String) 0'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item name='java.util.ResourceBundle java.lang.Object handleGetObject(java.lang.String) 0'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
+ <item name='java.util.ResourceBundle java.lang.String getString(java.lang.String)'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
<item name='java.util.ResourceBundle java.lang.String getString(java.lang.String) 0'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
+ <item name='java.util.ResourceBundle java.lang.String[] getStringArray(java.lang.String)'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
<item name='java.util.ResourceBundle java.lang.String[] getStringArray(java.lang.String) 0'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
diff --git a/java/jdkAnnotations/java/util/concurrent/atomic/annotations.xml b/java/jdkAnnotations/java/util/concurrent/atomic/annotations.xml
new file mode 100644
index 000000000000..dabc2661cad8
--- /dev/null
+++ b/java/jdkAnnotations/java/util/concurrent/atomic/annotations.xml
@@ -0,0 +1,36 @@
+<root>
+ <item name='java.util.concurrent.atomic.AtomicReferenceFieldUpdater V get(T) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.concurrent.atomic.AtomicReferenceFieldUpdater V getAndSet(T, V) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.concurrent.atomic.AtomicReferenceFieldUpdater boolean compareAndSet(T, V, V) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.concurrent.atomic.AtomicReferenceFieldUpdater boolean weakCompareAndSet(T, V, V) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item
+ name='java.util.concurrent.atomic.AtomicReferenceFieldUpdater java.util.concurrent.atomic.AtomicReferenceFieldUpdater&lt;U,W&gt; newUpdater(java.lang.Class&lt;U&gt;, java.lang.Class&lt;W&gt;, java.lang.String)'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item
+ name='java.util.concurrent.atomic.AtomicReferenceFieldUpdater java.util.concurrent.atomic.AtomicReferenceFieldUpdater&lt;U,W&gt; newUpdater(java.lang.Class&lt;U&gt;, java.lang.Class&lt;W&gt;, java.lang.String) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item
+ name='java.util.concurrent.atomic.AtomicReferenceFieldUpdater java.util.concurrent.atomic.AtomicReferenceFieldUpdater&lt;U,W&gt; newUpdater(java.lang.Class&lt;U&gt;, java.lang.Class&lt;W&gt;, java.lang.String) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item
+ name='java.util.concurrent.atomic.AtomicReferenceFieldUpdater java.util.concurrent.atomic.AtomicReferenceFieldUpdater&lt;U,W&gt; newUpdater(java.lang.Class&lt;U&gt;, java.lang.Class&lt;W&gt;, java.lang.String) 2'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.concurrent.atomic.AtomicReferenceFieldUpdater void lazySet(T, V) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.concurrent.atomic.AtomicReferenceFieldUpdater void set(T, V) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+</root> \ No newline at end of file
diff --git a/java/jsp-base-openapi/src/com/intellij/lang/jsp/JspVersion.java b/java/jsp-base-openapi/src/com/intellij/lang/jsp/JspVersion.java
index 7e5416d69b93..932104d52df2 100644
--- a/java/jsp-base-openapi/src/com/intellij/lang/jsp/JspVersion.java
+++ b/java/jsp-base-openapi/src/com/intellij/lang/jsp/JspVersion.java
@@ -65,6 +65,8 @@ public interface JspVersion {
}
};
+ JspVersion MAX_VERSION = JSP_2_3;
+
String getNumber();
boolean betterThan(JspVersion other);
diff --git a/java/manifest/test/org/jetbrains/lang/manifest/ManifestCompletionTest.java b/java/manifest/test/org/jetbrains/lang/manifest/ManifestCompletionTest.java
index a0f1bb998710..a52a4c564933 100644
--- a/java/manifest/test/org/jetbrains/lang/manifest/ManifestCompletionTest.java
+++ b/java/manifest/test/org/jetbrains/lang/manifest/ManifestCompletionTest.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,14 +19,14 @@ import com.intellij.codeInsight.completion.LightCompletionTestCase;
import com.intellij.testFramework.LightPlatformCodeInsightTestCase;
public class ManifestCompletionTest extends LightCompletionTestCase {
- public void testHeaderNameCompletionVariants() throws Exception {
+ public void testHeaderNameCompletionVariants() {
LightPlatformCodeInsightTestCase.configureFromFileText("MANIFEST.MF", "Specification-V<caret>\n");
complete();
assertContainsItems("Specification-Vendor", "Specification-Version");
assertNotContainItems("Specification-Title");
}
- public void testHeaderNameEnterCompletion() throws Exception {
+ public void testHeaderNameEnterCompletion() {
LightPlatformCodeInsightTestCase.configureFromFileText("MANIFEST.MF", "Specification-V<caret>\n");
complete();
assertContainsItems("Specification-Vendor");
@@ -34,7 +34,7 @@ public class ManifestCompletionTest extends LightCompletionTestCase {
checkResultByText("Specification-Vendor: <caret>\n");
}
- public void testHeaderNameColonCompletion() throws Exception {
+ public void testHeaderNameColonCompletion() {
LightPlatformCodeInsightTestCase.configureFromFileText("MANIFEST.MF", "Specification-V<caret>\n");
complete();
assertContainsItems("Specification-Vendor");
@@ -42,7 +42,7 @@ public class ManifestCompletionTest extends LightCompletionTestCase {
checkResultByText("Specification-Vendor: <caret>\n");
}
- public void testHeaderNameSpaceCompletion() throws Exception {
+ public void testHeaderNameSpaceCompletion() {
LightPlatformCodeInsightTestCase.configureFromFileText("MANIFEST.MF", "Specification-V<caret>\n");
complete();
assertContainsItems("Specification-Vendor");
diff --git a/java/mockJDK-1.8/jre/lib/rt.jar b/java/mockJDK-1.8/jre/lib/rt.jar
index db566fc40076..f3a4f893f3d4 100644
--- a/java/mockJDK-1.8/jre/lib/rt.jar
+++ b/java/mockJDK-1.8/jre/lib/rt.jar
Binary files differ
diff --git a/java/openapi/src/com/intellij/util/xml/ClassMappingNameConverter.java b/java/openapi/src/com/intellij/util/xml/ClassMappingNameConverter.java
index 609605b32a25..1e296e4d3523 100644
--- a/java/openapi/src/com/intellij/util/xml/ClassMappingNameConverter.java
+++ b/java/openapi/src/com/intellij/util/xml/ClassMappingNameConverter.java
@@ -26,6 +26,7 @@ import com.intellij.psi.codeStyle.VariableKind;
import com.intellij.psi.util.PsiTypesUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.Collection;
@@ -77,4 +78,12 @@ public class ClassMappingNameConverter extends ResolvingConverter.StringConverte
assert parent != null;
return parent.getXmlElement();
}
+
+ @Override
+ public boolean isReferenceTo(@NotNull PsiElement element,
+ String stringValue,
+ @Nullable String resolveResult,
+ ConvertContext context) {
+ return element.getManager().areElementsEquivalent(element, resolve(stringValue, context));
+ }
}
diff --git a/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaStructuralSearchProfile.java b/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaStructuralSearchProfile.java
index 869f01cc7394..acc59abd67da 100644
--- a/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaStructuralSearchProfile.java
+++ b/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaStructuralSearchProfile.java
@@ -67,6 +67,7 @@ public class JavaStructuralSearchProfile extends StructuralSearchProfile {
}
}
+ @NotNull
public String getTypedVarString(final PsiElement element) {
String text;
diff --git a/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/JavaMatchingVisitor.java b/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/JavaMatchingVisitor.java
index 0ea857b16362..418bc06d3b9e 100644
--- a/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/JavaMatchingVisitor.java
+++ b/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/JavaMatchingVisitor.java
@@ -90,19 +90,6 @@ public class JavaMatchingVisitor extends JavaElementVisitor {
}
}
- @Override
- public void visitDocTagValue(final PsiDocTagValue value) {
- final PsiDocTagValue value2 = (PsiDocTagValue)myMatchingVisitor.getElement();
- final boolean isTypedVar = myMatchingVisitor.getMatchContext().getPattern().isTypedVar(value);
-
- if (isTypedVar) {
- myMatchingVisitor.setResult(myMatchingVisitor.handleTypedElement(value, value2));
- }
- else {
- myMatchingVisitor.setResult(value.textMatches(value2));
- }
- }
-
private static boolean isNotInstanceModifier(final PsiModifierList list2) {
return list2.hasModifierProperty(PsiModifier.STATIC) ||
list2.hasModifierProperty(PsiModifier.ABSTRACT);
diff --git a/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/compiler/JavaCompilingVisitor.java b/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/compiler/JavaCompilingVisitor.java
index 271f1c468b0b..18c252d28111 100644
--- a/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/compiler/JavaCompilingVisitor.java
+++ b/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/compiler/JavaCompilingVisitor.java
@@ -1,20 +1,17 @@
package com.intellij.structuralsearch.impl.matcher.compiler;
+import com.intellij.dupLocator.iterators.NodeIterator;
import com.intellij.psi.*;
import com.intellij.psi.javadoc.PsiDocComment;
import com.intellij.psi.javadoc.PsiDocTag;
import com.intellij.psi.search.*;
import com.intellij.psi.search.searches.ClassInheritorsSearch;
-import com.intellij.structuralsearch.MatchOptions;
-import com.intellij.structuralsearch.MatchVariableConstraint;
-import com.intellij.structuralsearch.SSRBundle;
-import com.intellij.structuralsearch.UnsupportedPatternException;
+import com.intellij.structuralsearch.*;
import com.intellij.structuralsearch.impl.matcher.CompiledPattern;
import com.intellij.structuralsearch.impl.matcher.JavaCompiledPattern;
import com.intellij.structuralsearch.impl.matcher.filters.*;
import com.intellij.structuralsearch.impl.matcher.handlers.*;
import com.intellij.structuralsearch.impl.matcher.iterators.DocValuesIterator;
-import com.intellij.dupLocator.iterators.NodeIterator;
import com.intellij.structuralsearch.impl.matcher.predicates.RegExpPredicate;
import com.intellij.structuralsearch.impl.matcher.strategies.*;
import org.jetbrains.annotations.NonNls;
@@ -84,6 +81,9 @@ public class JavaCompilingVisitor extends JavaRecursiveElementWalkingVisitor {
);
SubstitutionHandler handler = (SubstitutionHandler)myCompilingVisitor.getContext().getPattern().getHandler(str);
+ if (handler == null) {
+ throw new MalformedPatternException();
+ }
if (handler.getPredicate() != null) {
((RegExpPredicate)handler.getPredicate()).setMultiline(true);
diff --git a/java/testFramework/src/com/intellij/codeInsight/CodeInsightTestCase.java b/java/testFramework/src/com/intellij/codeInsight/CodeInsightTestCase.java
index 9aee3cf51fdc..6ecec97f7fe7 100644
--- a/java/testFramework/src/com/intellij/codeInsight/CodeInsightTestCase.java
+++ b/java/testFramework/src/com/intellij/codeInsight/CodeInsightTestCase.java
@@ -537,11 +537,6 @@ public abstract class CodeInsightTestCase extends PsiTestCase {
}
}
- @Override
- public Object getData(String dataId) {
- return CommonDataKeys.EDITOR.is(dataId) ? myEditor : super.getData(dataId);
- }
-
protected VirtualFile getVirtualFile(@NonNls @NotNull String filePath) {
String fullPath = getTestDataPath() + filePath;
diff --git a/java/testFramework/src/com/intellij/debugger/DebuggerTestCase.java b/java/testFramework/src/com/intellij/debugger/DebuggerTestCase.java
index 8ec8e3f6ebdd..2409104c7116 100644
--- a/java/testFramework/src/com/intellij/debugger/DebuggerTestCase.java
+++ b/java/testFramework/src/com/intellij/debugger/DebuggerTestCase.java
@@ -138,12 +138,12 @@ public abstract class DebuggerTestCase extends ExecutionWithDebuggerToolsTestCas
DebuggerSettings.getInstance().DEBUGGER_TRANSPORT = DebuggerSettings.SOCKET_TRANSPORT;
GenericDebuggerRunnerSettings debuggerRunnerSettings = new GenericDebuggerRunnerSettings();
- debuggerRunnerSettings.LOCAL = true;
+ debuggerRunnerSettings.LOCAL = true;
final RemoteConnection debugParameters = DebuggerManagerImpl.createDebugParameters(javaParameters, debuggerRunnerSettings, false);
ExecutionEnvironment environment = new ExecutionEnvironmentBuilder(myProject, DefaultDebugExecutor.getDebugExecutorInstance())
- .setRunnerSettings(debuggerRunnerSettings)
+ .runnerSettings(debuggerRunnerSettings)
.setRunProfile(new MockConfiguration())
.build();
final JavaCommandLineState javaCommandLineState = new JavaCommandLineState(environment){
@@ -162,10 +162,12 @@ public abstract class DebuggerTestCase extends ExecutionWithDebuggerToolsTestCas
@Override
public void run() {
try {
- GenericDebuggerRunner runner = new GenericDebuggerRunner();
- myDebuggerSession = DebuggerManagerEx.getInstanceEx(myProject).attachVirtualMachine(DefaultDebugExecutor.getDebugExecutorInstance(),
- runner, new MockConfiguration(), javaCommandLineState, debugParameters, false);
- XDebuggerManager.getInstance(myProject).startSession(runner, javaCommandLineState.getEnvironment(), null, new XDebugProcessStarter() {
+ myDebuggerSession =
+ DebuggerManagerEx.getInstanceEx(myProject)
+ .attachVirtualMachine(new DefaultDebugEnvironment(new ExecutionEnvironmentBuilder(myProject, DefaultDebugExecutor.getDebugExecutorInstance())
+ .runProfile(new MockConfiguration())
+ .build(), javaCommandLineState, debugParameters, false));
+ XDebuggerManager.getInstance(myProject).startSession(javaCommandLineState.getEnvironment(), new XDebugProcessStarter() {
@Override
@NotNull
public XDebugProcess start(@NotNull XDebugSession session) {
@@ -208,8 +210,8 @@ public abstract class DebuggerTestCase extends ExecutionWithDebuggerToolsTestCas
debuggerRunnerSettings.DEBUG_PORT = "3456";
ExecutionEnvironment environment = new ExecutionEnvironmentBuilder(myProject, DefaultDebugExecutor.getDebugExecutorInstance())
- .setRunnerSettings(debuggerRunnerSettings)
- .setRunProfile(new MockConfiguration())
+ .runnerSettings(debuggerRunnerSettings)
+ .runProfile(new MockConfiguration())
.build();
final JavaCommandLineState javaCommandLineState = new JavaCommandLineState(environment) {
@Override
@@ -230,8 +232,7 @@ public abstract class DebuggerTestCase extends ExecutionWithDebuggerToolsTestCas
@Override
public void run() {
try {
- GenericDebuggerRunner runner = new GenericDebuggerRunner();
- debuggerSession[0] = attachVirtualMachine(runner, javaCommandLineState, javaCommandLineState.getEnvironment(), debugParameters, false);
+ debuggerSession[0] = attachVirtualMachine(javaCommandLineState, javaCommandLineState.getEnvironment(), debugParameters, false);
}
catch (ExecutionException e) {
fail(e.getMessage());
@@ -273,14 +274,12 @@ public abstract class DebuggerTestCase extends ExecutionWithDebuggerToolsTestCas
println(launchCommandLine, ProcessOutputTypes.SYSTEM);
- JavaParameters parameters = javaParameters;
-
for(StringTokenizer tokenizer = new StringTokenizer(launchCommandLine);tokenizer.hasMoreTokens();) {
String token = tokenizer.nextToken();
- parameters.getVMParametersList().add(token);
+ javaParameters.getVMParametersList().add(token);
}
- GeneralCommandLine commandLine = CommandLineBuilder.createFromJavaParameters(parameters);
+ GeneralCommandLine commandLine = CommandLineBuilder.createFromJavaParameters(javaParameters);
DebuggerSession debuggerSession;
@@ -305,16 +304,14 @@ public abstract class DebuggerTestCase extends ExecutionWithDebuggerToolsTestCas
throws InvocationTargetException, InterruptedException {
final RemoteState remoteState = new RemoteStateState(myProject, remoteConnection);
- final ExecutionEnvironment environment = new ExecutionEnvironmentBuilder(myProject, DefaultDebugExecutor.getDebugExecutorInstance())
- .setRunProfile(new MockConfiguration())
- .build();
-
final DebuggerSession[] debuggerSession = new DebuggerSession[1];
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
@Override
public void run() {
try {
- debuggerSession[0] = attachVirtualMachine(new GenericDebuggerRunner(), remoteState, environment, remoteConnection, pollConnection);
+ debuggerSession[0] = attachVirtualMachine(remoteState, new ExecutionEnvironmentBuilder(myProject, DefaultDebugExecutor.getDebugExecutorInstance())
+ .runProfile(new MockConfiguration())
+ .build(), remoteConnection, pollConnection);
}
catch (ExecutionException e) {
fail(e.getMessage());
@@ -366,7 +363,7 @@ public abstract class DebuggerTestCase extends ExecutionWithDebuggerToolsTestCas
try {
request.join();
}
- catch (Exception e) {
+ catch (Exception ignored) {
}
}
};
@@ -380,7 +377,7 @@ public abstract class DebuggerTestCase extends ExecutionWithDebuggerToolsTestCas
try {
thread.join();
}
- catch (InterruptedException e) {
+ catch (InterruptedException ignored) {
}
}
});
@@ -466,16 +463,13 @@ public abstract class DebuggerTestCase extends ExecutionWithDebuggerToolsTestCas
return myDebuggerSession;
}
- protected DebuggerSession attachVirtualMachine(ProgramRunner runner,
- RunProfileState state,
+ protected DebuggerSession attachVirtualMachine(RunProfileState state,
ExecutionEnvironment environment,
RemoteConnection remoteConnection,
boolean pollConnection) throws ExecutionException {
final DebuggerSession debuggerSession =
- DebuggerManagerEx.getInstanceEx(myProject).attachVirtualMachine(DefaultDebugExecutor.getDebugExecutorInstance(),
- runner, new MockConfiguration(), state, remoteConnection,
- pollConnection);
- XDebuggerManager.getInstance(myProject).startSession(runner, environment, null, new XDebugProcessStarter() {
+ DebuggerManagerEx.getInstanceEx(myProject).attachVirtualMachine(new DefaultDebugEnvironment(environment, state, remoteConnection, pollConnection));
+ XDebuggerManager.getInstance(myProject).startSession(environment, new XDebugProcessStarter() {
@Override
@NotNull
public XDebugProcess start(@NotNull XDebugSession session) {
@@ -569,5 +563,4 @@ public abstract class DebuggerTestCase extends ExecutionWithDebuggerToolsTestCas
//To change body of implemented methods use File | Settings | File Templates.
}
}
-
}
diff --git a/java/testFramework/src/com/intellij/testFramework/TestSourceBasedTestCase.java b/java/testFramework/src/com/intellij/testFramework/TestSourceBasedTestCase.java
index bc99f65d3c5c..55b55c55dfb7 100644
--- a/java/testFramework/src/com/intellij/testFramework/TestSourceBasedTestCase.java
+++ b/java/testFramework/src/com/intellij/testFramework/TestSourceBasedTestCase.java
@@ -50,7 +50,7 @@ import java.io.File;
setupContentRoot();
}
});
-
+ ProjectViewTestUtil.setupImpl(getProject(), true);
}
@Override
diff --git a/java/testFramework/src/com/intellij/testFramework/fixtures/LightCodeInsightFixtureTestCase.java b/java/testFramework/src/com/intellij/testFramework/fixtures/LightCodeInsightFixtureTestCase.java
index 3699fe36aff5..c6f04dfeb7bf 100644
--- a/java/testFramework/src/com/intellij/testFramework/fixtures/LightCodeInsightFixtureTestCase.java
+++ b/java/testFramework/src/com/intellij/testFramework/fixtures/LightCodeInsightFixtureTestCase.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.
@@ -39,13 +39,13 @@ public abstract class LightCodeInsightFixtureTestCase extends UsefulTestCase{
public static final LightProjectDescriptor JAVA_1_4 = new DefaultLightProjectDescriptor() {
@Override
public void configureModule(Module module, ModifiableRootModel model, ContentEntry contentEntry) {
- model.getModuleExtension(LanguageLevelModuleExtension.class).setLanguageLevel(LanguageLevel.JDK_1_6);
+ model.getModuleExtension(LanguageLevelModuleExtension.class).setLanguageLevel(LanguageLevel.JDK_1_4);
}
};
public static final LightProjectDescriptor JAVA_1_5 = new DefaultLightProjectDescriptor() {
@Override
public void configureModule(Module module, ModifiableRootModel model, ContentEntry contentEntry) {
- model.getModuleExtension(LanguageLevelModuleExtension.class).setLanguageLevel(LanguageLevel.JDK_1_6);
+ model.getModuleExtension(LanguageLevelModuleExtension.class).setLanguageLevel(LanguageLevel.JDK_1_5);
}
};
public static final LightProjectDescriptor JAVA_1_6 = new DefaultLightProjectDescriptor() {
diff --git a/java/typeMigration/src/com/intellij/refactoring/typeMigration/intentions/ConvertFieldToAtomicIntention.java b/java/typeMigration/src/com/intellij/refactoring/typeMigration/intentions/ConvertFieldToAtomicIntention.java
index d794d59f9943..e983453a11c6 100644
--- a/java/typeMigration/src/com/intellij/refactoring/typeMigration/intentions/ConvertFieldToAtomicIntention.java
+++ b/java/typeMigration/src/com/intellij/refactoring/typeMigration/intentions/ConvertFieldToAtomicIntention.java
@@ -99,6 +99,7 @@ public class ConvertFieldToAtomicIntention extends PsiElementBaseIntentionAction
public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException {
final PsiVariable psiVariable = getVariable(element);
LOG.assertTrue(psiVariable != null);
+ psiVariable.normalizeDeclaration();
final Query<PsiReference> refs = ReferencesSearch.search(psiVariable);
diff --git a/java/typeMigration/src/com/intellij/refactoring/typeMigration/intentions/ConvertFieldToThreadLocalIntention.java b/java/typeMigration/src/com/intellij/refactoring/typeMigration/intentions/ConvertFieldToThreadLocalIntention.java
index e01aaadae7d8..38ff0ef466ae 100644
--- a/java/typeMigration/src/com/intellij/refactoring/typeMigration/intentions/ConvertFieldToThreadLocalIntention.java
+++ b/java/typeMigration/src/com/intellij/refactoring/typeMigration/intentions/ConvertFieldToThreadLocalIntention.java
@@ -69,6 +69,7 @@ public class ConvertFieldToThreadLocalIntention extends PsiElementBaseIntentionA
public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException {
final PsiField psiField = PsiTreeUtil.getParentOfType(element, PsiField.class);
LOG.assertTrue(psiField != null);
+ psiField.normalizeDeclaration();
final Query<PsiReference> refs = ReferencesSearch.search(psiField);
final Set<PsiElement> elements = new HashSet<PsiElement>();
diff --git a/java/typeMigration/testData/intentions/atomic/afterNormalize.java b/java/typeMigration/testData/intentions/atomic/afterNormalize.java
new file mode 100644
index 000000000000..c454d5787206
--- /dev/null
+++ b/java/typeMigration/testData/intentions/atomic/afterNormalize.java
@@ -0,0 +1,8 @@
+import java.util.concurrent.atomic.AtomicReference;
+
+// "Convert to atomic" "true"
+class X {
+ private final AtomicReference<String> s = new AtomicReference<>("");
+ private String t;
+ private String u;
+} \ No newline at end of file
diff --git a/java/typeMigration/testData/intentions/atomic/beforeNormalize.java b/java/typeMigration/testData/intentions/atomic/beforeNormalize.java
new file mode 100644
index 000000000000..6ac1fd926ea4
--- /dev/null
+++ b/java/typeMigration/testData/intentions/atomic/beforeNormalize.java
@@ -0,0 +1,4 @@
+// "Convert to atomic" "true"
+class X {
+ private String <caret>s = "", t, u;
+} \ No newline at end of file
diff --git a/java/typeMigration/testData/intentions/threadLocal/afterNormalize.java b/java/typeMigration/testData/intentions/threadLocal/afterNormalize.java
new file mode 100644
index 000000000000..1b2532d9d1de
--- /dev/null
+++ b/java/typeMigration/testData/intentions/threadLocal/afterNormalize.java
@@ -0,0 +1,11 @@
+// "Convert to ThreadLocal" "true"
+class X {
+ private final ThreadLocal<String> s = new ThreadLocal<String>() {
+ @Override
+ protected String initialValue() {
+ return "";
+ }
+ };
+ private String t;
+ private String u;
+} \ No newline at end of file
diff --git a/java/typeMigration/testData/intentions/threadLocal/beforeNormalize.java b/java/typeMigration/testData/intentions/threadLocal/beforeNormalize.java
new file mode 100644
index 000000000000..03b757b721d6
--- /dev/null
+++ b/java/typeMigration/testData/intentions/threadLocal/beforeNormalize.java
@@ -0,0 +1,4 @@
+// "Convert to ThreadLocal" "true"
+class X {
+ private String <caret>s = "", t, u;
+} \ No newline at end of file
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleBuildTarget.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleBuildTarget.java
index a6ac897a1d2d..05c185862399 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleBuildTarget.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleBuildTarget.java
@@ -165,6 +165,10 @@ public final class ModuleBuildTarget extends JVMModuleBuildTarget<JavaSourceRoot
int fingerprint = getDependenciesFingerprint();
+ for (JavaSourceRootDescriptor root : pd.getBuildRootIndex().getTargetRoots(this, null)) {
+ fingerprint += FileUtil.fileHashCode(root.getRootFile());
+ }
+
final LanguageLevel level = JpsJavaExtensionService.getInstance().getLanguageLevel(module);
if (level != null) {
fingerprint += level.name().hashCode();
diff --git a/platform/analysis-api/src/com/intellij/analysis/AnalysisScope.java b/platform/analysis-api/src/com/intellij/analysis/AnalysisScope.java
index b18bb042c183..893a7f3d30da 100644
--- a/platform/analysis-api/src/com/intellij/analysis/AnalysisScope.java
+++ b/platform/analysis-api/src/com/intellij/analysis/AnalysisScope.java
@@ -80,6 +80,7 @@ public class AnalysisScope {
private boolean mySearchInLibraries = false;
@Type protected int myType;
+ private Set<VirtualFile> myVFiles;
protected Set<VirtualFile> myFilesSet;
protected boolean myIncludeTestSource = true;
@@ -145,7 +146,7 @@ public class AnalysisScope {
myModule = null;
myModules = null;
myScope = null;
- myFilesSet = new HashSet<VirtualFile>(virtualFiles);
+ myVFiles = new HashSet<VirtualFile>(virtualFiles);
myType = VIRTUAL_FILES;
}
@@ -241,9 +242,9 @@ public class AnalysisScope {
accept(createFileSearcher());
}
else if (myType == VIRTUAL_FILES) {
- final HashSet<VirtualFile> files = new HashSet<VirtualFile>();
+ myFilesSet = new HashSet<VirtualFile>();
final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(myProject).getFileIndex();
- for (Iterator<VirtualFile> iterator = myFilesSet.iterator(); iterator.hasNext(); ) {
+ for (Iterator<VirtualFile> iterator = myVFiles.iterator(); iterator.hasNext(); ) {
final VirtualFile vFile = iterator.next();
VfsUtilCore.visitChildrenRecursively(vFile, new VirtualFileVisitor() {
@NotNull
@@ -251,7 +252,7 @@ public class AnalysisScope {
public Result visitFileEx(@NotNull VirtualFile file) {
boolean ignored = fileIndex.isExcluded(file);
if (!ignored && !file.isDirectory()) {
- files.add(file);
+ myFilesSet.add(file);
}
return ignored ? SKIP_CHILDREN : CONTINUE;
}
@@ -261,7 +262,6 @@ public class AnalysisScope {
iterator.remove();
}
}
- myFilesSet.addAll(files);
}
}
@@ -592,7 +592,7 @@ public class AnalysisScope {
if (myType != VIRTUAL_FILES) {
myFilesSet = null;
} else {
- for (Iterator<VirtualFile> i = myFilesSet.iterator(); i.hasNext();) {
+ for (Iterator<VirtualFile> i = myVFiles.iterator(); i.hasNext();) {
final VirtualFile virtualFile = i.next();
if (virtualFile == null || !virtualFile.isValid()) {
i.remove();
diff --git a/platform/analysis-api/src/com/intellij/codeInspection/InspectionProfileEntry.java b/platform/analysis-api/src/com/intellij/codeInspection/InspectionProfileEntry.java
index 8d0f1da9d024..43d80faad886 100644
--- a/platform/analysis-api/src/com/intellij/codeInspection/InspectionProfileEntry.java
+++ b/platform/analysis-api/src/com/intellij/codeInspection/InspectionProfileEntry.java
@@ -119,7 +119,7 @@ public abstract class InspectionProfileEntry implements BatchSuppressableTool{
return alternativeId != null && !alternativeId.equals(toolId) && suppressor.isSuppressedFor(element, alternativeId);
}
- private static Set<InspectionSuppressor> getSuppressors(@NotNull PsiElement element) {
+ public static Set<InspectionSuppressor> getSuppressors(@NotNull PsiElement element) {
FileViewProvider viewProvider = element.getContainingFile().getViewProvider();
if (viewProvider instanceof TemplateLanguageFileViewProvider) {
LinkedHashSet<InspectionSuppressor> suppressors = new LinkedHashSet<InspectionSuppressor>();
@@ -127,6 +127,7 @@ public abstract class InspectionProfileEntry implements BatchSuppressableTool{
for (Language language : viewProvider.getLanguages()) {
ContainerUtil.addIfNotNull(suppressors, LanguageInspectionSuppressors.INSTANCE.forLanguage(language));
}
+ ContainerUtil.addIfNotNull(suppressors, LanguageInspectionSuppressors.INSTANCE.forLanguage(element.getLanguage()));
return suppressors;
}
return Collections.singleton(LanguageInspectionSuppressors.INSTANCE.forLanguage(element.getLanguage()));
diff --git a/platform/analysis-api/src/com/intellij/codeInspection/ex/InspectionToolsRegistrarCore.java b/platform/analysis-api/src/com/intellij/codeInspection/ex/InspectionToolsRegistrarCore.java
index 7d2ffb7ce405..eb99cc4d1594 100644
--- a/platform/analysis-api/src/com/intellij/codeInspection/ex/InspectionToolsRegistrarCore.java
+++ b/platform/analysis-api/src/com/intellij/codeInspection/ex/InspectionToolsRegistrarCore.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,36 +17,17 @@ package com.intellij.codeInspection.ex;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.util.ArrayUtil;
+import com.intellij.util.ReflectionUtil;
import org.jetbrains.annotations.NotNull;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-
public class InspectionToolsRegistrarCore {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.ex.InspectionToolsRegistrarCore");
static Object instantiateTool(@NotNull Class<?> toolClass) {
try {
- Constructor<?> constructor = toolClass.getDeclaredConstructor(ArrayUtil.EMPTY_CLASS_ARRAY);
- constructor.setAccessible(true);
- return constructor.newInstance(ArrayUtil.EMPTY_OBJECT_ARRAY);
- }
- catch (SecurityException e) {
- LOG.error(e);
- }
- catch (NoSuchMethodException e) {
- LOG.error(e);
- }
- catch (InstantiationException e) {
- LOG.error(e);
- }
- catch (IllegalAccessException e) {
- LOG.error(e);
- }
- catch (IllegalArgumentException e) {
- LOG.error(e);
+ return ReflectionUtil.newInstance(toolClass, ArrayUtil.EMPTY_CLASS_ARRAY);
}
- catch (InvocationTargetException e) {
- LOG.error(e);
+ catch (RuntimeException e) {
+ LOG.error(e.getCause());
}
return null;
diff --git a/platform/analysis-api/src/com/intellij/psi/search/scope/NonProjectFilesScope.java b/platform/analysis-api/src/com/intellij/psi/search/scope/NonProjectFilesScope.java
index 63fe1c8d28e5..ca229a64bebc 100644
--- a/platform/analysis-api/src/com/intellij/psi/search/scope/NonProjectFilesScope.java
+++ b/platform/analysis-api/src/com/intellij/psi/search/scope/NonProjectFilesScope.java
@@ -17,6 +17,7 @@ package com.intellij.psi.search.scope;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.vfs.NonPhysicalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.search.ProjectScope;
import com.intellij.psi.search.scope.packageSet.AbstractPackageSet;
@@ -43,7 +44,8 @@ public class NonProjectFilesScope extends NamedScope {
@Override
public boolean contains(VirtualFile file, @NotNull Project project, @Nullable NamedScopesHolder holder) {
- if (file == null) return true;
+ // do not include fake-files e.g. fragment-editors, database consoles, etc.
+ if (file == null || file.getFileSystem() instanceof NonPhysicalFileSystem) return false;
if (!file.isInLocalFileSystem()) return true;
if (isInsideProjectContent(project, file)) return false;
return !ProjectScope.getProjectScope(project).contains(file);
diff --git a/platform/analysis-api/src/com/intellij/psi/search/scope/ProjectProductionScope.java b/platform/analysis-api/src/com/intellij/psi/search/scope/ProjectProductionScope.java
index 7d44b0f91450..19788a0bd3d7 100644
--- a/platform/analysis-api/src/com/intellij/psi/search/scope/ProjectProductionScope.java
+++ b/platform/analysis-api/src/com/intellij/psi/search/scope/ProjectProductionScope.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.
@@ -30,8 +30,10 @@ import org.jetbrains.annotations.Nullable;
* @author Konstantin Bulenkov
*/
public class ProjectProductionScope extends NamedScope {
+ public static final String NAME = IdeBundle.message("predefined.scope.production.name");
+
public ProjectProductionScope() {
- super(IdeBundle.message("predefined.scope.production.name"), new AbstractPackageSet("src:*..*") {
+ super(NAME, new AbstractPackageSet("src:*..*") {
@Override
public boolean contains(VirtualFile file, NamedScopesHolder holder) {
return contains(file, holder.getProject(), holder);
diff --git a/platform/annotations/src/org/intellij/lang/annotations/Flow.java b/platform/annotations/src/org/intellij/lang/annotations/Flow.java
index a6ea57837336..c73fa57bf9f4 100644
--- a/platform/annotations/src/org/intellij/lang/annotations/Flow.java
+++ b/platform/annotations/src/org/intellij/lang/annotations/Flow.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.
@@ -59,7 +59,7 @@ public @interface Flow {
* </li>
* </ul>
*/
- String source() default DEFAULT_SOURCE;
+ String source() default org.intellij.lang.annotations.Flow.DEFAULT_SOURCE;
@NonNls String DEFAULT_SOURCE = "The method argument (if parameter was annotated) or this container (if instance method was annotated)";
@NonNls String THIS_SOURCE = "this";
@@ -108,7 +108,7 @@ public @interface Flow {
* </li>
* </ul>
*/
- String target() default DEFAULT_TARGET;
+ String target() default org.intellij.lang.annotations.Flow.DEFAULT_TARGET;
@NonNls String DEFAULT_TARGET = "This container (if the parameter was annotated) or the return value (if instance method was annotated)";
@NonNls String RETURN_METHOD_TARGET = "The return value of this method";
@NonNls String THIS_TARGET = "this";
diff --git a/platform/bootstrap/src/com/intellij/ide/startup/StartupActionScriptManager.java b/platform/bootstrap/src/com/intellij/ide/startup/StartupActionScriptManager.java
index fd2882dfb40b..2cf84526471a 100644
--- a/platform/bootstrap/src/com/intellij/ide/startup/StartupActionScriptManager.java
+++ b/platform/bootstrap/src/com/intellij/ide/startup/StartupActionScriptManager.java
@@ -17,6 +17,7 @@ package com.intellij.ide.startup;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.io.FileUtilRt;
import com.intellij.util.io.ZipUtil;
import org.jetbrains.annotations.NonNls;
@@ -71,21 +72,26 @@ public class StartupActionScriptManager {
private static List<ActionCommand> loadActionScript() throws IOException {
File file = new File(getActionScriptPath());
if (file.exists()) {
+ boolean fileCorrupted = false;
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
try {
//noinspection unchecked
return (List<ActionCommand>)ois.readObject();
}
- catch (ClassNotFoundException e) {
- // problem with scrambled code
- // fas fixed, but still appear because corrupted file still exists
- // return empty list.
+ catch (Throwable e) { // ClassNotFoundException / IOException
+ fileCorrupted = true;
LOG.error("Internal file was corrupted. Problem is fixed.\nIf some plugins has been installed/uninstalled, please re-install/-uninstall them.", e);
+ //noinspection InstanceofCatchParameter
+ if (e instanceof IOException) throw (IOException)e;
return new ArrayList<ActionCommand>();
}
finally {
- ois.close();
+ try {
+ ois.close();
+ } finally {
+ if (fileCorrupted) FileUtil.delete(file); // do not need corrupted file anymore
+ }
}
}
else {
@@ -189,7 +195,8 @@ public class StartupActionScriptManager {
public void execute() throws IOException {
if (!mySource.exists()) {
- //noinspection HardCodedStringLiteral
+ // Note, that we can not use LOG at this moment because it throws AssertionError
+ //noinspection HardCodedStringLiteral,UseOfSystemOutOrSystemErr
System.err.println("Source file " + mySource.getAbsolutePath() + " does not exist for action " + this);
}
else if (!canCreateFile(myDestination)) {
@@ -203,6 +210,7 @@ public class StartupActionScriptManager {
ZipUtil.extract(mySource, myDestination, myFilenameFilter);
}
catch(Exception ex) {
+ //noinspection CallToPrintStackTrace
ex.printStackTrace();
JOptionPane.showMessageDialog(JOptionPane.getRootFrame(),
MessageFormat.format("<html>Failed to extract ZIP file {0}<br>to<br>{1}<br>You may need to re-download the plugin you tried to install.",
@@ -228,7 +236,7 @@ public class StartupActionScriptManager {
public void execute() throws IOException {
if (mySource != null && mySource.exists() && !FileUtilRt.delete(mySource)) {
- //noinspection HardCodedStringLiteral
+ //noinspection HardCodedStringLiteral,UseOfSystemOutOrSystemErr
System.err.println("Action " + this + " failed.");
JOptionPane.showMessageDialog(JOptionPane.getRootFrame(),
MessageFormat.format("<html>Cannot delete {0}<br>Please, check your access rights on folder <br>{1}",
diff --git a/platform/lang-api/src/com/intellij/codeInsight/controlflow/ConditionalInstruction.java b/platform/core-api/src/com/intellij/codeInsight/controlflow/ConditionalInstruction.java
index daea33cd1e9a..3bb44937de4a 100644
--- a/platform/lang-api/src/com/intellij/codeInsight/controlflow/ConditionalInstruction.java
+++ b/platform/core-api/src/com/intellij/codeInsight/controlflow/ConditionalInstruction.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.
diff --git a/platform/core-api/src/com/intellij/codeInsight/controlflow/ControlFlow.java b/platform/core-api/src/com/intellij/codeInsight/controlflow/ControlFlow.java
new file mode 100644
index 000000000000..bf72d011c6ea
--- /dev/null
+++ b/platform/core-api/src/com/intellij/codeInsight/controlflow/ControlFlow.java
@@ -0,0 +1,23 @@
+/*
+ * 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.controlflow;
+
+/**
+ * @author oleg
+ */
+public interface ControlFlow {
+ Instruction[] getInstructions();
+}
diff --git a/platform/lang-api/src/com/intellij/codeInsight/controlflow/Instruction.java b/platform/core-api/src/com/intellij/codeInsight/controlflow/Instruction.java
index 26ecfcca2a5d..8b0dda01d226 100644
--- a/platform/lang-api/src/com/intellij/codeInsight/controlflow/Instruction.java
+++ b/platform/core-api/src/com/intellij/codeInsight/controlflow/Instruction.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.
diff --git a/platform/core-api/src/com/intellij/concurrency/JobScheduler.java b/platform/core-api/src/com/intellij/concurrency/JobScheduler.java
index a7e16644363c..30d668088824 100644
--- a/platform/core-api/src/com/intellij/concurrency/JobScheduler.java
+++ b/platform/core-api/src/com/intellij/concurrency/JobScheduler.java
@@ -81,8 +81,7 @@ public abstract class JobScheduler {
private static void enableRemoveOnCancelPolicy(ScheduledThreadPoolExecutor executor) {
if (Patches.USE_REFLECTION_TO_ACCESS_JDK7) {
try {
- Method setRemoveOnCancelPolicy = ScheduledThreadPoolExecutor.class.getDeclaredMethod("setRemoveOnCancelPolicy", boolean.class);
- setRemoveOnCancelPolicy.setAccessible(true);
+ Method setRemoveOnCancelPolicy = ReflectionUtil.getDeclaredMethod(ScheduledThreadPoolExecutor.class, "setRemoveOnCancelPolicy", boolean.class);
setRemoveOnCancelPolicy.invoke(executor, true);
}
catch (Exception ignored) {
diff --git a/platform/core-api/src/com/intellij/openapi/application/ModalityInvokator.java b/platform/core-api/src/com/intellij/openapi/application/ModalityInvokator.java
index 4dda4a664174..4a72e09dcd8e 100644
--- a/platform/core-api/src/com/intellij/openapi/application/ModalityInvokator.java
+++ b/platform/core-api/src/com/intellij/openapi/application/ModalityInvokator.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.
@@ -31,9 +31,11 @@ public interface ModalityInvokator {
*
* @param runnable the runnable to execute.
*/
- ActionCallback invokeLater(Runnable runnable);
+ @NotNull
+ ActionCallback invokeLater(@NotNull Runnable runnable);
- ActionCallback invokeLater(Runnable runnable, @NotNull Condition expired);
+ @NotNull
+ ActionCallback invokeLater(@NotNull Runnable runnable, @NotNull Condition expired);
/**
* Causes <i>runnable.run()</i> to be executed asynchronously on the
@@ -43,7 +45,9 @@ public interface ModalityInvokator {
* @param runnable the runnable to execute.
* @param state the state in which the runnable will be executed.
*/
- ActionCallback invokeLater(Runnable runnable, @NotNull ModalityState state);
+ @NotNull
+ ActionCallback invokeLater(@NotNull Runnable runnable, @NotNull ModalityState state);
- ActionCallback invokeLater(Runnable runnable, @NotNull ModalityState state, @NotNull Condition expired);
+ @NotNull
+ ActionCallback invokeLater(@NotNull Runnable runnable, @NotNull ModalityState state, @NotNull Condition expired);
} \ No newline at end of file
diff --git a/platform/core-api/src/com/intellij/openapi/progress/ProgressIndicatorProvider.java b/platform/core-api/src/com/intellij/openapi/progress/ProgressIndicatorProvider.java
index 0f50f8d05ecf..afe440b8588f 100644
--- a/platform/core-api/src/com/intellij/openapi/progress/ProgressIndicatorProvider.java
+++ b/platform/core-api/src/com/intellij/openapi/progress/ProgressIndicatorProvider.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.
@@ -25,7 +25,6 @@ public abstract class ProgressIndicatorProvider {
@Nullable
public static ProgressIndicatorProvider ourInstance;
- @Nullable
public static ProgressIndicatorProvider getInstance() {
return ourInstance;
}
@@ -39,6 +38,7 @@ public abstract class ProgressIndicatorProvider {
return ourInstance != null ? ourInstance.getProgressIndicator() : null;
}
+ @NotNull
public abstract NonCancelableSection startNonCancelableSection();
@NotNull
@@ -46,12 +46,12 @@ public abstract class ProgressIndicatorProvider {
return ourInstance != null ? ourInstance.startNonCancelableSection() : NonCancelableSection.EMPTY;
}
- public static volatile boolean ourNeedToCheckCancel = false;
+ protected static volatile boolean ourNeedToCheckCancel = false;
public static void checkCanceled() throws ProcessCanceledException {
// smart optimization! There's a thread started in ProgressManagerImpl, that set's this flag up once in 10 milliseconds
if (ourNeedToCheckCancel && ourInstance != null) {
+ ourNeedToCheckCancel = false; // doCheckCanceled() may flip it back to true
ourInstance.doCheckCanceled();
- ourNeedToCheckCancel = false;
}
}
}
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 e99b8e6bebf0..4b4ace28cd37 100644
--- a/platform/core-api/src/com/intellij/openapi/progress/ProgressManager.java
+++ b/platform/core-api/src/com/intellij/openapi/progress/ProgressManager.java
@@ -25,38 +25,17 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
-public abstract class ProgressManager {
- static {
- ProgressIndicatorProvider.ourInstance = new ProgressIndicatorProvider() {
- @Override
- public ProgressIndicator getProgressIndicator() {
- ProgressManager manager = ProgressManager.getInstance();
- return manager != null ? manager.getProgressIndicator() : null;
- }
-
- @Override
- protected void doCheckCanceled() throws ProcessCanceledException {
- ProgressManager manager = ProgressManager.getInstance();
- if (manager != null) {
- manager.doCheckCanceled();
- }
- }
-
- @Override
- public NonCancelableSection startNonCancelableSection() {
- ProgressManager manager = ProgressManager.getInstance();
- return manager != null ? manager.startNonCancelableSection() : NonCancelableSection.EMPTY;
- }
- };
+public abstract class ProgressManager extends ProgressIndicatorProvider {
+ public ProgressManager() {
+ ProgressIndicatorProvider.ourInstance = this;
}
- private static ProgressManager ourInstance;
+ private static class ProgressManagerHolder {
+ private static final ProgressManager ourInstance = ServiceManager.getService(ProgressManager.class);
+ }
public static ProgressManager getInstance() {
- if (ourInstance == null) {
- ourInstance = ServiceManager.getService(ProgressManager.class);
- }
- return ourInstance;
+ return ProgressManagerHolder.ourInstance;
}
public abstract boolean hasProgressIndicator();
@@ -66,17 +45,13 @@ public abstract class ProgressManager {
public abstract void runProcess(@NotNull Runnable process, ProgressIndicator progress) throws ProcessCanceledException;
public abstract <T> T runProcess(@NotNull Computable<T> process, ProgressIndicator progress) throws ProcessCanceledException;
+ @Override
public ProgressIndicator getProgressIndicator() {
return myThreadIndicator.get();
}
- protected static volatile boolean ourNeedToCheckCancel = false;
public static void checkCanceled() throws ProcessCanceledException {
- // smart optimization! There's a thread started in ProgressManagerImpl, that set's this flag up once in 10 milliseconds
- if (ourNeedToCheckCancel) {
- getInstance().doCheckCanceled();
- ourNeedToCheckCancel = false;
- }
+ ProgressIndicatorProvider.checkCanceled();
}
public static void progress(@NotNull String text) throws ProcessCanceledException {
@@ -100,11 +75,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);
diff --git a/platform/core-api/src/com/intellij/openapi/util/SimpleModificationTracker.java b/platform/core-api/src/com/intellij/openapi/util/SimpleModificationTracker.java
index 5232dc439b90..9b74576176fb 100644
--- a/platform/core-api/src/com/intellij/openapi/util/SimpleModificationTracker.java
+++ b/platform/core-api/src/com/intellij/openapi/util/SimpleModificationTracker.java
@@ -16,6 +16,7 @@
package com.intellij.openapi.util;
import com.intellij.Patches;
+import com.intellij.util.xmlb.annotations.Transient;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
@@ -28,6 +29,8 @@ public class SimpleModificationTracker implements ModificationTracker {
// fixed in JDK8
assert Patches.JDK_BUG_ID_7103570;
}
+
+ @Transient
public volatile int myCounter;
@Override
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 9e8c37880589..b3fc7550adfa 100644
--- a/platform/core-api/src/com/intellij/openapi/vfs/VfsUtilCore.java
+++ b/platform/core-api/src/com/intellij/openapi/vfs/VfsUtilCore.java
@@ -46,6 +46,8 @@ public class VfsUtilCore {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vfs.VfsUtilCore");
public static final String LOCALHOST_URI_PATH_PREFIX = "localhost/";
+ public static final char VFS_SEPARATOR_CHAR = '/';
+
private static final String PROTOCOL_DELIMITER = ":";
/**
@@ -118,6 +120,11 @@ public class VfsUtilCore {
return false;
}
+ @Nullable
+ public static String getRelativePath(@NotNull VirtualFile file, @NotNull VirtualFile ancestor) {
+ return getRelativePath(file, ancestor, VFS_SEPARATOR_CHAR);
+ }
+
/**
* Gets the relative path of <code>file</code> to its <code>ancestor</code>. Uses <code>separator</code> for
* separating files.
@@ -129,12 +136,10 @@ public class VfsUtilCore {
*/
@Nullable
public static String getRelativePath(@NotNull VirtualFile file, @NotNull VirtualFile ancestor, char separator) {
- if (!file.getFileSystem().equals(ancestor.getFileSystem())) return null;
-
- return doGetRelative(file, ancestor, separator);
- }
+ if (!file.getFileSystem().equals(ancestor.getFileSystem())) {
+ return null;
+ }
- public static String doGetRelative(VirtualFile file, VirtualFile ancestor, char separator) {
int length = 0;
VirtualFile parent = file;
while (true) {
diff --git a/platform/core-api/src/com/intellij/openapi/vfs/VirtualFile.java b/platform/core-api/src/com/intellij/openapi/vfs/VirtualFile.java
index e4c3e5c502f5..d265d5a8cd2e 100644
--- a/platform/core-api/src/com/intellij/openapi/vfs/VirtualFile.java
+++ b/platform/core-api/src/com/intellij/openapi/vfs/VirtualFile.java
@@ -717,6 +717,7 @@ public abstract class VirtualFile extends UserDataHolderBase implements Modifica
putUserData(BOM_KEY, BOM);
}
+ @Override
@NonNls
public String toString() {
return "VirtualFile: " + getPresentableUrl();
diff --git a/platform/core-api/src/com/intellij/psi/PsiElementResolveResult.java b/platform/core-api/src/com/intellij/psi/PsiElementResolveResult.java
index 205bf27fe1c0..4a2343ce2983 100644
--- a/platform/core-api/src/com/intellij/psi/PsiElementResolveResult.java
+++ b/platform/core-api/src/com/intellij/psi/PsiElementResolveResult.java
@@ -87,7 +87,7 @@ public class PsiElementResolveResult implements ResolveResult{
}
@NotNull
- public static ResolveResult[] createResults(@Nullable PsiElement[] elements) {
+ public static ResolveResult[] createResults(@Nullable PsiElement... elements) {
if (elements == null || elements.length == 0) return EMPTY_ARRAY;
final ResolveResult[] results = new ResolveResult[elements.length];
diff --git a/platform/core-api/src/com/intellij/psi/PsiFileFactory.java b/platform/core-api/src/com/intellij/psi/PsiFileFactory.java
index b31c03b6640a..e77ed1c3a4fb 100644
--- a/platform/core-api/src/com/intellij/psi/PsiFileFactory.java
+++ b/platform/core-api/src/com/intellij/psi/PsiFileFactory.java
@@ -63,6 +63,10 @@ public abstract class PsiFileFactory {
public abstract PsiFile createFileFromText(@NotNull String name, @NotNull Language language, @NotNull CharSequence text);
+ public PsiFile createFileFromText(@NotNull Language language, @NotNull CharSequence text) {
+ return createFileFromText("foo.bar", language, text);
+ }
+
public abstract PsiFile createFileFromText(@NotNull String name, @NotNull Language language, @NotNull CharSequence text,
boolean eventSystemEnabled, boolean markAsCopy);
diff --git a/platform/core-api/src/com/intellij/psi/PsiWalkingState.java b/platform/core-api/src/com/intellij/psi/PsiWalkingState.java
index b6207e8bf364..6418a0b60804 100644
--- a/platform/core-api/src/com/intellij/psi/PsiWalkingState.java
+++ b/platform/core-api/src/com/intellij/psi/PsiWalkingState.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.
@@ -52,7 +52,10 @@ public abstract class PsiWalkingState extends WalkingState<PsiElement> {
}
protected PsiWalkingState(@NotNull PsiElementVisitor delegate) {
- super(PsiTreeGuide.instance);
+ this(delegate, PsiTreeGuide.instance);
+ }
+ protected PsiWalkingState(@NotNull PsiElementVisitor delegate, @NotNull TreeGuide<PsiElement> guide) {
+ super(guide);
myVisitor = delegate;
}
diff --git a/platform/core-api/src/com/intellij/psi/ReferenceRange.java b/platform/core-api/src/com/intellij/psi/ReferenceRange.java
index cfb1f49a71e7..1ac18336abcb 100644
--- a/platform/core-api/src/com/intellij/psi/ReferenceRange.java
+++ b/platform/core-api/src/com/intellij/psi/ReferenceRange.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.
@@ -20,6 +20,7 @@
package com.intellij.psi;
import com.intellij.openapi.util.TextRange;
+import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Collections;
@@ -29,14 +30,16 @@ public class ReferenceRange {
private ReferenceRange() {
}
- public static List<TextRange> getRanges(PsiReference ref) {
+ @NotNull
+ public static List<TextRange> getRanges(@NotNull PsiReference ref) {
if (ref instanceof MultiRangeReference) {
return ((MultiRangeReference)ref).getRanges();
}
return Collections.singletonList(ref.getRangeInElement());
}
- public static List<TextRange> getAbsoluteRanges(PsiReference ref) {
+ @NotNull
+ public static List<TextRange> getAbsoluteRanges(@NotNull PsiReference ref) {
final PsiElement elt = ref.getElement();
final List<TextRange> relativeRanges = getRanges(ref);
final List<TextRange> answer = new ArrayList<TextRange>(relativeRanges.size());
@@ -47,7 +50,7 @@ public class ReferenceRange {
return answer;
}
- public static TextRange getRange(PsiReference ref) {
+ public static TextRange getRange(@NotNull PsiReference ref) {
if (ref instanceof MultiRangeReference) {
final List<TextRange> ranges = ((MultiRangeReference)ref).getRanges();
return new TextRange(ranges.get(0).getStartOffset(), ranges.get(ranges.size() - 1).getEndOffset());
@@ -56,7 +59,7 @@ public class ReferenceRange {
return ref.getRangeInElement();
}
- public static boolean containsOffsetInElement(PsiReference ref, int offset) {
+ public static boolean containsOffsetInElement(@NotNull PsiReference ref, int offset) {
if (ref instanceof MultiRangeReference) {
for (TextRange range : ((MultiRangeReference)ref).getRanges()) {
if (range.containsOffset(offset)) return true;
@@ -68,7 +71,7 @@ public class ReferenceRange {
return rangeInElement != null && rangeInElement.containsOffset(offset);
}
- public static boolean containsRangeInElement(PsiReference ref, TextRange rangeInElement) {
+ public static boolean containsRangeInElement(@NotNull PsiReference ref, @NotNull TextRange rangeInElement) {
if (ref instanceof MultiRangeReference) {
for (TextRange range : ((MultiRangeReference)ref).getRanges()) {
if (range.contains(rangeInElement)) return true;
diff --git a/platform/core-api/src/com/intellij/testFramework/LightVirtualFile.java b/platform/core-api/src/com/intellij/testFramework/LightVirtualFile.java
index bc518e1b66a3..982d921b9e97 100644
--- a/platform/core-api/src/com/intellij/testFramework/LightVirtualFile.java
+++ b/platform/core-api/src/com/intellij/testFramework/LightVirtualFile.java
@@ -19,10 +19,7 @@ import com.intellij.lang.Language;
import com.intellij.openapi.fileTypes.CharsetUtil;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.FileTypeRegistry;
-import com.intellij.openapi.vfs.DeprecatedVirtualFileSystem;
-import com.intellij.openapi.vfs.VfsUtilCore;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.openapi.vfs.VirtualFileSystem;
+import com.intellij.openapi.vfs.*;
import com.intellij.util.LocalTimeCounter;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -113,7 +110,7 @@ public class LightVirtualFile extends VirtualFile {
myOriginalFile = originalFile;
}
- private static class MyVirtualFileSystem extends DeprecatedVirtualFileSystem {
+ private static class MyVirtualFileSystem extends DeprecatedVirtualFileSystem implements NonPhysicalFileSystem{
@NonNls private static final String PROTOCOL = "mock";
private MyVirtualFileSystem() {
diff --git a/platform/core-impl/src/com/intellij/core/CoreApplicationEnvironment.java b/platform/core-impl/src/com/intellij/core/CoreApplicationEnvironment.java
index 633c25a0145a..f82e7a80d5fb 100644
--- a/platform/core-impl/src/com/intellij/core/CoreApplicationEnvironment.java
+++ b/platform/core-impl/src/com/intellij/core/CoreApplicationEnvironment.java
@@ -234,6 +234,7 @@ public class CoreApplicationEnvironment {
protected void doCheckCanceled() throws ProcessCanceledException {
}
+ @NotNull
@Override
public NonCancelableSection startNonCancelableSection() {
return NonCancelableSection.EMPTY;
diff --git a/platform/core-impl/src/com/intellij/ide/plugins/IdeaPluginDescriptorImpl.java b/platform/core-impl/src/com/intellij/ide/plugins/IdeaPluginDescriptorImpl.java
index 24e12524dc97..72d290e61e25 100644
--- a/platform/core-impl/src/com/intellij/ide/plugins/IdeaPluginDescriptorImpl.java
+++ b/platform/core-impl/src/com/intellij/ide/plugins/IdeaPluginDescriptorImpl.java
@@ -121,9 +121,7 @@ public class IdeaPluginDescriptorImpl implements IdeaPluginDescriptor {
@NotNull
public static String intern(@NotNull String s) {
- synchronized (ourInterner) {
- return ourInterner.intern(s);
- }
+ return ourInterner.intern(s);
}
public static void internJDOMElement(@NotNull Element rootElement) {
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 e834e33f0f42..d80d36822eb1 100644
--- a/platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java
+++ b/platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java
@@ -322,15 +322,8 @@ public class PluginManagerCore {
Extensions.registerAreaClass(ExtensionAreas.IDEA_MODULE, ExtensionAreas.IDEA_PROJECT);
}
- @SuppressWarnings({"HardCodedStringLiteral"})
- static Method getAddUrlMethod(final ClassLoader loader) throws NoSuchMethodException {
- if (loader instanceof URLClassLoader) {
- final Method addUrlMethod = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
- addUrlMethod.setAccessible(true);
- return addUrlMethod;
- }
-
- return loader.getClass().getDeclaredMethod("addURL", URL.class);
+ private static Method getAddUrlMethod(final ClassLoader loader) {
+ return ReflectionUtil.getDeclaredMethod(loader instanceof URLClassLoader ? URLClassLoader.class : loader.getClass(), "addURL", URL.class);
}
@Nullable
@@ -351,9 +344,6 @@ public class PluginManagerCore {
return loader;
}
- catch (NoSuchMethodException e) {
- e.printStackTrace();
- }
catch (IOException e) {
e.printStackTrace();
}
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 b68fa936af23..d67ae891d3bf 100644
--- a/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java
+++ b/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java
@@ -1113,7 +1113,7 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder {
if (curDepth > maxDepth) maxDepth = curDepth;
}
else if (item instanceof DoneMarker) {
- if (((DoneMarker)item).myStart != curNode) LOG.error(UNBALANCED_MESSAGE);
+ assertMarkersBalanced(((DoneMarker)item).myStart == curNode, item);
curNode = nodes.pop();
curDepth--;
}
@@ -1143,7 +1143,7 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder {
myLexStarts[myCurrentLexeme + 1] = 0;
myLexTypes[myCurrentLexeme] = null;
- LOG.assertTrue(curNode == rootMarker, UNBALANCED_MESSAGE);
+ assertMarkersBalanced(curNode == rootMarker, curNode);
checkTreeDepth(maxDepth, rootMarker.getTokenType() instanceof IFileElementType);
@@ -1151,6 +1151,16 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder {
return rootMarker;
}
+ private void assertMarkersBalanced(boolean condition, @Nullable ProductionMarker marker) {
+ if (condition) return;
+
+ int index = marker != null ? marker.getStartIndex() + 1 : myLexStarts.length;
+ CharSequence context =
+ index < myLexStarts.length ? myText.subSequence(Math.max(0, myLexStarts[index] - 1000), myLexStarts[index]) : "<none>";
+ String language = myFile != null ? myFile.getLanguage() + ", " : "";
+ LOG.error(UNBALANCED_MESSAGE + "\n" + language + context);
+ }
+
private void balanceWhiteSpaces() {
RelativeTokenTypesView wsTokens = new RelativeTokenTypesView();
RelativeTokenTextView tokenTextGetter = new RelativeTokenTextView();
@@ -1158,8 +1168,8 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder {
for (int i = 1, size = myProduction.size() - 1; i < size; i++) {
ProductionMarker item = myProduction.get(i);
- if (item instanceof StartMarker && ((StartMarker)item).myDoneMarker == null) {
- LOG.error(UNBALANCED_MESSAGE);
+ if (item instanceof StartMarker) {
+ assertMarkersBalanced(((StartMarker)item).myDoneMarker != null, item);
}
int prevProductionLexIndex = myProduction.get(i - 1).myLexemeIndex;
diff --git a/platform/core-impl/src/com/intellij/openapi/application/ex/ApplicationInfoEx.java b/platform/core-impl/src/com/intellij/openapi/application/ex/ApplicationInfoEx.java
index 4282eb20ff26..d1251c9c9ad0 100644
--- a/platform/core-impl/src/com/intellij/openapi/application/ex/ApplicationInfoEx.java
+++ b/platform/core-impl/src/com/intellij/openapi/application/ex/ApplicationInfoEx.java
@@ -16,6 +16,7 @@
package com.intellij.openapi.application.ex;
import com.intellij.openapi.application.ApplicationInfo;
+import org.jetbrains.annotations.Nullable;
import java.awt.*;
import java.util.Calendar;
@@ -117,4 +118,7 @@ public abstract class ApplicationInfoEx extends ApplicationInfo {
/** @deprecated to remove in IDEA 14 */
@SuppressWarnings("UnusedDeclaration")
public abstract String getWelcomeScreenDeveloperSloganUrl();
+
+ @Nullable
+ public abstract String getCustomizeIDEWizardStepsProvider();
}
diff --git a/platform/core-impl/src/com/intellij/openapi/application/ex/ApplicationUtil.java b/platform/core-impl/src/com/intellij/openapi/application/ex/ApplicationUtil.java
index 663cd6f9e0b3..1d7de90e5f61 100644
--- a/platform/core-impl/src/com/intellij/openapi/application/ex/ApplicationUtil.java
+++ b/platform/core-impl/src/com/intellij/openapi/application/ex/ApplicationUtil.java
@@ -35,6 +35,12 @@ public class ApplicationUtil {
throw new CannotRunReadActionException();
}
+ public static void tryRunReadAction(@NotNull final Runnable computable) throws CannotRunReadActionException {
+ if (!((ApplicationEx)ApplicationManager.getApplication()).tryRunReadAction(computable)) {
+ throw new CannotRunReadActionException();
+ }
+ }
+
public static class CannotRunReadActionException extends RuntimeException{
@Override
public Throwable fillInStackTrace() {
diff --git a/platform/core-impl/src/com/intellij/openapi/application/impl/ApplicationInfoImpl.java b/platform/core-impl/src/com/intellij/openapi/application/impl/ApplicationInfoImpl.java
index 62fbfa502c79..13d580ef0834 100644
--- a/platform/core-impl/src/com/intellij/openapi/application/impl/ApplicationInfoImpl.java
+++ b/platform/core-impl/src/com/intellij/openapi/application/impl/ApplicationInfoImpl.java
@@ -75,6 +75,7 @@ public class ApplicationInfoImpl extends ApplicationInfoEx implements JDOMExtern
private boolean myShowLicensee = true;
private String myWelcomeScreenCaptionUrl;
private String myWelcomeScreenDeveloperSloganUrl;
+ private String myCustomizeIDEWizardStepsProvider;
private UpdateUrls myUpdateUrls;
private String myDocumentationUrl;
private String mySupportUrl;
@@ -171,6 +172,8 @@ public class ApplicationInfoImpl extends ApplicationInfoEx implements JDOMExtern
@NonNls private static final String ELEMENT_THIRD_PARTY = "third-party";
+ @NonNls private static final String CUSTOMIZE_IDE_WIZARD_STEPS = "customize-ide-wizard";
+ @NonNls private static final String STEPS_PROVIDER = "provider";
public void initComponent() { }
@@ -311,6 +314,12 @@ public class ApplicationInfoImpl extends ApplicationInfoEx implements JDOMExtern
return myWelcomeScreenLogoUrl;
}
+ @Nullable
+ @Override
+ public String getCustomizeIDEWizardStepsProvider() {
+ return myCustomizeIDEWizardStepsProvider;
+ }
+
@Override
public String getEditorBackgroundImageUrl() {
return myEditorBackgroundImageUrl;
@@ -598,6 +607,11 @@ public class ApplicationInfoImpl extends ApplicationInfoEx implements JDOMExtern
myWelcomeScreenDeveloperSloganUrl = welcomeScreen.getAttributeValue(SLOGAN_URL_ATTR);
}
+ Element wizardSteps = parentNode.getChild(CUSTOMIZE_IDE_WIZARD_STEPS);
+ if (wizardSteps != null) {
+ myCustomizeIDEWizardStepsProvider = wizardSteps.getAttributeValue(STEPS_PROVIDER);
+ }
+
Element editor = parentNode.getChild(ELEMENT_EDITOR);
if (editor != null) {
myEditorBackgroundImageUrl = editor.getAttributeValue(BACKGROUND_URL_ATTR);
diff --git a/platform/core-impl/src/com/intellij/psi/impl/DocumentCommitProcessor.java b/platform/core-impl/src/com/intellij/psi/impl/DocumentCommitProcessor.java
index a42d7a1944f0..670aaf1d8493 100644
--- a/platform/core-impl/src/com/intellij/psi/impl/DocumentCommitProcessor.java
+++ b/platform/core-impl/src/com/intellij/psi/impl/DocumentCommitProcessor.java
@@ -51,20 +51,20 @@ public abstract class DocumentCommitProcessor {
public abstract void commitAsynchronously(@NotNull final Project project, @NotNull final Document document, @NonNls @NotNull Object reason);
protected static class CommitTask {
- public final Document document;
- public final Project project;
+ @NotNull public final Document document;
+ @NotNull public final Project project;
// when queued it's not started
// when dequeued it's started
// when failed it's canceled
- public final ProgressIndicator indicator; // progress to commit this doc under.
- public final Object reason;
+ @NotNull public final ProgressIndicator indicator; // progress to commit this doc under.
+ @NotNull public final Object reason;
public boolean removed; // task marked as removed, should be ignored.
public CommitTask(@NotNull Document document,
- @NotNull Project project,
- @NotNull ProgressIndicator indicator,
- @NotNull Object reason) {
+ @NotNull Project project,
+ @NotNull ProgressIndicator indicator,
+ @NotNull Object reason) {
this.document = document;
this.project = project;
this.indicator = indicator;
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/PsiCommentImpl.java b/platform/core-impl/src/com/intellij/psi/impl/source/tree/PsiCommentImpl.java
index d4e1b0d52f53..70bc987a91f8 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/PsiCommentImpl.java
+++ b/platform/core-impl/src/com/intellij/psi/impl/source/tree/PsiCommentImpl.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.
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/CommentLiteralEscaper.java b/platform/core-impl/src/com/intellij/psi/impl/source/tree/injected/CommentLiteralEscaper.java
index c6399e30b5f6..3374a2b59f87 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/CommentLiteralEscaper.java
+++ b/platform/core-impl/src/com/intellij/psi/impl/source/tree/injected/CommentLiteralEscaper.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.
diff --git a/platform/duplicates-analysis/src/com/intellij/dupLocator/index/DuplicatesIndex.java b/platform/duplicates-analysis/src/com/intellij/dupLocator/index/DuplicatesIndex.java
index cacbcf89aca0..1255a7fec9e3 100644
--- a/platform/duplicates-analysis/src/com/intellij/dupLocator/index/DuplicatesIndex.java
+++ b/platform/duplicates-analysis/src/com/intellij/dupLocator/index/DuplicatesIndex.java
@@ -58,7 +58,7 @@ public class DuplicatesIndex extends FileBasedIndexExtension<Integer, TIntArrayL
}
@NonNls public static final ID<Integer, TIntArrayList> NAME = ID.create("DuplicatesIndex");
- private static final int myBaseVersion = 9;
+ private static final int myBaseVersion = 10;
private final FileBasedIndex.InputFilter myInputFilter = new FileBasedIndex.InputFilter() {
@Override
diff --git a/platform/dvcs-api/dvcs-api.iml b/platform/dvcs-api/dvcs-api.iml
new file mode 100644
index 000000000000..f425c986a066
--- /dev/null
+++ b/platform/dvcs-api/dvcs-api.iml
@@ -0,0 +1,18 @@
+<?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-rt" />
+ <orderEntry type="module" module-name="vcs-log-graph-api" exported="" />
+ <orderEntry type="module" module-name="core-api" />
+ <orderEntry type="module" module-name="vcs-api" />
+ <orderEntry type="module" module-name="extensions" />
+ <orderEntry type="module" module-name="vcs-log-api" />
+ </component>
+</module>
+
diff --git a/platform/dvcs-api/src/com/intellij/dvcs/push/CommitLoader.java b/platform/dvcs-api/src/com/intellij/dvcs/push/CommitLoader.java
new file mode 100644
index 000000000000..71ffa32d93e2
--- /dev/null
+++ b/platform/dvcs-api/src/com/intellij/dvcs/push/CommitLoader.java
@@ -0,0 +1,20 @@
+/*
+ * 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.push;
+
+public interface CommitLoader {
+ void reloadCommits();
+}
diff --git a/platform/dvcs-api/src/com/intellij/dvcs/push/OutgoingCommitsProvider.java b/platform/dvcs-api/src/com/intellij/dvcs/push/OutgoingCommitsProvider.java
new file mode 100644
index 000000000000..4532146f9b4a
--- /dev/null
+++ b/platform/dvcs-api/src/com/intellij/dvcs/push/OutgoingCommitsProvider.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.dvcs.push;
+
+import com.intellij.dvcs.repo.Repository;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Provider for outgoing commits
+ */
+public abstract class OutgoingCommitsProvider {
+
+ /**
+ * Collect outgoing commits or errors for selected repo for specified {@link PushSpec} and store to {@link OutgoingResult}
+ *
+ * @param initial true for first commits loading, which identify that all inside actions should be silent
+ * and do not ask user about smth, a.e authorization request
+ */
+ @NotNull
+ public abstract OutgoingResult getOutgoingCommits(@NotNull Repository repository,
+ @NotNull PushSpec pushSpec, boolean initial);
+}
diff --git a/platform/dvcs-api/src/com/intellij/dvcs/push/OutgoingResult.java b/platform/dvcs-api/src/com/intellij/dvcs/push/OutgoingResult.java
new file mode 100644
index 000000000000..7b4b0a7b4a81
--- /dev/null
+++ b/platform/dvcs-api/src/com/intellij/dvcs/push/OutgoingResult.java
@@ -0,0 +1,41 @@
+/*
+ * 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.push;
+
+import com.intellij.vcs.log.VcsFullCommitDetails;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+public class OutgoingResult {
+ @NotNull private final List<VcsError> myErrors;
+ @NotNull private final List<? extends VcsFullCommitDetails> myCommits;
+
+ public OutgoingResult(@NotNull List<? extends VcsFullCommitDetails> commits, @NotNull List<VcsError> errors) {
+ myCommits = commits;
+ myErrors = errors;
+ }
+
+ @NotNull
+ public List<VcsError> getErrors() {
+ return myErrors;
+ }
+
+ @NotNull
+ public List<? extends VcsFullCommitDetails> getCommits() {
+ return myCommits;
+ }
+}
diff --git a/platform/dvcs-api/src/com/intellij/dvcs/push/PushSource.java b/platform/dvcs-api/src/com/intellij/dvcs/push/PushSource.java
new file mode 100644
index 000000000000..7ae7a33dd6e2
--- /dev/null
+++ b/platform/dvcs-api/src/com/intellij/dvcs/push/PushSource.java
@@ -0,0 +1,26 @@
+/*
+ * 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.push;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Source to push from. For example, local branch for git or branch/bookmark for mercurial.
+ */
+public interface PushSource {
+ @NotNull
+ String getPresentation();
+}
diff --git a/platform/dvcs-api/src/com/intellij/dvcs/push/PushSpec.java b/platform/dvcs-api/src/com/intellij/dvcs/push/PushSpec.java
new file mode 100644
index 000000000000..81ff874979bd
--- /dev/null
+++ b/platform/dvcs-api/src/com/intellij/dvcs/push/PushSpec.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 com.intellij.dvcs.push;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Specified a push from-to settings for one repository
+ */
+public class PushSpec {
+
+ @NotNull private PushSource mySource;
+ @Nullable private PushTarget myTarget;
+
+ public PushSpec(@NotNull PushSource source, @Nullable PushTarget target) {
+ mySource = source;
+ myTarget = target;
+ }
+
+ @NotNull
+ public PushSource getSource() {
+ return mySource;
+ }
+
+ @Nullable
+ public PushTarget getTarget() {
+ return myTarget;
+ }
+}
diff --git a/platform/dvcs-api/src/com/intellij/dvcs/push/PushSupport.java b/platform/dvcs-api/src/com/intellij/dvcs/push/PushSupport.java
new file mode 100644
index 000000000000..d6af8eec1088
--- /dev/null
+++ b/platform/dvcs-api/src/com/intellij/dvcs/push/PushSupport.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 com.intellij.dvcs.push;
+
+import com.intellij.dvcs.repo.Repository;
+import com.intellij.dvcs.repo.RepositoryManager;
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.openapi.vcs.AbstractVcs;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collection;
+
+/**
+ * Base class to provide vcs-specific info
+ */
+
+public abstract class PushSupport<Repo extends Repository> {
+
+ public static final ExtensionPointName<PushSupport<? extends Repository>> PUSH_SUPPORT_EP =
+ ExtensionPointName.create("com.intellij.pushSupport");
+
+ @NotNull
+ public abstract AbstractVcs getVcs();
+
+ @NotNull
+ public abstract Pusher getPusher();
+
+ @NotNull
+ public abstract OutgoingCommitsProvider getOutgoingCommitsProvider();
+
+ /**
+ * @return Default push destination
+ */
+ @Nullable
+ public abstract PushTarget getDefaultTarget(@NotNull Repo repository);
+
+ /**
+ * @return All remembered remote destinations used for completion
+ */
+ @NotNull
+ public abstract Collection<String> getTargetNames(@NotNull Repo repository);
+
+ /**
+ * @return current source(branch) for repository
+ */
+ @NotNull
+ public abstract PushSource getSource(@NotNull Repo repository);
+
+ /**
+ * Parse user input string, and create the valid target for push,
+ * or return <code><b>null</b></code> if the target name is not valid.
+ *
+ * @see #validateSpec(Repository, PushSpec)
+ */
+ @Nullable
+ public abstract PushTarget createTarget(@NotNull Repo repository, @NotNull String targetName);
+
+ /**
+ * @return RepositoryManager for vcs
+ */
+ @NotNull
+ public abstract RepositoryManager<Repo> getRepositoryManager();
+
+ @Nullable
+ public VcsPushOptionsPanel getVcsPushOptionsPanel() {
+ return null;
+ }
+
+ /**
+ * @return null if target is valid for selected repository
+ */
+ @Nullable
+ public abstract VcsError validate(@NotNull Repository repository, @Nullable String targetToValidate);
+}
diff --git a/platform/remote-servers/agent-rt/src/com/intellij/remoteServer/agent/util/CloudLoggingHandler.java b/platform/dvcs-api/src/com/intellij/dvcs/push/PushTarget.java
index 9fad3190e865..87c7244bd77c 100644
--- a/platform/remote-servers/agent-rt/src/com/intellij/remoteServer/agent/util/CloudLoggingHandler.java
+++ b/platform/dvcs-api/src/com/intellij/dvcs/push/PushTarget.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,14 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.intellij.remoteServer.agent.util;
+package com.intellij.dvcs.push;
+
+import org.jetbrains.annotations.NotNull;
-import com.intellij.remoteServer.agent.util.log.LogListener;
/**
- * @author michael.golubev
+ * Destination for push action. (Remote for git or push-path for mercurial).
*/
-public interface CloudLoggingHandler extends CloudAgentLoggingHandler {
+public interface PushTarget {
- LogListener getOrCreateLogListener(String pipeName);
+ @NotNull
+ String getPresentation();
}
diff --git a/platform/dvcs-api/src/com/intellij/dvcs/push/Pusher.java b/platform/dvcs-api/src/com/intellij/dvcs/push/Pusher.java
new file mode 100644
index 000000000000..6d5fc1611030
--- /dev/null
+++ b/platform/dvcs-api/src/com/intellij/dvcs/push/Pusher.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.dvcs.push;
+
+import com.intellij.dvcs.repo.Repository;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Map;
+
+/**
+ * Base class to execute push command.
+ */
+public abstract class Pusher {
+ /**
+ * Perform push command for all repositories belonged to one vcs.
+ *
+ * @param pushSpecs specify push from and to params
+ * @param vcsPushOptionValue specify additional options to push, null if not supported
+ * @param force if true then execute force push
+ */
+ public abstract void push(@NotNull Map<Repository, PushSpec> pushSpecs,
+ @Nullable VcsPushOptionValue vcsPushOptionValue,
+ boolean force);
+}
+
diff --git a/platform/dvcs-api/src/com/intellij/dvcs/push/TreeNodeLinkListener.java b/platform/dvcs-api/src/com/intellij/dvcs/push/TreeNodeLinkListener.java
new file mode 100644
index 000000000000..8ce03d299b29
--- /dev/null
+++ b/platform/dvcs-api/src/com/intellij/dvcs/push/TreeNodeLinkListener.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 com.intellij.dvcs.push;
+
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.tree.DefaultMutableTreeNode;
+
+public interface TreeNodeLinkListener {
+ void onClick(@NotNull DefaultMutableTreeNode source);
+}
diff --git a/platform/dvcs-api/src/com/intellij/dvcs/push/VcsError.java b/platform/dvcs-api/src/com/intellij/dvcs/push/VcsError.java
new file mode 100644
index 000000000000..de2c640d12b1
--- /dev/null
+++ b/platform/dvcs-api/src/com/intellij/dvcs/push/VcsError.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 com.intellij.dvcs.push;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class VcsError {
+ @NotNull String myErrorText;
+ @Nullable private final VcsErrorHandler myErrorHandleListener;
+
+ public VcsError(@NotNull String text) {
+ this(text, null);
+ }
+
+ public VcsError(@NotNull String text, @Nullable VcsErrorHandler listener) {
+ myErrorText = text;
+ myErrorHandleListener = listener;
+ }
+
+ public String getText() {
+ return myErrorText;
+ }
+
+ public void handleError(@NotNull CommitLoader loader) {
+ if (myErrorHandleListener != null) {
+ myErrorHandleListener.handleError(loader);
+ }
+ }
+}
diff --git a/platform/dvcs-api/src/com/intellij/dvcs/push/VcsErrorHandler.java b/platform/dvcs-api/src/com/intellij/dvcs/push/VcsErrorHandler.java
new file mode 100644
index 000000000000..c27e4c7e99d9
--- /dev/null
+++ b/platform/dvcs-api/src/com/intellij/dvcs/push/VcsErrorHandler.java
@@ -0,0 +1,22 @@
+/*
+ * 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.push;
+
+import org.jetbrains.annotations.NotNull;
+
+public interface VcsErrorHandler {
+ void handleError(@NotNull CommitLoader loader);
+}
diff --git a/platform/dvcs-api/src/com/intellij/dvcs/push/VcsPushOptionValue.java b/platform/dvcs-api/src/com/intellij/dvcs/push/VcsPushOptionValue.java
new file mode 100644
index 000000000000..61a50eb09d73
--- /dev/null
+++ b/platform/dvcs-api/src/com/intellij/dvcs/push/VcsPushOptionValue.java
@@ -0,0 +1,19 @@
+/*
+ * 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.push;
+
+public interface VcsPushOptionValue {
+}
diff --git a/platform/dvcs-api/src/com/intellij/dvcs/push/VcsPushOptionsPanel.java b/platform/dvcs-api/src/com/intellij/dvcs/push/VcsPushOptionsPanel.java
new file mode 100644
index 000000000000..5ecd9af0d182
--- /dev/null
+++ b/platform/dvcs-api/src/com/intellij/dvcs/push/VcsPushOptionsPanel.java
@@ -0,0 +1,29 @@
+/*
+ * 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.push;
+
+import javax.swing.*;
+import java.awt.event.ActionListener;
+
+public abstract class VcsPushOptionsPanel extends JPanel {
+
+ public abstract VcsPushOptionValue getValue();
+
+ /**
+ * @param listener handle valueChange event
+ */
+ public abstract void addValueChangeListener(ActionListener listener);
+}
diff --git a/platform/dvcs-api/src/com/intellij/dvcs/push/VcsPushReferenceStrategy.java b/platform/dvcs-api/src/com/intellij/dvcs/push/VcsPushReferenceStrategy.java
new file mode 100644
index 000000000000..7e4cbecb796b
--- /dev/null
+++ b/platform/dvcs-api/src/com/intellij/dvcs/push/VcsPushReferenceStrategy.java
@@ -0,0 +1,26 @@
+/*
+ * 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.push;
+
+/**
+ * Specify which references(tags) should be pushed
+ */
+
+public enum VcsPushReferenceStrategy {
+ none, // do not push references/tags
+ follow, // push references only for selected sources
+ all // push all references for all repositories
+}
diff --git a/platform/dvcs/src/com/intellij/dvcs/repo/Repository.java b/platform/dvcs-api/src/com/intellij/dvcs/repo/Repository.java
index c12cf4ff0407..47cc17866c08 100644
--- a/platform/dvcs/src/com/intellij/dvcs/repo/Repository.java
+++ b/platform/dvcs-api/src/com/intellij/dvcs/repo/Repository.java
@@ -17,6 +17,7 @@ package com.intellij.dvcs.repo;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vcs.AbstractVcs;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -97,6 +98,9 @@ public interface Repository extends Disposable {
@NotNull
State getState();
+ @Nullable
+ AbstractVcs getVcs();
+
/**
* Returns the hash of the revision, which HEAD currently points to.
* Returns null only in the case of a fresh repository, when no commit have been made.
diff --git a/platform/dvcs/src/com/intellij/dvcs/repo/RepositoryManager.java b/platform/dvcs-api/src/com/intellij/dvcs/repo/RepositoryManager.java
index d27694cd05d0..d27694cd05d0 100644
--- a/platform/dvcs/src/com/intellij/dvcs/repo/RepositoryManager.java
+++ b/platform/dvcs-api/src/com/intellij/dvcs/repo/RepositoryManager.java
diff --git a/platform/dvcs/dvcs.iml b/platform/dvcs-impl/dvcs-impl.iml
index 145ad6363140..43dd32b785b4 100644
--- a/platform/dvcs/dvcs.iml
+++ b/platform/dvcs-impl/dvcs-impl.iml
@@ -5,6 +5,7 @@
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/testFramework" isTestSource="true" />
+ <sourceFolder url="file://$MODULE_DIR$/resources" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
@@ -17,6 +18,8 @@
<orderEntry type="module" module-name="vcs-log-api" />
<orderEntry type="module" module-name="vcs-log-impl" />
<orderEntry type="module" module-name="images" />
+ <orderEntry type="module" module-name="lang-impl" />
+ <orderEntry type="module" module-name="dvcs-api" />
</component>
</module>
diff --git a/platform/dvcs-impl/resources/icons/Loading@2x.gif b/platform/dvcs-impl/resources/icons/Loading@2x.gif
new file mode 100644
index 000000000000..77c756d99cb1
--- /dev/null
+++ b/platform/dvcs-impl/resources/icons/Loading@2x.gif
Binary files differ
diff --git a/platform/dvcs-impl/resources/icons/Loading@2x_dark.gif b/platform/dvcs-impl/resources/icons/Loading@2x_dark.gif
new file mode 100644
index 000000000000..f95c9287108f
--- /dev/null
+++ b/platform/dvcs-impl/resources/icons/Loading@2x_dark.gif
Binary files differ
diff --git a/platform/dvcs-impl/resources/icons/loading.gif b/platform/dvcs-impl/resources/icons/loading.gif
new file mode 100644
index 000000000000..bfd4da223753
--- /dev/null
+++ b/platform/dvcs-impl/resources/icons/loading.gif
Binary files differ
diff --git a/platform/dvcs-impl/resources/icons/loading_dark.gif b/platform/dvcs-impl/resources/icons/loading_dark.gif
new file mode 100644
index 000000000000..e41778b2c6e7
--- /dev/null
+++ b/platform/dvcs-impl/resources/icons/loading_dark.gif
Binary files differ
diff --git a/platform/dvcs-impl/src/META-INF/dvcs.xml b/platform/dvcs-impl/src/META-INF/dvcs.xml
new file mode 100644
index 000000000000..aa81616f24f6
--- /dev/null
+++ b/platform/dvcs-impl/src/META-INF/dvcs.xml
@@ -0,0 +1,12 @@
+<idea-plugin>
+ <extensionPoints>
+ <extensionPoint name="pushSupport"
+ interface="com.intellij.dvcs.push.PushSupport" area="IDEA_PROJECT"/>
+ </extensionPoints>
+ <actions>
+ <!--<action id="Vcs.Push" class="">-->
+ <!--<keyboard-shortcut first-keystroke="control shift K" keymap="$default"/>-->
+ <!--</action>-->
+ </actions>
+</idea-plugin>
+
diff --git a/platform/dvcs/src/com/intellij/dvcs/DvcsCommitAdditionalComponent.java b/platform/dvcs-impl/src/com/intellij/dvcs/DvcsCommitAdditionalComponent.java
index 26c87c7de627..26c87c7de627 100644
--- a/platform/dvcs/src/com/intellij/dvcs/DvcsCommitAdditionalComponent.java
+++ b/platform/dvcs-impl/src/com/intellij/dvcs/DvcsCommitAdditionalComponent.java
diff --git a/platform/dvcs/src/com/intellij/dvcs/DvcsPlatformFacade.java b/platform/dvcs-impl/src/com/intellij/dvcs/DvcsPlatformFacade.java
index 91adfa23dd92..91adfa23dd92 100644
--- a/platform/dvcs/src/com/intellij/dvcs/DvcsPlatformFacade.java
+++ b/platform/dvcs-impl/src/com/intellij/dvcs/DvcsPlatformFacade.java
diff --git a/platform/dvcs/src/com/intellij/dvcs/DvcsPlatformFacadeImpl.java b/platform/dvcs-impl/src/com/intellij/dvcs/DvcsPlatformFacadeImpl.java
index 9f10311f68d3..9f10311f68d3 100644
--- a/platform/dvcs/src/com/intellij/dvcs/DvcsPlatformFacadeImpl.java
+++ b/platform/dvcs-impl/src/com/intellij/dvcs/DvcsPlatformFacadeImpl.java
diff --git a/platform/dvcs/src/com/intellij/dvcs/DvcsRememberedInputs.java b/platform/dvcs-impl/src/com/intellij/dvcs/DvcsRememberedInputs.java
index 58292aa17f91..58292aa17f91 100644
--- a/platform/dvcs/src/com/intellij/dvcs/DvcsRememberedInputs.java
+++ b/platform/dvcs-impl/src/com/intellij/dvcs/DvcsRememberedInputs.java
diff --git a/platform/dvcs/src/com/intellij/dvcs/DvcsUtil.java b/platform/dvcs-impl/src/com/intellij/dvcs/DvcsUtil.java
index c2aef0502db5..1fba1827084c 100644
--- a/platform/dvcs/src/com/intellij/dvcs/DvcsUtil.java
+++ b/platform/dvcs-impl/src/com/intellij/dvcs/DvcsUtil.java
@@ -39,6 +39,8 @@ import com.intellij.openapi.wm.WindowManager;
import com.intellij.openapi.wm.impl.status.StatusBarUtil;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.text.DateFormatUtil;
+import com.intellij.vcs.log.TimedVcsCommit;
import com.intellij.vcs.log.VcsLog;
import com.intellij.vcs.log.VcsLogProvider;
import org.intellij.images.editor.ImageFileEditor;
@@ -55,6 +57,8 @@ import java.util.List;
*/
public class DvcsUtil {
+ private static final int SHORT_HASH_LENGTH = 8;
+
public static void installStatusBarWidget(@NotNull Project project, @NotNull StatusBarWidget widget) {
StatusBar statusBar = WindowManager.getInstance().getStatusBar(project);
if (statusBar != null) {
@@ -183,4 +187,19 @@ public class DvcsUtil {
return result;
}
+ @NotNull
+ public static String getShortHash(@NotNull String hash) {
+ if (hash.length() == 0) return "";
+ if (hash.length() == 40) return hash.substring(0, SHORT_HASH_LENGTH);
+ if (hash.length() > 40) // revision string encoded with date too
+ {
+ return hash.substring(hash.indexOf("[") + 1, SHORT_HASH_LENGTH);
+ }
+ return hash;
+ }
+
+ @NotNull
+ public static String getDateString(@NotNull TimedVcsCommit commit) {
+ return DateFormatUtil.formatPrettyDateTime(commit.getTimestamp()) + " ";
+ }
}
diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/PushController.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/PushController.java
new file mode 100644
index 000000000000..2a409e12c854
--- /dev/null
+++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/PushController.java
@@ -0,0 +1,445 @@
+/*
+ * 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.push;
+
+import com.intellij.dvcs.DvcsUtil;
+import com.intellij.dvcs.push.ui.*;
+import com.intellij.dvcs.repo.Repository;
+import com.intellij.dvcs.repo.RepositoryManager;
+import com.intellij.openapi.Disposable;
+import com.intellij.openapi.application.ModalityState;
+import com.intellij.openapi.extensions.Extensions;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.Task;
+import com.intellij.openapi.progress.impl.ProgressManagerImpl;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.ValidationInfo;
+import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.Disposer;
+import com.intellij.openapi.vcs.AbstractVcs;
+import com.intellij.ui.CheckedTreeNode;
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.hash.HashMap;
+import com.intellij.vcs.log.VcsFullCommitDetails;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import javax.swing.tree.DefaultMutableTreeNode;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.*;
+import java.util.concurrent.atomic.AtomicReference;
+
+public class PushController implements Disposable {
+
+ @NotNull private final Project myProject;
+ @NotNull private final List<PushSupport<? extends Repository>> myPushSupports;
+ @NotNull private final PushLog myPushLog;
+ @NotNull private final VcsPushDialog myDialog;
+ private boolean mySingleRepoProject;
+ private static final int DEFAULT_CHILDREN_PRESENTATION_NUMBER = 20;
+ private final Map<PushSupport, MyPushOptionValueModel> myAdditionalValuesMap;
+
+ private final Map<RepositoryNode, MyRepoModel> myView2Model = new HashMap<RepositoryNode, MyRepoModel>();
+
+
+ public PushController(@NotNull Project project,
+ @NotNull VcsPushDialog dialog,
+ @NotNull List<? extends Repository> preselectedRepositories) {
+ myProject = project;
+ //todo what would be in case of null
+ myPushSupports = Arrays.asList(Extensions.getExtensions(PushSupport.PUSH_SUPPORT_EP, myProject));
+ CheckedTreeNode rootNode = new CheckedTreeNode(null);
+ mySingleRepoProject = createTreeModel(rootNode, preselectedRepositories);
+ myPushLog = new PushLog(myProject, rootNode);
+ myAdditionalValuesMap = new HashMap<PushSupport, MyPushOptionValueModel>();
+ myDialog = dialog;
+ myDialog.updateButtons();
+ startLoadingCommits();
+ Disposer.register(dialog.getDisposable(), this);
+ }
+
+ @Nullable
+ public ValidationInfo validate() {
+ ValidationInfo validInfo = new ValidationInfo("There are no selected repository to push!");
+ for (Map.Entry<RepositoryNode, MyRepoModel> entry : myView2Model.entrySet()) {
+ MyRepoModel model = entry.getValue();
+ if (model.isSelected()) {
+ //has one or more selected roots
+ validInfo = null;
+ RepositoryNode node = entry.getKey();
+ PushTarget target = model.getSpec().getTarget();
+ //todo add validation for model -> hasErrors, too
+ if (target == null) {
+ JComponent editingComponent = myPushLog.startEditNode(node);
+ return new ValidationInfo("Invalid remote for repository " + DvcsUtil.getShortRepositoryName(model.getRepository()),
+ editingComponent);
+ }
+ }
+ }
+ return validInfo;
+ }
+
+ private void startLoadingCommits() {
+ //todo should be reworked
+ Map<RepositoryNode, MyRepoModel> priorityLoading = new HashMap<RepositoryNode, MyRepoModel>();
+ Map<RepositoryNode, MyRepoModel> others = new HashMap<RepositoryNode, MyRepoModel>();
+ for (Map.Entry<RepositoryNode, MyRepoModel> entry : myView2Model.entrySet()) {
+ MyRepoModel model = entry.getValue();
+ if (model.isSelected()) {
+ priorityLoading.put(entry.getKey(), model);
+ }
+ else {
+ others.put(entry.getKey(), model);
+ }
+ }
+ loadCommitsFromMap(priorityLoading);
+ loadCommitsFromMap(others);
+ }
+
+ private void loadCommitsFromMap(@NotNull Map<RepositoryNode, MyRepoModel> items) {
+ for (Map.Entry<RepositoryNode, MyRepoModel> entry : items.entrySet()) {
+ RepositoryNode node = entry.getKey();
+ loadCommits(entry.getValue(), node, true);
+ }
+ }
+
+ //return is single repository project or not
+ private boolean createTreeModel(@NotNull CheckedTreeNode rootNode, @NotNull List<? extends Repository> preselectedRepositories) {
+ if (myPushSupports.isEmpty()) return true;
+ int repoCount = 0;
+ for (PushSupport<? extends Repository> support : myPushSupports) {
+ repoCount += createNodesForVcs(support, rootNode, preselectedRepositories);
+ }
+ return repoCount == 1;
+ }
+
+ private <T extends Repository> int createNodesForVcs(@NotNull PushSupport<T> pushSupport,
+ @NotNull CheckedTreeNode rootNode,
+ @NotNull List<? extends Repository> preselectedRepositories) {
+ RepositoryManager<T> repositoryManager = pushSupport.getRepositoryManager();
+ List<T> repositories = repositoryManager.getRepositories();
+ for (T repository : repositories) {
+ createRepoNode(pushSupport, repository, rootNode, preselectedRepositories.contains(repository), repositories.size() == 1);
+ }
+ return repositories.size();
+ }
+
+ private <T extends Repository> void createRepoNode(@NotNull final PushSupport<T> support,
+ @NotNull final T repository,
+ @NotNull CheckedTreeNode rootNode,
+ boolean isSelected,
+ boolean isSingleRepositoryProject) {
+ PushTarget target = support.getDefaultTarget(repository);
+ final MyRepoModel model = new MyRepoModel(repository, support, isSelected, new PushSpec(support.getSource(repository), target),
+ DEFAULT_CHILDREN_PRESENTATION_NUMBER);
+ RepositoryWithBranchPanel repoPanel = new RepositoryWithBranchPanel(myProject, DvcsUtil.getShortRepositoryName(repository),
+ support.getSource(repository).getPresentation(),
+ target == null ? "" : target.getPresentation(),
+ support.getTargetNames(repository));
+ final RepositoryNode repoNode = isSingleRepositoryProject ? new SingleRepositoryNode(repoPanel) : new RepositoryNode(repoPanel);
+ myView2Model.put(repoNode, model);
+ repoNode.setChecked(model.isSelected());
+ repoPanel.addRepoNodeListener(new RepositoryNodeListener() {
+ @Override
+ public void onTargetChanged(String newValue) {
+ VcsError validationError = support.validate(model.getRepository(), newValue);
+ if (validationError == null) {
+ myView2Model.get(repoNode).setSpec(new PushSpec(model.getSpec().getSource(), support.createTarget(repository, newValue)));
+ loadCommits(model, repoNode, false);
+ }
+ else {
+ //todo may be should store validation errors in model and get errors during dialog validation
+ myView2Model.get(repoNode).setSpec(new PushSpec(model.getSpec().getSource(), null));
+ }
+ myDialog.updateButtons();
+ }
+
+ @Override
+ public void onSelectionChanged(boolean isSelected) {
+ myView2Model.get(repoNode).setSelected(isSelected);
+ repoNode.setChecked(isSelected);
+ myDialog.updateButtons();
+ }
+ });
+ rootNode.add(repoNode);
+ }
+
+ private void loadCommits(@NotNull final MyRepoModel model,
+ @NotNull final RepositoryNode node,
+ final boolean initial) {
+ node.stopLoading();
+ myPushLog.startLoading(node);
+ final ProgressIndicator indicator = node.startLoading();
+ final PushSupport support = model.getSupport();
+ final AtomicReference<OutgoingResult> result = new AtomicReference<OutgoingResult>();
+ Task.Backgroundable task = new Task.Backgroundable(myProject, "Loading Commits", true) {
+
+ @Override
+ public void onCancel() {
+ node.stopLoading();
+ }
+
+ @Override
+ public void onSuccess() {
+ OutgoingResult outgoing = result.get();
+ List<VcsError> errors = outgoing.getErrors();
+ if (!errors.isEmpty()) {
+ myPushLog.setChildren(node, ContainerUtil.map(errors, new Function<VcsError, DefaultMutableTreeNode>() {
+ @Override
+ public DefaultMutableTreeNode fun(final VcsError error) {
+ VcsLinkedText errorLinkText = new VcsLinkedText(error.getText(), new VcsLinkListener() {
+ @Override
+ public void hyperlinkActivated(@NotNull DefaultMutableTreeNode sourceNode) {
+ error.handleError(new CommitLoader() {
+ @Override
+ public void reloadCommits() {
+ loadCommits(model, node, false);
+ }
+ });
+ }
+ });
+ return new TextWithLinkNode(errorLinkText);
+ }
+ }), model.isSelected());
+ }
+ else {
+ model.setLoadedCommits(outgoing.getCommits());
+ myPushLog.setChildren(node,
+ getPresentationForCommits(PushController.this.myProject, model.getLoadedCommits(),
+ model.getNumberOfShownCommits()), model.isSelected());
+ }
+ }
+
+ @Override
+ public void run(@NotNull ProgressIndicator indicator) {
+ OutgoingResult outgoing = support.getOutgoingCommitsProvider()
+ .getOutgoingCommits(model.getRepository(), model.getSpec(), initial);
+ result.compareAndSet(null, outgoing);
+ }
+ };
+
+ ProgressManagerImpl.runProcessWithProgressAsynchronously(task, indicator, null, ModalityState.any());
+ }
+
+
+ public PushLog getPushPanelInfo() {
+ return myPushLog;
+ }
+
+ public void push(final boolean force) {
+ Task.Backgroundable task = new Task.Backgroundable(myProject, "Pushing...", false) {
+ @Override
+ public void run(@NotNull ProgressIndicator indicator) {
+ for (PushSupport support : myPushSupports) {
+ MyPushOptionValueModel additionalOptionsModel = myAdditionalValuesMap.get(support);
+ support.getPusher()
+ .push(collectPushInfoForVcs(support), additionalOptionsModel == null ? null : additionalOptionsModel.getCurrentValue(), force);
+ }
+ }
+ };
+ task.queue();
+ }
+
+ @NotNull
+ private Map<Repository, PushSpec> collectPushInfoForVcs(@NotNull final PushSupport pushSupport) {
+ Map<Repository, PushSpec> pushSpecs = new HashMap<Repository, PushSpec>();
+ Collection<MyRepoModel> repositoriesInformation = getSelectedRepoNode();
+ for (MyRepoModel repoModel : repositoriesInformation) {
+ if (pushSupport.equals(repoModel.getSupport())) {
+ pushSpecs.put(repoModel.getRepository(), repoModel.getSpec());
+ }
+ }
+ return pushSpecs;
+ }
+
+ public Collection<MyRepoModel> getSelectedRepoNode() {
+ if (mySingleRepoProject) {
+ return myView2Model.values();
+ }
+ return ContainerUtil.filter(myView2Model.values(), new Condition<MyRepoModel>() {
+ @Override
+ public boolean value(MyRepoModel model) {
+ return model.isSelected();
+ }
+ });
+ }
+
+ @Override
+ public void dispose() {
+ for (RepositoryNode node : myView2Model.keySet()) {
+ node.stopLoading();
+ }
+ }
+
+ private void addMoreCommits(RepositoryNode repositoryNode) {
+ MyRepoModel repoModel = myView2Model.get(repositoryNode);
+ repoModel.increaseShownCommits();
+ myPushLog.setChildren(repositoryNode,
+ getPresentationForCommits(
+ myProject,
+ repoModel.getLoadedCommits(),
+ repoModel.getNumberOfShownCommits()
+ ));
+ }
+
+
+ @NotNull
+ public List<DefaultMutableTreeNode> getPresentationForCommits(@NotNull final Project project,
+ @NotNull List<? extends VcsFullCommitDetails> commits,
+ int commitsNum) {
+ Function<VcsFullCommitDetails, DefaultMutableTreeNode> commitToNode = new Function<VcsFullCommitDetails, DefaultMutableTreeNode>() {
+ @Override
+ public DefaultMutableTreeNode fun(VcsFullCommitDetails commit) {
+ return new VcsFullCommitDetailsNode(project, commit);
+ }
+ };
+ List<DefaultMutableTreeNode> childrenToShown = new ArrayList<DefaultMutableTreeNode>();
+ for (int i = 0; i < commits.size(); ++i) {
+ if (i >= commitsNum) {
+ final VcsLinkedText moreCommitsLink = new VcsLinkedText("<a href='loadMore'>...</a>", new VcsLinkListener() {
+ @Override
+ public void hyperlinkActivated(@NotNull DefaultMutableTreeNode sourceNode) {
+ addMoreCommits((RepositoryNode)sourceNode);
+ }
+ });
+ childrenToShown.add(new TextWithLinkNode(moreCommitsLink));
+ break;
+ }
+ childrenToShown.add(commitToNode.fun(commits.get(i)));
+ }
+ return childrenToShown;
+ }
+
+ @NotNull
+ public List<VcsPushOptionsPanel> getAdditionalPanels() {
+ List<VcsPushOptionsPanel> additionalPanels = new ArrayList<VcsPushOptionsPanel>();
+ for (final PushSupport support : myPushSupports) {
+ if (hasRepoForPushSupport(support)) {
+ final VcsPushOptionsPanel panel = support.getVcsPushOptionsPanel();
+ if (panel != null) {
+ additionalPanels.add(panel);
+ myAdditionalValuesMap.put(support, new MyPushOptionValueModel(panel.getValue()));
+ panel.addValueChangeListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ myAdditionalValuesMap.get(support).setCurrentValue(panel.getValue());
+ }
+ });
+ }
+ }
+ }
+ return additionalPanels;
+ }
+
+ private boolean hasRepoForPushSupport(@NotNull final PushSupport support) {
+ return ContainerUtil.exists(myView2Model.values(), new Condition<MyRepoModel>() {
+ @Override
+ public boolean value(MyRepoModel model) {
+ return support.equals(model.getSupport());
+ }
+ });
+ }
+
+ private static class MyRepoModel {
+ @NotNull final Repository myRepository;
+ @NotNull private PushSupport mySupport;
+
+ @NotNull PushSpec mySpec;
+ int myNumberOfShownCommits;
+
+ List<? extends VcsFullCommitDetails> myLoadedCommits;
+ boolean myIsSelected;
+
+ public MyRepoModel(@NotNull Repository repository,
+ @NotNull PushSupport supportForRepo,
+ boolean isSelected,
+ @NotNull PushSpec spec,
+ int num) {
+ myRepository = repository;
+ mySupport = supportForRepo;
+ myIsSelected = isSelected;
+ mySpec = spec;
+ myNumberOfShownCommits = num;
+ }
+
+ @NotNull
+ public Repository getRepository() {
+ return myRepository;
+ }
+
+ @NotNull
+ public PushSupport getSupport() {
+ return mySupport;
+ }
+
+ public boolean isSelected() {
+ return myIsSelected;
+ }
+
+ public AbstractVcs<?> getVcs() {
+ return myRepository.getVcs();
+ }
+
+ @NotNull
+ public PushSpec getSpec() {
+ return mySpec;
+ }
+
+ public void setSpec(@NotNull PushSpec spec) {
+ mySpec = spec;
+ }
+
+ public void setSelected(boolean isSelected) {
+ myIsSelected = isSelected;
+ }
+
+ public int getNumberOfShownCommits() {
+ return myNumberOfShownCommits;
+ }
+
+ public void increaseShownCommits() {
+ myNumberOfShownCommits *= 2;
+ }
+
+ public List<? extends VcsFullCommitDetails> getLoadedCommits() {
+ return myLoadedCommits;
+ }
+
+ public void setLoadedCommits(List<? extends VcsFullCommitDetails> loadedCommits) {
+ myLoadedCommits = loadedCommits;
+ }
+ }
+
+ private static class MyPushOptionValueModel {
+ @NotNull private VcsPushOptionValue myCurrentValue;
+
+ public MyPushOptionValueModel(@NotNull VcsPushOptionValue currentValue) {
+ myCurrentValue = currentValue;
+ }
+
+ public void setCurrentValue(@NotNull VcsPushOptionValue currentValue) {
+ myCurrentValue = currentValue;
+ }
+
+ @NotNull
+ public VcsPushOptionValue getCurrentValue() {
+ return myCurrentValue;
+ }
+ }
+}
diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/RepositoryNodeListener.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/RepositoryNodeListener.java
new file mode 100644
index 000000000000..7ca285fc95aa
--- /dev/null
+++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/RepositoryNodeListener.java
@@ -0,0 +1,23 @@
+/*
+ * 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.push;
+
+public interface RepositoryNodeListener {
+
+ void onTargetChanged(String newValue);
+
+ void onSelectionChanged(boolean isSelected);
+}
diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/CustomRenderedTreeNode.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/CustomRenderedTreeNode.java
new file mode 100644
index 000000000000..18a69bae53be
--- /dev/null
+++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/CustomRenderedTreeNode.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 com.intellij.dvcs.push.ui;
+
+import com.intellij.ui.ColoredTreeCellRenderer;
+import org.jetbrains.annotations.NotNull;
+
+interface CustomRenderedTreeNode {
+
+ void render(@NotNull ColoredTreeCellRenderer renderer);
+} \ No newline at end of file
diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/DvcsStrategyPanel.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/DvcsStrategyPanel.java
new file mode 100644
index 000000000000..5b3aa4b153ed
--- /dev/null
+++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/DvcsStrategyPanel.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 com.intellij.dvcs.push.ui;
+
+import com.intellij.dvcs.push.VcsPushReferenceStrategy;
+import com.intellij.openapi.ui.ComboBox;
+
+import javax.swing.*;
+import java.awt.*;
+
+public class DvcsStrategyPanel extends JPanel {
+
+ private ComboBox myReferenceStrategyCombobox;
+
+ public DvcsStrategyPanel() {
+ setLayout(new BorderLayout());
+ myReferenceStrategyCombobox = new ComboBox();
+ DefaultComboBoxModel comboModel = new DefaultComboBoxModel(VcsPushReferenceStrategy.values());
+ myReferenceStrategyCombobox.setModel(comboModel);
+ JPanel bottomPanel = new JPanel(new FlowLayout());
+ JLabel referenceStrategyLabel = new JLabel("Push Reference Strategy: ");
+ bottomPanel.add(referenceStrategyLabel, FlowLayout.LEFT);
+ bottomPanel.add(myReferenceStrategyCombobox);
+ add(bottomPanel, BorderLayout.WEST);
+ }
+
+ public VcsPushReferenceStrategy getStrategy() {
+ return (VcsPushReferenceStrategy)myReferenceStrategyCombobox.getSelectedItem();
+ }
+}
diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/EditableTreeNode.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/EditableTreeNode.java
new file mode 100644
index 000000000000..5d0d20cdc4c0
--- /dev/null
+++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/EditableTreeNode.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.intellij.dvcs.push.ui;
+
+import com.intellij.openapi.progress.ProgressIndicator;
+import org.jetbrains.annotations.NotNull;
+
+public interface EditableTreeNode extends CustomRenderedTreeNode {
+
+ void fireOnChange(@NotNull String value);
+
+ void fireOnSelectionChange(boolean isSelected);
+
+ void stopLoading();
+
+ @NotNull
+ ProgressIndicator startLoading();
+
+ String getValue();
+}
diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/LoadingTreeNode.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/LoadingTreeNode.java
new file mode 100644
index 000000000000..dc424df43b81
--- /dev/null
+++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/LoadingTreeNode.java
@@ -0,0 +1,51 @@
+/*
+ * 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.push.ui;
+
+import com.intellij.ui.ColoredTreeCellRenderer;
+import com.intellij.ui.JBColor;
+import com.intellij.ui.SimpleTextAttributes;
+import com.intellij.util.ImageLoader;
+import com.intellij.util.ui.JBImageIcon;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import javax.swing.tree.DefaultMutableTreeNode;
+import java.awt.*;
+import java.net.URL;
+
+public class LoadingTreeNode extends DefaultMutableTreeNode implements CustomRenderedTreeNode {
+ @NotNull protected ImageIcon myLoadingIcon;
+ private static final String LOADING_ICON = "/icons/loading.gif";
+
+ @NotNull
+ public ImageIcon getIcon() {
+ return myLoadingIcon;
+ }
+
+ public LoadingTreeNode() {
+ super(null, false);
+ URL loadingIconUrl = getClass().getResource(LOADING_ICON);
+ Image image = ImageLoader.loadFromUrl(loadingIconUrl);
+ myLoadingIcon = new JBImageIcon(image);
+ }
+
+ @Override
+ public void render(@NotNull ColoredTreeCellRenderer renderer) {
+ renderer.setIcon(myLoadingIcon);
+ renderer.append("Loading Commits...", new SimpleTextAttributes(SimpleTextAttributes.STYLE_SMALLER, JBColor.GRAY));
+ }
+}
diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/NodeImageObserver.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/NodeImageObserver.java
new file mode 100644
index 000000000000..1e3d82015afe
--- /dev/null
+++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/NodeImageObserver.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.push.ui;
+
+import javax.swing.*;
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.TreeNode;
+import javax.swing.tree.TreePath;
+import java.awt.*;
+import java.awt.image.ImageObserver;
+
+class NodeImageObserver implements ImageObserver {
+ JTree tree;
+ DefaultTreeModel model;
+ TreeNode node;
+
+ NodeImageObserver(JTree tree, TreeNode node) {
+ this.tree = tree;
+ this.model = (DefaultTreeModel)tree.getModel();
+ this.node = node;
+ }
+
+ public boolean imageUpdate(Image img, int flags, int x, int y, int w, int h) {
+ if ((flags & (FRAMEBITS | ALLBITS)) != 0) {
+ TreePath path = new TreePath(model.getPathToRoot(node));
+ Rectangle rect = tree.getPathBounds(path);
+ if (rect != null) {
+ tree.repaint(rect);
+ }
+ }
+ return (flags & (ALLBITS | ABORT)) == 0;
+ }
+} \ No newline at end of file
diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/PushLog.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/PushLog.java
new file mode 100644
index 000000000000..b07bf9243f8a
--- /dev/null
+++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/PushLog.java
@@ -0,0 +1,289 @@
+/*
+ * 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.push.ui;
+
+import com.intellij.openapi.actionSystem.CommonShortcuts;
+import com.intellij.openapi.actionSystem.DataKey;
+import com.intellij.openapi.actionSystem.DataSink;
+import com.intellij.openapi.actionSystem.TypeSafeDataProvider;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.Splitter;
+import com.intellij.openapi.vcs.VcsDataKeys;
+import com.intellij.openapi.vcs.changes.Change;
+import com.intellij.openapi.vcs.changes.committed.CommittedChangesTreeBrowser;
+import com.intellij.openapi.vcs.changes.ui.ChangesBrowser;
+import com.intellij.ui.*;
+import com.intellij.ui.components.JBTextField;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.ui.tree.TreeUtil;
+import com.intellij.vcs.log.VcsFullCommitDetails;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import javax.swing.event.CellEditorListener;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.TreeSelectionEvent;
+import javax.swing.event.TreeSelectionListener;
+import javax.swing.tree.*;
+import java.awt.*;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.EventObject;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+public class PushLog extends JPanel implements TypeSafeDataProvider {
+
+ private final ReentrantReadWriteLock TREE_CONSTRUCTION_LOCK = new ReentrantReadWriteLock();
+
+ private static final String START_EDITING = "startEditing";
+ private final ChangesBrowser myChangesBrowser;
+ private final CheckboxTree myTree;
+ private final MyTreeCellRenderer myTreeCellRenderer;
+
+ public PushLog(Project project, CheckedTreeNode root) {
+ DefaultTreeModel treeModel = new DefaultTreeModel(root);
+ treeModel.nodeStructureChanged(root);
+ myTreeCellRenderer = new MyTreeCellRenderer();
+ myTree = new CheckboxTree(myTreeCellRenderer, root) {
+
+ public boolean isPathEditable(TreePath path) {
+ return isEditable() && path.getLastPathComponent() instanceof DefaultMutableTreeNode;
+ }
+
+ @Override
+ protected void onNodeStateChanged(CheckedTreeNode node) {
+ if (node instanceof EditableTreeNode) {
+ ((EditableTreeNode)node).fireOnSelectionChange(node.isChecked());
+ }
+ }
+
+ @Override
+ public String getToolTipText(MouseEvent event) {
+ final TreePath path = myTree.getPathForLocation(event.getX(), event.getY());
+ if (path == null) {
+ return "";
+ }
+ Object node = path.getLastPathComponent();
+ if (node == null || (!(node instanceof DefaultMutableTreeNode))) {
+ return "";
+ }
+ if (node instanceof TooltipNode) {
+ return ((TooltipNode)node).getTooltip();
+ }
+ return "";
+ }
+ };
+ myTree.setEditable(true);
+ MyTreeCellEditor treeCellEditor = new MyTreeCellEditor(new JBTextField());
+ myTree.setCellEditor(treeCellEditor);
+ treeCellEditor.addCellEditorListener(new CellEditorListener() {
+ @Override
+ public void editingStopped(ChangeEvent e) {
+ }
+
+ @Override
+ public void editingCanceled(ChangeEvent e) {
+ DefaultMutableTreeNode node = (DefaultMutableTreeNode)myTree.getLastSelectedPathComponent();
+ if (node != null && node instanceof EditableTreeNode) {
+ //todo restore from appropriate editor
+ ((EditableTreeNode)node).fireOnChange(((EditableTreeNode)node).getValue());
+ }
+ }
+ });
+ myTree.setRootVisible(false);
+ TreeUtil.expandAll(myTree);
+ final VcsBranchEditorListener linkMouseListener = new VcsBranchEditorListener(myTreeCellRenderer);
+ linkMouseListener.installOn(myTree);
+
+ myTree.getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
+ myTree.addTreeSelectionListener(new TreeSelectionListener() {
+ @Override
+ public void valueChanged(TreeSelectionEvent e) {
+ TreePath[] nodes = myTree.getSelectionPaths();
+ if (nodes != null) {
+ ArrayList<Change> changes = new ArrayList<Change>();
+ for (TreePath node : nodes) {
+ Object nodeInfo = ((DefaultMutableTreeNode)node.getLastPathComponent()).getUserObject();
+ if (nodeInfo instanceof VcsFullCommitDetails) {
+ changes.addAll(((VcsFullCommitDetails)nodeInfo).getChanges());
+ }
+ }
+ myChangesBrowser.getViewer().setEmptyText("No differences");
+ myChangesBrowser.setChangesToDisplay(CommittedChangesTreeBrowser.zipChanges(changes));
+ return;
+ }
+ setDefaultEmptyText();
+ myChangesBrowser.setChangesToDisplay(Collections.<Change>emptyList());
+ }
+ });
+ myTree.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_F2, 0), START_EDITING);
+ myTree.setRowHeight(0);
+ ToolTipManager.sharedInstance().registerComponent(myTree);
+
+ myChangesBrowser =
+ new ChangesBrowser(project, null, Collections.<Change>emptyList(), null, false, true, null, ChangesBrowser.MyUseCase.LOCAL_CHANGES,
+ null);
+ myChangesBrowser.getDiffAction().registerCustomShortcutSet(CommonShortcuts.getDiff(), myTree);
+ setDefaultEmptyText();
+
+ Splitter splitter = new Splitter(false, 0.7f);
+ splitter.setFirstComponent(ScrollPaneFactory.createScrollPane(myTree));
+ splitter.setSecondComponent(myChangesBrowser);
+
+ setLayout(new BorderLayout());
+ add(splitter);
+ }
+
+ private void setDefaultEmptyText() {
+ myChangesBrowser.getViewer().setEmptyText("No commits selected");
+ }
+
+ // Make changes available for diff action
+ @Override
+ public void calcData(DataKey key, DataSink sink) {
+ if (VcsDataKeys.CHANGES.equals(key)) {
+ DefaultMutableTreeNode[] selectedNodes = myTree.getSelectedNodes(DefaultMutableTreeNode.class, null);
+ if (selectedNodes.length == 0) {
+ return;
+ }
+ Object object = selectedNodes[0].getUserObject();
+ if (object instanceof VcsFullCommitDetails) {
+ sink.put(key, ArrayUtil.toObjectArray(((VcsFullCommitDetails)object).getChanges(), Change.class));
+ }
+ }
+ }
+
+ @Override
+ protected boolean processKeyBinding(KeyStroke ks, KeyEvent e, int condition, boolean pressed) {
+ if (e.getKeyCode() == KeyEvent.VK_ENTER && myTree.isEditing()) {
+ myTree.cancelEditing();
+ return true;
+ }
+ return super.processKeyBinding(ks, e, condition, pressed);
+ }
+
+ public void startLoading(DefaultMutableTreeNode parentNode) {
+ LoadingTreeNode loading = new LoadingTreeNode();
+ loading.getIcon().setImageObserver(new NodeImageObserver(myTree, loading));
+ setChildren(parentNode, Collections.singleton(loading));
+ }
+
+ private class MyTreeCellEditor extends DefaultCellEditor {
+
+ public MyTreeCellEditor(JTextField field) {
+ super(field);
+ setClickCountToStart(1);
+ }
+
+ @Override
+ public Component getTreeCellEditorComponent(JTree tree, Object value, boolean isSelected, boolean expanded, boolean leaf, int row) {
+ final Object node = ((DefaultMutableTreeNode)value).getUserObject();
+ editorComponent =
+ (JComponent)((RepositoryWithBranchPanel)node).getTreeCellRendererComponent(tree, value, isSelected, expanded, leaf, row, true);
+ return editorComponent;
+ }
+
+ @Override
+ public boolean isCellEditable(EventObject anEvent) {
+ if (anEvent instanceof MouseEvent) {
+ MouseEvent me = ((MouseEvent)anEvent);
+ final TreePath path = myTree.getClosestPathForLocation(me.getX(), me.getY());
+ final int row = myTree.getRowForLocation(me.getX(), me.getY());
+ myTree.getCellRenderer().getTreeCellRendererComponent(myTree, path.getLastPathComponent(), false, false, true, row, true);
+ Object tag = me.getClickCount() >= clickCountToStart
+ ? PushLogTreeUtil.getTagAtForRenderer(myTreeCellRenderer, me)
+ : null;
+ return tag instanceof EditorTextField;
+ }
+ //if keyboard event - then anEvent will be null =( See BasicTreeUi
+ TreePath treePath = myTree.getAnchorSelectionPath();
+ //there is no selection path if we start editing during initial validation//
+ if (treePath == null) return true;
+ Object treeNode = treePath.getLastPathComponent();
+ return treeNode instanceof EditableTreeNode;
+ }
+
+ //Implement the one CellEditor method that AbstractCellEditor doesn't.
+ public Object getCellEditorValue() {
+ return ((RepositoryWithBranchPanel)editorComponent).getRemoteTargetName();
+ }
+ }
+
+ private static class MyTreeCellRenderer extends CheckboxTree.CheckboxTreeCellRenderer {
+
+ @Override
+ public void customizeRenderer(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
+ if (!(value instanceof DefaultMutableTreeNode)) {
+ return;
+ }
+ if (value instanceof RepositoryNode) {
+ //todo simplify, remove instance of
+ myCheckbox.setVisible(((RepositoryNode)value).isCheckboxVisible());
+ }
+ Object userObject = ((DefaultMutableTreeNode)value).getUserObject();
+ ColoredTreeCellRenderer renderer = getTextRenderer();
+ renderer.setBorder(null);
+ if (value instanceof CustomRenderedTreeNode) {
+ ((CustomRenderedTreeNode)value).render(renderer);
+ }
+ else {
+ renderer.append(userObject == null ? "" : userObject.toString());
+ }
+ }
+ }
+
+ public void setChildren(DefaultMutableTreeNode parentNode, @NotNull Collection<? extends DefaultMutableTreeNode> childrenNodes) {
+ setChildren(parentNode, childrenNodes, true);
+ }
+
+ public void setChildren(DefaultMutableTreeNode parentNode,
+ @NotNull Collection<? extends DefaultMutableTreeNode> childrenNodes,
+ boolean shouldExpand) {
+ try {
+ TREE_CONSTRUCTION_LOCK.writeLock().lock();
+ parentNode.removeAllChildren();
+ for (DefaultMutableTreeNode child : childrenNodes) {
+ parentNode.add(child);
+ }
+ final DefaultTreeModel model = ((DefaultTreeModel)myTree.getModel());
+ model.nodeStructureChanged(parentNode);
+ TreePath path = TreeUtil.getPathFromRoot(parentNode);
+ if (shouldExpand) {
+ myTree.expandPath(path);
+ }
+ else {
+ myTree.collapsePath(path);
+ }
+ }
+ finally {
+ TREE_CONSTRUCTION_LOCK.writeLock().unlock();
+ }
+ }
+
+ @Nullable
+ public JComponent startEditNode(@NotNull TreeNode node) {
+ TreePath path = TreeUtil.getPathFromRoot(node);
+ if (!myTree.isEditing()) {
+ myTree.startEditingAtPath(path);
+ }
+ return (JComponent)myTree.getCellEditor()
+ .getTreeCellEditorComponent(myTree, node, false, false, false, myTree.getRowForPath(path));
+ }
+}
diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/PushLogTreeUtil.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/PushLogTreeUtil.java
new file mode 100644
index 000000000000..c7da9247ae74
--- /dev/null
+++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/PushLogTreeUtil.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.dvcs.push.ui;
+
+import com.intellij.ui.CheckboxTree;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import javax.swing.tree.TreeNode;
+import javax.swing.tree.TreePath;
+import java.awt.*;
+import java.awt.event.MouseEvent;
+
+public class PushLogTreeUtil {
+
+ @Nullable
+ public static Object getTagAtForRenderer(CheckboxTree.CheckboxTreeCellRenderer renderer, MouseEvent e) {
+ JTree tree = (JTree)e.getSource();
+ Object tag = null;
+ final TreePath path = tree.getPathForLocation(e.getX(), e.getY());
+ if (path != null) {
+ final Rectangle rectangle = tree.getPathBounds(path);
+ assert rectangle != null;
+ int dx = e.getX() - rectangle.x;
+ final TreeNode treeNode = (TreeNode)path.getLastPathComponent();
+ final int row = tree.getRowForLocation(e.getX(), e.getY());
+ tree.getCellRenderer().getTreeCellRendererComponent(tree, treeNode, false, false, true, row, true);
+ if (treeNode instanceof RepositoryNode) {
+ RepositoryNode repositoryNode = (RepositoryNode)treeNode;
+ int checkBoxWidth = repositoryNode.isCheckboxVisible() ? renderer.getCheckbox().getWidth() : 0;
+ tag = renderer.getTextRenderer().getFragmentTagAt(dx - checkBoxWidth);
+ }
+ else {
+ tag = renderer.getTextRenderer().getFragmentTagAt(dx);
+ }
+ }
+ return tag;
+ }
+}
diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/RepositoryNode.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/RepositoryNode.java
new file mode 100644
index 000000000000..24a26ece96d9
--- /dev/null
+++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/RepositoryNode.java
@@ -0,0 +1,97 @@
+/*
+ * 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.push.ui;
+
+import com.intellij.openapi.progress.EmptyProgressIndicator;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.ui.CheckedTreeNode;
+import com.intellij.ui.ColoredTreeCellRenderer;
+import com.intellij.ui.EditorTextField;
+import com.intellij.ui.SimpleTextAttributes;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import javax.swing.border.EmptyBorder;
+import java.awt.*;
+
+public class RepositoryNode extends CheckedTreeNode implements EditableTreeNode {
+ protected final static String ENTER_REMOTE = "Enter Remote";
+ @NotNull private final RepositoryWithBranchPanel myRepositoryPanel;
+
+ private ProgressIndicator myCurrentIndicator;
+
+ public RepositoryNode(@NotNull RepositoryWithBranchPanel repositoryPanel) {
+ super(repositoryPanel);
+ myRepositoryPanel = repositoryPanel;
+ }
+
+ public boolean isCheckboxVisible() {
+ return true;
+ }
+
+ @Override
+ public void render(@NotNull ColoredTreeCellRenderer renderer) {
+ String repositoryPath = myRepositoryPanel.getRepositoryName();
+ renderer.append(repositoryPath, SimpleTextAttributes.GRAY_ATTRIBUTES);
+ renderer.appendFixedTextFragmentWidth(120);
+ renderer.append(myRepositoryPanel.getSourceName(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
+ renderer.append(myRepositoryPanel.getArrow(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
+ EditorTextField textField = myRepositoryPanel.getRemoteTextFiled();
+ renderTargetName(renderer, textField, myRepositoryPanel.getRemoteTargetName());
+ Insets insets = BorderFactory.createEmptyBorder().getBorderInsets(textField);
+ renderer.setBorder(new EmptyBorder(insets));
+ }
+
+ protected void renderTargetName(@NotNull ColoredTreeCellRenderer renderer, @NotNull EditorTextField textField,
+ @NotNull String targetName) {
+ if (StringUtil.isEmptyOrSpaces(targetName)) {
+ renderer.append(ENTER_REMOTE, SimpleTextAttributes.GRAY_ITALIC_ATTRIBUTES, textField);
+ }
+ else {
+ renderer.append(targetName, SimpleTextAttributes.SYNTHETIC_ATTRIBUTES, textField);
+ }
+ }
+
+ @Override
+ @NotNull
+ public String getValue() {
+ return myRepositoryPanel.getRemoteTargetName();
+ }
+
+ @Override
+ public void fireOnChange(@NotNull String value) {
+ myRepositoryPanel.fireOnChange(value);
+ }
+
+ @Override
+ public void fireOnSelectionChange(boolean isSelected) {
+ myRepositoryPanel.fireOnSelectionChange(isSelected);
+ }
+
+ @Override
+ public void stopLoading() {
+ if (myCurrentIndicator != null && myCurrentIndicator.isRunning()) {
+ myCurrentIndicator.cancel();
+ }
+ }
+
+ @Override
+ @NotNull
+ public ProgressIndicator startLoading() {
+ return myCurrentIndicator = new EmptyProgressIndicator();
+ }
+}
diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/RepositoryWithBranchPanel.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/RepositoryWithBranchPanel.java
new file mode 100644
index 000000000000..c1afcdd52839
--- /dev/null
+++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/RepositoryWithBranchPanel.java
@@ -0,0 +1,185 @@
+/*
+ * 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.push.ui;
+
+import com.intellij.dvcs.push.RepositoryNodeListener;
+import com.intellij.openapi.editor.ex.EditorEx;
+import com.intellij.openapi.project.Project;
+import com.intellij.ui.ColoredTreeCellRenderer;
+import com.intellij.ui.SimpleTextAttributes;
+import com.intellij.ui.TextFieldWithAutoCompletion;
+import com.intellij.ui.TextFieldWithAutoCompletionListProvider;
+import com.intellij.ui.components.JBCheckBox;
+import com.intellij.ui.components.JBLabel;
+import com.intellij.ui.components.panels.NonOpaquePanel;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import javax.swing.tree.TreeCellRenderer;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.FocusAdapter;
+import java.awt.event.FocusEvent;
+import java.util.Collection;
+import java.util.List;
+
+public class RepositoryWithBranchPanel extends NonOpaquePanel implements TreeCellRenderer {
+
+ private final JBCheckBox myRepositoryCheckbox;
+ private final TextFieldWithAutoCompletion myDestBranchTextField;
+ private final JBLabel myLocalBranch;
+ private final JLabel myArrowLabel;
+ private final JLabel myRepositoryLabel;
+ private final ColoredTreeCellRenderer myTextRenderer;
+ @NotNull private final List<RepositoryNodeListener> myListeners = ContainerUtil.createLockFreeCopyOnWriteList();
+
+ public RepositoryWithBranchPanel(Project project, @NotNull String repoName,
+ @NotNull String sourceName, String targetName, @NotNull Collection<String> targetVariants) {
+ super();
+ setLayout(new BorderLayout());
+ myRepositoryCheckbox = new JBCheckBox();
+ myRepositoryCheckbox.setOpaque(false);
+ myRepositoryCheckbox.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ fireOnSelectionChange(myRepositoryCheckbox.isSelected());
+ }
+ });
+ myRepositoryLabel = new JLabel(repoName);
+ myLocalBranch = new JBLabel(sourceName);
+ myArrowLabel = new JLabel(" -> ");
+ TextFieldWithAutoCompletionListProvider<String> provider =
+ new TextFieldWithAutoCompletion.StringsCompletionProvider(targetVariants, null);
+ myDestBranchTextField = new TextFieldWithAutoCompletion<String>(project, provider, true, targetName) {
+
+ @Override
+ public boolean shouldHaveBorder() {
+ return false;
+ }
+
+ @Override
+ protected void updateBorder(@NotNull final EditorEx editor) {
+ }
+ };
+ myDestBranchTextField.setBorder(UIUtil.getTableFocusCellHighlightBorder());//getTextFieldBorder());
+ myDestBranchTextField.setOneLineMode(true);
+ myDestBranchTextField.setOpaque(true);
+ myDestBranchTextField.addFocusListener(new FocusAdapter() {
+ @Override
+ public void focusGained(FocusEvent e) {
+ myDestBranchTextField.selectAll();
+ }
+ });
+
+ myTextRenderer = new ColoredTreeCellRenderer() {
+ public void customizeCellRenderer(@NotNull JTree tree,
+ Object value,
+ boolean selected,
+ boolean expanded,
+ boolean leaf,
+ int row,
+ boolean hasFocus) {
+
+ }
+ };
+ myTextRenderer.setOpaque(false);
+ layoutComponents();
+ }
+
+ private void layoutComponents() {
+ add(myRepositoryCheckbox, BorderLayout.WEST);
+ JPanel panel = new NonOpaquePanel(new BorderLayout());
+ panel.add(myTextRenderer, BorderLayout.WEST);
+ panel.add(myDestBranchTextField, BorderLayout.CENTER);
+ add(panel, BorderLayout.CENTER);
+ }
+
+ @NotNull
+ public String getRepositoryName() {
+ return myRepositoryLabel.getText();
+ }
+
+ public String getSourceName() {
+ return myLocalBranch.getText();
+ }
+
+ public String getArrow() {
+ return myArrowLabel.getText();
+ }
+
+ public TextFieldWithAutoCompletion getRemoteTextFiled() {
+ return myDestBranchTextField;
+ }
+
+ @NotNull
+ public String getRemoteTargetName() {
+ return myDestBranchTextField.getText();
+ }
+
+ @Override
+ public Component getTreeCellRendererComponent(JTree tree,
+ Object value,
+ boolean selected,
+ boolean expanded,
+ boolean leaf,
+ int row,
+ boolean hasFocus) {
+ Rectangle bounds = tree.getPathBounds(tree.getPathForRow(row));
+ invalidate();
+ if (!(value instanceof SingleRepositoryNode)) {
+ RepositoryNode node = (RepositoryNode)value;
+ myRepositoryCheckbox.setSelected(node.isChecked());
+ myRepositoryCheckbox.setVisible(true);
+ myTextRenderer.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
+ myTextRenderer.append(getRepositoryName(), SimpleTextAttributes.GRAY_ATTRIBUTES);
+ myTextRenderer.appendFixedTextFragmentWidth(120);
+ }
+ else {
+ myTextRenderer.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
+ myRepositoryCheckbox.setVisible(false);
+ }
+ myTextRenderer.append(getSourceName(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
+ myTextRenderer.append(getArrow(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
+ if (bounds != null) {
+ setPreferredSize(new Dimension(tree.getWidth() - bounds.x, bounds.height));
+ }
+ myDestBranchTextField.grabFocus();
+ myDestBranchTextField.requestFocus();
+ revalidate();
+ return this;
+ }
+
+ public void addRepoNodeListener(@NotNull RepositoryNodeListener listener) {
+ myListeners.add(listener);
+ }
+
+ public void fireOnChange(@NotNull String newValue) {
+ for (RepositoryNodeListener listener : myListeners) {
+ listener.onTargetChanged(newValue);
+ }
+ }
+
+ public void fireOnSelectionChange(boolean isSelected) {
+ for (RepositoryNodeListener listener : myListeners) {
+ listener.onSelectionChanged(isSelected);
+ }
+ }
+}
+
+
diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/SingleRepositoryNode.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/SingleRepositoryNode.java
new file mode 100644
index 000000000000..c566dd6f2867
--- /dev/null
+++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/SingleRepositoryNode.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.dvcs.push.ui;
+
+import com.intellij.ui.ColoredTreeCellRenderer;
+import com.intellij.ui.EditorTextField;
+import com.intellij.ui.SimpleTextAttributes;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import javax.swing.border.EmptyBorder;
+import java.awt.*;
+
+public class SingleRepositoryNode extends RepositoryNode {
+
+ @NotNull private final RepositoryWithBranchPanel myRepositoryPanel;
+
+ public SingleRepositoryNode(@NotNull RepositoryWithBranchPanel repositoryPanel) {
+ super(repositoryPanel);
+ myRepositoryPanel = repositoryPanel;
+ }
+
+ @Override
+ public boolean isCheckboxVisible() {
+ return false;
+ }
+
+ @Override
+ public void render(@NotNull ColoredTreeCellRenderer renderer) {
+ renderer.append(myRepositoryPanel.getSourceName(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
+ renderer.append(myRepositoryPanel.getArrow(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
+ EditorTextField textField = myRepositoryPanel.getRemoteTextFiled();
+ String targetName = myRepositoryPanel.getRemoteTargetName();
+ renderTargetName(renderer, textField, targetName);
+ Insets insets = BorderFactory.createEmptyBorder().getBorderInsets(textField);
+ renderer.setBorder(new EmptyBorder(insets));
+ }
+
+}
diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/TextWithLinkNode.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/TextWithLinkNode.java
new file mode 100644
index 000000000000..685fcb81fd05
--- /dev/null
+++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/TextWithLinkNode.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.dvcs.push.ui;
+
+
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.ui.ColoredTreeCellRenderer;
+import com.intellij.ui.SimpleTextAttributes;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.TreeNode;
+
+public class TextWithLinkNode extends DefaultMutableTreeNode implements CustomRenderedTreeNode {
+
+ @NotNull protected VcsLinkedText myLinkedText;
+
+ public TextWithLinkNode(@NotNull VcsLinkedText linkedText) {
+ myLinkedText = linkedText;
+ }
+
+ public void fireOnClick(@NotNull TextWithLinkNode relatedNode) {
+ TreeNode parent = relatedNode.getParent();
+ if (parent instanceof RepositoryNode) {
+ myLinkedText.hyperLinkActivate((RepositoryNode)parent);
+ }
+ }
+
+ @Override
+ public void render(@NotNull ColoredTreeCellRenderer renderer) {
+ renderer.append(myLinkedText.getTextBefore(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
+ String linkedText = myLinkedText.getLinkText();
+ if (!StringUtil.isEmptyOrSpaces(linkedText)) {
+ renderer.append(" ");
+ renderer.append(myLinkedText.getLinkText(), SimpleTextAttributes.SYNTHETIC_ATTRIBUTES, this);
+ }
+ renderer.append(myLinkedText.getTextAfter(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
+ }
+} \ No newline at end of file
diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/TooltipNode.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/TooltipNode.java
new file mode 100644
index 000000000000..fef83cc12f63
--- /dev/null
+++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/TooltipNode.java
@@ -0,0 +1,21 @@
+/*
+ * 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.push.ui;
+
+public interface TooltipNode {
+
+ String getTooltip();
+}
diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsBranchEditorListener.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsBranchEditorListener.java
new file mode 100644
index 000000000000..d8e35fd25d53
--- /dev/null
+++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsBranchEditorListener.java
@@ -0,0 +1,61 @@
+/*
+ * 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.push.ui;
+
+import com.intellij.openapi.vcs.changes.issueLinks.LinkMouseListenerBase;
+import com.intellij.ui.CheckboxTree;
+import com.intellij.ui.EditorTextField;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.awt.*;
+import java.awt.event.MouseEvent;
+
+public class VcsBranchEditorListener extends LinkMouseListenerBase {
+ private final CheckboxTree.CheckboxTreeCellRenderer myRenderer;
+
+ public VcsBranchEditorListener(final CheckboxTree.CheckboxTreeCellRenderer renderer) {
+ myRenderer = renderer;
+ }
+
+ @Override
+ public void mouseMoved(MouseEvent e) {
+ Component component = (Component)e.getSource();
+ Object tag = getTagAt(e);
+ if (tag != null && tag instanceof EditorTextField) {
+ component.setCursor(Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR));
+ }
+ else if (tag != null && tag instanceof TextWithLinkNode) {
+ component.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
+ }
+ else {
+ component.setCursor(Cursor.getDefaultCursor());
+ }
+ }
+
+ @Nullable
+ @Override
+ protected Object getTagAt(@NotNull final MouseEvent e) {
+ return PushLogTreeUtil.getTagAtForRenderer(myRenderer, e);
+ }
+
+ protected void handleTagClick(@Nullable Object tag, @NotNull MouseEvent event) {
+ if (tag instanceof TextWithLinkNode) {
+ TextWithLinkNode textWithLink = (TextWithLinkNode)tag;
+ textWithLink.fireOnClick(textWithLink);
+ }
+ }
+}
diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsFullCommitDetailsNode.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsFullCommitDetailsNode.java
new file mode 100644
index 000000000000..0df7af05d496
--- /dev/null
+++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsFullCommitDetailsNode.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.dvcs.push.ui;
+
+import com.intellij.dvcs.DvcsUtil;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vcs.changes.issueLinks.IssueLinkHtmlRenderer;
+import com.intellij.ui.ColoredTreeCellRenderer;
+import com.intellij.ui.SimpleTextAttributes;
+import com.intellij.vcs.log.VcsFullCommitDetails;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.tree.DefaultMutableTreeNode;
+
+public class VcsFullCommitDetailsNode extends DefaultMutableTreeNode implements CustomRenderedTreeNode, TooltipNode {
+
+ @NotNull private final Project myProject;
+ private final VcsFullCommitDetails myCommit;
+
+ public VcsFullCommitDetailsNode(@NotNull Project project, VcsFullCommitDetails commit) {
+ super(commit, false);
+ myProject = project;
+ myCommit = commit;
+ }
+
+ @Override
+ public void render(@NotNull ColoredTreeCellRenderer renderer) {
+ renderer
+ .append(myCommit.getSubject(), new SimpleTextAttributes(SimpleTextAttributes.STYLE_SMALLER, renderer.getForeground()));
+ }
+
+ public String getTooltip() {
+ return DvcsUtil.getShortHash(myCommit.getId().toString()) +
+ " " +
+ DvcsUtil.getDateString(myCommit) +
+ " by " +
+ myCommit.getAuthor().getName() +
+ "\n\n" +
+ IssueLinkHtmlRenderer.formatTextWithLinks(myProject, myCommit.getFullMessage());
+ }
+}
diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsLinkListener.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsLinkListener.java
new file mode 100644
index 000000000000..76578165b37c
--- /dev/null
+++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsLinkListener.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 com.intellij.dvcs.push.ui;
+
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.tree.DefaultMutableTreeNode;
+
+public interface VcsLinkListener {
+ void hyperlinkActivated(@NotNull DefaultMutableTreeNode sourceNode);
+}
diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsLinkedText.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsLinkedText.java
new file mode 100644
index 000000000000..35c4989f160e
--- /dev/null
+++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsLinkedText.java
@@ -0,0 +1,70 @@
+/*
+ * 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.push.ui;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.tree.DefaultMutableTreeNode;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class VcsLinkedText {
+
+ private static final Pattern HREF_PATTERN = Pattern.compile("<a(?:\\s+href\\s*=\\s*[\"']([^\"']*)[\"'])?\\s*>([^<]*)</a>");
+
+ @NotNull private String myTextBefore;
+ @NotNull private String myTextAfter;
+ @NotNull private String myHandledLink;
+
+ @Nullable private final VcsLinkListener myLinkListener;
+
+ public VcsLinkedText(@NotNull String text, @Nullable VcsLinkListener listener) {
+ Matcher aMatcher = HREF_PATTERN.matcher(text);
+ if (aMatcher.find()) {
+ myTextBefore = text.substring(0, aMatcher.start());
+ myHandledLink = aMatcher.group(2);
+ myTextAfter = text.substring(aMatcher.end(), text.length());
+ }
+ else {
+ myTextBefore = text;
+ myHandledLink = "";
+ myTextAfter = "";
+ }
+ myLinkListener = listener;
+ }
+
+ @NotNull
+ public String getTextBefore() {
+ return myTextBefore;
+ }
+
+ @NotNull
+ public String getTextAfter() {
+ return myTextAfter;
+ }
+
+ @NotNull
+ public String getLinkText() {
+ return myHandledLink;
+ }
+
+ public void hyperLinkActivate(@NotNull DefaultMutableTreeNode relatedNode) {
+ if (myLinkListener != null) {
+ myLinkListener.hyperlinkActivated(relatedNode);
+ }
+ }
+}
diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsPushDialog.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsPushDialog.java
new file mode 100644
index 000000000000..b441952f7a43
--- /dev/null
+++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsPushDialog.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 com.intellij.dvcs.push.ui;
+
+import com.intellij.dvcs.push.PushController;
+import com.intellij.dvcs.push.VcsPushOptionsPanel;
+import com.intellij.dvcs.repo.Repository;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.DialogWrapper;
+import com.intellij.openapi.ui.OptionAction;
+import com.intellij.openapi.ui.ValidationInfo;
+import net.miginfocom.swing.MigLayout;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.util.ArrayList;
+import java.util.List;
+
+public class VcsPushDialog extends DialogWrapper {
+
+ private final PushLog myListPanel;
+ private final PushController myController;
+ private final Action[] myExecutorActions = {new DvcsPushAction("&Force Push", true)};
+ @NotNull private final JPanel myAdditionalOptionsFromVcsPanel;
+
+ private DvcsPushAction myPushAction;
+
+ public VcsPushDialog(@NotNull Project project, @NotNull List<? extends Repository> selectedRepositories) {
+ super(project);
+ myController = new PushController(project, this, selectedRepositories);
+ myListPanel = myController.getPushPanelInfo();
+ myAdditionalOptionsFromVcsPanel = new JPanel(new MigLayout("ins 0 0, flowx"));
+ init();
+ setOKButtonText("Push");
+ setOKButtonMnemonic('P');
+ setTitle("Push Dialog");
+ }
+
+ @Override
+ protected JComponent createCenterPanel() {
+
+ JComponent rootPanel = new JPanel(new BorderLayout(0, 15));
+ rootPanel.add(myListPanel, BorderLayout.CENTER);
+ for (VcsPushOptionsPanel panel : myController.getAdditionalPanels()) {
+ myAdditionalOptionsFromVcsPanel.add(panel);
+ }
+ rootPanel.add(myAdditionalOptionsFromVcsPanel, BorderLayout.SOUTH);
+ return rootPanel;
+ }
+
+ @Override
+ protected String getDimensionServiceKey() {
+ return VcsPushDialog.class.getName();
+ }
+
+ @Override
+ @NotNull
+ protected Action[] createActions() {
+ final List<Action> actions = new ArrayList<Action>();
+ myPushAction = new DvcsPushAction("&Push", false);
+ myPushAction.putValue(DEFAULT_ACTION, Boolean.TRUE);
+ actions.add(myPushAction);
+ myPushAction.setOptions(myExecutorActions);
+ actions.add(getCancelAction());
+ actions.add(getHelpAction());
+ return actions.toArray(new Action[actions.size()]);
+ }
+
+ @NotNull
+ @Override
+ protected Action getOKAction() {
+ return myPushAction;
+ }
+
+ @Nullable
+ @Override
+ protected ValidationInfo doValidate() {
+ return myController.validate();
+ }
+
+ @Override
+ protected String getHelpId() {
+ return "reference.mercurial.push.dialog";
+ }
+
+ public void updateButtons() {
+ initValidation();
+ }
+
+ @Override
+ protected boolean postponeValidation() {
+ return false;
+ }
+
+ private class DvcsPushAction extends AbstractAction implements OptionAction {
+ private Action[] myOptions = new Action[0];
+ private final boolean myForce;
+
+ private DvcsPushAction(String title, boolean force) {
+ super(title);
+ myForce = force;
+ }
+
+ @Override
+ public void setEnabled(boolean isEnabled) {
+ super.setEnabled(isEnabled);
+ for (Action optionAction : myOptions) {
+ optionAction.setEnabled(isEnabled);
+ }
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ myController.push(myForce);
+ close(OK_EXIT_CODE);
+ }
+
+ @NotNull
+ @Override
+ public Action[] getOptions() {
+ return myOptions;
+ }
+
+ public void setOptions(Action[] actions) {
+ myOptions = actions;
+ }
+ }
+}
diff --git a/platform/dvcs/src/com/intellij/dvcs/repo/AbstractRepositoryManager.java b/platform/dvcs-impl/src/com/intellij/dvcs/repo/AbstractRepositoryManager.java
index 992654248e83..992654248e83 100644
--- a/platform/dvcs/src/com/intellij/dvcs/repo/AbstractRepositoryManager.java
+++ b/platform/dvcs-impl/src/com/intellij/dvcs/repo/AbstractRepositoryManager.java
diff --git a/platform/dvcs/src/com/intellij/dvcs/repo/RepoStateException.java b/platform/dvcs-impl/src/com/intellij/dvcs/repo/RepoStateException.java
index cfe1f0e5c014..cfe1f0e5c014 100644
--- a/platform/dvcs/src/com/intellij/dvcs/repo/RepoStateException.java
+++ b/platform/dvcs-impl/src/com/intellij/dvcs/repo/RepoStateException.java
diff --git a/platform/dvcs/src/com/intellij/dvcs/repo/RepositoryImpl.java b/platform/dvcs-impl/src/com/intellij/dvcs/repo/RepositoryImpl.java
index 5a605c566710..5a605c566710 100644
--- a/platform/dvcs/src/com/intellij/dvcs/repo/RepositoryImpl.java
+++ b/platform/dvcs-impl/src/com/intellij/dvcs/repo/RepositoryImpl.java
diff --git a/platform/dvcs/src/com/intellij/dvcs/repo/RepositoryUtil.java b/platform/dvcs-impl/src/com/intellij/dvcs/repo/RepositoryUtil.java
index 5a5a555768ba..5a5a555768ba 100644
--- a/platform/dvcs/src/com/intellij/dvcs/repo/RepositoryUtil.java
+++ b/platform/dvcs-impl/src/com/intellij/dvcs/repo/RepositoryUtil.java
diff --git a/platform/dvcs/src/com/intellij/dvcs/ui/BranchActionGroupPopup.java b/platform/dvcs-impl/src/com/intellij/dvcs/ui/BranchActionGroupPopup.java
index 3b935745a212..44b4c8c5c3f0 100644
--- a/platform/dvcs/src/com/intellij/dvcs/ui/BranchActionGroupPopup.java
+++ b/platform/dvcs-impl/src/com/intellij/dvcs/ui/BranchActionGroupPopup.java
@@ -34,13 +34,10 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
-/**
- * @author Nadya Zabrodina
- */
public class BranchActionGroupPopup extends PopupFactoryImpl.ActionGroupPopup {
public BranchActionGroupPopup(@NotNull String title, @NotNull Project project,
@NotNull Condition<AnAction> preselectActionCondition, @NotNull ActionGroup actions) {
- super(title, actions, SimpleDataContext.getProjectContext(project), false, false, false, false, null, -1,
+ super(title, actions, SimpleDataContext.getProjectContext(project), false, false, true, false, null, -1,
preselectActionCondition, null);
}
diff --git a/platform/dvcs/src/com/intellij/dvcs/ui/CloneDvcsDialog.form b/platform/dvcs-impl/src/com/intellij/dvcs/ui/CloneDvcsDialog.form
index 53d957676c8b..53d957676c8b 100644
--- a/platform/dvcs/src/com/intellij/dvcs/ui/CloneDvcsDialog.form
+++ b/platform/dvcs-impl/src/com/intellij/dvcs/ui/CloneDvcsDialog.form
diff --git a/platform/dvcs/src/com/intellij/dvcs/ui/CloneDvcsDialog.java b/platform/dvcs-impl/src/com/intellij/dvcs/ui/CloneDvcsDialog.java
index 8e06c99775e2..8e06c99775e2 100644
--- a/platform/dvcs/src/com/intellij/dvcs/ui/CloneDvcsDialog.java
+++ b/platform/dvcs-impl/src/com/intellij/dvcs/ui/CloneDvcsDialog.java
diff --git a/platform/dvcs/src/com/intellij/dvcs/ui/DvcsBundle.java b/platform/dvcs-impl/src/com/intellij/dvcs/ui/DvcsBundle.java
index 879def5e1802..879def5e1802 100644
--- a/platform/dvcs/src/com/intellij/dvcs/ui/DvcsBundle.java
+++ b/platform/dvcs-impl/src/com/intellij/dvcs/ui/DvcsBundle.java
diff --git a/platform/dvcs/src/com/intellij/dvcs/ui/DvcsBundle.properties b/platform/dvcs-impl/src/com/intellij/dvcs/ui/DvcsBundle.properties
index 14822049588d..14822049588d 100644
--- a/platform/dvcs/src/com/intellij/dvcs/ui/DvcsBundle.properties
+++ b/platform/dvcs-impl/src/com/intellij/dvcs/ui/DvcsBundle.properties
diff --git a/platform/dvcs/src/com/intellij/dvcs/ui/NewBranchAction.java b/platform/dvcs-impl/src/com/intellij/dvcs/ui/NewBranchAction.java
index 29481e236c2a..92ba9515b5d6 100644
--- a/platform/dvcs/src/com/intellij/dvcs/ui/NewBranchAction.java
+++ b/platform/dvcs-impl/src/com/intellij/dvcs/ui/NewBranchAction.java
@@ -25,9 +25,6 @@ import org.jetbrains.annotations.NotNull;
import java.util.List;
-/**
- * @author Nadya Zabrodina
- */
public abstract class NewBranchAction<T extends Repository> extends DumbAwareAction {
protected final List<T> myRepositories;
protected Project myProject;
@@ -43,7 +40,7 @@ public abstract class NewBranchAction<T extends Repository> extends DumbAwareAct
public void update(AnActionEvent e) {
if (DvcsUtil.anyRepositoryIsFresh(myRepositories)) {
e.getPresentation().setEnabled(false);
- e.getPresentation().setDescription("Checkout of a new branch is not possible before the first commit.");
+ e.getPresentation().setDescription("Checkout of a new branch is not possible before the first commit");
}
}
diff --git a/platform/dvcs/src/com/intellij/dvcs/ui/RootAction.java b/platform/dvcs-impl/src/com/intellij/dvcs/ui/RootAction.java
index 93e49042648c..93e49042648c 100644
--- a/platform/dvcs/src/com/intellij/dvcs/ui/RootAction.java
+++ b/platform/dvcs-impl/src/com/intellij/dvcs/ui/RootAction.java
diff --git a/platform/dvcs/src/com/intellij/dvcs/ui/VcsLogAction.java b/platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogAction.java
index bb7f64f9b24c..bb7f64f9b24c 100644
--- a/platform/dvcs/src/com/intellij/dvcs/ui/VcsLogAction.java
+++ b/platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogAction.java
diff --git a/platform/dvcs/src/com/intellij/dvcs/ui/VcsLogOneCommitPerRepoAction.java b/platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogOneCommitPerRepoAction.java
index 1b4be918a3e1..1b4be918a3e1 100644
--- a/platform/dvcs/src/com/intellij/dvcs/ui/VcsLogOneCommitPerRepoAction.java
+++ b/platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogOneCommitPerRepoAction.java
diff --git a/platform/dvcs/src/com/intellij/dvcs/ui/VcsLogSingleCommitAction.java b/platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogSingleCommitAction.java
index 4b43380ea9eb..4b43380ea9eb 100644
--- a/platform/dvcs/src/com/intellij/dvcs/ui/VcsLogSingleCommitAction.java
+++ b/platform/dvcs-impl/src/com/intellij/dvcs/ui/VcsLogSingleCommitAction.java
diff --git a/platform/dvcs/testFramework/com/intellij/dvcs/test/MockProject.java b/platform/dvcs-impl/testFramework/com/intellij/dvcs/test/MockProject.java
index 6ca5f302607c..a8dc262d7be1 100644
--- a/platform/dvcs/testFramework/com/intellij/dvcs/test/MockProject.java
+++ b/platform/dvcs-impl/testFramework/com/intellij/dvcs/test/MockProject.java
@@ -15,15 +15,15 @@
*/
package com.intellij.dvcs.test;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.components.BaseComponent;
-import org.picocontainer.PicoContainer;
-import com.intellij.util.messages.MessageBus;
import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Key;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.messages.MessageBus;
import org.jetbrains.annotations.NotNull;
+import org.picocontainer.PicoContainer;
/**
*
diff --git a/platform/dvcs/testFramework/com/intellij/dvcs/test/MockProjectRootManager.java b/platform/dvcs-impl/testFramework/com/intellij/dvcs/test/MockProjectRootManager.java
index d89b92878f54..d89b92878f54 100644
--- a/platform/dvcs/testFramework/com/intellij/dvcs/test/MockProjectRootManager.java
+++ b/platform/dvcs-impl/testFramework/com/intellij/dvcs/test/MockProjectRootManager.java
diff --git a/platform/dvcs/testFramework/com/intellij/dvcs/test/MockVcsHelper.java b/platform/dvcs-impl/testFramework/com/intellij/dvcs/test/MockVcsHelper.java
index 55e0a0e68b17..55e0a0e68b17 100644
--- a/platform/dvcs/testFramework/com/intellij/dvcs/test/MockVcsHelper.java
+++ b/platform/dvcs-impl/testFramework/com/intellij/dvcs/test/MockVcsHelper.java
diff --git a/platform/dvcs/testFramework/com/intellij/dvcs/test/MockVirtualFile.java b/platform/dvcs-impl/testFramework/com/intellij/dvcs/test/MockVirtualFile.java
index 3b36381dcf85..3b36381dcf85 100644
--- a/platform/dvcs/testFramework/com/intellij/dvcs/test/MockVirtualFile.java
+++ b/platform/dvcs-impl/testFramework/com/intellij/dvcs/test/MockVirtualFile.java
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 e6b2553085a8..aff6216c3dba 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
@@ -21,9 +21,10 @@ import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.components.*;
-import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.SimpleModificationTracker;
import com.intellij.openapi.util.SystemInfo;
+import com.intellij.util.EventDispatcher;
import com.intellij.util.PlatformUtilsCore;
import com.intellij.util.SystemProperties;
import com.intellij.util.ui.UIUtil;
@@ -36,7 +37,6 @@ import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
-import javax.swing.event.EventListenerList;
import java.awt.*;
import java.io.File;
import java.util.Map;
@@ -50,7 +50,7 @@ import static com.intellij.util.ui.UIUtil.isValidFont;
file = StoragePathMacros.APP_CONFIG + "/ui.lnf.xml"
)}
)
-public class UISettings implements PersistentStateComponent<UISettings>, ExportableApplicationComponent {
+public class UISettings extends SimpleModificationTracker implements PersistentStateComponent<UISettings>, ExportableApplicationComponent {
/** Not tabbed pane. */
public static final int TABS_NONE = 0;
@@ -121,10 +121,9 @@ public class UISettings implements PersistentStateComponent<UISettings>, Exporta
public boolean SHOW_TABS_TOOLTIPS = true;
public boolean SHOW_DIRECTORY_FOR_NON_UNIQUE_FILENAMES = true;
- private final EventListenerList myListenerList;
+ private final EventDispatcher<UISettingsListener> myDispatcher = EventDispatcher.create(UISettingsListener.class);
public UISettings() {
- myListenerList = new EventListenerList();
tweakPlatformDefaults();
setSystemFontFaceAndSize();
}
@@ -142,31 +141,24 @@ public class UISettings implements PersistentStateComponent<UISettings>, Exporta
* @deprecated use {@link UISettings#addUISettingsListener(com.intellij.ide.ui.UISettingsListener, Disposable disposable)} instead.
*/
public void addUISettingsListener(UISettingsListener listener) {
- myListenerList.add(UISettingsListener.class, listener);
+ myDispatcher.addListener(listener);
}
public void addUISettingsListener(@NotNull final UISettingsListener listener, @NotNull Disposable parentDisposable) {
- myListenerList.add(UISettingsListener.class, listener);
- Disposer.register(parentDisposable, new Disposable() {
- @Override
- public void dispose() {
- removeUISettingsListener(listener);
- }
- });
+ myDispatcher.addListener(listener, parentDisposable);
}
/**
* Notifies all registered listeners that UI settings has been changed.
*/
public void fireUISettingsChanged() {
- UISettingsListener[] listeners = myListenerList.getListeners(UISettingsListener.class);
- for (UISettingsListener listener : listeners) {
- listener.uiSettingsChanged(this);
- }
+ incModificationCount();
+ myDispatcher.getMulticaster().uiSettingsChanged(this);
+ ApplicationManager.getApplication().getMessageBus().syncPublisher(UISettingsListener.TOPIC).uiSettingsChanged(this);
}
public void removeUISettingsListener(UISettingsListener listener) {
- myListenerList.remove(UISettingsListener.class, listener);
+ myDispatcher.removeListener(listener);
}
private void setSystemFontFaceAndSize() {
diff --git a/platform/editor-ui-api/src/com/intellij/ide/ui/UISettingsListener.java b/platform/editor-ui-api/src/com/intellij/ide/ui/UISettingsListener.java
index 035fb700e481..1dcce2c076a3 100644
--- a/platform/editor-ui-api/src/com/intellij/ide/ui/UISettingsListener.java
+++ b/platform/editor-ui-api/src/com/intellij/ide/ui/UISettingsListener.java
@@ -19,8 +19,12 @@
*/
package com.intellij.ide.ui;
+import com.intellij.util.messages.Topic;
+
import java.util.EventListener;
public interface UISettingsListener extends EventListener{
+ Topic<UISettingsListener> TOPIC = Topic.create("UI settings", UISettingsListener.class);
+
void uiSettingsChanged(UISettings source);
}
diff --git a/platform/editor-ui-api/src/com/intellij/openapi/actionSystem/AnAction.java b/platform/editor-ui-api/src/com/intellij/openapi/actionSystem/AnAction.java
index 1d1540910539..42da54a61d72 100644
--- a/platform/editor-ui-api/src/com/intellij/openapi/actionSystem/AnAction.java
+++ b/platform/editor-ui-api/src/com/intellij/openapi/actionSystem/AnAction.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.
@@ -297,6 +297,10 @@ public abstract class AnAction implements PossiblyDumbAware {
return myIsDefaultIcon;
}
+ /**
+ * Enables automatic detection of injected fragments in editor. Values in DataContext, passed to the action, like EDITOR, PSI_FILE
+ * will refer to an injected fragment, if caret is currently positioned on it.
+ */
public void setInjectedContext(boolean worksInInjected) {
myWorksInInjected = worksInInjected;
}
diff --git a/platform/editor-ui-api/src/com/intellij/openapi/actionSystem/AnActionEvent.java b/platform/editor-ui-api/src/com/intellij/openapi/actionSystem/AnActionEvent.java
index 5202aa291224..94dcccb71778 100644
--- a/platform/editor-ui-api/src/com/intellij/openapi/actionSystem/AnActionEvent.java
+++ b/platform/editor-ui-api/src/com/intellij/openapi/actionSystem/AnActionEvent.java
@@ -37,7 +37,7 @@ import java.util.Map;
public class AnActionEvent implements PlaceProvider<String> {
private final InputEvent myInputEvent;
- private final ActionManager myActionManager;
+ @NotNull private final ActionManager myActionManager;
@NotNull private final DataContext myDataContext;
@NotNull private final String myPlace;
@NotNull private final Presentation myPresentation;
@@ -49,12 +49,14 @@ public class AnActionEvent implements PlaceProvider<String> {
/**
* @throws IllegalArgumentException if <code>dataContext</code> is <code>null</code> or
* <code>place</code> is <code>null</code> or <code>presentation</code> is <code>null</code>
+ *
+ * @see ActionManager#getInstance()
*/
public AnActionEvent(InputEvent inputEvent,
@NotNull DataContext dataContext,
@NotNull @NonNls String place,
@NotNull Presentation presentation,
- ActionManager actionManager,
+ @NotNull ActionManager actionManager,
@JdkConstants.InputEventMask int modifiers) {
// TODO[vova,anton] make this constructor package local. No one is allowed to create AnActionEvents
myInputEvent = inputEvent;
@@ -69,7 +71,7 @@ public class AnActionEvent implements PlaceProvider<String> {
public static AnActionEvent createFromInputEvent(@NotNull AnAction action, InputEvent event, @NotNull String place) {
DataContext context = event == null ? DataManager.getInstance().getDataContext() : DataManager.getInstance().getDataContext(event.getComponent());
int modifiers = event == null ? 0 : event.getModifiers();
- return new AnActionEvent(
+ AnActionEvent anActionEvent = new AnActionEvent(
event,
context,
place,
@@ -77,6 +79,8 @@ public class AnActionEvent implements PlaceProvider<String> {
ActionManager.getInstance(),
modifiers
);
+ anActionEvent.setInjectedContext(action.isInInjectedContext());
+ return anActionEvent;
}
/**
@@ -113,6 +117,18 @@ public class AnActionEvent implements PlaceProvider<String> {
return StringUtil.trimStart(dataId, ourInjectedPrefix);
}
+ public static DataContext getInjectedDataContext(final DataContext context) {
+ return new DataContextWrapper(context) {
+ @Nullable
+ @Override
+ public Object getData(@NonNls String dataId) {
+ Object injected = super.getData(injectedId(dataId));
+ if (injected != null) return injected;
+ return super.getData(dataId);
+ }
+ };
+ }
+
/**
* Returns the context which allows to retrieve information about the state of IDEA related to
* the action invocation (active editor, selection and so on).
@@ -121,18 +137,7 @@ public class AnActionEvent implements PlaceProvider<String> {
*/
@NotNull
public DataContext getDataContext() {
- if (!myWorksInInjected) {
- return myDataContext;
- }
- return new DataContext() {
- @Override
- @Nullable
- public Object getData(@NonNls String dataId) {
- Object injected = myDataContext.getData(injectedId(dataId));
- if (injected != null) return injected;
- return myDataContext.getData(dataId);
- }
- };
+ return myWorksInInjected ? getInjectedDataContext(myDataContext) : myDataContext;
}
@Nullable
@@ -203,9 +208,11 @@ public class AnActionEvent implements PlaceProvider<String> {
return myModifiers;
}
+ @NotNull
public ActionManager getActionManager() {
return myActionManager;
}
+
public void setInjectedContext(boolean worksInInjected) {
myWorksInInjected = worksInInjected;
}
diff --git a/platform/editor-ui-api/src/com/intellij/openapi/actionSystem/CommonDataKeys.java b/platform/editor-ui-api/src/com/intellij/openapi/actionSystem/CommonDataKeys.java
index cb7449a2c914..edde5ca34f8c 100644
--- a/platform/editor-ui-api/src/com/intellij/openapi/actionSystem/CommonDataKeys.java
+++ b/platform/editor-ui-api/src/com/intellij/openapi/actionSystem/CommonDataKeys.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,6 +15,7 @@
*/
package com.intellij.openapi.actionSystem;
+import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
@@ -25,7 +26,14 @@ import com.intellij.psi.PsiFile;
public class CommonDataKeys {
public static final DataKey<Project> PROJECT = DataKey.create("project");
public static final DataKey<Editor> EDITOR = DataKey.create("editor");
-
+ /**
+ * This key can be used to obtain reference to host editor instance, in case {@link #EDITOR} key is referring to an injected editor.
+ */
+ public static final DataKey<Editor> HOST_EDITOR = DataKey.create("host.editor");
+ /**
+ * A key to retrieve caret instance (in host or injected editor, depending on context).
+ */
+ public static final DataKey<Caret> CARET = DataKey.create("caret");
/**
* Returns com.intellij.openapi.editor.Editor even if focus currently is in find bar
*/
diff --git a/platform/editor-ui-api/src/com/intellij/openapi/actionSystem/DataContextWrapper.java b/platform/editor-ui-api/src/com/intellij/openapi/actionSystem/DataContextWrapper.java
new file mode 100644
index 000000000000..091153d67cc5
--- /dev/null
+++ b/platform/editor-ui-api/src/com/intellij/openapi/actionSystem/DataContextWrapper.java
@@ -0,0 +1,51 @@
+/*
+ * 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.actionSystem;
+
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.UserDataHolder;
+import com.intellij.openapi.util.UserDataHolderBase;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+// We implement UserDataHolder to support DataManager.saveInDataContext/loadFromDataContext methods
+public class DataContextWrapper implements DataContext, UserDataHolder {
+ private final DataContext myDelegate;
+ private final UserDataHolder myDataHolder;
+
+ public DataContextWrapper(@NotNull DataContext delegate) {
+ myDelegate = delegate;
+ myDataHolder = delegate instanceof UserDataHolder ? (UserDataHolder) delegate : new UserDataHolderBase();
+ }
+
+ @Nullable
+ @Override
+ public Object getData(@NonNls String dataId) {
+ return myDelegate.getData(dataId);
+ }
+
+ @Nullable
+ @Override
+ public <T> T getUserData(@NotNull Key<T> key) {
+ return myDataHolder.getUserData(key);
+ }
+
+ @Override
+ public <T> void putUserData(@NotNull Key<T> key, @Nullable T value) {
+ myDataHolder.putUserData(key, value);
+ }
+}
diff --git a/platform/editor-ui-api/src/com/intellij/openapi/actionSystem/RightAlignedToolbarAction.java b/platform/editor-ui-api/src/com/intellij/openapi/actionSystem/RightAlignedToolbarAction.java
new file mode 100644
index 000000000000..d977bfa1e1f9
--- /dev/null
+++ b/platform/editor-ui-api/src/com/intellij/openapi/actionSystem/RightAlignedToolbarAction.java
@@ -0,0 +1,22 @@
+/*
+ * 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.actionSystem;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public interface RightAlignedToolbarAction {
+}
diff --git a/platform/editor-ui-api/src/com/intellij/ui/switcher/QuickActionProvider.java b/platform/editor-ui-api/src/com/intellij/ui/switcher/QuickActionProvider.java
index 7de29e05f281..a41abe4bc1ca 100644
--- a/platform/editor-ui-api/src/com/intellij/ui/switcher/QuickActionProvider.java
+++ b/platform/editor-ui-api/src/com/intellij/ui/switcher/QuickActionProvider.java
@@ -18,7 +18,6 @@ package com.intellij.ui.switcher;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.DataKey;
-import javax.swing.*;
import java.util.List;
public interface QuickActionProvider extends QuickAccessProvider {
diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemTaskDebugRunner.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemTaskDebugRunner.java
index 71b74f6e2272..86d1b6138f0d 100644
--- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemTaskDebugRunner.java
+++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemTaskDebugRunner.java
@@ -17,7 +17,6 @@ package com.intellij.openapi.externalSystem.service.execution;
import com.intellij.debugger.impl.GenericDebuggerRunner;
import com.intellij.execution.ExecutionException;
-import com.intellij.execution.Executor;
import com.intellij.execution.configurations.RemoteConnection;
import com.intellij.execution.configurations.RunProfile;
import com.intellij.execution.configurations.RunProfileState;
@@ -26,7 +25,6 @@ import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.externalSystem.util.ExternalSystemConstants;
-import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -35,8 +33,7 @@ import org.jetbrains.annotations.Nullable;
* @since 6/7/13 11:18 AM
*/
public class ExternalSystemTaskDebugRunner extends GenericDebuggerRunner {
-
- private static final Logger LOG = Logger.getInstance("#" + ExternalSystemTaskDebugRunner.class.getName());
+ private static final Logger LOG = Logger.getInstance(ExternalSystemTaskDebugRunner.class);
@NotNull
@Override
@@ -51,16 +48,12 @@ public class ExternalSystemTaskDebugRunner extends GenericDebuggerRunner {
@Nullable
@Override
- protected RunContentDescriptor createContentDescriptor(Project project,
- RunProfileState state,
- RunContentDescriptor contentToReuse,
- ExecutionEnvironment env) throws ExecutionException
- {
+ protected RunContentDescriptor createContentDescriptor(@NotNull RunProfileState state, @NotNull ExecutionEnvironment environment) throws ExecutionException {
if (state instanceof ExternalSystemRunConfiguration.MyRunnableState) {
int port = ((ExternalSystemRunConfiguration.MyRunnableState)state).getDebugPort();
if (port > 0) {
RemoteConnection connection = new RemoteConnection(true, "127.0.0.1", String.valueOf(port), true);
- return attachVirtualMachine(project, state, contentToReuse, env, connection, true);
+ return attachVirtualMachine(state, environment, connection, true);
}
else {
LOG.warn("Can't attach debugger to external system task execution. Reason: target debug port is unknown");
diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemTaskRunner.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemTaskRunner.java
index 90ca62f1bd54..d45be42bbbd9 100644
--- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemTaskRunner.java
+++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemTaskRunner.java
@@ -51,12 +51,8 @@ public class ExternalSystemTaskRunner extends GenericProgramRunner {
protected RunContentDescriptor doExecute(@NotNull Project project,
@NotNull RunProfileState state,
RunContentDescriptor contentToReuse,
- @NotNull ExecutionEnvironment env) throws ExecutionException
- {
+ @NotNull ExecutionEnvironment env) throws ExecutionException {
ExecutionResult executionResult = state.execute(env.getExecutor(), this);
- if (executionResult == null) return null;
-
- final RunContentBuilder contentBuilder = new RunContentBuilder(this, executionResult, env);
- return contentBuilder.showRunContent(contentToReuse);
+ return executionResult == null ? null : new RunContentBuilder(executionResult, env).showRunContent(contentToReuse);
}
}
diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/settings/AbstractExternalSystemConfigurable.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/settings/AbstractExternalSystemConfigurable.java
index 59b1e5f0dc74..5a933ab18e42 100644
--- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/settings/AbstractExternalSystemConfigurable.java
+++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/settings/AbstractExternalSystemConfigurable.java
@@ -166,7 +166,6 @@ public abstract class AbstractExternalSystemConfigurable<
if (!myProjectsModel.isEmpty()) {
- addTitle(ExternalSystemBundle.message("settings.title.system.settings", myExternalSystemId.getReadableName()));
myProjectsList.setSelectedIndex(0);
}
}
@@ -196,6 +195,7 @@ public abstract class AbstractExternalSystemConfigurable<
private void prepareSystemSettings(@NotNull SystemSettings s) {
mySystemSettingsControl = createSystemSettingsControl(s);
if (mySystemSettingsControl != null) {
+ addTitle(ExternalSystemBundle.message("settings.title.system.settings", myExternalSystemId.getReadableName()));
mySystemSettingsControl.fillUi(myComponent, 1);
}
}
diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/task/ui/AbstractExternalSystemToolWindowFactory.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/task/ui/AbstractExternalSystemToolWindowFactory.java
index 8c3ef0099e0d..1e08045faeea 100644
--- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/task/ui/AbstractExternalSystemToolWindowFactory.java
+++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/task/ui/AbstractExternalSystemToolWindowFactory.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.
@@ -45,7 +45,7 @@ public abstract class AbstractExternalSystemToolWindowFactory implements ToolWin
}
@Override
- public void createToolWindowContent(final Project project, final ToolWindow toolWindow) {
+ public void createToolWindowContent(@NotNull final Project project, @NotNull final ToolWindow toolWindow) {
toolWindow.setTitle(myExternalSystemId.getReadableName());
ContentManager contentManager = toolWindow.getContentManager();
String tasksTitle = ExternalSystemBundle.message("tool.window.title.tasks");
diff --git a/platform/icons/src/actions/GroupByClass.png b/platform/icons/src/actions/GroupByClass.png
new file mode 100644
index 000000000000..dddca942c295
--- /dev/null
+++ b/platform/icons/src/actions/GroupByClass.png
Binary files differ
diff --git a/platform/icons/src/actions/GroupByClass@2x.png b/platform/icons/src/actions/GroupByClass@2x.png
new file mode 100644
index 000000000000..25f262ea99ff
--- /dev/null
+++ b/platform/icons/src/actions/GroupByClass@2x.png
Binary files differ
diff --git a/platform/icons/src/actions/GroupByClass@2x_dark.png b/platform/icons/src/actions/GroupByClass@2x_dark.png
new file mode 100644
index 000000000000..8b8c42ceb33b
--- /dev/null
+++ b/platform/icons/src/actions/GroupByClass@2x_dark.png
Binary files differ
diff --git a/platform/icons/src/actions/GroupByClass_dark.png b/platform/icons/src/actions/GroupByClass_dark.png
new file mode 100644
index 000000000000..4ff7bde4a984
--- /dev/null
+++ b/platform/icons/src/actions/GroupByClass_dark.png
Binary files differ
diff --git a/platform/icons/src/gutter/extAnnotation.png b/platform/icons/src/gutter/extAnnotation.png
index 68fcd67c54ca..83bfdd350f5c 100644
--- a/platform/icons/src/gutter/extAnnotation.png
+++ b/platform/icons/src/gutter/extAnnotation.png
Binary files differ
diff --git a/platform/icons/src/gutter/extAnnotation@2x.png b/platform/icons/src/gutter/extAnnotation@2x.png
index 91b7e88e5864..a09a1571711f 100644
--- a/platform/icons/src/gutter/extAnnotation@2x.png
+++ b/platform/icons/src/gutter/extAnnotation@2x.png
Binary files differ
diff --git a/platform/icons/src/gutter/extAnnotation@2x_dark.png b/platform/icons/src/gutter/extAnnotation@2x_dark.png
index d84a71dbeba1..2793ff7fa8cc 100644
--- a/platform/icons/src/gutter/extAnnotation@2x_dark.png
+++ b/platform/icons/src/gutter/extAnnotation@2x_dark.png
Binary files differ
diff --git a/platform/icons/src/gutter/extAnnotation_dark.png b/platform/icons/src/gutter/extAnnotation_dark.png
index a0cc10b27be8..7303f547addc 100644
--- a/platform/icons/src/gutter/extAnnotation_dark.png
+++ b/platform/icons/src/gutter/extAnnotation_dark.png
Binary files differ
diff --git a/platform/indexing-api/src/com/intellij/psi/RefResolveService.java b/platform/indexing-api/src/com/intellij/psi/RefResolveService.java
new file mode 100644
index 000000000000..f53316506e78
--- /dev/null
+++ b/platform/indexing-api/src/com/intellij/psi/RefResolveService.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 com.intellij.psi;
+
+import com.intellij.openapi.components.AbstractProjectComponent;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.vfs.VirtualFileWithId;
+import com.intellij.psi.search.GlobalSearchScope;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collection;
+
+public abstract class RefResolveService extends AbstractProjectComponent {
+ public RefResolveService(Project project) {
+ super(project);
+ }
+
+ public static RefResolveService getInstance(Project project) {
+ return project.getComponent(RefResolveService.class);
+ }
+
+ @Nullable("null means the service has not resolved all files and is not ready yet")
+ public abstract int[] getBackwardIds(@NotNull VirtualFileWithId file);
+
+ /**
+ * @return subset of scope containing only files which reference the virtualFile
+ */
+ @NotNull
+ public abstract GlobalSearchScope restrictByBackwardIds(@NotNull VirtualFile virtualFile, @NotNull GlobalSearchScope scope);
+
+ /**
+ * @return add files to the resolve queue. until all files from there are resolved, the service is in incomplete state and returns null from getBackwardIds()
+ */
+ public abstract boolean queue(@NotNull Collection<VirtualFile> files, Object reason);
+}
diff --git a/platform/indexing-api/src/com/intellij/psi/search/PsiSearchHelper.java b/platform/indexing-api/src/com/intellij/psi/search/PsiSearchHelper.java
index cc283d0bb2b7..bef3d0350563 100644
--- a/platform/indexing-api/src/com/intellij/psi/search/PsiSearchHelper.java
+++ b/platform/indexing-api/src/com/intellij/psi/search/PsiSearchHelper.java
@@ -86,7 +86,7 @@ public interface PsiSearchHelper {
@NotNull GlobalSearchScope searchScope);
/**
- * Passes all occurrences of the specified full-qualified class name in plain text context in the
+ * Passes all occurrences of the specified fully qualified class name in plain text context in the
* use scope of the specified element to the specified processor.
*
* @param originalElement the element whose use scope is used to restrict the search scope,
@@ -126,7 +126,7 @@ public interface PsiSearchHelper {
final boolean caseSensitively);
/**
- * Passes all files containing the specified word in {@link UsageSearchContext#IN_PLAIN_TEXT code}
+ * Passes all files containing the specified word in {@link UsageSearchContext#IN_PLAIN_TEXT plain text}
* context to the specified processor.
*
* @param word the word to search.
@@ -189,7 +189,7 @@ public interface PsiSearchHelper {
@NotNull
SearchCostResult isCheapEnoughToSearch(@NotNull String name,
@NotNull GlobalSearchScope scope,
- @Nullable PsiFile fileToIgnoreOccurencesIn,
+ @Nullable PsiFile fileToIgnoreOccurrencesIn,
@Nullable ProgressIndicator progress);
enum SearchCostResult {
diff --git a/platform/indexing-api/src/com/intellij/psi/stubs/StubIndex.java b/platform/indexing-api/src/com/intellij/psi/stubs/StubIndex.java
index 11074f83781f..d9bbf9ee58a9 100644
--- a/platform/indexing-api/src/com/intellij/psi/stubs/StubIndex.java
+++ b/platform/indexing-api/src/com/intellij/psi/stubs/StubIndex.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.
@@ -162,5 +162,5 @@ public abstract class StubIndex {
protected <Psi extends PsiElement> void reportStubPsiMismatch(Psi psi, VirtualFile file, Class<Psi> requiredClass) {
LOG.error("Invalid stub element type in index: " + file + ". found: " + psi + ". expected: " + requiredClass);
}
-
+ public abstract void forceRebuild(@NotNull Throwable e);
}
diff --git a/platform/indexing-impl/src/com/intellij/psi/impl/PersistentIntList.java b/platform/indexing-impl/src/com/intellij/psi/impl/PersistentIntList.java
new file mode 100644
index 000000000000..aa5998364db4
--- /dev/null
+++ b/platform/indexing-impl/src/com/intellij/psi/impl/PersistentIntList.java
@@ -0,0 +1,386 @@
+/*
+ * 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.psi.impl;
+
+import com.intellij.openapi.Disposable;
+import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.io.Bits;
+import com.intellij.util.io.IntToIntBtree;
+import com.intellij.util.io.PagedFileStorage;
+import com.intellij.util.io.RandomAccessDataFile;
+import gnu.trove.TIntHashSet;
+import gnu.trove.TIntIntHashMap;
+import gnu.trove.TIntIntProcedure;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+
+/**
+ * the (int -> int[]) map which is persisted to the specified file.
+ */
+public class PersistentIntList implements Disposable {
+ public static final int MAX_DATA_BYTES = 500000000;
+ public static final int MAX_LIST_LENGTH = 100000;
+ private final IntToIntBtree index;
+ private RandomAccessDataFile data;
+ public int gap; // bytes lost due to fragmentation
+ private final int dataStart; // offset of real data; the bytes before are reserved for 'index' meta information, see persistsVarsTo()
+
+ public PersistentIntList(@NotNull File indexFile, @NotNull File dataFile, boolean initial) throws IOException {
+ if (initial) {
+ FileUtil.writeToFile(dataFile, ArrayUtil.EMPTY_BYTE_ARRAY);
+ }
+ PagedFileStorage.StorageLockContext context = new PagedFileStorage.StorageLockContext(true);
+ context.lock();
+ try {
+ data = new RandomAccessDataFile(dataFile);
+ index = new IntToIntBtree(4096, indexFile, context, initial);
+ dataStart = persistsVarsTo(data, initial);
+ }
+ finally {
+ context.unlock();
+ }
+ }
+
+ private int persistsVarsTo(@NotNull final RandomAccessDataFile data, boolean toDisk) {
+ return index.persistVars(new IntToIntBtree.BtreeDataStorage() {
+ @Override
+ public int persistInt(int offset, int value, boolean toDisk) {
+ if (toDisk) {
+ data.putInt(offset, value);
+ return value;
+ }
+ else {
+ return data.getInt(offset);
+ }
+ }
+ }, toDisk);
+ }
+
+ @Override
+ public void dispose() {
+ index.withStorageLock(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ persistsVarsTo(data, true);
+ index.doClose();
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ data.dispose();
+ }
+ });
+ }
+
+ @NotNull
+ public int[] get(final int id) {
+ final Ref<int[]> res = new Ref<int[]>();
+
+ index.withStorageLock(new Runnable() {
+ @Override
+ public void run() {
+ final int[] ptrPtr = new int[1];
+ boolean exists = index.get(id, ptrPtr);
+ if (!exists) {
+ ptrPtr[0] = 0;
+ }
+ int pointer = ptrPtr[0];
+ if (pointer == 0) {
+ res.set(ArrayUtil.EMPTY_INT_ARRAY);
+ }
+ else {
+ assertPointer(pointer);
+ int listLength = data.getInt(pointer);
+ int capacity = data.getInt(pointer + 4);
+ assertListLength(listLength, capacity);
+ int[] result = new int[listLength];
+ byte[] bytes = new byte[listLength * 4];
+ data.get(pointer + 8, bytes, 0, bytes.length);
+ for (int i = 0; i < listLength; i++) {
+ result[i] = Bits.getInt(bytes, i*4);
+ }
+ res.set(result);
+ }
+ }
+ });
+ return res.get();
+ }
+
+ // return true if was added
+ public boolean add(final int id, final int value) {
+ assert value > 0;
+ assert id > 0;
+ final boolean[] added = new boolean[1];
+ index.withStorageLock(new Runnable() {
+ @Override
+ public void run() {
+ int[] ptrPtr = new int[1];
+ index.get(id, ptrPtr);
+ final int pointer = ptrPtr[0];
+ int[] stored;
+ int capacity;
+ final int listLength;
+ if (pointer == 0) {
+ stored = ArrayUtil.EMPTY_INT_ARRAY;
+ listLength = 0;
+ capacity = 2;
+ }
+ else {
+ assertPointer(pointer);
+ listLength = data.getInt(pointer);
+ capacity = data.getInt(pointer+4);
+ assertListLength(listLength,capacity);
+ stored = new int[listLength];
+ for (int i = 0; i < listLength; i++) {
+ int v = data.getInt(pointer + (i + 2) * 4);
+ stored[i] = v;
+ if (v == value) return;
+ }
+ // append
+ if (capacity > listLength /*|| data.length() == pointer + 4 + 4 + 4*capacity*/) {
+ data.putInt(pointer + (listLength + 2) * 4, value);
+ data.putInt(pointer, listLength + 1);
+ if (capacity <= listLength) {
+ data.putInt(pointer+4, capacity + 1);
+ }
+ added[0] = true;
+ return;
+ }
+ // reallocate
+ gap += 4 + 4 + 4 * capacity;
+ }
+
+ int storePointer = (int)data.length();
+ data.putInt(storePointer, stored.length + 1);
+ int newCapacity = capacity < 10 ? capacity * 2 : (int)(capacity * 1.5);
+ assert newCapacity > stored.length + 1;
+ data.putInt(storePointer+4, newCapacity);
+ for (int i = 0; i < stored.length; i++) {
+ int v = stored[i];
+ data.putInt(storePointer + (i+2)*4, v);
+ }
+ data.putInt(storePointer + (stored.length+2)*4, value);
+ for (int i = stored.length + 1; i < newCapacity; i++) {
+ data.putInt(storePointer + (i+2)*4, 0); // gap
+ }
+ index.put(id, storePointer);
+ if (storePointer > 10000000) {
+ int i = 0;
+ }
+ added[0] = true;
+ }
+ });
+
+ return added[0];
+ }
+
+ private static void assertListLength(int listLength, int capacity) {
+ assert 0 < listLength && listLength <= MAX_LIST_LENGTH : listLength;
+ assert 0 < capacity && capacity <= MAX_LIST_LENGTH : capacity;
+ assert capacity >= listLength : listLength + ", " + capacity;
+ assert capacity <= (listLength+1)*2 : listLength + ", " + capacity;
+ }
+
+ public void addAll(final int id, @NotNull final int[] values) {
+ assertListLength(values.length, values.length);
+ assert id > 0;
+ Arrays.sort(values);
+
+ index.withStorageLock(new Runnable() {
+ @Override
+ public void run() {
+ int[] ptrPtr = new int[1];
+ index.get(id, ptrPtr);
+ final int pointer = ptrPtr[0];
+ int capacity;
+ final int newListLength;
+ byte[] mergedBytes;
+
+ if (pointer == 0) {
+ mergedBytes = toBytes(values);
+ newListLength = values.length;
+ capacity = 0;
+ }
+ else {
+ int[] oldIds = get(id);
+ checkSorted(oldIds);
+
+ assertPointer(pointer);
+ int storedListLength = data.getInt(pointer);
+ capacity = data.getInt(pointer + 4);
+ assertListLength(storedListLength, capacity);
+ // try to merge inplace and if failed, reallocate at the end
+ byte[] storedBytes = new byte[storedListLength * 4];
+ data.get(pointer + 8, storedBytes, 0, storedListLength * 4);
+
+ mergedBytes = new byte[storedBytes.length + values.length * 4];
+ int outPtr = 0;
+ int i = 0;
+ int j = 0;
+ while (i < storedListLength || j < values.length) {
+ int stored = i < storedListLength ? Bits.getInt(storedBytes, i * 4) : Integer.MAX_VALUE;
+ int value = j < values.length ? values[j] : Integer.MAX_VALUE;
+ if (stored < value) {
+ Bits.putInt(mergedBytes, outPtr, stored);
+ outPtr += 4;
+ i++;
+ }
+ else if (stored > value) {
+ Bits.putInt(mergedBytes, outPtr, value);
+ outPtr += 4;
+ j++;
+ }
+ else {
+ Bits.putInt(mergedBytes, outPtr, value);
+ outPtr += 4;
+ j++;
+ i++;
+ }
+ }
+ int[] mergedInts = fromBytes(mergedBytes, outPtr);
+ checkSorted(mergedInts);
+
+ newListLength = outPtr / 4;
+ assertListLength(newListLength, newListLength);
+ if (newListLength <= capacity) {
+ storeArray(data, pointer, newListLength, capacity, mergedBytes);
+ return;
+ }
+ gap += capacity * 4 + 8;
+ }
+ // reallocate at the end
+
+ int storePointer = (int)data.length();
+ assertPointer(storePointer);
+ int oldCapacity = Math.max(capacity, newListLength);
+ int newCapacity = oldCapacity < 10 ? (oldCapacity + 1) * 2 : (int)(oldCapacity * 1.5);
+ assert newCapacity > newListLength + 1;
+ storeArray(data, storePointer, newListLength, newCapacity, mergedBytes);
+ index.put(id, storePointer);
+ }
+ });
+
+ int[] ids = get(id);
+ checkSorted(ids);
+ TIntHashSet set = new TIntHashSet(ids);
+ assert set.containsAll(values): "ids: "+Arrays.toString(ids)+";\n values:"+Arrays.toString(values);
+ }
+
+ private static void checkSorted(int[] oldIds) {
+ for (int i = 1; i < oldIds.length; i++) {
+ assert oldIds[i - 1] < oldIds[i] : oldIds[i-1] + ", " + oldIds[i];
+ }
+ }
+
+ private static byte[] toBytes(@NotNull int[] values) {
+ byte[] mergedBytes = new byte[4 * values.length];
+ for (int i = 0; i < values.length; i++) {
+ int value = values[i];
+ Bits.putInt(mergedBytes, i * 4, value);
+ }
+ return mergedBytes;
+ }
+
+ private static int[] fromBytes(@NotNull byte[] bytes, int length) {
+ assert length % 4 == 0;
+ int[] ints = new int[length/4];
+ for (int i = 0; i < length; i+=4) {
+ int value = Bits.getInt(bytes, i);
+ ints[i/4] = value;
+ }
+ return ints;
+ }
+
+ private static void storeArray(@NotNull RandomAccessDataFile data,
+ int storePointer,
+ int newListLength,
+ int newCapacity,
+ @NotNull byte[] mergedBytes) {
+ assertListLength(newListLength, newCapacity);
+ data.putInt(storePointer, newListLength);
+ data.putInt(storePointer + 4, newCapacity);
+ data.put(storePointer + 8, mergedBytes, 0, newListLength * 4);
+ byte[] fill = new byte[(newCapacity - newListLength) * 4];
+ Arrays.fill(fill, (byte)-1);
+ data.put(storePointer + 8 + newListLength * 4, fill, 0, fill.length);
+ }
+
+ private static void assertPointer(int pointer) {
+ assert 0 < pointer && pointer <= MAX_DATA_BYTES : pointer;
+ }
+
+ public void flush() {
+ index.withStorageLock(new Runnable() {
+ @Override
+ public void run() {
+ persistsVarsTo(data, true);
+ index.doFlush();
+ data.sync();
+ //data.force();
+ }
+ });
+ }
+
+ private void compactIfNecessary() {
+ if (gap < data.length() / 2) return;
+ index.withStorageLock(new Runnable() {
+ @Override
+ public void run() {
+ persistsVarsTo(data, true);
+ index.doFlush();
+ data.sync();
+
+ try {
+ final RandomAccessDataFile newData = new RandomAccessDataFile(new File(data.getFile().getParentFile(), "newData"));
+ persistsVarsTo(newData, true);
+ final TIntIntHashMap map = new TIntIntHashMap();
+ index.processMappings(new IntToIntBtree.KeyValueProcessor() {
+ @Override
+ public boolean process(int key, int value) throws IOException {
+ map.put(key, value);
+ return true;
+ }
+ });
+ map.forEachEntry(new TIntIntProcedure() {
+ @Override
+ public boolean execute(int key, int value) {
+ int[] ids = get(key);
+ int pointer = (int)newData.length();
+ byte[] bytes = toBytes(ids);
+ storeArray(newData, pointer, ids.length, (int)(ids.length * 1.3), bytes);
+ index.put(key, pointer);
+ return true;
+ }
+ });
+
+ data.dispose();
+ data = newData;
+ gap = 0;
+ flush();
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
+ }
+}
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 b89042b68257..15112d3a100e 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
@@ -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.project.Project;
import com.intellij.openapi.roots.*;
import com.intellij.openapi.roots.impl.LibraryScopeCache;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.vfs.VirtualFileWithId;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiManagerImpl;
import com.intellij.psi.impl.ResolveScopeManager;
@@ -37,14 +38,17 @@ import java.util.List;
import java.util.Map;
public class ResolveScopeManagerImpl extends ResolveScopeManager {
-
+ /**
+ * if true then getUseScope() returns scope restricted to only relevant files which are stored in {@link RefResolveService}
+ */
+ public static final boolean ENABLED_REF_BACK = /*ApplicationManager.getApplication().isUnitTestMode() ||*/ Boolean.getBoolean("ref.back");
private final Project myProject;
private final ProjectRootManager myProjectRootManager;
private final PsiManager myManager;
private final Map<VirtualFile, GlobalSearchScope> myDefaultResolveScopesCache = new ConcurrentFactoryMap<VirtualFile, GlobalSearchScope>() {
@Override
- protected GlobalSearchScope create(VirtualFile key) {
+ protected GlobalSearchScope create(@NotNull VirtualFile key) {
GlobalSearchScope scope = null;
for(ResolveScopeProvider resolveScopeProvider: ResolveScopeProvider.EP_NAME.getExtensions()) {
scope = resolveScopeProvider.getResolveScope(key, myProject);
@@ -180,34 +184,37 @@ public class ResolveScopeManagerImpl extends ResolveScopeManager {
@Override
@NotNull
public GlobalSearchScope getUseScope(@NotNull PsiElement element) {
- VirtualFile vFile;
+ VirtualFile vDirectory;
+ final VirtualFile virtualFile;
+ final PsiFile containingFile;
final GlobalSearchScope allScope = GlobalSearchScope.allScope(myManager.getProject());
if (element instanceof PsiDirectory) {
- vFile = ((PsiDirectory)element).getVirtualFile();
+ vDirectory = ((PsiDirectory)element).getVirtualFile();
+ virtualFile = null;
+ containingFile = null;
}
else {
- final PsiFile containingFile = element.getContainingFile();
+ containingFile = element.getContainingFile();
if (containingFile == null) return allScope;
- final VirtualFile virtualFile = containingFile.getVirtualFile();
+ virtualFile = containingFile.getVirtualFile();
if (virtualFile == null) return allScope;
- vFile = virtualFile.getParent();
+ vDirectory = virtualFile.getParent();
}
- if (vFile == null) return allScope;
- ProjectFileIndex projectFileIndex = myProjectRootManager.getFileIndex();
- Module module = projectFileIndex.getModuleForFile(vFile);
- if (module != null) {
- boolean isTest = projectFileIndex.isInTestSourceContent(vFile);
- return isTest
- ? GlobalSearchScope.moduleTestsWithDependentsScope(module)
- : GlobalSearchScope.moduleWithDependentsScope(module);
+ if (vDirectory == null) return allScope;
+ final ProjectFileIndex projectFileIndex = myProjectRootManager.getFileIndex();
+ final Module module = projectFileIndex.getModuleForFile(vDirectory);
+ if (module == null) {
+ return containingFile == null || virtualFile.isDirectory() || allScope.contains(virtualFile)
+ ? allScope : GlobalSearchScope.fileScope(containingFile).uniteWith(allScope);
}
- else {
- final PsiFile f = element.getContainingFile();
- final VirtualFile vf = f == null ? null : f.getVirtualFile();
-
- return f == null || vf == null || vf.isDirectory() || allScope.contains(vf)
- ? allScope : GlobalSearchScope.fileScope(f).uniteWith(allScope);
+ boolean isTest = projectFileIndex.isInTestSourceContent(vDirectory);
+ GlobalSearchScope scope = isTest
+ ? GlobalSearchScope.moduleTestsWithDependentsScope(module)
+ : GlobalSearchScope.moduleWithDependentsScope(module);
+ if (virtualFile instanceof VirtualFileWithId && ENABLED_REF_BACK) {
+ return RefResolveService.getInstance(myProject).restrictByBackwardIds(virtualFile, scope);
}
+ return scope;
}
}
diff --git a/platform/lang-api/src/com/intellij/codeInsight/controlflow/ControlFlow.java b/platform/lang-api/src/com/intellij/codeInsight/controlflow/ControlFlow.java
deleted file mode 100644
index 99e7c2887d01..000000000000
--- a/platform/lang-api/src/com/intellij/codeInsight/controlflow/ControlFlow.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.intellij.codeInsight.controlflow;
-
-/**
- * @author oleg
- */
-public interface ControlFlow {
- Instruction[] getInstructions();
-}
diff --git a/platform/lang-api/src/com/intellij/execution/BeforeRunTaskProvider.java b/platform/lang-api/src/com/intellij/execution/BeforeRunTaskProvider.java
index f3331f899ff1..6799cfd7e6da 100644
--- a/platform/lang-api/src/com/intellij/execution/BeforeRunTaskProvider.java
+++ b/platform/lang-api/src/com/intellij/execution/BeforeRunTaskProvider.java
@@ -80,7 +80,7 @@ public abstract class BeforeRunTaskProvider<T extends BeforeRunTask> {
@Nullable
public static <T extends BeforeRunTask> BeforeRunTaskProvider<T> getProvider(Project project, Key<T> key) {
- BeforeRunTaskProvider<BeforeRunTask>[] providers = Extensions.getExtensions(BeforeRunTaskProvider.EXTENSION_POINT_NAME, project);
+ BeforeRunTaskProvider<BeforeRunTask>[] providers = Extensions.getExtensions(EXTENSION_POINT_NAME, project);
for (BeforeRunTaskProvider<BeforeRunTask> provider : providers) {
if (provider.getId() == key)
return (BeforeRunTaskProvider<T>)provider;
diff --git a/platform/lang-api/src/com/intellij/execution/ExecutionManager.java b/platform/lang-api/src/com/intellij/execution/ExecutionManager.java
index 5e9029ebf93f..183d6ada5ad2 100644
--- a/platform/lang-api/src/com/intellij/execution/ExecutionManager.java
+++ b/platform/lang-api/src/com/intellij/execution/ExecutionManager.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.
@@ -21,6 +21,7 @@ import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.runners.ProgramRunner;
import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.execution.ui.RunContentManager;
+import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.project.Project;
import com.intellij.util.messages.Topic;
import org.jetbrains.annotations.NotNull;
@@ -30,11 +31,11 @@ import org.jetbrains.annotations.Nullable;
* Manages the execution of run configurations and the relationship between running processes and Run/Debug toolwindow tabs.
*/
public abstract class ExecutionManager {
- public static final Topic<ExecutionListener> EXECUTION_TOPIC
- = new Topic<ExecutionListener>("configuration executed", ExecutionListener.class, Topic.BroadcastDirection.TO_PARENT);
+ public static final Topic<ExecutionListener> EXECUTION_TOPIC =
+ Topic.create("configuration executed", ExecutionListener.class, Topic.BroadcastDirection.TO_PARENT);
- public static ExecutionManager getInstance(final Project project) {
- return project.getComponent(ExecutionManager.class);
+ public static ExecutionManager getInstance(@NotNull Project project) {
+ return ServiceManager.getService(project, ExecutionManager.class);
}
/**
@@ -49,12 +50,12 @@ public abstract class ExecutionManager {
* Executes the before launch tasks for a run configuration.
*
* @param startRunnable the runnable to actually start the process for the run configuration.
- * @param env the execution environment describing the process to be started.
+ * @param environment the execution environment describing the process to be started.
* @param state the ready-to-start process
* @param onCancelRunnable the callback to call if one of the before launch tasks cancels the process execution.
*/
public abstract void compileAndRun(@NotNull Runnable startRunnable,
- @NotNull ExecutionEnvironment env,
+ @NotNull ExecutionEnvironment environment,
@Nullable RunProfileState state,
@Nullable Runnable onCancelRunnable);
@@ -63,27 +64,19 @@ public abstract class ExecutionManager {
*
* @return the list of processes.
*/
+ @NotNull
public abstract ProcessHandler[] getRunningProcesses();
/**
- * @deprecated use {@link #startRunProfile(RunProfileStarter, com.intellij.execution.configurations.RunProfileState, com.intellij.execution.runners.ExecutionEnvironment)}
- */
- public abstract void startRunProfile(@NotNull RunProfileStarter starter,
- @NotNull RunProfileState state,
- @NotNull Project project,
- @NotNull Executor executor,
- @NotNull ExecutionEnvironment env);
-
- /**
* Prepares the run or debug tab for running the specified process and calls a callback to start it.
*
* @param starter the callback to start the process execution.
* @param state the ready-to-start process
- * @param env the execution environment describing the process to be started.
+ * @param environment the execution environment describing the process to be started.
*/
public abstract void startRunProfile(@NotNull RunProfileStarter starter,
@NotNull RunProfileState state,
- @NotNull ExecutionEnvironment env);
+ @NotNull ExecutionEnvironment environment);
public abstract void restartRunProfile(@NotNull Project project,
@NotNull Executor executor,
@@ -91,9 +84,10 @@ public abstract class ExecutionManager {
@Nullable RunnerAndConfigurationSettings configuration,
@Nullable ProcessHandler processHandler);
- //currentDescriptor is null for toolbar/popup action and not null for actions in run/debug toolwindows
/**
- * @deprecated use {@link #restartRunProfile(com.intellij.execution.runners.ProgramRunner, com.intellij.execution.runners.ExecutionEnvironment, com.intellij.execution.ui.RunContentDescriptor)}
+ * currentDescriptor is null for toolbar/popup action and not null for actions in run/debug toolwindows
+ * @deprecated use {@link #restartRunProfile(com.intellij.execution.runners.ExecutionEnvironment)}
+ * to remove in IDEA 15
*/
public abstract void restartRunProfile(@NotNull Project project,
@NotNull Executor executor,
@@ -101,7 +95,14 @@ public abstract class ExecutionManager {
@Nullable RunnerAndConfigurationSettings configuration,
@Nullable RunContentDescriptor currentDescriptor);
+ /**
+ * currentDescriptor is null for toolbar/popup action and not null for actions in run/debug toolwindows
+ * @deprecated use {@link #restartRunProfile(com.intellij.execution.runners.ExecutionEnvironment)}
+ * to remove in IDEA 15
+ */
public abstract void restartRunProfile(@Nullable ProgramRunner runner,
@NotNull ExecutionEnvironment environment,
@Nullable RunContentDescriptor currentDescriptor);
+
+ public abstract void restartRunProfile(@NotNull ExecutionEnvironment environment);
}
diff --git a/platform/lang-api/src/com/intellij/execution/ExecutionTargetManager.java b/platform/lang-api/src/com/intellij/execution/ExecutionTargetManager.java
index b48a2e8919fb..612c9c1c80ea 100644
--- a/platform/lang-api/src/com/intellij/execution/ExecutionTargetManager.java
+++ b/platform/lang-api/src/com/intellij/execution/ExecutionTargetManager.java
@@ -15,6 +15,8 @@
*/
package com.intellij.execution;
+import com.intellij.execution.runners.ExecutionEnvironment;
+import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.project.Project;
import com.intellij.util.messages.Topic;
import org.jetbrains.annotations.NotNull;
@@ -26,10 +28,9 @@ import java.util.List;
public abstract class ExecutionTargetManager {
public static final Topic<ExecutionTargetListener> TOPIC = Topic.create("ExecutionTarget topic", ExecutionTargetListener.class);
-
@NotNull
public static ExecutionTargetManager getInstance(@NotNull Project project) {
- return project.getComponent(ExecutionTargetManager.class);
+ return ServiceManager.getService(project, ExecutionTargetManager.class);
}
@NotNull
@@ -57,6 +58,10 @@ public abstract class ExecutionTargetManager {
return settings != null && target != null && settings.canRunOn(target) && target.canRun(settings);
}
+ public static boolean canRun(@NotNull ExecutionEnvironment environment) {
+ return canRun(environment.getRunnerAndConfigurationSettings(), environment.getExecutionTarget());
+ }
+
public static void update(@NotNull Project project) {
getInstance(project).update();
}
diff --git a/platform/lang-api/src/com/intellij/execution/ExecutorRegistry.java b/platform/lang-api/src/com/intellij/execution/ExecutorRegistry.java
index 49139be54e58..31d39087d1f1 100644
--- a/platform/lang-api/src/com/intellij/execution/ExecutorRegistry.java
+++ b/platform/lang-api/src/com/intellij/execution/ExecutorRegistry.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,6 +16,7 @@
package com.intellij.execution;
+import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.ApplicationComponent;
import com.intellij.openapi.project.Project;
@@ -25,7 +26,6 @@ import org.jetbrains.annotations.NotNull;
* @author spleaner
*/
public abstract class ExecutorRegistry implements ApplicationComponent {
-
public static ExecutorRegistry getInstance() {
return ApplicationManager.getApplication().getComponent(ExecutorRegistry.class);
}
@@ -35,5 +35,10 @@ public abstract class ExecutorRegistry implements ApplicationComponent {
public abstract Executor getExecutorById(final String executorId);
+ /**
+ * Consider to use {@link #isStarting(com.intellij.execution.runners.ExecutionEnvironment)}
+ */
public abstract boolean isStarting(Project project, String executorId, String runnerId);
+
+ public abstract boolean isStarting(@NotNull ExecutionEnvironment environment);
}
diff --git a/platform/lang-api/src/com/intellij/execution/RunnerRegistry.java b/platform/lang-api/src/com/intellij/execution/RunnerRegistry.java
index 39eb47de921d..fec7223b1721 100644
--- a/platform/lang-api/src/com/intellij/execution/RunnerRegistry.java
+++ b/platform/lang-api/src/com/intellij/execution/RunnerRegistry.java
@@ -30,7 +30,7 @@ public abstract class RunnerRegistry implements ApplicationComponent {
public abstract boolean hasRunner(@NotNull final String executorId, @NotNull final RunProfile settings);
@Nullable
- public abstract ProgramRunner getRunner(@NotNull final String executorId, final RunProfile settings);
+ public abstract ProgramRunner getRunner(@NotNull String executorId, @Nullable RunProfile settings);
public abstract ProgramRunner[] getRegisteredRunners();
diff --git a/platform/lang-api/src/com/intellij/execution/configurations/LogFileOptions.java b/platform/lang-api/src/com/intellij/execution/configurations/LogFileOptions.java
index d159fa03ac3a..6f23831c9e3a 100644
--- a/platform/lang-api/src/com/intellij/execution/configurations/LogFileOptions.java
+++ b/platform/lang-api/src/com/intellij/execution/configurations/LogFileOptions.java
@@ -123,11 +123,8 @@ public class LogFileOptions implements JDOMExternalizable {
final File[] dirs = root.listFiles();
if (dirs == null) return;
for (File dir : dirs) {
- if (dir.isFile()) {
- final String path = FileUtil.toSystemIndependentName(FileUtil.getRelativePath(root, dir));
- if (pattern.matcher(path).matches()) {
- files.add(dir);
- }
+ if (pattern.matcher(dir.getName()).matches() && dir.isFile()) {
+ files.add(dir);
}
}
}
diff --git a/platform/lang-api/src/com/intellij/execution/runners/ExecutionEnvironment.java b/platform/lang-api/src/com/intellij/execution/runners/ExecutionEnvironment.java
index 6acc467249e3..e85e36669f2c 100644
--- a/platform/lang-api/src/com/intellij/execution/runners/ExecutionEnvironment.java
+++ b/platform/lang-api/src/com/intellij/execution/runners/ExecutionEnvironment.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.execution.runners;
import com.intellij.execution.*;
@@ -39,9 +38,7 @@ import java.util.concurrent.atomic.AtomicLong;
import static com.intellij.openapi.actionSystem.LangDataKeys.*;
-
-public class ExecutionEnvironment extends UserDataHolderBase {
-
+public class ExecutionEnvironment extends UserDataHolderBase implements Disposable {
private static final AtomicLong myIdHolder = new AtomicLong(1L);
@NotNull private final Project myProject;
@@ -54,7 +51,7 @@ public class ExecutionEnvironment extends UserDataHolderBase {
@Nullable private ConfigurationPerRunnerSettings myConfigurationSettings;
@Nullable private final RunnerAndConfigurationSettings myRunnerAndConfigurationSettings;
@Nullable private RunContentDescriptor myContentToReuse;
- @Nullable private String myRunnerId;
+ private final ProgramRunner<?> myRunner;
private long myExecutionId = 0;
@Nullable private DataContext myDataContext;
@@ -64,11 +61,12 @@ public class ExecutionEnvironment extends UserDataHolderBase {
myContentToReuse = null;
myRunnerAndConfigurationSettings = null;
myExecutor = null;
+ myRunner = null;
}
public ExecutionEnvironment(@NotNull Executor executor,
- @NotNull final ProgramRunner runner,
- @NotNull final RunnerAndConfigurationSettings configuration,
+ @NotNull ProgramRunner runner,
+ @NotNull RunnerAndConfigurationSettings configuration,
@NotNull Project project) {
this(configuration.getConfiguration(),
executor,
@@ -78,11 +76,12 @@ public class ExecutionEnvironment extends UserDataHolderBase {
configuration.getConfigurationSettings(runner),
null,
null,
- runner.getRunnerId());
+ runner);
}
/**
* @deprecated, use {@link com.intellij.execution.runners.ExecutionEnvironmentBuilder} instead
+ * to remove in IDEA 14
*/
@TestOnly
public ExecutionEnvironment(@NotNull Executor executor,
@@ -97,45 +96,46 @@ public class ExecutionEnvironment extends UserDataHolderBase {
configuration.getRunnerSettings(runner),
configuration.getConfigurationSettings(runner),
null,
- configuration, runner.getRunnerId());
+ configuration,
+ runner);
}
/**
* @deprecated, use {@link com.intellij.execution.runners.ExecutionEnvironmentBuilder} instead
+ * to remove in IDEA 15
*/
public ExecutionEnvironment(@NotNull RunProfile runProfile,
@NotNull Executor executor,
@NotNull Project project,
@Nullable RunnerSettings runnerSettings) {
- this(runProfile, executor, DefaultExecutionTarget.INSTANCE, project, runnerSettings, null, null, null, null);
+ //noinspection ConstantConditions
+ this(runProfile, executor, DefaultExecutionTarget.INSTANCE, project, runnerSettings, null, null, null, RunnerRegistry.getInstance().getRunner(executor.getId(), runProfile));
}
- public ExecutionEnvironment(@NotNull RunProfile runProfile,
- @NotNull Executor executor,
- @NotNull ExecutionTarget target,
- @NotNull Project project,
- @Nullable RunnerSettings runnerSettings,
- @Nullable ConfigurationPerRunnerSettings configurationSettings,
- @Nullable RunContentDescriptor contentToReuse,
- @Nullable RunnerAndConfigurationSettings settings,
- @Nullable String runnerId) {
+ ExecutionEnvironment(@NotNull RunProfile runProfile,
+ @NotNull Executor executor,
+ @NotNull ExecutionTarget target,
+ @NotNull Project project,
+ @Nullable RunnerSettings runnerSettings,
+ @Nullable ConfigurationPerRunnerSettings configurationSettings,
+ @Nullable RunContentDescriptor contentToReuse,
+ @Nullable RunnerAndConfigurationSettings settings,
+ @NotNull ProgramRunner<?> runner) {
myExecutor = executor;
myTarget = target;
myRunProfile = runProfile;
myRunnerSettings = runnerSettings;
myConfigurationSettings = configurationSettings;
myProject = project;
- myContentToReuse = contentToReuse;
+ setContentToReuse(contentToReuse);
myRunnerAndConfigurationSettings = settings;
- myRunnerId = runnerId;
- if (myContentToReuse != null) {
- Disposer.register(myContentToReuse, new Disposable() {
- @Override
- public void dispose() {
- myContentToReuse = null;
- }
- });
- }
+
+ myRunner = runner;
+ }
+
+ @Override
+ public void dispose() {
+ myContentToReuse = null;
}
@NotNull
@@ -163,9 +163,27 @@ public class ExecutionEnvironment extends UserDataHolderBase {
return myContentToReuse;
}
+ public void setContentToReuse(@Nullable RunContentDescriptor contentToReuse) {
+ myContentToReuse = contentToReuse;
+
+ if (contentToReuse != null) {
+ Disposer.register(contentToReuse, this);
+ }
+ }
+
@Nullable
+ @Deprecated
+ /**
+ * Use {@link #getRunner()} instead
+ * to remove in IDEA 15
+ */
public String getRunnerId() {
- return myRunnerId;
+ return myRunner.getRunnerId();
+ }
+
+ @NotNull
+ public ProgramRunner<?> getRunner() {
+ return myRunner;
}
@Nullable
diff --git a/platform/lang-api/src/com/intellij/execution/runners/ExecutionEnvironmentBuilder.java b/platform/lang-api/src/com/intellij/execution/runners/ExecutionEnvironmentBuilder.java
index cb5891a0040e..6bdb1942171e 100644
--- a/platform/lang-api/src/com/intellij/execution/runners/ExecutionEnvironmentBuilder.java
+++ b/platform/lang-api/src/com/intellij/execution/runners/ExecutionEnvironmentBuilder.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,16 +15,13 @@
*/
package com.intellij.execution.runners;
-import com.intellij.execution.DefaultExecutionTarget;
-import com.intellij.execution.ExecutionTarget;
-import com.intellij.execution.Executor;
-import com.intellij.execution.RunnerAndConfigurationSettings;
+import com.intellij.execution.*;
import com.intellij.execution.configurations.ConfigurationPerRunnerSettings;
+import com.intellij.execution.configurations.RunConfiguration;
import com.intellij.execution.configurations.RunProfile;
import com.intellij.execution.configurations.RunnerSettings;
import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -33,7 +30,6 @@ import org.jetbrains.annotations.Nullable;
* User: Vassiliy.Kudryashov
*/
public final class ExecutionEnvironmentBuilder {
- private static final Logger LOG = Logger.getInstance("#com.intellij.execution.runners.ExecutionEnvironmentBuilder");
@NotNull private RunProfile myRunProfile;
@NotNull private ExecutionTarget myTarget = DefaultExecutionTarget.INSTANCE;
@@ -44,6 +40,7 @@ public final class ExecutionEnvironmentBuilder {
@Nullable private RunContentDescriptor myContentToReuse;
@Nullable private RunnerAndConfigurationSettings myRunnerAndConfigurationSettings;
@Nullable private String myRunnerId;
+ private ProgramRunner<?> myRunner;
private boolean myAssignNewId;
@NotNull private Executor myExecutor;
@Nullable private DataContext myDataContext;
@@ -53,83 +50,224 @@ public final class ExecutionEnvironmentBuilder {
myExecutor = executor;
}
+ @NotNull
+ public static ExecutionEnvironmentBuilder create(@NotNull Project project, @NotNull Executor executor, @NotNull RunProfile runProfile) throws ExecutionException {
+ ExecutionEnvironmentBuilder builder = createOrNull(project, executor, runProfile);
+ if (builder == null) {
+ throw new ExecutionException("Cannot find runner for " + runProfile.getName());
+ }
+ return builder;
+ }
+
+ @Nullable
+ public static ExecutionEnvironmentBuilder createOrNull(@NotNull Project project, @NotNull Executor executor, @NotNull RunProfile runProfile) {
+ ProgramRunner runner = RunnerRegistry.getInstance().getRunner(executor.getId(), runProfile);
+ if (runner == null) {
+ return null;
+ }
+ return new ExecutionEnvironmentBuilder(project, executor).runner(runner).runProfile(runProfile);
+ }
+
+ @Nullable
+ public static ExecutionEnvironmentBuilder createOrNull(@NotNull Executor executor, @NotNull RunnerAndConfigurationSettings settings) {
+ ExecutionEnvironmentBuilder builder = createOrNull(settings.getConfiguration().getProject(), executor, settings.getConfiguration());
+ return builder == null ? null : builder.runnerAndSettings(builder.myRunner, settings);
+ }
+
+ @NotNull
+ public static ExecutionEnvironmentBuilder create(@NotNull Executor executor, @NotNull RunnerAndConfigurationSettings settings) throws ExecutionException {
+ ExecutionEnvironmentBuilder builder = create(settings.getConfiguration().getProject(), executor, settings.getConfiguration());
+ return builder.runnerAndSettings(builder.myRunner, settings);
+ }
+
+ @NotNull
+ public static ExecutionEnvironmentBuilder create(@NotNull Executor executor, @NotNull RunConfiguration configuration) {
+ return new ExecutionEnvironmentBuilder(configuration.getProject(), executor).runProfile(configuration);
+ }
+
+ @NotNull
+ Executor getExecutor() {
+ return myExecutor;
+ }
+
/**
* Creates an execution environment builder initialized with a copy of the specified environment.
*
* @param copySource the environment to copy from.
*/
public ExecutionEnvironmentBuilder(@NotNull ExecutionEnvironment copySource) {
- setTarget(copySource.getExecutionTarget());
+ myTarget = copySource.getExecutionTarget();
myProject = copySource.getProject();
myRunnerAndConfigurationSettings = copySource.getRunnerAndConfigurationSettings();
myRunProfile = copySource.getRunProfile();
myRunnerSettings = copySource.getRunnerSettings();
myConfigurationSettings = copySource.getConfigurationSettings();
- myRunnerId = copySource.getRunnerId();
- setContentToReuse(copySource.getContentToReuse());
+ //noinspection deprecation
+ myRunner = copySource.getRunner();
+ myContentToReuse = copySource.getContentToReuse();
myExecutor = copySource.getExecutor();
}
+ @SuppressWarnings("UnusedDeclaration")
+ @Deprecated
+ /**
+ * to remove in IDEA 15
+ */
public ExecutionEnvironmentBuilder setTarget(@NotNull ExecutionTarget target) {
- myTarget = target;
+ return target(target);
+ }
+
+ public ExecutionEnvironmentBuilder target(@Nullable ExecutionTarget target) {
+ if (target != null) {
+ myTarget = target;
+ }
+ return this;
+ }
+
+ public ExecutionEnvironmentBuilder activeTarget() {
+ myTarget = ExecutionTargetManager.getActiveTarget(myProject);
return this;
}
+ @SuppressWarnings("UnusedDeclaration")
+ @Deprecated
+ /**
+ * to remove in IDEA 15
+ */
public ExecutionEnvironmentBuilder setRunnerAndSettings(@NotNull ProgramRunner programRunner,
@NotNull RunnerAndConfigurationSettings settings) {
+ return runnerAndSettings(programRunner, settings);
+ }
+
+ public ExecutionEnvironmentBuilder runnerAndSettings(@NotNull ProgramRunner runner,
+ @NotNull RunnerAndConfigurationSettings settings) {
myRunnerAndConfigurationSettings = settings;
- setRunProfile(settings.getConfiguration());
- setRunnerSettings(settings.getRunnerSettings(programRunner));
- setConfigurationSettings(settings.getConfigurationSettings(programRunner));
- setRunnerId(programRunner.getRunnerId());
+ myRunProfile = settings.getConfiguration();
+ myRunnerSettings = settings.getRunnerSettings(runner);
+ myConfigurationSettings = settings.getConfigurationSettings(runner);
+ myRunner = runner;
return this;
}
+ @SuppressWarnings("UnusedDeclaration")
+ @Deprecated
+ /**
+ * to remove in IDEA 15
+ */
public ExecutionEnvironmentBuilder setRunnerSettings(@Nullable RunnerSettings runnerSettings) {
myRunnerSettings = runnerSettings;
return this;
}
+ public ExecutionEnvironmentBuilder runnerSettings(@Nullable RunnerSettings runnerSettings) {
+ myRunnerSettings = runnerSettings;
+ return this;
+ }
+
+ @SuppressWarnings("UnusedDeclaration")
+ @Deprecated
+ /**
+ * to remove in IDEA 15
+ */
public ExecutionEnvironmentBuilder setConfigurationSettings(@Nullable ConfigurationPerRunnerSettings configurationSettings) {
myConfigurationSettings = configurationSettings;
return this;
}
+ @SuppressWarnings("UnusedDeclaration")
+ @Deprecated
+ /**
+ * to remove in IDEA 15
+ */
public ExecutionEnvironmentBuilder setContentToReuse(@Nullable RunContentDescriptor contentToReuse) {
+ contentToReuse(contentToReuse);
+ return this;
+ }
+
+ public ExecutionEnvironmentBuilder contentToReuse(@Nullable RunContentDescriptor contentToReuse) {
myContentToReuse = contentToReuse;
return this;
}
+ @SuppressWarnings("UnusedDeclaration")
+ @Deprecated
+ /**
+ * to remove in IDEA 15
+ */
public ExecutionEnvironmentBuilder setRunProfile(@NotNull RunProfile runProfile) {
+ return runProfile(runProfile);
+ }
+
+ public ExecutionEnvironmentBuilder runProfile(@NotNull RunProfile runProfile) {
myRunProfile = runProfile;
return this;
}
+ @SuppressWarnings("UnusedDeclaration")
+ @Deprecated
+ /**
+ * to remove in IDEA 15
+ */
public ExecutionEnvironmentBuilder setRunnerId(@Nullable String runnerId) {
myRunnerId = runnerId;
return this;
}
+ public ExecutionEnvironmentBuilder runner(@NotNull ProgramRunner<?> runner) {
+ myRunner = runner;
+ return this;
+ }
+
public ExecutionEnvironmentBuilder assignNewId() {
myAssignNewId = true;
return this;
}
+ @SuppressWarnings("UnusedDeclaration")
+ @Deprecated
+ /**
+ * to remove in IDEA 15
+ */
public ExecutionEnvironmentBuilder setDataContext(@Nullable DataContext dataContext) {
+ return dataContext(dataContext);
+ }
+
+ public ExecutionEnvironmentBuilder dataContext(@Nullable DataContext dataContext) {
myDataContext = dataContext;
return this;
}
+ @SuppressWarnings("UnusedDeclaration")
+ @Deprecated
+ /**
+ * to remove in IDEA 15
+ */
public ExecutionEnvironmentBuilder setExecutor(@NotNull Executor executor) {
+ return executor(executor);
+ }
+
+ public ExecutionEnvironmentBuilder executor(@NotNull Executor executor) {
myExecutor = executor;
return this;
}
@NotNull
public ExecutionEnvironment build() {
- ExecutionEnvironment environment =
- new ExecutionEnvironment(myRunProfile, myExecutor, myTarget, myProject, myRunnerSettings, myConfigurationSettings, myContentToReuse,
- myRunnerAndConfigurationSettings, myRunnerId);
+ if (myRunner == null) {
+ if (myRunnerId == null) {
+ myRunner = RunnerRegistry.getInstance().getRunner(myExecutor.getId(), myRunProfile);
+ }
+ else {
+ myRunner = RunnerRegistry.getInstance().findRunnerById(myRunnerId);
+ }
+ }
+
+ if (myRunner == null) {
+ throw new IllegalStateException("Runner must be specified");
+ }
+
+ ExecutionEnvironment environment = new ExecutionEnvironment(myRunProfile, myExecutor, myTarget, myProject, myRunnerSettings, myConfigurationSettings, myContentToReuse,
+ myRunnerAndConfigurationSettings, myRunner);
if (myAssignNewId) {
environment.assignNewExecutionId();
}
@@ -138,4 +276,9 @@ public final class ExecutionEnvironmentBuilder {
}
return environment;
}
+
+ public void buildAndExecute() throws ExecutionException {
+ ExecutionEnvironment environment = build();
+ myRunner.execute(environment);
+ }
}
diff --git a/platform/lang-api/src/com/intellij/execution/runners/ExecutionUtil.java b/platform/lang-api/src/com/intellij/execution/runners/ExecutionUtil.java
index f0d67274d61a..0d15a272498c 100644
--- a/platform/lang-api/src/com/intellij/execution/runners/ExecutionUtil.java
+++ b/platform/lang-api/src/com/intellij/execution/runners/ExecutionUtil.java
@@ -16,24 +16,29 @@
package com.intellij.execution.runners;
-import com.intellij.execution.ExecutionBundle;
-import com.intellij.execution.ExecutionException;
-import com.intellij.execution.RunCanceledByUserException;
+import com.intellij.execution.*;
import com.intellij.execution.configurations.RunProfile;
+import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.process.ProcessNotCreatedException;
+import com.intellij.execution.ui.RunContentDescriptor;
+import com.intellij.ide.DataManager;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.notification.NotificationGroup;
import com.intellij.notification.NotificationListener;
import com.intellij.notification.NotificationType;
+import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.wm.ToolWindowManager;
+import com.intellij.ui.content.Content;
import com.intellij.util.ObjectUtils;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import javax.swing.*;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
@@ -52,6 +57,10 @@ public class ExecutionUtil {
handleExecutionError(project, toolWindowId, runProfile.getName(), e);
}
+ public static void handleExecutionError(@NotNull ExecutionEnvironment environment, @NotNull ExecutionException e) {
+ handleExecutionError(environment.getProject(), environment.getExecutor().getToolWindowId(), environment.getRunProfile().getName(), e);
+ }
+
public static void handleExecutionError(@NotNull final Project project,
@NotNull final String toolWindowId,
@NotNull String taskName,
@@ -59,15 +68,15 @@ public class ExecutionUtil {
if (e instanceof RunCanceledByUserException) return;
LOG.debug(e);
-
+
String description = e.getMessage();
HyperlinkListener listener = null;
-
+
if (description == null) {
LOG.warn("Execution error without description", e);
description = "Unknown error";
}
-
+
if ((description.contains("87") || description.contains("111") || description.contains("206")) &&
e instanceof ProcessNotCreatedException &&
!PropertiesComponent.getInstance(project).isTrueValue("dynamic.classpath")) {
@@ -107,4 +116,57 @@ public class ExecutionUtil {
}
});
}
+
+ public static void restartIfActive(@NotNull RunContentDescriptor descriptor) {
+ ProcessHandler processHandler = descriptor.getProcessHandler();
+ if (processHandler != null
+ && processHandler.isStartNotified()
+ && !processHandler.isProcessTerminating()
+ && !processHandler.isProcessTerminated()) {
+ restart(descriptor);
+ }
+ }
+
+ public static void restart(@NotNull RunContentDescriptor descriptor) {
+ restart(descriptor.getComponent());
+ }
+
+ public static void restart(@NotNull Content content) {
+ restart(content.getComponent());
+ }
+
+ private static void restart(@Nullable JComponent component) {
+ if (component != null) {
+ ExecutionEnvironment environment = LangDataKeys.EXECUTION_ENVIRONMENT.getData(DataManager.getInstance().getDataContext(component));
+ if (environment != null) {
+ restart(environment);
+ }
+ }
+ }
+
+ public static void restart(@NotNull ExecutionEnvironment environment) {
+ if (!ExecutorRegistry.getInstance().isStarting(environment)) {
+ ExecutionManager.getInstance(environment.getProject()).restartRunProfile(environment);
+ }
+ }
+
+ public static void runConfiguration(@NotNull RunnerAndConfigurationSettings configuration, @NotNull Executor executor) {
+ ExecutionEnvironmentBuilder builder = createEnvironment(executor, configuration);
+ if (builder != null) {
+ ExecutionManager.getInstance(configuration.getConfiguration().getProject()).restartRunProfile(builder
+ .activeTarget()
+ .build());
+ }
+ }
+
+ @Nullable
+ public static ExecutionEnvironmentBuilder createEnvironment(@NotNull Executor executor, @NotNull RunnerAndConfigurationSettings settings) {
+ try {
+ return ExecutionEnvironmentBuilder.create(executor, settings);
+ }
+ catch (ExecutionException e) {
+ handleExecutionError(settings.getConfiguration().getProject(), executor.getToolWindowId(), settings.getConfiguration().getName(), e);
+ return null;
+ }
+ }
}
diff --git a/platform/lang-api/src/com/intellij/execution/runners/GenericProgramRunner.java b/platform/lang-api/src/com/intellij/execution/runners/GenericProgramRunner.java
index ec8ec49a790b..adbd04e822e6 100644
--- a/platform/lang-api/src/com/intellij/execution/runners/GenericProgramRunner.java
+++ b/platform/lang-api/src/com/intellij/execution/runners/GenericProgramRunner.java
@@ -51,7 +51,8 @@ public abstract class GenericProgramRunner<Settings extends RunnerSettings> exte
}
@Nullable
- protected abstract RunContentDescriptor doExecute(@NotNull Project project, @NotNull RunProfileState state,
+ protected abstract RunContentDescriptor doExecute(@NotNull Project project,
+ @NotNull RunProfileState state,
@Nullable RunContentDescriptor contentToReuse,
@NotNull ExecutionEnvironment environment) throws ExecutionException;
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 8d4d3b29b088..60e7f03d54db 100644
--- a/platform/lang-api/src/com/intellij/execution/ui/RunContentDescriptor.java
+++ b/platform/lang-api/src/com/intellij/execution/ui/RunContentDescriptor.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,23 +15,20 @@
*/
package com.intellij.execution.ui;
+import com.intellij.execution.ExecutionResult;
+import com.intellij.execution.configurations.RunProfile;
import com.intellij.execution.process.ProcessHandler;
-import com.intellij.ide.DataManager;
import com.intellij.ide.HelpIdProvider;
import com.intellij.openapi.Disposable;
-import com.intellij.openapi.actionSystem.DataProvider;
-import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Disposer;
import com.intellij.ui.content.Content;
-import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
public class RunContentDescriptor implements Disposable {
- private static final Logger LOG = Logger.getInstance("#com.intellij.execution.ui.RunContentDescriptor");
-
private ExecutionConsole myExecutionConsole;
private ProcessHandler myProcessHandler;
private JComponent myComponent;
@@ -45,37 +42,33 @@ public class RunContentDescriptor implements Disposable {
private Computable<JComponent> myFocusComputable = null;
private boolean myAutoFocusContent = false;
- /**
- * Used to hack {@link com.intellij.execution.runners.RestartAction}
- */
private Content myContent;
private Runnable myRestarter;
- public RunContentDescriptor(final ExecutionConsole executionConsole,
- final ProcessHandler processHandler, final JComponent component, final String displayName, final Icon icon) {
+ public RunContentDescriptor(@Nullable ExecutionConsole executionConsole,
+ @Nullable ProcessHandler processHandler,
+ @NotNull JComponent component,
+ String displayName,
+ @Nullable Icon icon) {
myExecutionConsole = executionConsole;
myProcessHandler = processHandler;
myComponent = component;
myDisplayName = displayName;
myIcon = icon;
myHelpId = myExecutionConsole instanceof HelpIdProvider ? ((HelpIdProvider)myExecutionConsole).getHelpId() : null;
- DataManager.registerDataProvider(myComponent, new DataProvider() {
-
- @Override
- public Object getData(@NonNls final String dataId) {
- if (RunContentManager.RUN_CONTENT_DESCRIPTOR.is(dataId)) {
- return RunContentDescriptor.this;
- }
- return null;
- }
- });
}
- public RunContentDescriptor(final ExecutionConsole executionConsole,
- final ProcessHandler processHandler, final JComponent component, final String displayName) {
+ public RunContentDescriptor(@Nullable ExecutionConsole executionConsole,
+ @Nullable ProcessHandler processHandler,
+ @NotNull JComponent component,
+ String displayName) {
this(executionConsole, processHandler, component, displayName, null);
}
+ public RunContentDescriptor(@NotNull RunProfile profile, @NotNull ExecutionResult executionResult, @NotNull RunnerLayoutUi ui) {
+ this(executionResult.getExecutionConsole(), executionResult.getProcessHandler(), ui.getComponent(), profile.getName(), profile.getIcon());
+ }
+
public ExecutionConsole getExecutionConsole() {
return myExecutionConsole;
}
@@ -86,10 +79,7 @@ public class RunContentDescriptor implements Disposable {
Disposer.dispose(myExecutionConsole);
myExecutionConsole = null;
}
- if (myComponent != null) {
- DataManager.removeDataProvider(myComponent);
- myComponent = null;
- }
+ myComponent = null;
myRestarter = null;
}
@@ -128,25 +118,30 @@ public class RunContentDescriptor implements Disposable {
return myHelpId;
}
- /**
- * @see #myContent
- */
- public void setAttachedContent(final Content content) {
- myContent = content;
- }
-
- /**
- * @see #myContent
- */
+ @Nullable
public Content getAttachedContent() {
return myContent;
}
+ public void setAttachedContent(@NotNull Content content) {
+ myContent = content;
+ }
+
@Nullable
+ @Deprecated
+ /**
+ * @deprecated Use {@link com.intellij.execution.runners.ExecutionUtil#restart(RunContentDescriptor)} instead
+ * to remove in IDEA 15
+ */
public Runnable getRestarter() {
return myRestarter;
}
+ @SuppressWarnings("UnusedDeclaration")
+ @Deprecated
+ /**
+ * @deprecated to remove in IDEA 15
+ */
public void setRestarter(@Nullable Runnable runnable) {
myRestarter = runnable;
}
diff --git a/platform/lang-api/src/com/intellij/execution/ui/RunContentManager.java b/platform/lang-api/src/com/intellij/execution/ui/RunContentManager.java
index 4f192197b0f9..5a2b53c97bc8 100644
--- a/platform/lang-api/src/com/intellij/execution/ui/RunContentManager.java
+++ b/platform/lang-api/src/com/intellij/execution/ui/RunContentManager.java
@@ -20,15 +20,24 @@ import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.DataKey;
+import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.wm.ToolWindow;
+import com.intellij.util.messages.Topic;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public interface RunContentManager {
+ Topic<RunContentWithExecutorListener> TOPIC =
+ Topic.create("Run Content", RunContentWithExecutorListener.class);
- DataKey<RunContentDescriptor> RUN_CONTENT_DESCRIPTOR = DataKey.create("RUN_CONTENT_DESCRIPTOR");
+ @SuppressWarnings("UnusedDeclaration")
+ @Deprecated
+ /**
+ * @deprecated Use {@link LangDataKeys#RUN_CONTENT_DESCRIPTOR} instead
+ */
+ DataKey<RunContentDescriptor> RUN_CONTENT_DESCRIPTOR = LangDataKeys.RUN_CONTENT_DESCRIPTOR;
@Nullable
RunContentDescriptor getSelectedContent();
@@ -38,28 +47,35 @@ public interface RunContentManager {
@NotNull
List<RunContentDescriptor> getAllDescriptors();
+
/**
- * to reduce number of open contents RunContentManager reuses
- * some of them during showRunContent (for ex. if a process was stopped)
- * @return content that will be reused by showRunContent
- * @deprecated use {@link #getReuseContent(com.intellij.execution.Executor, ExecutionEnvironment)}
+ * @deprecated use {@link #getReuseContent(ExecutionEnvironment)}
+ * to remove in IDEA 15
*/
+ @Deprecated
@Nullable
RunContentDescriptor getReuseContent(Executor requestor, @Nullable RunContentDescriptor contentToReuse);
/**
* @deprecated use {@link #getReuseContent(ExecutionEnvironment)}
+ * to remove in IDEA 15
*/
@Deprecated
@Nullable
RunContentDescriptor getReuseContent(Executor requestor, @NotNull ExecutionEnvironment executionEnvironment);
@Nullable
+ /**
+ * To reduce number of open contents RunContentManager reuses
+ * some of them during showRunContent (for ex. if a process was stopped)
+ */
RunContentDescriptor getReuseContent(@NotNull ExecutionEnvironment executionEnvironment);
/**
* @deprecated use {@link #getReuseContent(ExecutionEnvironment)}
+ * to remove in IDEA 15
*/
+ @SuppressWarnings("UnusedDeclaration")
@Deprecated
@Nullable
RunContentDescriptor getReuseContent(Executor requestor, DataContext dataContext);
@@ -67,19 +83,42 @@ public interface RunContentManager {
@Nullable
RunContentDescriptor findContentDescriptor(Executor requestor, ProcessHandler handler);
- void showRunContent(@NotNull Executor executor, RunContentDescriptor descriptor, RunContentDescriptor contentToReuse);
- void showRunContent(@NotNull Executor executor, RunContentDescriptor descriptor);
+ void showRunContent(@NotNull Executor executor, @NotNull RunContentDescriptor descriptor, @Nullable RunContentDescriptor contentToReuse);
+
+ void showRunContent(@NotNull Executor executor, @NotNull RunContentDescriptor descriptor);
+
void hideRunContent(@NotNull Executor executor, RunContentDescriptor descriptor);
+
boolean removeRunContent(@NotNull Executor executor, RunContentDescriptor descriptor);
void toFrontRunContent(Executor requestor, RunContentDescriptor descriptor);
+
void toFrontRunContent(Executor requestor, ProcessHandler handler);
- void addRunContentListener(RunContentListener listener);
+ @SuppressWarnings("UnusedDeclaration")
+ @Deprecated
+ /**
+ * @deprecated Use {@link RunContentManager#TOPIC} instead
+ * to remove in IDEA 15
+ */
+ void addRunContentListener(@NotNull RunContentListener listener);
+
+ @SuppressWarnings("UnusedDeclaration")
+ @Deprecated
+ /**
+ * @deprecated Use {@link RunContentManager#TOPIC} instead
+ * to remove in IDEA 15
+ */
void removeRunContentListener(RunContentListener listener);
- void addRunContentListener(RunContentListener myContentListener, Executor executor);
+ @SuppressWarnings("UnusedDeclaration")
+ @Deprecated
+ /**
+ * @deprecated Use {@link RunContentManager#TOPIC} instead
+ * to remove in IDEA 15
+ */
+ void addRunContentListener(@NotNull RunContentListener myContentListener, Executor executor);
@Nullable
ToolWindow getToolWindowByDescriptor(@NotNull RunContentDescriptor descriptor);
-} \ No newline at end of file
+}
diff --git a/platform/lang-impl/src/com/intellij/execution/ui/RunContentWithExecutorListener.java b/platform/lang-api/src/com/intellij/execution/ui/RunContentWithExecutorListener.java
index 8231f0d1d1d8..ef18d75ab699 100644
--- a/platform/lang-impl/src/com/intellij/execution/ui/RunContentWithExecutorListener.java
+++ b/platform/lang-api/src/com/intellij/execution/ui/RunContentWithExecutorListener.java
@@ -17,11 +17,13 @@ package com.intellij.execution.ui;
import com.intellij.execution.Executor;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
/**
* @author nik
*/
public interface RunContentWithExecutorListener {
- void contentSelected(RunContentDescriptor descriptor, @NotNull Executor executor);
- void contentRemoved(RunContentDescriptor descriptor, @NotNull Executor executor);
+ void contentSelected(@Nullable RunContentDescriptor descriptor, @NotNull Executor executor);
+
+ void contentRemoved(@Nullable RunContentDescriptor descriptor, @NotNull Executor executor);
}
diff --git a/platform/lang-api/src/com/intellij/execution/ui/layout/ViewContext.java b/platform/lang-api/src/com/intellij/execution/ui/layout/ViewContext.java
index 90dfad98dbbc..7fdb851514fe 100644
--- a/platform/lang-api/src/com/intellij/execution/ui/layout/ViewContext.java
+++ b/platform/lang-api/src/com/intellij/execution/ui/layout/ViewContext.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.
@@ -53,6 +53,7 @@ public interface ViewContext extends Disposable {
ContentManager getContentManager();
+ @NotNull
ActionManager getActionManager();
IdeFocusManager getFocusManager();
diff --git a/platform/lang-api/src/com/intellij/facet/frameworks/SettingsConnectionService.java b/platform/lang-api/src/com/intellij/facet/frameworks/SettingsConnectionService.java
index e896c9f14246..cb3518834423 100644
--- a/platform/lang-api/src/com/intellij/facet/frameworks/SettingsConnectionService.java
+++ b/platform/lang-api/src/com/intellij/facet/frameworks/SettingsConnectionService.java
@@ -17,10 +17,12 @@ package com.intellij.facet.frameworks;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.JDOMUtil;
+import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.util.containers.hash.HashMap;
+import com.intellij.util.containers.ContainerUtil;
import org.jdom.Document;
import org.jdom.Element;
+import org.jdom.JDOMException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -65,18 +67,23 @@ public abstract class SettingsConnectionService {
@Nullable
private Map<String, String> readSettings(String... attributes) {
- Map<String, String> settings = new HashMap<String, String>();
+ Map<String, String> settings = ContainerUtil.newLinkedHashMap();
try {
- final URL url = new URL(getSettingsUrl());
- final InputStream is = getStream(url);
- final Document document = JDOMUtil.loadDocument(is);
- final Element root = document.getRootElement();
- for (String s : attributes) {
- final String attributeValue = root.getAttributeValue(s);
- if (StringUtil.isNotEmpty(attributeValue)) {
- settings.put(s, attributeValue);
+ URL url = new URL(getSettingsUrl());
+ String text = FileUtil.loadTextAndClose(getStream(url));
+ try {
+ Document document = JDOMUtil.loadDocument(text);
+ Element root = document.getRootElement();
+ for (String s : attributes) {
+ String attributeValue = root.getAttributeValue(s);
+ if (StringUtil.isNotEmpty(attributeValue)) {
+ settings.put(s, attributeValue);
+ }
}
}
+ catch (JDOMException e) {
+ LOG.error("", e, text);
+ }
}
catch (MalformedURLException e) {
LOG.error(e);
diff --git a/platform/lang-api/src/com/intellij/facet/ui/FacetEditorValidator.java b/platform/lang-api/src/com/intellij/facet/ui/FacetEditorValidator.java
index f3a6d087da35..c04efa50ba33 100644
--- a/platform/lang-api/src/com/intellij/facet/ui/FacetEditorValidator.java
+++ b/platform/lang-api/src/com/intellij/facet/ui/FacetEditorValidator.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,12 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package com.intellij.facet.ui;
+import org.jetbrains.annotations.NotNull;
+
/**
* @author nik
*/
public abstract class FacetEditorValidator {
+ @NotNull
public abstract ValidationResult check();
}
diff --git a/platform/lang-api/src/com/intellij/ide/IdeView.java b/platform/lang-api/src/com/intellij/ide/IdeView.java
index 7ee910f0925f..8f2dc5ce51a8 100644
--- a/platform/lang-api/src/com/intellij/ide/IdeView.java
+++ b/platform/lang-api/src/com/intellij/ide/IdeView.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,6 +18,7 @@ package com.intellij.ide;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiElement;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
@@ -41,6 +42,7 @@ public interface IdeView {
*
* @return the list of directories, or an empty array if nothing is selected.
*/
+ @NotNull
PsiDirectory[] getDirectories();
/**
diff --git a/platform/lang-api/src/com/intellij/openapi/actionSystem/LangDataKeys.java b/platform/lang-api/src/com/intellij/openapi/actionSystem/LangDataKeys.java
index c3f1bc3cb2fd..0dd1683899f4 100644
--- a/platform/lang-api/src/com/intellij/openapi/actionSystem/LangDataKeys.java
+++ b/platform/lang-api/src/com/intellij/openapi/actionSystem/LangDataKeys.java
@@ -16,7 +16,10 @@
package com.intellij.openapi.actionSystem;
+import com.intellij.execution.configurations.RunProfile;
+import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.ui.ConsoleView;
+import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.ide.IdeView;
import com.intellij.lang.Language;
import com.intellij.openapi.module.ModifiableModuleModel;
@@ -54,10 +57,14 @@ public class LangDataKeys extends PlatformDataKeys {
public static final DataKey<PsiElement> PASTE_TARGET_PSI_ELEMENT = DataKey.create("psi.pasteTargetElement");
public static final DataKey<ConsoleView> CONSOLE_VIEW = DataKey.create("consoleView");
-
+
public static final DataKey<JBPopup> POSITION_ADJUSTER_POPUP = DataKey.create("chooseByNameDropDown");
public static final DataKey<JBPopup> PARENT_POPUP = DataKey.create("chooseByNamePopup");
public static final DataKey<Library> LIBRARY = DataKey.create("project.model.library");
+
+ public static final DataKey<RunProfile> RUN_PROFILE = DataKey.create("runProfile");
+ public static final DataKey<ExecutionEnvironment> EXECUTION_ENVIRONMENT = DataKey.create("executionEnvironment");
+ public static final DataKey<RunContentDescriptor> RUN_CONTENT_DESCRIPTOR = DataKey.create("RUN_CONTENT_DESCRIPTOR");
}
diff --git a/platform/lang-api/src/com/intellij/psi/WeigherExtensionPoint.java b/platform/lang-api/src/com/intellij/psi/WeigherExtensionPoint.java
index 2c38cd057b2b..11bf87e7a2cd 100644
--- a/platform/lang-api/src/com/intellij/psi/WeigherExtensionPoint.java
+++ b/platform/lang-api/src/com/intellij/psi/WeigherExtensionPoint.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,11 +18,10 @@ package com.intellij.psi;
import com.intellij.openapi.extensions.AbstractExtensionPointBean;
import com.intellij.openapi.util.NotNullLazyValue;
import com.intellij.util.KeyedLazyInstance;
+import com.intellij.util.ReflectionUtil;
import com.intellij.util.xmlb.annotations.Attribute;
import org.jetbrains.annotations.NotNull;
-import java.lang.reflect.Constructor;
-
/**
* @author peter
*/
@@ -44,24 +43,13 @@ public class WeigherExtensionPoint extends AbstractExtensionPointBean implements
protected final Weigher compute() {
try {
Class<Weigher> tClass = findClass(implementationClass);
- Constructor<Weigher> constructor = tClass.getConstructor();
- constructor.setAccessible(true);
- final Weigher weigher = tClass.newInstance();
+ final Weigher weigher = ReflectionUtil.newInstance(tClass);
weigher.setDebugName(id);
return weigher;
}
- catch (InstantiationException e) {
- throw new RuntimeException(e);
- }
- catch (IllegalAccessException e) {
- throw new RuntimeException(e);
- }
catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
- catch (NoSuchMethodException e) {
- throw new RuntimeException(e);
- }
}
};
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 d858bfc01fcb..2683db2a846d 100644
--- a/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettings.java
+++ b/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettings.java
@@ -113,7 +113,7 @@ public class CodeStyleSettings extends CommonCodeStyleSettings implements Clonea
}
}
- public <T extends CustomCodeStyleSettings> T getCustomSettings(Class<T> aClass) {
+ public <T extends CustomCodeStyleSettings> T getCustomSettings(@NotNull Class<T> aClass) {
synchronized (myCustomSettings) {
return (T)myCustomSettings.get(aClass);
}
@@ -127,7 +127,9 @@ public class CodeStyleSettings extends CommonCodeStyleSettings implements Clonea
}
private void copyCustomSettingsFrom(@NotNull CodeStyleSettings from) {
- myCustomSettings.clear();
+ synchronized (myCustomSettings) {
+ myCustomSettings.clear();
+ }
for (final CustomCodeStyleSettings settings : from.getCustomSettingsValues()) {
addCustomSettings((CustomCodeStyleSettings) settings.clone());
}
@@ -247,6 +249,10 @@ public class CodeStyleSettings extends CommonCodeStyleSettings implements Clonea
public int INNER_CLASSES_ORDER_WEIGHT = 7;
//----------------- WRAPPING ---------------------------
+ /**
+ * @deprecated Use get/setRightMargin() methods instead.
+ */
+ @Deprecated
public int RIGHT_MARGIN = 120;
public boolean WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN = false;
@@ -435,6 +441,7 @@ public class CodeStyleSettings extends CommonCodeStyleSettings implements Clonea
private CodeStyleSettings myParentSettings;
private boolean myLoadedAdditionalIndentOptions;
+ @NotNull
private Collection<CustomCodeStyleSettings> getCustomSettingsValues() {
synchronized (myCustomSettings) {
return Collections.unmodifiableCollection(myCustomSettings.values());
@@ -524,7 +531,7 @@ public class CodeStyleSettings extends CommonCodeStyleSettings implements Clonea
@NonNls Element option = (Element)option1;
@NonNls final String name = option.getAttributeValue("name");
if ("TAB_SIZE".equals(name)) {
- final int value = Integer.valueOf(option.getAttributeValue("value")).intValue();
+ final int value = Integer.parseInt(option.getAttributeValue("value"));
JAVA_INDENT_OPTIONS.TAB_SIZE = value;
JSP_INDENT_OPTIONS.TAB_SIZE = value;
XML_INDENT_OPTIONS.TAB_SIZE = value;
@@ -532,7 +539,7 @@ public class CodeStyleSettings extends CommonCodeStyleSettings implements Clonea
optionsImported = true;
}
else if ("INDENT_SIZE".equals(name)) {
- final int value = Integer.valueOf(option.getAttributeValue("value")).intValue();
+ final int value = Integer.parseInt(option.getAttributeValue("value"));
JAVA_INDENT_OPTIONS.INDENT_SIZE = value;
JSP_INDENT_OPTIONS.INDENT_SIZE = value;
XML_INDENT_OPTIONS.INDENT_SIZE = value;
@@ -540,7 +547,7 @@ public class CodeStyleSettings extends CommonCodeStyleSettings implements Clonea
optionsImported = true;
}
else if ("CONTINUATION_INDENT_SIZE".equals(name)) {
- final int value = Integer.valueOf(option.getAttributeValue("value")).intValue();
+ final int value = Integer.parseInt(option.getAttributeValue("value"));
JAVA_INDENT_OPTIONS.CONTINUATION_INDENT_SIZE = value;
JSP_INDENT_OPTIONS.CONTINUATION_INDENT_SIZE = value;
XML_INDENT_OPTIONS.CONTINUATION_INDENT_SIZE = value;
@@ -548,7 +555,7 @@ public class CodeStyleSettings extends CommonCodeStyleSettings implements Clonea
optionsImported = true;
}
else if ("USE_TAB_CHARACTER".equals(name)) {
- final boolean value = Boolean.valueOf(option.getAttributeValue("value")).booleanValue();
+ final boolean value = Boolean.parseBoolean(option.getAttributeValue("value"));
JAVA_INDENT_OPTIONS.USE_TAB_CHARACTER = value;
JSP_INDENT_OPTIONS.USE_TAB_CHARACTER = value;
XML_INDENT_OPTIONS.USE_TAB_CHARACTER = value;
@@ -556,14 +563,15 @@ public class CodeStyleSettings extends CommonCodeStyleSettings implements Clonea
optionsImported = true;
}
else if ("SMART_TABS".equals(name)) {
- final boolean value = Boolean.valueOf(option.getAttributeValue("value")).booleanValue();
+ final boolean value = Boolean.parseBoolean(option.getAttributeValue("value"));
JAVA_INDENT_OPTIONS.SMART_TABS = value;
JSP_INDENT_OPTIONS.SMART_TABS = value;
XML_INDENT_OPTIONS.SMART_TABS = value;
OTHER_INDENT_OPTIONS.SMART_TABS = value;
optionsImported = true;
- } else if ("SPACE_AFTER_UNARY_OPERATOR".equals(name)) {
- SPACE_AROUND_UNARY_OPERATOR = Boolean.valueOf(option.getAttributeValue("value")).booleanValue();
+ }
+ else if ("SPACE_AFTER_UNARY_OPERATOR".equals(name)) {
+ SPACE_AROUND_UNARY_OPERATOR = Boolean.parseBoolean(option.getAttributeValue("value"));
optionsImported = true;
}
}
@@ -751,6 +759,7 @@ public class CodeStyleSettings extends CommonCodeStyleSettings implements Clonea
myNames.addAll(from.myNames);
}
+ @Override
public boolean equals(Object other) {
if (other instanceof TypeToNameMap) {
TypeToNameMap otherMap = (TypeToNameMap)other;
@@ -759,6 +768,7 @@ public class CodeStyleSettings extends CommonCodeStyleSettings implements Clonea
return false;
}
+ @Override
public int hashCode() {
int code = 0;
for (String myPattern : myPatterns) {
@@ -900,7 +910,7 @@ public class CodeStyleSettings extends CommonCodeStyleSettings implements Clonea
if (langSettings.RIGHT_MARGIN >= 0) return langSettings.RIGHT_MARGIN;
}
}
- return RIGHT_MARGIN;
+ return getDefaultRightMargin();
}
/**
@@ -917,6 +927,16 @@ public class CodeStyleSettings extends CommonCodeStyleSettings implements Clonea
return;
}
}
+ setDefaultRightMargin(rightMargin);
+ }
+
+ @SuppressWarnings("deprecation")
+ public int getDefaultRightMargin() {
+ return RIGHT_MARGIN;
+ }
+
+ @SuppressWarnings("deprecation")
+ public void setDefaultRightMargin(int rightMargin) {
RIGHT_MARGIN = rightMargin;
}
}
diff --git a/platform/lang-api/src/com/intellij/psi/util/PsiUtilBase.java b/platform/lang-api/src/com/intellij/psi/util/PsiUtilBase.java
index 56fe91a0dc28..13f84cb1dc4f 100644
--- a/platform/lang-api/src/com/intellij/psi/util/PsiUtilBase.java
+++ b/platform/lang-api/src/com/intellij/psi/util/PsiUtilBase.java
@@ -32,6 +32,7 @@ import com.intellij.openapi.fileEditor.TextEditor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.AsyncResult;
import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.vfs.NonPhysicalFileSystem;
import com.intellij.openapi.vfs.VFileProperty;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
@@ -221,12 +222,13 @@ public class PsiUtilBase extends PsiUtilCore implements PsiEditorUtil {
* Tries to find editor for the given element.
* <p/>
* There are at least two approaches to achieve the target. Current method is intended to encapsulate both of them:
- * <pre>
* <ul>
* <li>target editor works with a real file that remains at file system;</li>
* <li>target editor works with a virtual file;</li>
* </ul>
- * </pre>
+ * <p/>
+ * Please don't use this method for finding an editor for quick fix.
+ * @see {@link com.intellij.codeInspection.LocalQuickFixAndIntentionActionOnPsiElement}
*
* @param element target element
* @return editor that works with a given element if the one is found; <code>null</code> otherwise
@@ -234,30 +236,28 @@ public class PsiUtilBase extends PsiUtilCore implements PsiEditorUtil {
@Nullable
public static Editor findEditor(@NotNull PsiElement element) {
PsiFile psiFile = element.getContainingFile();
- if (psiFile == null) {
- return null;
- }
- VirtualFile virtualFile = psiFile.getOriginalFile().getVirtualFile();
+ VirtualFile virtualFile = PsiUtilCore.getVirtualFile(element);
if (virtualFile == null) {
return null;
}
- if (virtualFile.isInLocalFileSystem()) {
+ Project project = psiFile.getProject();
+ if (virtualFile.isInLocalFileSystem() || virtualFile.getFileSystem() instanceof NonPhysicalFileSystem) {
// Try to find editor for the real file.
- final FileEditor[] editors = FileEditorManager.getInstance(psiFile.getProject()).getEditors(virtualFile);
+ final FileEditor[] editors = FileEditorManager.getInstance(project).getEditors(virtualFile);
for (FileEditor editor : editors) {
if (editor instanceof TextEditor) {
return ((TextEditor)editor).getEditor();
}
}
}
- else if (SwingUtilities.isEventDispatchThread()) {
+ if (SwingUtilities.isEventDispatchThread()) {
// We assume that data context from focus-based retrieval should success if performed from EDT.
AsyncResult<DataContext> asyncResult = DataManager.getInstance().getDataContextFromFocus();
if (asyncResult.isDone()) {
Editor editor = CommonDataKeys.EDITOR.getData(asyncResult.getResult());
if (editor != null) {
- Document cachedDocument = PsiDocumentManager.getInstance(psiFile.getProject()).getCachedDocument(psiFile);
+ Document cachedDocument = PsiDocumentManager.getInstance(project).getCachedDocument(psiFile);
// Ensure that target editor is found by checking its document against the one from given PSI element.
if (cachedDocument == editor.getDocument()) {
return editor;
diff --git a/platform/lang-impl/src/com/intellij/application/options/CodeStyleSchemesConfigurable.java b/platform/lang-impl/src/com/intellij/application/options/CodeStyleSchemesConfigurable.java
index 9f38c6605f11..b07c7a62bc47 100644
--- a/platform/lang-impl/src/com/intellij/application/options/CodeStyleSchemesConfigurable.java
+++ b/platform/lang-impl/src/com/intellij/application/options/CodeStyleSchemesConfigurable.java
@@ -23,6 +23,7 @@ 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.util.registry.Registry;
import com.intellij.psi.codeStyle.CodeStyleScheme;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CodeStyleSettingsProvider;
@@ -55,6 +56,9 @@ public class CodeStyleSchemesConfigurable extends SearchableConfigurable.Parent.
public JComponent createComponent() {
myModel = ensureModel();
+ if (Registry.is("ide.file.settings.order.new")) {
+ return myPanels == null || myPanels.isEmpty() ? null : myPanels.get(0).createComponent();
+ }
return myRootSchemesPanel.getPanel();
}
@@ -232,6 +236,14 @@ public class CodeStyleSchemesConfigurable extends SearchableConfigurable.Parent.
}
}
+ if (Registry.is("ide.file.settings.order.new")) {
+ int size = myPanels.size();
+ Configurable[] result = new Configurable[size > 0 ? size - 1 : 0];
+ for (int i = 0; i < result.length; i++) {
+ result[i] = myPanels.get(i + 1);
+ }
+ return result;
+ }
return myPanels.toArray(new Configurable[myPanels.size()]);
}
@@ -255,7 +267,7 @@ public class CodeStyleSchemesConfigurable extends SearchableConfigurable.Parent.
@Override
public void currentSettingsChanged() {
-
+
}
@Override
diff --git a/platform/lang-impl/src/com/intellij/application/options/GeneralCodeStylePanel.java b/platform/lang-impl/src/com/intellij/application/options/GeneralCodeStylePanel.java
index d51ddbd827d5..e3dabad85b21 100644
--- a/platform/lang-impl/src/com/intellij/application/options/GeneralCodeStylePanel.java
+++ b/platform/lang-impl/src/com/intellij/application/options/GeneralCodeStylePanel.java
@@ -111,7 +111,7 @@ public class GeneralCodeStylePanel extends CodeStyleAbstractPanel {
myLineSeparatorCombo.addItem(MACINTOSH_STRING);
addPanelToWatch(myPanel);
- myRightMarginSpinner.setModel(new SpinnerNumberModel(settings.RIGHT_MARGIN, 1, 1000000, 1));
+ myRightMarginSpinner.setModel(new SpinnerNumberModel(settings.getDefaultRightMargin(), 1, 1000000, 1));
myIndentOptionsEditor = new SmartIndentOptionsEditor();
myDefaultIndentOptionsPanel.add(myIndentOptionsEditor.createPanel(), BorderLayout.CENTER);
@@ -165,7 +165,7 @@ public class GeneralCodeStylePanel extends CodeStyleAbstractPanel {
public void apply(CodeStyleSettings settings) {
settings.LINE_SEPARATOR = getSelectedLineSeparator();
- settings.RIGHT_MARGIN = ((Number) myRightMarginSpinner.getValue()).intValue();
+ settings.setDefaultRightMargin(((Number) myRightMarginSpinner.getValue()).intValue());
settings.WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN = myCbWrapWhenTypingReachesRightMargin.isSelected();
myIndentOptionsEditor.setEnabled(true);
myIndentOptionsEditor.apply(settings, settings.OTHER_INDENT_OPTIONS);
@@ -226,7 +226,7 @@ public class GeneralCodeStylePanel extends CodeStyleAbstractPanel {
return true;
}
- if (!Comparing.equal(myRightMarginSpinner.getValue(), settings.RIGHT_MARGIN)) return true;
+ if (!Comparing.equal(myRightMarginSpinner.getValue(), settings.getDefaultRightMargin())) return true;
myIndentOptionsEditor.setEnabled(true);
if (myEnableFormatterTags.isSelected()) {
@@ -265,7 +265,7 @@ public class GeneralCodeStylePanel extends CodeStyleAbstractPanel {
myLineSeparatorCombo.setSelectedItem(SYSTEM_DEPENDANT_STRING);
}
- myRightMarginSpinner.setValue(settings.RIGHT_MARGIN);
+ myRightMarginSpinner.setValue(settings.getDefaultRightMargin());
myCbWrapWhenTypingReachesRightMargin.setSelected(settings.WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN);
myIndentOptionsEditor.reset(settings, settings.OTHER_INDENT_OPTIONS);
myIndentOptionsEditor.setEnabled(true);
diff --git a/platform/lang-impl/src/com/intellij/application/options/OtherTabsAndIndentsPanel.java b/platform/lang-impl/src/com/intellij/application/options/OtherTabsAndIndentsPanel.java
index cf118835aa0e..aadc34a0ac1f 100644
--- a/platform/lang-impl/src/com/intellij/application/options/OtherTabsAndIndentsPanel.java
+++ b/platform/lang-impl/src/com/intellij/application/options/OtherTabsAndIndentsPanel.java
@@ -91,7 +91,7 @@ public class OtherTabsAndIndentsPanel extends CodeStyleAbstractPanel {
installPreviewPanel(myPreviewPanel);
addPanelToWatch(myPanel);
- myRightMargin = settings.RIGHT_MARGIN;
+ myRightMargin = settings.getDefaultRightMargin();
}
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
index 70c747dc11ca..0759052ee623 100644
--- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/RightMarginForm.java
+++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/RightMarginForm.java
@@ -48,7 +48,7 @@ public class RightMarginForm {
public RightMarginForm(@NotNull Language language, @NotNull CodeStyleSettings settings) {
myLanguage = language;
- myDefaultRightMargin = settings.RIGHT_MARGIN;
+ myDefaultRightMargin = settings.getDefaultRightMargin();
myDefaultGeneralCheckBox.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
@@ -71,7 +71,7 @@ public class RightMarginForm {
}
else {
myDefaultGeneralCheckBox.setSelected(true);
- myRightMarginField.setText(Integer.toString(settings.RIGHT_MARGIN));
+ myRightMarginField.setText(Integer.toString(settings.getDefaultRightMargin()));
if (langSettings == settings) {
myDefaultGeneralCheckBox.setEnabled(false);
myRightMarginField.setEnabled(false);
@@ -86,7 +86,7 @@ public class RightMarginForm {
langSettings.RIGHT_MARGIN = -1;
}
else {
- langSettings.RIGHT_MARGIN = getFieldRightMargin(settings.RIGHT_MARGIN);
+ langSettings.RIGHT_MARGIN = getFieldRightMargin(settings.getDefaultRightMargin());
}
}
}
@@ -97,7 +97,7 @@ public class RightMarginForm {
return langSettings.RIGHT_MARGIN >= 0;
}
else {
- return langSettings.RIGHT_MARGIN != getFieldRightMargin(settings.RIGHT_MARGIN);
+ return langSettings.RIGHT_MARGIN != getFieldRightMargin(settings.getDefaultRightMargin());
}
}
diff --git a/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontOptions.java b/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontOptions.java
index 5e3017206132..ce2a00d3d671 100644
--- a/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontOptions.java
+++ b/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontOptions.java
@@ -81,6 +81,8 @@ import java.util.*;
import java.util.List;
public class ColorAndFontOptions extends SearchableConfigurable.Parent.Abstract implements EditorOptionsProvider {
+ public static final String ID = "reference.settingsdialog.IDE.editor.colors";
+
private HashMap<String,MyColorScheme> mySchemes;
private MyColorScheme mySelectedScheme;
public static final String DIFF_GROUP = ApplicationBundle.message("title.diff");
@@ -999,7 +1001,7 @@ public class ColorAndFontOptions extends SearchableConfigurable.Parent.Abstract
@Override
@NotNull
public String getHelpTopic() {
- return "reference.settingsdialog.IDE.editor.colors";
+ return ID;
}
private static class MyColorScheme extends EditorColorsSchemeImpl {
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 db23ce17b2c3..edb9fcdb9e18 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,12 +3,12 @@
<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="585"/>
+ <xy x="20" y="20" width="500" height="614"/>
</constraints>
<properties/>
<border type="none"/>
<children>
- <grid id="ed507" layout-manager="GridLayoutManager" row-count="7" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <grid id="ed507" layout-manager="GridLayoutManager" row-count="8" 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="9" fill="3" indent="0" use-parent-layout="false"/>
@@ -101,6 +101,35 @@
<text resource-bundle="messages/ApplicationBundle" key="checkbox.show.tabs.tooltips"/>
</properties>
</component>
+ <grid id="e3283" 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="7" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="2479d" class="javax.swing.JLabel">
+ <constraints>
+ <grid row="0" 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="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="27"/>
+ </grid>
+ </constraints>
+ <properties>
+ <columns value="2"/>
+ <text value="30"/>
+ </properties>
+ </component>
+ </children>
+ </grid>
</children>
</grid>
<vspacer id="651b4">
@@ -119,7 +148,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="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <grid id="5a5a7" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
@@ -147,25 +176,6 @@
<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">
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 af6bbdc931ca..0bc36c17325d 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java
@@ -312,8 +312,8 @@ public class FormatChangedTextUtil {
List<TextRange> ranges = ContainerUtil.newArrayList();
for (Range range : changedRanges) {
if (range.getType() != Range.DELETED) {
- int changeStartLine = range.getOffset1();
- int changeEndLine = range.getOffset2();
+ int changeStartLine = range.getLine1();
+ int changeEndLine = range.getLine2();
int lineStartOffset = document.getLineStartOffset(changeStartLine);
int lineEndOffset = document.getLineEndOffset(changeEndLine - 1);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonListeners.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonListeners.java
index 75a4fd410959..c8d5ec4b8ddb 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonListeners.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonListeners.java
@@ -104,7 +104,7 @@ public class DaemonListeners implements Disposable {
private final ProjectLevelVcsManager myProjectLevelVcsManager;
private final VcsDirtyScopeManager myVcsDirtyScopeManager;
private final FileStatusManager myFileStatusManager;
- private final ActionManager myActionManager;
+ @NotNull private final ActionManager myActionManager;
private final TooltipController myTooltipController;
private boolean myEscPressed;
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/HectorComponent.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/HectorComponent.java
index 0483d5a05027..825e72bc98e6 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/HectorComponent.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/HectorComponent.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.
@@ -91,7 +91,7 @@ public class HectorComponent extends JPanel {
Collections.sort(languages, PsiUtilBase.LANGUAGE_COMPARATOR);
for (Language language : languages) {
@SuppressWarnings("UseOfObsoleteCollectionType")
- final Hashtable<Integer, JLabel> sliderLabels = new Hashtable<Integer, JLabel>();
+ final Hashtable<Integer, JComponent> sliderLabels = new Hashtable<Integer, JComponent>();
sliderLabels.put(1, new JLabel(EditorBundle.message("hector.none.slider.label")));
sliderLabels.put(2, new JLabel(EditorBundle.message("hector.syntax.slider.label")));
if (notInLibrary) {
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CodeBlockEndAction.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CodeBlockEndAction.java
index e7c723c17f8b..28b733cb1d5c 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CodeBlockEndAction.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CodeBlockEndAction.java
@@ -26,10 +26,12 @@ package com.intellij.codeInsight.editorActions;
import com.intellij.openapi.actionSystem.CommonDataKeys;
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 com.intellij.openapi.project.Project;
+import org.jetbrains.annotations.Nullable;
public class CodeBlockEndAction extends EditorAction {
public CodeBlockEndAction() {
@@ -43,7 +45,7 @@ public class CodeBlockEndAction extends EditorAction {
}
@Override
- public void execute(Editor editor, DataContext dataContext) {
+ public void doExecute(Editor editor, @Nullable Caret caret, DataContext dataContext) {
Project project = CommonDataKeys.PROJECT.getData(dataContext);
if (project != null) {
CodeBlockUtil.moveCaretToCodeBlockEnd(project, editor, false);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CodeBlockEndWithSelectionAction.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CodeBlockEndWithSelectionAction.java
index 9431da1fc4d7..10a71a5edc86 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CodeBlockEndWithSelectionAction.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CodeBlockEndWithSelectionAction.java
@@ -26,10 +26,12 @@ package com.intellij.codeInsight.editorActions;
import com.intellij.openapi.actionSystem.CommonDataKeys;
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 com.intellij.openapi.project.Project;
+import org.jetbrains.annotations.Nullable;
public class CodeBlockEndWithSelectionAction extends EditorAction {
public CodeBlockEndWithSelectionAction() {
@@ -43,7 +45,7 @@ public class CodeBlockEndWithSelectionAction extends EditorAction {
}
@Override
- public void execute(Editor editor, DataContext dataContext) {
+ public void doExecute(Editor editor, @Nullable Caret caret, DataContext dataContext) {
Project project = CommonDataKeys.PROJECT.getData(dataContext);
if (project != null) {
CodeBlockUtil.moveCaretToCodeBlockEnd(project, editor, true);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CodeBlockStartAction.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CodeBlockStartAction.java
index 690efff63d16..fc8ac9cf119a 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CodeBlockStartAction.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CodeBlockStartAction.java
@@ -26,10 +26,12 @@ package com.intellij.codeInsight.editorActions;
import com.intellij.openapi.actionSystem.CommonDataKeys;
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 com.intellij.openapi.project.Project;
+import org.jetbrains.annotations.Nullable;
public class CodeBlockStartAction extends EditorAction {
public CodeBlockStartAction() {
@@ -43,7 +45,7 @@ public class CodeBlockStartAction extends EditorAction {
}
@Override
- public void execute(Editor editor, DataContext dataContext) {
+ public void doExecute(Editor editor, @Nullable Caret caret, DataContext dataContext) {
Project project = CommonDataKeys.PROJECT.getData(dataContext);
if (project != null) {
CodeBlockUtil.moveCaretToCodeBlockStart(project, editor, false);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CodeBlockStartWithSelectionAction.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CodeBlockStartWithSelectionAction.java
index 9819efcdc439..fcae25ac1a2b 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CodeBlockStartWithSelectionAction.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CodeBlockStartWithSelectionAction.java
@@ -26,10 +26,12 @@ package com.intellij.codeInsight.editorActions;
import com.intellij.openapi.actionSystem.CommonDataKeys;
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 com.intellij.openapi.project.Project;
+import org.jetbrains.annotations.Nullable;
public class CodeBlockStartWithSelectionAction extends EditorAction {
public CodeBlockStartWithSelectionAction() {
@@ -43,7 +45,7 @@ public class CodeBlockStartWithSelectionAction extends EditorAction {
}
@Override
- public void execute(Editor editor, DataContext dataContext) {
+ public void doExecute(Editor editor, @Nullable Caret caret, DataContext dataContext) {
Project project = CommonDataKeys.PROJECT.getData(dataContext);
if (project != null) {
CodeBlockUtil.moveCaretToCodeBlockStart(project, editor, true);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/EnterHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/EnterHandler.java
index c8a1ab3b7730..5db0a1a7e93b 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/EnterHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/EnterHandler.java
@@ -61,8 +61,8 @@ public class EnterHandler extends BaseEnterHandler {
}
@Override
- public boolean isEnabled(Editor editor, DataContext dataContext) {
- return myOriginalHandler.isEnabled(editor, dataContext);
+ public boolean isEnabledForCaret(@NotNull Editor editor, @NotNull Caret caret, DataContext dataContext) {
+ return myOriginalHandler.isEnabled(editor, caret, dataContext);
}
@Override
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/JoinLinesHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/JoinLinesHandler.java
index eebdb50ea2ee..5f416dd307c4 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/JoinLinesHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/JoinLinesHandler.java
@@ -239,7 +239,7 @@ public class JoinLinesHandler extends EditorWriteActionHandler {
docManager.commitDocument(doc);
try {
- CodeStyleManager.getInstance(project).reformatText(psiFile, start + 1, end);
+ CodeStyleManager.getInstance(project).reformatRange(psiFile, start + 1, end, true);
}
catch (IncorrectOperationException e) {
LOG.error(e);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/SelectWordHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/SelectWordHandler.java
index 8edbb3f5f11d..bfddf17054b5 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/SelectWordHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/SelectWordHandler.java
@@ -25,6 +25,7 @@ import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
@@ -51,14 +52,14 @@ public class SelectWordHandler extends EditorActionHandler {
}
@Override
- public void execute(@NotNull Editor editor, DataContext dataContext) {
+ public void doExecute(@NotNull Editor editor, @Nullable Caret caret, DataContext dataContext) {
if (LOG.isDebugEnabled()) {
LOG.debug("enter: execute(editor='" + editor + "')");
}
Project project = CommonDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext(editor.getComponent()));
if (project == null) {
if (myOriginalHandler != null) {
- myOriginalHandler.execute(editor, dataContext);
+ myOriginalHandler.execute(editor, caret, dataContext);
}
return;
}
@@ -74,7 +75,7 @@ public class SelectWordHandler extends EditorActionHandler {
}
if (range == null) {
if (myOriginalHandler != null) {
- myOriginalHandler.execute(editor, dataContext);
+ myOriginalHandler.execute(editor, caret, dataContext);
}
}
else {
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/UnSelectWordHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/UnSelectWordHandler.java
index cb1d0a6f2be9..de59e9e8fa6b 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/UnSelectWordHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/UnSelectWordHandler.java
@@ -19,6 +19,7 @@ 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.editor.Caret;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.FoldRegion;
@@ -28,6 +29,7 @@ import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.util.Processor;
+import org.jetbrains.annotations.Nullable;
public class UnSelectWordHandler extends EditorActionHandler {
private final EditorActionHandler myOriginalHandler;
@@ -38,14 +40,17 @@ public class UnSelectWordHandler extends EditorActionHandler {
}
@Override
- public void execute(Editor editor, DataContext dataContext) {
+ public void doExecute(Editor editor, @Nullable Caret caret, DataContext dataContext) {
Project project = CommonDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext(editor.getComponent()));
+ if (project == null) {
+ return;
+ }
Document document = editor.getDocument();
final PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(document);
if (file == null) {
if (myOriginalHandler != null) {
- myOriginalHandler.execute(editor, dataContext);
+ myOriginalHandler.execute(editor, caret, dataContext);
}
return;
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/smartEnter/SmartEnterAction.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/smartEnter/SmartEnterAction.java
index bbb1e163729e..19fb28086099 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/smartEnter/SmartEnterAction.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/smartEnter/SmartEnterAction.java
@@ -16,13 +16,13 @@
package com.intellij.codeInsight.editorActions.smartEnter;
-import com.intellij.codeInsight.actions.BaseCodeInsightAction;
import com.intellij.codeInsight.editorActions.enter.EnterAfterUnmatchedBraceHandler;
import com.intellij.codeInsight.lookup.LookupManager;
import com.intellij.lang.Language;
import com.intellij.openapi.actionSystem.CommonDataKeys;
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.actionSystem.EditorAction;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
@@ -41,15 +41,7 @@ import java.util.List;
public class SmartEnterAction extends EditorAction {
public SmartEnterAction() {
super(new Handler());
- }
-
- @Override
- protected Editor getEditor(@NotNull final DataContext dataContext) {
- final Editor editor = CommonDataKeys.EDITOR.getData(dataContext);
- if (editor == null) return null;
- Project project = editor.getProject();
- if (project == null) project = CommonDataKeys.PROJECT.getData(dataContext);
- return project == null ? null : BaseCodeInsightAction.getInjectedEditor(project, editor);
+ setInjectedContext(true);
}
private static class Handler extends EditorWriteActionHandler {
@@ -58,15 +50,15 @@ public class SmartEnterAction extends EditorAction {
}
@Override
- public boolean isEnabled(Editor editor, DataContext dataContext) {
- return getEnterHandler().isEnabled(editor, dataContext);
+ public boolean isEnabledForCaret(@NotNull Editor editor, @NotNull Caret caret, DataContext dataContext) {
+ return getEnterHandler().isEnabled(editor, caret, dataContext);
}
@Override
- public void executeWriteAction(Editor editor, DataContext dataContext) {
+ public void executeWriteAction(Editor editor, Caret caret, DataContext dataContext) {
Project project = CommonDataKeys.PROJECT.getData(dataContext);
if (project == null || editor.isOneLineMode()) {
- plainEnter(editor, dataContext);
+ plainEnter(editor, caret, dataContext);
return;
}
@@ -76,13 +68,13 @@ public class SmartEnterAction extends EditorAction {
PsiFile psiFile = PsiUtilBase.getPsiFileInEditor(editor, project);
if (psiFile == null) {
- plainEnter(editor, dataContext);
+ plainEnter(editor, caret, dataContext);
return;
}
if (EnterAfterUnmatchedBraceHandler.isAfterUnmatchedLBrace(editor, caretOffset, psiFile.getFileType())) {
EditorActionHandler enterHandler = EditorActionManager.getInstance().getActionHandler(IdeActions.ACTION_EDITOR_ENTER);
- enterHandler.execute(editor, dataContext);
+ enterHandler.execute(editor, caret, dataContext);
return;
}
@@ -100,13 +92,13 @@ public class SmartEnterAction extends EditorAction {
}
}
if (!processed) {
- plainEnter(editor, dataContext);
+ plainEnter(editor, caret, dataContext);
}
}
}
- public static void plainEnter(Editor editor, DataContext dataContext) {
- getEnterHandler().execute(editor, dataContext);
+ public static void plainEnter(Editor editor, Caret caret, DataContext dataContext) {
+ getEnterHandler().execute(editor, caret, dataContext);
}
private static EditorActionHandler getEnterHandler() {
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/FoldingUpdate.java b/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/FoldingUpdate.java
index 7d0b4453c517..4c137f8d2a37 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/FoldingUpdate.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/FoldingUpdate.java
@@ -174,7 +174,7 @@ public class FoldingUpdate {
injectedFiles.add(injectedFile);
final FoldingMap map = new FoldingMap();
maps.add(map);
- getFoldingsFor(injectedFile, injectedDocument, map, false);
+ getFoldingsFor(injectedFile, injectedEditor.getDocument(), map, false);
}
});
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/PsiNamesElementSignatureProvider.java b/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/PsiNamesElementSignatureProvider.java
index 17a85304d4a1..3409d3f93fc8 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/PsiNamesElementSignatureProvider.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/PsiNamesElementSignatureProvider.java
@@ -89,11 +89,23 @@ public class PsiNamesElementSignatureProvider extends AbstractElementSignaturePr
return candidate instanceof PsiComment ? candidate : null;
}
else if (CODE_BLOCK_MARKER.equals(elementMarker)) {
+ int index = 0;
+ if (tokenizer.hasMoreTokens()) {
+ String indexStr = tokenizer.nextToken();
+ try {
+ index = Integer.parseInt(indexStr);
+ }
+ catch (NumberFormatException e) {
+ if (processingInfoStorage != null) {
+ processingInfoStorage.append("Invalid block index: ").append(indexStr).append("\n");
+ }
+ }
+ }
for (PsiElement child = parent.getFirstChild(); child != null; child = child.getNextSibling()) {
- PsiElement firstChild = child.getFirstChild();
- PsiElement lastChild = child.getLastChild();
- if (firstChild != null && lastChild != null && "{".equals(firstChild.getText()) && "}".equals(lastChild.getText())) {
- return child;
+ if (isBlockElement(child)) {
+ if (--index < 0) {
+ return child;
+ }
}
}
return null;
@@ -212,18 +224,39 @@ public class PsiNamesElementSignatureProvider extends AbstractElementSignaturePr
PsiElement parent = element.getParent();
if (parent instanceof PsiNamedElement && !(parent instanceof PsiFile)) {
- PsiElement firstChild = element.getFirstChild();
- PsiElement lastChild = element.getLastChild();
- if (firstChild != null && "{".equals(firstChild.getText()) && lastChild != null && "}".equals(lastChild.getText())) {
+ if (isBlockElement(element)) {
+ int index = getBlockElementIndex(element);
StringBuilder bufferToUse = buffer;
if (bufferToUse == null) {
bufferToUse = new StringBuilder();
}
bufferToUse.append(TYPE_MARKER).append(ELEMENT_TOKENS_SEPARATOR).append(CODE_BLOCK_MARKER);
+ if (index > 0) {
+ bufferToUse.append(ELEMENT_TOKENS_SEPARATOR).append(index);
+ }
return bufferToUse;
}
}
return null;
}
+
+ private static boolean isBlockElement(@NotNull PsiElement element) {
+ PsiElement firstChild = element.getFirstChild();
+ PsiElement lastChild = element.getLastChild();
+ return firstChild != null && "{".equals(firstChild.getText()) && lastChild != null && "}".equals(lastChild.getText());
+ }
+
+ private static int getBlockElementIndex(@NotNull PsiElement element) {
+ int i = 0;
+ for (PsiElement sibling : element.getParent().getChildren()) {
+ if (element.equals(sibling)) {
+ return i;
+ }
+ if (isBlockElement(sibling)) {
+ i++;
+ }
+ }
+ throw new RuntimeException("Malformed PSI");
+ }
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditAction.java b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditAction.java
index ee4c91972046..62e3bcba3a22 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditAction.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditAction.java
@@ -25,7 +25,10 @@ import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.EditorFactory;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.popup.Balloon;
-import com.intellij.openapi.util.*;
+import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
@@ -138,7 +141,7 @@ public class QuickEditAction implements IntentionAction, LowPriorityAction {
}
@Nullable
- protected JComponent createBalloonComponent(PsiFile file, Ref<Balloon> ref) {
+ protected JComponent createBalloonComponent(@NotNull PsiFile file) {
return null;
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditHandler.java
index 2f4aa4198f85..2c5d8642e46d 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditHandler.java
@@ -55,6 +55,7 @@ import com.intellij.psi.impl.source.PostprocessReformattingAspect;
import com.intellij.psi.impl.source.resolve.FileContextUtil;
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
import com.intellij.psi.impl.source.tree.injected.Place;
+import com.intellij.psi.util.PsiUtilCore;
import com.intellij.testFramework.LightVirtualFile;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.util.DocumentUtil;
@@ -108,18 +109,19 @@ public class QuickEditHandler extends DocumentAdapter implements Disposable {
myEditor = editor;
myAction = action;
myOrigDocument = editor.getDocument();
- final Place shreds = InjectedLanguageUtil.getShreds(injectedFile);
- final FileType fileType = injectedFile.getFileType();
- final Language language = injectedFile.getLanguage();
-
- final PsiFileFactory factory = PsiFileFactory.getInstance(project);
- final String text = InjectedLanguageManager.getInstance(project).getUnescapedText(injectedFile);
- final String newFileName =
+ Place shreds = InjectedLanguageUtil.getShreds(injectedFile);
+ FileType fileType = injectedFile.getFileType();
+ Language language = injectedFile.getLanguage();
+ PsiLanguageInjectionHost.Shred firstShred = ContainerUtil.getFirstItem(shreds);
+
+ PsiFileFactory factory = PsiFileFactory.getInstance(project);
+ String text = InjectedLanguageManager.getInstance(project).getUnescapedText(injectedFile);
+ String newFileName =
StringUtil.notNullize(language.getDisplayName(), "Injected") + " Fragment " + "(" +
- origFile.getName() + ":" + shreds.get(0).getHost().getTextRange().getStartOffset() + ")" + "." + fileType.getDefaultExtension();
+ origFile.getName() + ":" + firstShred.getHost().getTextRange().getStartOffset() + ")" + "." + fileType.getDefaultExtension();
// preserve \r\n as it is done in MultiHostRegistrarImpl
- myNewFile = factory.createFileFromText(newFileName, language, text, true, true);
+ myNewFile = factory.createFileFromText(newFileName, language, text, true, false);
myNewVirtualFile = ObjectUtils.assertNotNull((LightVirtualFile)myNewFile.getVirtualFile());
myNewVirtualFile.setOriginalFile(origFile.getVirtualFile());
@@ -130,8 +132,7 @@ public class QuickEditHandler extends DocumentAdapter implements Disposable {
// suppress possible errors as in injected mode
myNewFile.putUserData(InjectedLanguageUtil.FRANKENSTEIN_INJECTION,
injectedFile.getUserData(InjectedLanguageUtil.FRANKENSTEIN_INJECTION));
- final SmartPointerManager smartPointerManager = SmartPointerManager.getInstance(project);
- myNewFile.putUserData(FileContextUtil.INJECTED_IN_ELEMENT, smartPointerManager.createSmartPsiElementPointer(origFile));
+ myNewFile.putUserData(FileContextUtil.INJECTED_IN_ELEMENT, shreds.getHostPointer());
myNewDocument = PsiDocumentManager.getInstance(project).getDocument(myNewFile);
assert myNewDocument != null;
EditorActionManager.getInstance().setReadonlyFragmentModificationHandler(myNewDocument, new MyQuietHandler());
@@ -149,22 +150,23 @@ public class QuickEditHandler extends DocumentAdapter implements Disposable {
if (event.getEditor().getDocument() != myNewDocument) return;
myEditorCount ++;
final EditorActionHandler editorEscape = EditorActionManager.getInstance().getActionHandler(IdeActions.ACTION_EDITOR_ESCAPE);
- new AnAction() {
- @Override
- public void update(AnActionEvent e) {
- Editor editor = CommonDataKeys.EDITOR.getData(e.getDataContext());
- e.getPresentation().setEnabled(
- !myAction.isShowInBalloon() &&
- editor != null && LookupManager.getActiveLookup(editor) == null &&
- TemplateManager.getInstance(myProject).getActiveTemplate(editor) == null &&
- (editorEscape == null || !editorEscape.isEnabled(editor, e.getDataContext())));
- }
+ if (!myAction.isShowInBalloon()) {
+ new AnAction() {
+ @Override
+ public void update(AnActionEvent e) {
+ Editor editor = CommonDataKeys.EDITOR.getData(e.getDataContext());
+ e.getPresentation().setEnabled(
+ editor != null && LookupManager.getActiveLookup(editor) == null &&
+ TemplateManager.getInstance(myProject).getActiveTemplate(editor) == null &&
+ (editorEscape == null || !editorEscape.isEnabled(editor, e.getDataContext())));
+ }
- @Override
- public void actionPerformed(AnActionEvent e) {
- closeEditor();
- }
- }.registerCustomShortcutSet(CommonShortcuts.ESCAPE, event.getEditor().getContentComponent());
+ @Override
+ public void actionPerformed(AnActionEvent e) {
+ closeEditor();
+ }
+ }.registerCustomShortcutSet(CommonShortcuts.ESCAPE, event.getEditor().getContentComponent());
+ }
}
@Override
@@ -178,10 +180,11 @@ public class QuickEditHandler extends DocumentAdapter implements Disposable {
}
}, this);
- if ("JAVA".equals(shreds.get(0).getHost().getLanguage().getID())) {
+ if ("JAVA".equals(firstShred.getHost().getLanguage().getID())) {
+ PsiLanguageInjectionHost.Shred lastShred = ContainerUtil.getLastItem(shreds);
myAltFullRange = myOrigDocument.createRangeMarker(
- shreds.get(0).getHostRangeMarker().getStartOffset(),
- shreds.get(shreds.size() - 1).getHostRangeMarker().getEndOffset());
+ firstShred.getHostRangeMarker().getStartOffset(),
+ lastShred.getHostRangeMarker().getEndOffset());
myAltFullRange.setGreedyToLeft(true);
myAltFullRange.setGreedyToRight(true);
@@ -201,8 +204,7 @@ public class QuickEditHandler extends DocumentAdapter implements Disposable {
public void navigate(int injectedOffset) {
if (myAction.isShowInBalloon()) {
- Ref<Balloon> ref = Ref.create(null);
- final JComponent component = myAction.createBalloonComponent(myNewFile, ref);
+ final JComponent component = myAction.createBalloonComponent(myNewFile);
if (component != null) {
final Balloon balloon = JBPopupFactory.getInstance().createBalloonBuilder(component)
.setShadow(true)
@@ -212,7 +214,12 @@ public class QuickEditHandler extends DocumentAdapter implements Disposable {
.setHideOnAction(false)
.setFillColor(UIUtil.getControlColor())
.createBalloon();
- ref.set(balloon);
+ new AnAction() {
+ @Override
+ public void actionPerformed(AnActionEvent e) {
+ balloon.hide();
+ }
+ }.registerCustomShortcutSet(CommonShortcuts.ESCAPE, component);
Disposer.register(myNewFile.getProject(), balloon);
final Balloon.Position position = QuickEditAction.getBalloonPosition(myEditor);
RelativePoint point = JBPopupFactory.getInstance().guessBestPopupLocation(myEditor);
@@ -353,11 +360,10 @@ public class QuickEditHandler extends DocumentAdapter implements Disposable {
private void commitToOriginal() {
if (!isValid()) return;
- final PsiFile origFile = (PsiFile)myNewFile.getUserData(FileContextUtil.INJECTED_IN_ELEMENT).getElement();
- VirtualFile origFileVirtualFile = origFile != null? origFile.getVirtualFile() : null;
+ VirtualFile origVirtualFile = PsiUtilCore.getVirtualFile(ObjectUtils.assertNotNull(myNewFile.getContext()));
myCommittingToOriginal = true;
try {
- if (origFileVirtualFile == null || !ReadonlyStatusHandler.getInstance(myProject).ensureFilesWritable(origFileVirtualFile).hasReadonlyFiles()) {
+ if (origVirtualFile == null || !ReadonlyStatusHandler.getInstance(myProject).ensureFilesWritable(origVirtualFile).hasReadonlyFiles()) {
PostprocessReformattingAspect.getInstance(myProject).disablePostprocessFormattingInside(new Runnable() {
@Override
public void run() {
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java
index 3666b4642efd..2f56d3714943 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java
@@ -19,6 +19,7 @@ package com.intellij.codeInsight.navigation;
import com.intellij.codeInsight.CodeInsightBundle;
import com.intellij.codeInsight.TargetElementUtilBase;
import com.intellij.codeInsight.documentation.DocumentationManager;
+import com.intellij.codeInsight.documentation.DocumentationManagerProtocol;
import com.intellij.codeInsight.hint.HintManager;
import com.intellij.codeInsight.hint.HintManagerImpl;
import com.intellij.codeInsight.hint.HintUtil;
@@ -34,9 +35,7 @@ import com.intellij.openapi.actionSystem.MouseShortcut;
import com.intellij.openapi.actionSystem.Shortcut;
import com.intellij.openapi.actionSystem.impl.ActionButton;
import com.intellij.openapi.actionSystem.impl.PresentationFactory;
-import com.intellij.openapi.application.AccessToken;
import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.components.AbstractProjectComponent;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
@@ -66,7 +65,7 @@ import com.intellij.openapi.project.IndexNotReadyException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.startup.StartupManager;
import com.intellij.openapi.util.Comparing;
-import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
@@ -104,16 +103,14 @@ import java.util.List;
public class CtrlMouseHandler extends AbstractProjectComponent {
private static final AbstractDocumentationTooltipAction[] ourTooltipActions = {new ShowQuickDocAtPinnedWindowFromTooltipAction()};
- private static Key<?> ourDebuggerHighlighterKey;
- private static Key<?> ourXDebuggerHighlighterKey;
private final EditorColorsManager myEditorColorsManager;
- private HighlightersSet myHighlighter;
- @JdkConstants.InputEventMask private int myStoredModifiers = 0;
- private TooltipProvider myTooltipProvider = null;
- private final FileEditorManager myFileEditorManager;
- private final DocumentationManager myDocumentationManager;
- @Nullable private Point myPrevMouseLocation;
+ private HighlightersSet myHighlighter;
+ @JdkConstants.InputEventMask private int myStoredModifiers = 0;
+ private TooltipProvider myTooltipProvider = null;
+ private final FileEditorManager myFileEditorManager;
+ private final DocumentationManager myDocumentationManager;
+ @Nullable private Point myPrevMouseLocation;
private LightweightHint myHint;
private enum BrowseMode {None, Declaration, TypeDeclaration, Implementation}
@@ -137,7 +134,11 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
BrowseMode browseMode = getBrowseMode(modifiers);
- if (browseMode != BrowseMode.None) {
+ if (browseMode == BrowseMode.None) {
+ disposeHighlighter();
+ cancelPreviousTooltip();
+ }
+ else {
TooltipProvider tooltipProvider = myTooltipProvider;
if (tooltipProvider != null) {
if (browseMode != tooltipProvider.getBrowseMode()) {
@@ -149,10 +150,6 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
myTooltipProvider.execute(browseMode);
}
}
- else {
- disposeHighlighter();
- cancelPreviousTooltip();
- }
}
};
@@ -240,8 +237,7 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
EditorColorsManager colorsManager,
FileEditorManager fileEditorManager,
@NotNull DocumentationManager documentationManager,
- @NotNull final EditorFactory editorFactory)
- {
+ @NotNull final EditorFactory editorFactory) {
super(project);
myEditorColorsManager = colorsManager;
startupManager.registerPostStartupActivity(new DumbAwareRunnable() {
@@ -289,6 +285,7 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
return new Rectangle(hintComponent.getLocationOnScreen(), hintComponent.getSize());
}
+ @NotNull
private static BrowseMode getBrowseMode(@JdkConstants.InputEventMask int modifiers) {
if (modifiers != 0) {
final Keymap activeKeymap = KeymapManager.getInstance().getActiveKeymap();
@@ -375,9 +372,9 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
private abstract static class Info {
@NotNull protected final PsiElement myElementAtPointer;
- private final List<TextRange> myRanges;
+ @NotNull private final List<TextRange> myRanges;
- public Info(@NotNull PsiElement elementAtPointer, List<TextRange> ranges) {
+ public Info(@NotNull PsiElement elementAtPointer, @NotNull List<TextRange> ranges) {
myElementAtPointer = elementAtPointer;
myRanges = ranges;
}
@@ -387,10 +384,11 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
elementAtPointer.getTextOffset() + elementAtPointer.getTextLength())));
}
- boolean isSimilarTo(final Info that) {
+ boolean isSimilarTo(@NotNull Info that) {
return Comparing.equal(myElementAtPointer, that.myElementAtPointer) && myRanges.equals(that.myRanges);
}
+ @NotNull
public List<TextRange> getRanges() {
return myRanges;
}
@@ -398,11 +396,11 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
@NotNull
public abstract DocInfo getInfo();
- public abstract boolean isValid(Document document);
+ public abstract boolean isValid(@NotNull Document document);
public abstract void showDocInfo(@NotNull DocumentationManager docManager);
- protected boolean rangesAreCorrect(Document document) {
+ protected boolean rangesAreCorrect(@NotNull Document document) {
final TextRange docRange = new TextRange(0, document.getTextLength());
for (TextRange range : getRanges()) {
if (!docRange.contains(range)) return false;
@@ -412,7 +410,7 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
}
}
- private static void showDumbModeNotification(final Project project) {
+ private static void showDumbModeNotification(@NotNull Project project) {
DumbService.getInstance(project).showDumbModeNotification("Element information is not available during index update");
}
@@ -424,7 +422,7 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
myTargetElement = targetElement;
}
- public InfoSingle(final PsiReference ref, @NotNull final PsiElement targetElement) {
+ public InfoSingle(@NotNull PsiReference ref, @NotNull final PsiElement targetElement) {
super(ref.getElement(), ReferenceRange.getAbsoluteRanges(ref));
myTargetElement = targetElement;
}
@@ -432,21 +430,22 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
@Override
@NotNull
public DocInfo getInfo() {
- AccessToken token = ReadAction.start();
- try {
- return generateInfo(myTargetElement, myElementAtPointer);
- }
- catch (IndexNotReadyException e) {
- showDumbModeNotification(myTargetElement.getProject());
- return DocInfo.EMPTY;
- }
- finally {
- token.finish();
- }
+ return ApplicationManager.getApplication().runReadAction(new Computable<DocInfo>() {
+ @Override
+ public DocInfo compute() {
+ try {
+ return generateInfo(myTargetElement, myElementAtPointer);
+ }
+ catch (IndexNotReadyException e) {
+ showDumbModeNotification(myTargetElement.getProject());
+ return DocInfo.EMPTY;
+ }
+ }
+ });
}
@Override
- public boolean isValid(Document document) {
+ public boolean isValid(@NotNull Document document) {
if (!myTargetElement.isValid()) return false;
if (!myElementAtPointer.isValid()) return false;
if (myTargetElement == myElementAtPointer) return false;
@@ -462,7 +461,6 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
}
private static class InfoMultiple extends Info {
-
public InfoMultiple(@NotNull final PsiElement elementAtPointer) {
super(elementAtPointer);
}
@@ -478,7 +476,7 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
}
@Override
- public boolean isValid(Document document) {
+ public boolean isValid(@NotNull Document document) {
return rangesAreCorrect(document);
}
@@ -489,7 +487,7 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
}
@Nullable
- private Info getInfoAt(@NotNull Editor editor, PsiFile file, int offset, BrowseMode browseMode) {
+ private Info getInfoAt(@NotNull Editor editor, @NotNull PsiFile file, int offset, @NotNull BrowseMode browseMode) {
PsiElement targetElement = null;
if (browseMode == BrowseMode.TypeDeclaration) {
@@ -502,7 +500,7 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
}
else if (browseMode == BrowseMode.Declaration) {
final PsiReference ref = TargetElementUtilBase.findReference(editor, offset);
- final List<PsiElement> resolvedElements = ref != null ? resolve(ref) : Collections.<PsiElement>emptyList();
+ final List<PsiElement> resolvedElements = ref == null ? Collections.<PsiElement>emptyList() : resolve(ref);
final PsiElement resolvedElement = resolvedElements.size() == 1 ? resolvedElements.get(0) : null;
final PsiElement[] targetElements = GotoDeclarationAction.findTargetElementsNoVS(myProject, editor, offset, false);
@@ -572,7 +570,8 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
return null;
}
- private static List<PsiElement> resolve(final PsiReference ref) {
+ @NotNull
+ private static List<PsiElement> resolve(@NotNull PsiReference ref) {
// IDEA-56727 try resolve first as in GotoDeclarationAction
PsiElement resolvedElement = ref.resolve();
@@ -734,13 +733,13 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
}
private class TooltipProvider {
- private final Editor myEditor;
- private final LogicalPosition myPosition;
+ @NotNull private final Editor myEditor;
+ @NotNull private final LogicalPosition myPosition;
private BrowseMode myBrowseMode;
private boolean myDisposed;
private final ProgressIndicator myProgress = new ProgressIndicatorBase();
- TooltipProvider(Editor editor, LogicalPosition pos) {
+ TooltipProvider(@NotNull Editor editor, @NotNull LogicalPosition pos) {
myEditor = editor;
myPosition = pos;
}
@@ -754,7 +753,7 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
return myBrowseMode;
}
- void execute(BrowseMode browseMode) {
+ void execute(@NotNull BrowseMode browseMode) {
myBrowseMode = browseMode;
Document document = myEditor.getDocument();
@@ -785,16 +784,16 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
});
}
- private void doExecute(PsiFile file, int offset) {
+ private void doExecute(@NotNull PsiFile file, int offset) {
final Info info;
try {
info = getInfoAt(myEditor, file, offset, myBrowseMode);
+ if (info == null) return;
}
catch (IndexNotReadyException e) {
showDumbModeNotification(myProject);
return;
}
- if (info == null) return;
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
@@ -805,7 +804,7 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
});
}
- private void showHint(Info info) {
+ private void showHint(@NotNull Info info) {
if (myDisposed || myEditor.isDisposed()) return;
Component internalComponent = myEditor.getContentComponent();
if (myHighlighter != null) {
@@ -856,10 +855,6 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
@Override
public void mouseClicked(MouseEvent e) {
- QuickDocInfoPane pane = quickDocPaneRef.get();
- if (pane != null) {
- pane.mouseClicked(e);
- }
}
};
Ref<Consumer<String>> newTextConsumerRef = new Ref<Consumer<String>>();
@@ -889,7 +884,7 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
showHint(hint);
}
- public void showHint(LightweightHint hint) {
+ public void showHint(@NotNull LightweightHint hint) {
final HintManagerImpl hintManager = HintManagerImpl.getInstanceImpl();
Point p = HintManagerImpl.getHintPosition(hint, myEditor, myPosition, HintManager.ABOVE);
hintManager.showEditorHint(hint, myEditor, p,
@@ -898,7 +893,8 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
}
}
- private HighlightersSet installHighlighterSet(Info info, Editor editor) {
+ @NotNull
+ private HighlightersSet installHighlighterSet(@NotNull Info info, @NotNull Editor editor) {
final JComponent internalComponent = editor.getContentComponent();
internalComponent.addKeyListener(myEditorKeyListener);
editor.getScrollingModel().addVisibleAreaListener(myVisibleAreaListener);
@@ -922,12 +918,15 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
private class HighlightersSet {
- private final List<RangeHighlighter> myHighlighters;
- private final Editor myHighlighterView;
- private final Cursor myStoredCursor;
- private final Info myStoredInfo;
-
- private HighlightersSet(List<RangeHighlighter> highlighters, Editor highlighterView, Cursor storedCursor, Info storedInfo) {
+ @NotNull private final List<RangeHighlighter> myHighlighters;
+ @NotNull private final Editor myHighlighterView;
+ @NotNull private final Cursor myStoredCursor;
+ @NotNull private final Info myStoredInfo;
+
+ private HighlightersSet(@NotNull List<RangeHighlighter> highlighters,
+ @NotNull Editor highlighterView,
+ @NotNull Cursor storedCursor,
+ @NotNull Info storedInfo) {
myHighlighters = highlighters;
myHighlighterView = highlighterView;
myStoredCursor = storedCursor;
@@ -946,18 +945,18 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
myFileEditorManager.removeFileEditorManagerListener(myFileEditorManagerListener);
}
+ @NotNull
public Info getStoredInfo() {
return myStoredInfo;
}
}
private static class DocInfo {
-
public static final DocInfo EMPTY = new DocInfo(null, null, null);
- @Nullable public final String text;
+ @Nullable public final String text;
@Nullable public final DocumentationProvider docProvider;
- @Nullable public final PsiElement documentationAnchor;
+ @Nullable public final PsiElement documentationAnchor;
DocInfo(@Nullable String text, @Nullable DocumentationProvider provider, @Nullable PsiElement documentationAnchor) {
this.text = text;
@@ -967,7 +966,6 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
}
private class QuickDocInfoPane extends JBLayeredPane {
-
private static final int BUTTON_HGAP = 5;
@NotNull private final List<JComponent> myButtons = new ArrayList<JComponent>();
@@ -1073,11 +1071,6 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
processStateChangeIfNecessary(e.getLocationOnScreen(), false);
}
- public void mouseClicked(@NotNull MouseEvent e) {
- // TODO den check the processing.
- int i = 1;
- }
-
private void processStateChangeIfNecessary(@NotNull Point mouseScreenLocation, boolean mouseEntered) {
// Don't show 'view quick doc' buttons if docked quick doc control is already active.
if (myDocumentationManager.hasActiveDockedDocWindow()) {
@@ -1095,9 +1088,8 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
}
private class QuickDocHyperlinkListener implements HyperlinkListener {
-
@NotNull private final DocumentationProvider myProvider;
- @NotNull private final PsiElement myContext;
+ @NotNull private final PsiElement myContext;
QuickDocHyperlinkListener(@NotNull DocumentationProvider provider, @NotNull PsiElement context) {
myProvider = provider;
@@ -1111,11 +1103,11 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
}
String description = e.getDescription();
- if (StringUtil.isEmpty(description) || !description.startsWith(DocumentationManager.PSI_ELEMENT_PROTOCOL)) {
+ if (StringUtil.isEmpty(description) || !description.startsWith(DocumentationManagerProtocol.PSI_ELEMENT_PROTOCOL)) {
return;
}
- String elementName = e.getDescription().substring(DocumentationManager.PSI_ELEMENT_PROTOCOL.length());
+ String elementName = e.getDescription().substring(DocumentationManagerProtocol.PSI_ELEMENT_PROTOCOL.length());
final PsiElement targetElement = myProvider.getDocumentationElementForLink(PsiManager.getInstance(myProject), elementName, myContext);
if (targetElement != null) {
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/actions/NextVariableAction.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/actions/NextVariableAction.java
index 6605dacbc209..102626785a24 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/actions/NextVariableAction.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/actions/NextVariableAction.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.
@@ -28,11 +28,13 @@ import com.intellij.codeInsight.CodeInsightBundle;
import com.intellij.codeInsight.template.impl.TemplateManagerImpl;
import com.intellij.codeInsight.template.impl.TemplateState;
import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.openapi.command.CommandProcessor;
+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.EditorWriteActionHandler;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
public class NextVariableAction extends EditorAction {
public NextVariableAction() {
@@ -42,16 +44,17 @@ public class NextVariableAction extends EditorAction {
private static class Handler extends EditorWriteActionHandler {
@Override
- public void executeWriteAction(Editor editor, DataContext dataContext) {
+ public void executeWriteAction(Editor editor, @Nullable Caret caret, DataContext dataContext) {
TemplateState templateState = TemplateManagerImpl.getTemplateState(editor);
+ assert templateState != null;
CommandProcessor.getInstance().setCurrentCommandName(CodeInsightBundle.message("template.next.variable.command"));
templateState.nextTab();
}
- }
- @Override
- public void update(Editor editor, Presentation presentation, DataContext dataContext) {
- TemplateState templateState = TemplateManagerImpl.getTemplateState(editor);
- presentation.setEnabled(templateState != null && !templateState.isFinished() && templateState.isToProcessTab());
+ @Override
+ protected boolean isEnabledForCaret(@NotNull Editor editor, @NotNull Caret caret, DataContext dataContext) {
+ TemplateState templateState = TemplateManagerImpl.getTemplateState(editor);
+ return templateState != null && !templateState.isFinished() && templateState.isToProcessTab();
+ }
}
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/actions/PreviousVariableAction.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/actions/PreviousVariableAction.java
index bbb1f6a2bdf7..04a19bdd9b65 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/actions/PreviousVariableAction.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/actions/PreviousVariableAction.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.
@@ -28,11 +28,12 @@ import com.intellij.codeInsight.CodeInsightBundle;
import com.intellij.codeInsight.template.impl.TemplateManagerImpl;
import com.intellij.codeInsight.template.impl.TemplateState;
import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.openapi.command.CommandProcessor;
+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.EditorWriteActionHandler;
+import org.jetbrains.annotations.NotNull;
public class PreviousVariableAction extends EditorAction {
public PreviousVariableAction() {
@@ -42,16 +43,17 @@ public class PreviousVariableAction extends EditorAction {
private static class Handler extends EditorWriteActionHandler {
@Override
- public void executeWriteAction(Editor editor, DataContext dataContext) {
+ public void executeWriteAction(Editor editor, Caret caret, DataContext dataContext) {
final TemplateState templateState = TemplateManagerImpl.getTemplateState(editor);
+ assert templateState != null;
CommandProcessor.getInstance().setCurrentCommandName(CodeInsightBundle.message("template.previous.variable.command"));
templateState.previousTab();
}
- }
- @Override
- public void update(Editor editor, Presentation presentation, DataContext dataContext) {
- final TemplateState templateState = TemplateManagerImpl.getTemplateState(editor);
- presentation.setEnabled(templateState != null && !templateState.isFinished());
+ @Override
+ protected boolean isEnabledForCaret(@NotNull Editor editor, @NotNull Caret caret, DataContext dataContext) {
+ final TemplateState templateState = TemplateManagerImpl.getTemplateState(editor);
+ return templateState != null && !templateState.isFinished();
+ }
}
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/editorActions/EnterHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/editorActions/EnterHandler.java
index d071b24416b3..de503d125f30 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/editorActions/EnterHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/editorActions/EnterHandler.java
@@ -26,6 +26,7 @@ import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiDocumentManager;
+import org.jetbrains.annotations.NotNull;
public class EnterHandler extends BaseEnterHandler {
private final EditorActionHandler myOriginalHandler;
@@ -36,8 +37,8 @@ public class EnterHandler extends BaseEnterHandler {
}
@Override
- public boolean isEnabled(Editor editor, DataContext dataContext) {
- return myOriginalHandler.isEnabled(editor, dataContext);
+ public boolean isEnabledForCaret(@NotNull Editor editor, @NotNull Caret caret, DataContext dataContext) {
+ return myOriginalHandler.isEnabled(editor, caret, dataContext);
}
@Override
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/editorActions/ExpandLiveTemplateByTabAction.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/editorActions/ExpandLiveTemplateByTabAction.java
index 13798639227f..326daba46e1e 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/editorActions/ExpandLiveTemplateByTabAction.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/editorActions/ExpandLiveTemplateByTabAction.java
@@ -19,11 +19,13 @@ import com.intellij.codeInsight.template.TemplateManager;
import com.intellij.codeInsight.template.impl.TemplateManagerImpl;
import com.intellij.codeInsight.template.impl.TemplateSettings;
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.EditorWriteActionHandler;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiDocumentManager;
+import org.jetbrains.annotations.Nullable;
/**
* @author peter
@@ -32,7 +34,7 @@ public class ExpandLiveTemplateByTabAction extends EditorAction {
public ExpandLiveTemplateByTabAction() {
super(new EditorWriteActionHandler(true) {
@Override
- public void executeWriteAction(Editor editor, DataContext dataContext) {
+ public void executeWriteAction(Editor editor, @Nullable Caret caret, DataContext dataContext) {
Project project = editor.getProject();
assert project != null;
PsiDocumentManager.getInstance(project).commitDocument(editor.getDocument());
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/settings/PostfixTemplatesCheckboxTree.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/settings/PostfixTemplatesCheckboxTree.java
index b6a507ec67a2..68d5e7417d2a 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/settings/PostfixTemplatesCheckboxTree.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/settings/PostfixTemplatesCheckboxTree.java
@@ -17,6 +17,7 @@ package com.intellij.codeInsight.template.postfix.settings;
import com.intellij.codeInsight.template.postfix.templates.PostfixTemplate;
import com.intellij.ide.util.treeView.TreeState;
+import com.intellij.lang.Language;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.CheckboxTree;
import com.intellij.ui.CheckedTreeNode;
@@ -35,7 +36,10 @@ import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import java.awt.*;
-import java.util.*;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.Map;
+import java.util.Set;
public class PostfixTemplatesCheckboxTree extends CheckboxTree {
@@ -102,7 +106,7 @@ public class PostfixTemplatesCheckboxTree extends CheckboxTree {
getSelectionModel().addTreeSelectionListener(new TreeSelectionListener() {
@Override
- public void valueChanged(TreeSelectionEvent event) {
+ public void valueChanged(@NotNull TreeSelectionEvent event) {
selectionChanged();
}
});
@@ -117,10 +121,13 @@ public class PostfixTemplatesCheckboxTree extends CheckboxTree {
public void initTree(@NotNull MultiMap<String, PostfixTemplate> langToTemplates) {
myRoot.removeAllChildren();
for (Map.Entry<String, Collection<PostfixTemplate>> entry : langToTemplates.entrySet()) {
- CheckedTreeNode langNode = new CheckedTreeNode(entry.getKey());
+ String id = entry.getKey();
+ Language language = Language.findLanguageByID(id);
+ String langName = language != null ? language.getDisplayName() : id;
+ CheckedTreeNode langNode = new CheckedTreeNode(langName);
myRoot.add(langNode);
for (PostfixTemplate template : entry.getValue()) {
- CheckedTreeNode templateNode = new PostfixTemplateCheckedTreeNode(template, entry.getKey());
+ CheckedTreeNode templateNode = new PostfixTemplateCheckedTreeNode(template, langName);
langNode.add(templateNode);
}
}
diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java
index f109d0dfe8dd..090d83389b6c 100644
--- a/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java
+++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java
@@ -58,6 +58,7 @@ import com.intellij.psi.*;
import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.util.PsiUtilCore;
import com.intellij.ui.content.*;
import com.intellij.util.Processor;
import com.intellij.util.SequentialModalProgressTask;
@@ -354,7 +355,7 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp
final FileViewProvider viewProvider = psiManager.findViewProvider(virtualFile);
final com.intellij.openapi.editor.Document document = viewProvider == null ? null : viewProvider.getDocument();
- if (document == null || virtualFile.getFileType().isBinary()) return; //do not inspect binary files
+ if (document == null || isBinary(file)) return; //do not inspect binary files
final LocalInspectionsPass pass = new LocalInspectionsPass(file, document, 0,
file.getTextLength(), LocalInspectionsPass.EMPTY_PRIORITY_RANGE, true,
HighlightInfoProcessor.getEmpty());
@@ -656,8 +657,7 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp
scope.accept(new PsiElementVisitor() {
@Override
public void visitFile(PsiFile file) {
- final VirtualFile virtualFile = file.getVirtualFile();
- if (virtualFile == null || virtualFile.getFileType().isBinary()) return;
+ if (isBinary(file)) return;
for (final Tools tools : profile.getAllEnabledInspectionTools(project)) {
if (tools.getTool().getTool() instanceof CleanupLocalInspectionTool) {
final InspectionToolWrapper tool = tools.getEnabledTool(file);
@@ -724,4 +724,8 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp
ApplicationManager.getApplication().invokeLater(runnable);
}
}
+
+ private static boolean isBinary(PsiFile file) {
+ return file instanceof PsiBinaryFile || file.getFileType().isBinary();
+ }
}
diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/SeverityEditorDialog.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/SeverityEditorDialog.java
index 527235b5166c..e239678af0ad 100644
--- a/platform/lang-impl/src/com/intellij/codeInspection/ex/SeverityEditorDialog.java
+++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/SeverityEditorDialog.java
@@ -37,6 +37,7 @@ import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.options.SearchableConfigurable;
import com.intellij.openapi.options.ShowSettingsUtil;
+import com.intellij.openapi.options.ex.ConfigurableWrapper;
import com.intellij.openapi.options.newEditor.OptionsEditor;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.InputValidator;
@@ -231,7 +232,8 @@ public class SeverityEditorDialog extends DialogWrapper {
final DataContext dataContext = DataManager.getInstance().getDataContext(myPanel);
final OptionsEditor optionsEditor = OptionsEditor.KEY.getData(dataContext);
if (optionsEditor != null) {
- final ColorAndFontOptions colorAndFontOptions = optionsEditor.findConfigurable(ColorAndFontOptions.class);
+ final ColorAndFontOptions colorAndFontOptions =
+ (ColorAndFontOptions)((ConfigurableWrapper)optionsEditor.findConfigurableById(ColorAndFontOptions.ID)).getConfigurable();
assert colorAndFontOptions != null;
final SearchableConfigurable javaPage = colorAndFontOptions.findSubConfigurable(InspectionColorSettingsPage.class);
LOG.assertTrue(javaPage != null);
diff --git a/platform/lang-impl/src/com/intellij/diagnostic/logging/LogConsoleManagerBase.java b/platform/lang-impl/src/com/intellij/diagnostic/logging/LogConsoleManagerBase.java
index 026de56c9491..cb034daeaf5a 100644
--- a/platform/lang-impl/src/com/intellij/diagnostic/logging/LogConsoleManagerBase.java
+++ b/platform/lang-impl/src/com/intellij/diagnostic/logging/LogConsoleManagerBase.java
@@ -52,7 +52,9 @@ public abstract class LogConsoleManagerBase implements LogConsoleManager, Dispos
/**
* @deprecated use {@link #LogConsoleManagerBase(com.intellij.openapi.project.Project, com.intellij.psi.search.GlobalSearchScope)}
+ * to remove in IDEA 15
*/
+ @SuppressWarnings("UnusedDeclaration")
protected LogConsoleManagerBase(@NotNull Project project) {
this(project, GlobalSearchScope.allScope(project));
}
@@ -66,8 +68,8 @@ public abstract class LogConsoleManagerBase implements LogConsoleManager, Dispos
return myProject;
}
- public void setEnvironment(@NotNull final ExecutionEnvironment env) {
- myEnvironment = env;
+ public void setEnvironment(@NotNull ExecutionEnvironment environment) {
+ myEnvironment = environment;
}
protected final ExecutionEnvironment getEnvironment() {
diff --git a/platform/lang-impl/src/com/intellij/diagnostic/logging/LogFilesManager.java b/platform/lang-impl/src/com/intellij/diagnostic/logging/LogFilesManager.java
index 05abeb4b7790..a581a15ed6b8 100644
--- a/platform/lang-impl/src/com/intellij/diagnostic/logging/LogFilesManager.java
+++ b/platform/lang-impl/src/com/intellij/diagnostic/logging/LogFilesManager.java
@@ -23,9 +23,11 @@ import com.intellij.openapi.Disposable;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.Conditions;
import com.intellij.openapi.util.Disposer;
import com.intellij.util.Alarm;
import gnu.trove.THashSet;
+import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.io.File;
@@ -36,18 +38,17 @@ import java.util.*;
* Date: 01-Feb-2006
*/
public class LogFilesManager implements Disposable {
- public static final Logger LOG = Logger.getInstance("#" + LogFilesManager.class.getName());
+ public static final Logger LOG = Logger.getInstance(LogFilesManager.class);
private static final int UPDATE_INTERVAL = 500;
private final Map<LogFileOptions, Set<String>> myLogFileManagerMap = new LinkedHashMap<LogFileOptions, Set<String>>();
- private final Map<LogFileOptions, RunConfigurationBase> myLogFileToConfiguration = new HashMap<LogFileOptions, RunConfigurationBase>();
private final Runnable myUpdateRequest;
private final LogConsoleManager myManager;
private final Alarm myUpdateAlarm = new Alarm(Alarm.ThreadToUse.POOLED_THREAD, this);
private boolean myDisposed;
- public LogFilesManager(final Project project, LogConsoleManager manager, Disposable parentDisposable) {
+ public LogFilesManager(@NotNull final Project project, LogConsoleManager manager, Disposable parentDisposable) {
myManager = manager;
Disposer.register(parentDisposable, this);
@@ -86,12 +87,11 @@ public class LogFilesManager implements Disposable {
};
}
- public void registerFileMatcher(final RunConfigurationBase runConfiguration) {
+ public void registerFileMatcher(@NotNull RunConfigurationBase runConfiguration) {
final ArrayList<LogFileOptions> logFiles = runConfiguration.getAllLogFiles();
for (LogFileOptions logFile : logFiles) {
if (logFile.isEnabled()) {
myLogFileManagerMap.put(logFile, logFile.getPaths());
- myLogFileToConfiguration.put(logFile, runConfiguration);
}
}
Alarm updateAlarm = myUpdateAlarm;
@@ -108,11 +108,11 @@ public class LogFilesManager implements Disposable {
}
}
- public void initLogConsoles(RunConfigurationBase base, ProcessHandler startedProcess) {
- final ArrayList<LogFileOptions> logFiles = base.getAllLogFiles();
+ public void initLogConsoles(@NotNull RunConfigurationBase base, ProcessHandler startedProcess) {
+ List<LogFileOptions> logFiles = base.getAllLogFiles();
for (LogFileOptions logFile : logFiles) {
if (logFile.isEnabled()) {
- addConfigurationConsoles(logFile, Condition.TRUE, logFile.getPaths());
+ addConfigurationConsoles(logFile, Conditions.<String>alwaysTrue(), logFile.getPaths());
}
}
base.createAdditionalTabComponents(myManager, startedProcess);
diff --git a/platform/lang-impl/src/com/intellij/diagnostic/logging/OutputFileUtil.java b/platform/lang-impl/src/com/intellij/diagnostic/logging/OutputFileUtil.java
index fc7e6a342406..1f82f25307a3 100644
--- a/platform/lang-impl/src/com/intellij/diagnostic/logging/OutputFileUtil.java
+++ b/platform/lang-impl/src/com/intellij/diagnostic/logging/OutputFileUtil.java
@@ -34,6 +34,7 @@ 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 org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
@@ -51,41 +52,43 @@ public class OutputFileUtil {
private OutputFileUtil() {
}
- public static void attachDumpListener(final RunConfigurationBase base, final ProcessHandler startedProcess, ExecutionConsole console) {
- if (base.isSaveOutputToFile()) {
- final String outputFilePath = base.getOutputFilePath();
- if (outputFilePath != null) {
- final String filePath = FileUtil.toSystemDependentName(outputFilePath);
- startedProcess.addProcessListener(new ProcessAdapter() {
- private PrintStream myOutput;
- @Override
- public void onTextAvailable(ProcessEvent event, Key outputType) {
- if (base.collectOutputFromProcessHandler() && myOutput != null && outputType != ProcessOutputTypes.SYSTEM) {
- myOutput.print(event.getText());
- }
+ public static void attachDumpListener(@NotNull final RunConfigurationBase configuration, @NotNull final ProcessHandler startedProcess, @Nullable ExecutionConsole console) {
+ if (!configuration.isSaveOutputToFile()) {
+ return;
+ }
+
+ String outputFilePath = configuration.getOutputFilePath();
+ if (outputFilePath != null) {
+ final String filePath = FileUtil.toSystemDependentName(outputFilePath);
+ startedProcess.addProcessListener(new ProcessAdapter() {
+ private PrintStream myOutput;
+ @Override
+ public void onTextAvailable(ProcessEvent event, Key outputType) {
+ if (configuration.collectOutputFromProcessHandler() && myOutput != null && outputType != ProcessOutputTypes.SYSTEM) {
+ myOutput.print(event.getText());
}
+ }
- @Override
- public void startNotified(ProcessEvent event) {
- try {
- myOutput = new PrintStream(new FileOutputStream(new File(filePath)));
- }
- catch (FileNotFoundException ignored) {
- }
- startedProcess.notifyTextAvailable(CONSOLE_OUTPUT_FILE_MESSAGE + filePath + "\n", ProcessOutputTypes.SYSTEM);
+ @Override
+ public void startNotified(ProcessEvent event) {
+ try {
+ myOutput = new PrintStream(new FileOutputStream(new File(filePath)));
+ }
+ catch (FileNotFoundException ignored) {
}
+ startedProcess.notifyTextAvailable(CONSOLE_OUTPUT_FILE_MESSAGE + filePath + "\n", ProcessOutputTypes.SYSTEM);
+ }
- @Override
- public void processTerminated(ProcessEvent event) {
- startedProcess.removeProcessListener(this);
- if (myOutput != null) {
- myOutput.close();
- }
+ @Override
+ public void processTerminated(ProcessEvent event) {
+ startedProcess.removeProcessListener(this);
+ if (myOutput != null) {
+ myOutput.close();
}
- });
- if (console instanceof ConsoleView) {
- ((ConsoleView)console).addMessageFilter(new ShowOutputFileFilter());
}
+ });
+ if (console instanceof ConsoleView) {
+ ((ConsoleView)console).addMessageFilter(new ShowOutputFileFilter());
}
}
}
diff --git a/platform/lang-impl/src/com/intellij/execution/ExecutionHelper.java b/platform/lang-impl/src/com/intellij/execution/ExecutionHelper.java
index c4b5eaf71daf..cce4fc571abb 100644
--- a/platform/lang-impl/src/com/intellij/execution/ExecutionHelper.java
+++ b/platform/lang-impl/src/com/intellij/execution/ExecutionHelper.java
@@ -21,6 +21,7 @@ import com.intellij.execution.executors.DefaultRunExecutor;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.process.ProcessOutput;
import com.intellij.execution.ui.RunContentDescriptor;
+import com.intellij.execution.ui.RunContentManager;
import com.intellij.ide.errorTreeView.NewErrorTreeViewPanel;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.application.ApplicationManager;
@@ -44,12 +45,8 @@ import com.intellij.ui.ListCellRendererWrapper;
import com.intellij.ui.components.JBList;
import com.intellij.ui.content.Content;
import com.intellij.ui.content.ContentFactory;
-import com.intellij.ui.content.ContentManager;
import com.intellij.ui.content.MessageView;
-import com.intellij.util.ArrayUtil;
-import com.intellij.util.Consumer;
-import com.intellij.util.Function;
-import com.intellij.util.NotNullFunction;
+import com.intellij.util.*;
import com.intellij.util.concurrency.Semaphore;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.ErrorTreeView;
@@ -170,10 +167,8 @@ public class ExecutionHelper {
openMessagesView(errorTreeView, myProject, tabDisplayName);
}
catch (NullPointerException e) {
- final StringBuilder builder = new StringBuilder();
- builder.append(stdOutTitle).append("\n").append(stdout != null ? stdout : "<empty>").append("\n");
- builder.append(stderrTitle).append("\n").append(stderr != null ? stderr : "<empty>");
- Messages.showErrorDialog(builder.toString(), "Process Output");
+ Messages.showErrorDialog(stdOutTitle + "\n" + (stdout != null ? stdout : "<empty>") + "\n" + stderrTitle + "\n"
+ + (stderr != null ? stderr : "<empty>"), "Process Output");
return;
}
@@ -267,13 +262,12 @@ public class ExecutionHelper {
});
}
- public static Collection<RunContentDescriptor> findRunningConsole(final Project project,
- @NotNull final NotNullFunction<RunContentDescriptor, Boolean> descriptorMatcher) {
- final ExecutionManager executionManager = ExecutionManager.getInstance(project);
-
- final RunContentDescriptor selectedContent = executionManager.getContentManager().getSelectedContent();
+ public static Collection<RunContentDescriptor> findRunningConsole(@NotNull Project project,
+ @NotNull NotNullFunction<RunContentDescriptor, Boolean> descriptorMatcher) {
+ RunContentManager contentManager = ExecutionManager.getInstance(project).getContentManager();
+ final RunContentDescriptor selectedContent = contentManager.getSelectedContent();
if (selectedContent != null) {
- final ToolWindow toolWindow = ExecutionManager.getInstance(project).getContentManager().getToolWindowByDescriptor(selectedContent);
+ final ToolWindow toolWindow = contentManager.getToolWindowByDescriptor(selectedContent);
if (toolWindow != null && toolWindow.isVisible()) {
if (descriptorMatcher.fun(selectedContent)) {
return Collections.singletonList(selectedContent);
@@ -282,7 +276,7 @@ public class ExecutionHelper {
}
final ArrayList<RunContentDescriptor> result = ContainerUtil.newArrayList();
- for (RunContentDescriptor runContentDescriptor : executionManager.getContentManager().getAllDescriptors()) {
+ for (RunContentDescriptor runContentDescriptor : contentManager.getAllDescriptors()) {
if (descriptorMatcher.fun(runContentDescriptor)) {
result.add(runContentDescriptor);
}
@@ -290,11 +284,10 @@ public class ExecutionHelper {
return result;
}
- public static List<RunContentDescriptor> collectConsolesByDisplayName(final Project project,
+ public static List<RunContentDescriptor> collectConsolesByDisplayName(@NotNull Project project,
@NotNull NotNullFunction<String, Boolean> titleMatcher) {
- List<RunContentDescriptor> result = ContainerUtil.newArrayList();
- final ExecutionManager executionManager = ExecutionManager.getInstance(project);
- for (RunContentDescriptor runContentDescriptor : executionManager.getContentManager().getAllDescriptors()) {
+ List<RunContentDescriptor> result = new SmartList<RunContentDescriptor>();
+ for (RunContentDescriptor runContentDescriptor : ExecutionManager.getInstance(project).getContentManager().getAllDescriptors()) {
if (titleMatcher.fun(runContentDescriptor.getDisplayName())) {
result.add(runContentDescriptor);
}
@@ -343,21 +336,18 @@ public class ExecutionHelper {
}
}
- private static void descriptorToFront(final Project project, final RunContentDescriptor descriptor) {
+ private static void descriptorToFront(@NotNull final Project project, @NotNull final RunContentDescriptor descriptor) {
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
- final ToolWindow toolWindow = ExecutionManager.getInstance(project).getContentManager().getToolWindowByDescriptor(descriptor);
-
+ ToolWindow toolWindow = ExecutionManager.getInstance(project).getContentManager().getToolWindowByDescriptor(descriptor);
if (toolWindow != null) {
toolWindow.show(null);
-
- final ContentManager contentManager = toolWindow.getContentManager();
-
- contentManager.setSelectedContent(descriptor.getAttachedContent());
+ //noinspection ConstantConditions
+ toolWindow.getContentManager().setSelectedContent(descriptor.getAttachedContent());
}
}
- });
+ }, project.getDisposed());
}
public static class ErrorViewPanel extends NewErrorTreeViewPanel {
@@ -384,8 +374,6 @@ public class ExecutionHelper {
@NotNull final ExecutionMode mode,
@NotNull final String presentableCmdline) {
final String title = mode.getTitle() != null ? mode.getTitle() : "Please wait...";
- assert title != null;
-
final Runnable process;
if (mode.cancelable()) {
process = createCancelableExecutionProcess(processHandler, mode.shouldCancelFun());
@@ -400,7 +388,7 @@ public class ExecutionHelper {
};
}
else {
- process = createTimelimitedExecutionProcess(processHandler, mode.getTimeout(), presentableCmdline);
+ process = createTimeLimitedExecutionProcess(processHandler, mode.getTimeout(), presentableCmdline);
}
}
if (mode.withModalProgress()) {
@@ -447,7 +435,7 @@ public class ExecutionHelper {
private final Runnable myCancelListener = new Runnable() {
@Override
public void run() {
- for (; ; ) {
+ while (true) {
if ((myProgressIndicator != null && (myProgressIndicator.isCanceled()
|| !myProgressIndicator.isRunning()))
|| (cancelableFun != null && cancelableFun.fun(null).booleanValue())
@@ -493,7 +481,7 @@ public class ExecutionHelper {
};
}
- private static Runnable createTimelimitedExecutionProcess(final ProcessHandler processHandler,
+ private static Runnable createTimeLimitedExecutionProcess(final ProcessHandler processHandler,
final int timeout,
@NotNull final String presentableCmdline) {
return new Runnable() {
diff --git a/platform/lang-impl/src/com/intellij/execution/ExecutionTargetManagerImpl.java b/platform/lang-impl/src/com/intellij/execution/ExecutionTargetManagerImpl.java
index d0170430613e..e4d7b9cff49e 100644
--- a/platform/lang-impl/src/com/intellij/execution/ExecutionTargetManagerImpl.java
+++ b/platform/lang-impl/src/com/intellij/execution/ExecutionTargetManagerImpl.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,9 +15,11 @@
*/
package com.intellij.execution;
-import com.intellij.execution.impl.RunManagerImpl;
import com.intellij.openapi.application.ApplicationManager;
-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.components.StoragePathMacros;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.project.Project;
import com.intellij.util.containers.ContainerUtil;
@@ -29,25 +31,30 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-
-@State(name = "ExecutionTargetManager", storages = {@Storage(file = StoragePathMacros.WORKSPACE_FILE, scheme = StorageScheme.DEFAULT)})
-public class ExecutionTargetManagerImpl extends ExecutionTargetManager implements ProjectComponent, PersistentStateComponent<Element> {
+@State(name = "ExecutionTargetManager", storages = {@Storage(file = StoragePathMacros.WORKSPACE_FILE)})
+public class ExecutionTargetManagerImpl extends ExecutionTargetManager implements PersistentStateComponent<Element> {
@NotNull private final Project myProject;
@NotNull private final Object myActiveTargetLock = new Object();
@Nullable private ExecutionTarget myActiveTarget;
@Nullable private String mySavedActiveTargetId;
- public ExecutionTargetManagerImpl(@NotNull Project project) {
+ public ExecutionTargetManagerImpl(@NotNull Project project, @NotNull RunManager runManager) {
myProject = project;
- }
- @Override
- public void projectOpened() {
- }
+ ((RunManagerEx)runManager).addRunManagerListener(new RunManagerAdapter() {
+ @Override
+ public void runConfigurationChanged(@NotNull RunnerAndConfigurationSettings settings) {
+ if (settings == RunManager.getInstance(myProject).getSelectedConfiguration()) {
+ updateActiveTarget(settings);
+ }
+ }
- @Override
- public void projectClosed() {
+ @Override
+ public void runConfigurationSelected() {
+ updateActiveTarget();
+ }
+ });
}
@Override
@@ -70,33 +77,6 @@ public class ExecutionTargetManagerImpl extends ExecutionTargetManager implement
}
}
- @Override
- public void initComponent() {
- RunManagerImpl.getInstanceImpl(myProject).addRunManagerListener(new RunManagerAdapter() {
- @Override
- public void runConfigurationChanged(@NotNull RunnerAndConfigurationSettings settings) {
- if (settings == RunManager.getInstance(myProject).getSelectedConfiguration()) {
- updateActiveTarget(settings);
- }
- }
-
- @Override
- public void runConfigurationSelected() {
- updateActiveTarget();
- }
- });
- }
-
- @Override
- public void disposeComponent() {
- }
-
- @NotNull
- @Override
- public String getComponentName() {
- return ExecutionTargetManager.class.getName();
- }
-
@NotNull
@Override
public ExecutionTarget getActiveTarget() {
@@ -128,7 +108,7 @@ public class ExecutionTargetManagerImpl extends ExecutionTargetManager implement
private void updateActiveTarget(@Nullable RunnerAndConfigurationSettings settings, @Nullable ExecutionTarget toSelect) {
List<ExecutionTarget> suitable = settings == null ? Collections.singletonList(DefaultExecutionTarget.INSTANCE)
: getTargetsFor(settings);
- ExecutionTarget toNotify = null;
+ ExecutionTarget toNotify;
synchronized (myActiveTargetLock) {
if (toSelect == null) toSelect = myActiveTarget;
diff --git a/platform/lang-impl/src/com/intellij/execution/ExecutorRegistryImpl.java b/platform/lang-impl/src/com/intellij/execution/ExecutorRegistryImpl.java
index bd9f5014fabb..44af49d36cdd 100644
--- a/platform/lang-impl/src/com/intellij/execution/ExecutorRegistryImpl.java
+++ b/platform/lang-impl/src/com/intellij/execution/ExecutorRegistryImpl.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.execution;
import com.intellij.execution.actions.RunContextAction;
@@ -35,12 +34,8 @@ import org.jetbrains.annotations.Nullable;
import java.util.*;
-/**
- * @author spleaner
- */
public class ExecutorRegistryImpl extends ExecutorRegistry {
- private static final Logger LOG = Logger.getInstance("#com.intellij.execution.ExecutorRegistryImpl");
-
+ private static final Logger LOG = Logger.getInstance(ExecutorRegistryImpl.class);
@NonNls public static final String RUNNERS_GROUP = "RunnerActions";
@NonNls public static final String RUN_CONTEXT_GROUP = "RunContextGroup";
@@ -84,8 +79,7 @@ public class ExecutorRegistryImpl extends ExecutorRegistry {
action = anAction;
}
- final DefaultActionGroup group = (DefaultActionGroup) myActionManager.getAction(groupId);
- group.add(action);
+ ((DefaultActionGroup)myActionManager.getAction(groupId)).add(action);
}
synchronized void deinitExecutor(@NotNull final Executor executor) {
@@ -135,18 +129,18 @@ public class ExecutorRegistryImpl extends ExecutorRegistry {
final MessageBusConnection connect = project.getMessageBus().connect(project);
connect.subscribe(ExecutionManager.EXECUTION_TOPIC, new ExecutionAdapter(){
@Override
- public void processStartScheduled(String executorId, ExecutionEnvironment env) {
- myInProgress.add(createExecutionId(executorId, env, project));
+ public void processStartScheduled(String executorId, ExecutionEnvironment environment) {
+ myInProgress.add(createExecutionId(executorId, environment));
}
@Override
- public void processNotStarted(String executorId, @NotNull ExecutionEnvironment env) {
- myInProgress.remove(createExecutionId(executorId, env, project));
+ public void processNotStarted(String executorId, @NotNull ExecutionEnvironment environment) {
+ myInProgress.remove(createExecutionId(executorId, environment));
}
@Override
- public void processStarted(String executorId, @NotNull ExecutionEnvironment env, @NotNull ProcessHandler handler) {
- myInProgress.remove(createExecutionId(executorId, env, project));
+ public void processStarted(String executorId, @NotNull ExecutionEnvironment environment, @NotNull ProcessHandler handler) {
+ myInProgress.remove(createExecutionId(executorId, environment));
}
});
}
@@ -172,26 +166,29 @@ public class ExecutorRegistryImpl extends ExecutorRegistry {
}
}
- private static Trinity<Project, String, String> createExecutionId(String executorId, ExecutionEnvironment env, Project project) {
- return new Trinity<Project, String, String>(project, executorId, env.getRunnerId());
+ @NotNull
+ private static Trinity<Project, String, String> createExecutionId(String executorId, @NotNull ExecutionEnvironment environment) {
+ return Trinity.create(environment.getProject(), executorId, environment.getRunner().getRunnerId());
}
@Override
public boolean isStarting(Project project, final String executorId, final String runnerId) {
- return myInProgress.contains(new Trinity<Project, String, String>(project, executorId, runnerId));
+ return myInProgress.contains(Trinity.create(project, executorId, runnerId));
+ }
+
+ @Override
+ public boolean isStarting(@NotNull ExecutionEnvironment environment) {
+ return isStarting(environment.getProject(), environment.getExecutor().getId(), environment.getRunner().getRunnerId());
}
@Override
public synchronized void disposeComponent() {
- if (myExecutors.size() > 0) {
- List<Executor> executors = new ArrayList<Executor>(myExecutors);
- for (Executor executor : executors) {
+ if (!myExecutors.isEmpty()) {
+ for (Executor executor : new ArrayList<Executor>(myExecutors)) {
deinitExecutor(executor);
}
-
- myExecutors = null;
}
-
+ myExecutors = null;
myActionManager = null;
}
@@ -206,7 +203,7 @@ public class ExecutorRegistryImpl extends ExecutorRegistry {
@Override
public void update(final AnActionEvent e) {
final Presentation presentation = e.getPresentation();
- final Project project = CommonDataKeys.PROJECT.getData(e.getDataContext());
+ final Project project = e.getProject();
if (project == null || !project.isInitialized() || project.isDisposed() || DumbService.getInstance(project).isDumb()) {
presentation.setEnabled(false);
@@ -222,7 +219,7 @@ public class ExecutorRegistryImpl extends ExecutorRegistry {
ExecutionTarget target = ExecutionTargetManager.getActiveTarget(project);
enabled = ExecutionTargetManager.canRun(selectedConfiguration, target)
- && runner != null && !isStarting(project, myExecutor.getId(), runner.getRunnerId());
+ && runner != null && !isStarting(project, myExecutor.getId(), runner.getRunnerId());
if (enabled) {
presentation.setDescription(myExecutor.getDescription());
@@ -244,25 +241,17 @@ public class ExecutorRegistryImpl extends ExecutorRegistry {
@Override
public void actionPerformed(final AnActionEvent e) {
- final DataContext dataContext = e.getDataContext();
final Project project = e.getProject();
if (project == null || project.isDisposed()) {
return;
}
- final RunnerAndConfigurationSettings configuration = getConfiguration(project);
- if (configuration == null) {
- return;
- }
- ExecutionTarget target = ExecutionTargetManager.getActiveTarget(project);
- ExecutionEnvironmentBuilder builder = new ExecutionEnvironmentBuilder(project, myExecutor);
- ProgramRunner runner = ProgramRunnerUtil.getRunner(myExecutor.getId(), configuration);
- if (runner == null) {
+ RunnerAndConfigurationSettings configuration = getConfiguration(project);
+ ExecutionEnvironmentBuilder builder = configuration == null ? null : ExecutionEnvironmentBuilder.createOrNull(myExecutor, configuration);
+ if (builder == null) {
return;
}
-
- builder.setDataContext(dataContext).setTarget(target).setRunnerAndSettings(runner, configuration);
- ExecutionManager.getInstance(project).restartRunProfile(runner, builder.build(), null);
+ ExecutionManager.getInstance(project).restartRunProfile(builder.activeTarget().dataContext(e.getDataContext()).build());
}
}
}
diff --git a/platform/lang-impl/src/com/intellij/execution/ProgramRunnerUtil.java b/platform/lang-impl/src/com/intellij/execution/ProgramRunnerUtil.java
index b27a939dd57c..5ad5f73b954a 100644
--- a/platform/lang-impl/src/com/intellij/execution/ProgramRunnerUtil.java
+++ b/platform/lang-impl/src/com/intellij/execution/ProgramRunnerUtil.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,23 +13,20 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package com.intellij.execution;
import com.intellij.execution.configurations.ConfigurationFactory;
import com.intellij.execution.configurations.ConfigurationType;
import com.intellij.execution.configurations.RunConfiguration;
-import com.intellij.execution.configurations.RunProfile;
import com.intellij.execution.impl.RunDialog;
import com.intellij.execution.impl.RunManagerImpl;
+import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.runners.ExecutionEnvironmentBuilder;
import com.intellij.execution.runners.ExecutionUtil;
import com.intellij.execution.runners.ProgramRunner;
-import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.icons.AllIcons;
import com.intellij.internal.statistic.UsageTrigger;
import com.intellij.internal.statistic.beans.ConvertUsagesUtil;
-import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
@@ -41,11 +38,8 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
-/**
- * @author spleaner
- */
public class ProgramRunnerUtil {
- private static final Logger LOG = Logger.getInstance("#com.intellij.execution.ProgramRunnerUtil");
+ private static final Logger LOG = Logger.getInstance(ProgramRunnerUtil.class);
private ProgramRunnerUtil() {
}
@@ -55,102 +49,82 @@ public class ProgramRunnerUtil {
return configuration == null ? null : RunnerRegistry.getInstance().getRunner(executorId, configuration.getConfiguration());
}
- public static void executeConfiguration(@NotNull final Project project,
- @Nullable final DataContext context,
- @NotNull final RunnerAndConfigurationSettings configuration,
- @NotNull final Executor executor,
- @NotNull final ExecutionTarget target,
- @Nullable RunContentDescriptor contentToReuse,
- final boolean showSettings) {
- ProgramRunner runner = getRunner(executor.getId(), configuration);
- if (runner == null) {
- LOG.error("Runner MUST not be null! Cannot find runner for " +
- executor.getId() +
- " and " +
- configuration.getConfiguration().getFactory().getName());
- return;
- }
- executeConfiguration(project, context, configuration, executor, target, contentToReuse, showSettings, runner, null, true);
- }
-
- public static void executeConfiguration(Project project,
- @Nullable DataContext context,
- @Nullable RunnerAndConfigurationSettings configuration,
- Executor executor,
- ExecutionTarget target,
- RunContentDescriptor contentToReuse,
- boolean showSettings,
- @NotNull ProgramRunner runner,
- @Nullable RunProfile runProfile,
- boolean assignNewId) {
- if (ExecutorRegistry.getInstance().isStarting(project, executor.getId(), runner.getRunnerId())) {
- return;
- }
-
- if (configuration != null && !ExecutionTargetManager.canRun(configuration, target)) {
- ExecutionUtil.handleExecutionError(
- project, executor.getToolWindowId(), configuration.getConfiguration(),
- new ExecutionException(StringUtil.escapeXml("Cannot run '" + configuration.getName() + "' on '" + target.getDisplayName() + "'")));
+ public static void executeConfiguration(@NotNull ExecutionEnvironment environment, boolean showSettings, boolean assignNewId) {
+ if (ExecutorRegistry.getInstance().isStarting(environment)) {
return;
}
- if (configuration != null &&
- (!RunManagerImpl.canRunConfiguration(configuration, executor) || (showSettings && configuration.isEditBeforeRun()))) {
- if (!RunDialog.editConfiguration(project, configuration, "Edit configuration", executor)) {
+ RunnerAndConfigurationSettings runnerAndConfigurationSettings = environment.getRunnerAndConfigurationSettings();
+ if (runnerAndConfigurationSettings != null) {
+ if (!ExecutionTargetManager.canRun(environment)) {
+ ExecutionUtil.handleExecutionError(environment, new ExecutionException(
+ StringUtil.escapeXml("Cannot run '" + environment.getRunProfile().getName() + "' on '" + environment.getExecutionTarget().getDisplayName() + "'")));
return;
}
- while (!RunManagerImpl.canRunConfiguration(configuration, executor)) {
- if (Messages.YES == Messages
- .showYesNoDialog(project, "Configuration is still incorrect. Do you want to edit it again?", "Change Configuration Settings",
- "Edit", "Continue Anyway", Messages.getErrorIcon())) {
- if (!RunDialog.editConfiguration(project, configuration, "Edit configuration", executor)) {
- return;
- }
+ if (!RunManagerImpl.canRunConfiguration(environment) || (showSettings && runnerAndConfigurationSettings.isEditBeforeRun())) {
+ if (!RunDialog.editConfiguration(environment, "Edit configuration")) {
+ return;
}
- else {
- break;
+
+ while (!RunManagerImpl.canRunConfiguration(environment)) {
+ if (Messages.YES == Messages
+ .showYesNoDialog(environment.getProject(), "Configuration is still incorrect. Do you want to edit it again?", "Change Configuration Settings",
+ "Edit", "Continue Anyway", Messages.getErrorIcon())) {
+ if (!RunDialog.editConfiguration(environment, "Edit configuration")) {
+ return;
+ }
+ }
+ else {
+ break;
+ }
}
}
- }
- final ConfigurationType configurationType = configuration != null ? configuration.getType() : null;
- if (configurationType != null) {
- UsageTrigger.trigger("execute." + ConvertUsagesUtil.ensureProperKey(configurationType.getId()) + "." + executor.getId());
+ ConfigurationType configurationType = runnerAndConfigurationSettings.getType();
+ if (configurationType != null) {
+ UsageTrigger.trigger("execute." + ConvertUsagesUtil.ensureProperKey(configurationType.getId()) + "." + environment.getExecutor().getId());
+ }
}
try {
- ExecutionEnvironmentBuilder builder =
- new ExecutionEnvironmentBuilder(project, executor);
- if (configuration != null) {
- builder.setRunnerAndSettings(runner, configuration);
- }
- else {
- builder.setRunnerId(runner.getRunnerId());
- }
- builder.setTarget(target).setContentToReuse(contentToReuse).setDataContext(context);
if (assignNewId) {
- builder.assignNewId();
- }
- if (runProfile != null) {
- builder.setRunProfile(runProfile);
+ environment.assignNewExecutionId();
}
- runner.execute(builder.build());
+ environment.getRunner().execute(environment);
}
catch (ExecutionException e) {
- String name = configuration != null ? configuration.getName() : null;
- if (name == null && runProfile != null) name = runProfile.getName();
- if (name == null && contentToReuse != null) name = contentToReuse.getDisplayName();
- if (name == null) name = "<Unknown>";
- ExecutionUtil.handleExecutionError(project, executor.getToolWindowId(), name, e);
+ String name = runnerAndConfigurationSettings != null ? runnerAndConfigurationSettings.getName() : null;
+ if (name == null) {
+ name = environment.getRunProfile().getName();
+ }
+ if (name == null && environment.getContentToReuse() != null) {
+ name = environment.getContentToReuse().getDisplayName();
+ }
+ if (name == null) {
+ name = "<Unknown>";
+ }
+ ExecutionUtil.handleExecutionError(environment.getProject(), environment.getExecutor().getToolWindowId(), name, e);
}
}
-
public static void executeConfiguration(@NotNull Project project,
@NotNull RunnerAndConfigurationSettings configuration,
@NotNull Executor executor) {
- executeConfiguration(project, null, configuration, executor, ExecutionTargetManager.getActiveTarget(project), null, true);
+ ExecutionEnvironmentBuilder builder;
+ try {
+ builder = ExecutionEnvironmentBuilder.create(executor, configuration);
+ }
+ catch (ExecutionException e) {
+ LOG.error(e);
+ return;
+ }
+
+ executeConfiguration(builder
+ .contentToReuse(null)
+ .dataContext(null)
+ .activeTarget()
+ .build(), true, true);
}
public static Icon getConfigurationIcon(final RunnerAndConfigurationSettings settings,
diff --git a/platform/lang-impl/src/com/intellij/execution/actions/ChooseRunConfigurationPopup.java b/platform/lang-impl/src/com/intellij/execution/actions/ChooseRunConfigurationPopup.java
index 1a0235ac9d46..a4764dae0036 100644
--- a/platform/lang-impl/src/com/intellij/execution/actions/ChooseRunConfigurationPopup.java
+++ b/platform/lang-impl/src/com/intellij/execution/actions/ChooseRunConfigurationPopup.java
@@ -22,8 +22,8 @@ import com.intellij.execution.configurations.UnknownConfigurationType;
import com.intellij.execution.impl.EditConfigurationsDialog;
import com.intellij.execution.impl.RunDialog;
import com.intellij.execution.impl.RunnerAndConfigurationSettingsImpl;
+import com.intellij.execution.runners.ExecutionUtil;
import com.intellij.execution.runners.ProgramRunner;
-import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.icons.AllIcons;
import com.intellij.ide.DataManager;
import com.intellij.ide.util.PropertiesComponent;
@@ -193,10 +193,7 @@ public class ChooseRunConfigurationPopup implements ExecutorProvider {
}
private void updatePresentation() {
- final Executor executor = getExecutor();
- if (executor != null) {
- myPopup.setCaption(executor.getActionName());
- }
+ myPopup.setCaption(getExecutor().getActionName());
}
static void execute(final ItemWrapper itemWrapper, final Executor executor) {
@@ -218,12 +215,10 @@ public class ChooseRunConfigurationPopup implements ExecutorProvider {
void editConfiguration(@NotNull final Project project, @NotNull final RunnerAndConfigurationSettings configuration) {
final Executor executor = getExecutor();
- assert executor != null;
-
PropertiesComponent.getInstance().setValue("run.configuration.edit.ad", Boolean.toString(true));
if (RunDialog.editConfiguration(project, configuration, "Edit configuration settings", executor)) {
RunManagerEx.getInstanceEx(project).setSelectedConfiguration(configuration);
- doRunConfiguration(configuration, executor, project);
+ ExecutionUtil.runConfiguration(configuration, executor);
}
}
@@ -379,7 +374,7 @@ public class ChooseRunConfigurationPopup implements ExecutorProvider {
public void perform(@NotNull Project project, @NotNull Executor executor, @NotNull DataContext context) {
RunnerAndConfigurationSettings config = getValue();
RunManagerEx.getInstanceEx(project).setSelectedConfiguration(config);
- doRunConfiguration(config, executor, project);
+ ExecutionUtil.runConfiguration(config, executor);
}
@Override
@@ -404,7 +399,7 @@ public class ChooseRunConfigurationPopup implements ExecutorProvider {
@Override
public boolean available(Executor executor) {
- return null != ProgramRunnerUtil.getRunner(executor.getId(), getValue());
+ return ProgramRunnerUtil.getRunner(executor.getId(), getValue()) != null;
}
@Override
@@ -462,7 +457,7 @@ public class ChooseRunConfigurationPopup implements ExecutorProvider {
final List<ItemWrapper> configurations = getValues();
final int index = configurations.indexOf(value);
if (index > 0 && index <= configurations.size() - 1) {
- final ItemWrapper aboveConfiguration = index == 0 ? null : configurations.get(index - 1);
+ final ItemWrapper aboveConfiguration = configurations.get(index - 1);
if (aboveConfiguration != null && aboveConfiguration.isDynamic() != value.isDynamic()) {
return new ListSeparator();
@@ -508,18 +503,15 @@ public class ChooseRunConfigurationPopup implements ExecutorProvider {
}
}
- final Executor executor = myAction.getExecutor();
- assert executor != null;
-
- if (finalChoice && wrapper.available(executor)) {
+ if (finalChoice && wrapper.available(myAction.getExecutor())) {
return doFinalStep(new Runnable() {
@Override
public void run() {
- if (executor == myAction.myAlternativeExecutor) {
+ if (myAction.getExecutor() == myAction.myAlternativeExecutor) {
PropertiesComponent.getInstance().setValue(myAction.myAddKey, Boolean.toString(true));
}
- wrapper.perform(myProject, executor, DataManager.getInstance().getDataContext());
+ wrapper.perform(myProject, myAction.getExecutor(), DataManager.getInstance().getDataContext());
}
});
}
@@ -545,14 +537,6 @@ public class ChooseRunConfigurationPopup implements ExecutorProvider {
}
}
- private static void doRunConfiguration(RunnerAndConfigurationSettings configuration, Executor executor, Project project) {
- ExecutionManager.getInstance(project).restartRunProfile(project,
- executor,
- ExecutionTargetManager.getActiveTarget(project),
- configuration,
- (RunContentDescriptor)null);
- }
-
private static final class ConfigurationActionsStep extends BaseListPopupStep<ActionWrapper> {
@NotNull private final RunnerAndConfigurationSettings mySettings;
@@ -600,11 +584,13 @@ public class ChooseRunConfigurationPopup implements ExecutorProvider {
@Override
public void perform() {
final RunManagerEx manager = RunManagerEx.getInstanceEx(project);
- if (dynamic) manager.setTemporaryConfiguration(settings);
+ if (dynamic) {
+ manager.setTemporaryConfiguration(settings);
+ }
manager.setSelectedConfiguration(settings);
ExecutionTargetManager.setActiveTarget(project, eachTarget);
- doRunConfiguration(settings, action.getExecutor(), project);
+ ExecutionUtil.runConfiguration(settings, action.getExecutor());
}
});
}
@@ -617,9 +603,11 @@ public class ChooseRunConfigurationPopup implements ExecutorProvider {
@Override
public void perform() {
final RunManagerEx manager = RunManagerEx.getInstanceEx(project);
- if (dynamic) manager.setTemporaryConfiguration(settings);
+ if (dynamic) {
+ manager.setTemporaryConfiguration(settings);
+ }
manager.setSelectedConfiguration(settings);
- doRunConfiguration(settings, executor, project);
+ ExecutionUtil.runConfiguration(settings, executor);
}
});
isFirst = false;
@@ -857,7 +845,7 @@ public class ChooseRunConfigurationPopup implements ExecutorProvider {
RunnerAndConfigurationSettings selectedConfiguration = RunManagerEx.getInstanceEx(project).getSelectedConfiguration();
if (myConfigurations.contains(selectedConfiguration)) {
RunManagerEx.getInstanceEx(project).setSelectedConfiguration(selectedConfiguration);
- doRunConfiguration(selectedConfiguration, myExecutorProvider.getExecutor(), project);
+ ExecutionUtil.runConfiguration(selectedConfiguration, myExecutorProvider.getExecutor());
}
}
@@ -906,8 +894,7 @@ public class ChooseRunConfigurationPopup implements ExecutorProvider {
public void run() {
RunnerAndConfigurationSettings settings = selectedValue.getSettings();
RunManagerEx.getInstanceEx(myProject).setSelectedConfiguration(settings);
- doRunConfiguration(settings, myExecutorProvider.getExecutor(), myProject);
-
+ ExecutionUtil.runConfiguration(settings, myExecutorProvider.getExecutor());
}
});
} else {
@@ -961,7 +948,7 @@ public class ChooseRunConfigurationPopup implements ExecutorProvider {
@Override
public void perform(@NotNull final Project project, @NotNull final Executor executor, @NotNull DataContext context) {
ExecutionTargetManager.setActiveTarget(project, eachTarget);
- doRunConfiguration(selectedConfiguration, executor, project);
+ ExecutionUtil.runConfiguration(selectedConfiguration, executor);
}
@Override
@@ -1035,7 +1022,7 @@ public class ChooseRunConfigurationPopup implements ExecutorProvider {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
- doRunConfiguration(RunManager.getInstance(project).getSelectedConfiguration(), executor, project);
+ ExecutionUtil.runConfiguration(RunManager.getInstance(project).getSelectedConfiguration(), executor);
}
});
}
@@ -1116,7 +1103,7 @@ public class ChooseRunConfigurationPopup implements ExecutorProvider {
public void perform(@NotNull Project project, @NotNull Executor executor, @NotNull DataContext context) {
manager.setTemporaryConfiguration(configuration);
RunManagerEx.getInstanceEx(project).setSelectedConfiguration(configuration);
- doRunConfiguration(configuration, executor, project);
+ ExecutionUtil.runConfiguration(configuration, executor);
}
@Override
diff --git a/platform/lang-impl/src/com/intellij/execution/actions/RunContextAction.java b/platform/lang-impl/src/com/intellij/execution/actions/RunContextAction.java
index f5741242089d..0a467c7cec23 100644
--- a/platform/lang-impl/src/com/intellij/execution/actions/RunContextAction.java
+++ b/platform/lang-impl/src/com/intellij/execution/actions/RunContextAction.java
@@ -18,10 +18,9 @@ package com.intellij.execution.actions;
import com.intellij.execution.*;
import com.intellij.execution.configurations.RunConfiguration;
+import com.intellij.execution.runners.ExecutionUtil;
import com.intellij.execution.runners.ProgramRunner;
-import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.openapi.actionSystem.Presentation;
-import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -47,12 +46,8 @@ public class RunContextAction extends BaseRunConfigurationAction {
runManager.setTemporaryConfiguration(configuration);
}
runManager.setSelectedConfiguration(configuration);
- Project project = context.getProject();
- ExecutionManager.getInstance(project).restartRunProfile(project,
- myExecutor,
- ExecutionTargetManager.getActiveTarget(project),
- configuration,
- (RunContentDescriptor)null);
+
+ ExecutionUtil.runConfiguration(configuration, myExecutor);
}
@Override
@@ -81,11 +76,10 @@ public class RunContextAction extends BaseRunConfigurationAction {
configuration = context.getConfiguration();
}
- if (configuration == null) return Pair.create(false, false);
-
- final ProgramRunner runner = getRunner(configuration.getConfiguration());
- if (runner == null) return Pair.create(false, false);
-
+ ProgramRunner runner = configuration == null ? null : getRunner(configuration.getConfiguration());
+ if (runner == null) {
+ return Pair.create(false, false);
+ }
return Pair.create(!ExecutorRegistry.getInstance().isStarting(context.getProject(), myExecutor.getId(), runner.getRunnerId()), true);
}
}
diff --git a/platform/lang-impl/src/com/intellij/execution/actions/StopAction.java b/platform/lang-impl/src/com/intellij/execution/actions/StopAction.java
index 618a4b1c65c5..75466528ae2f 100644
--- a/platform/lang-impl/src/com/intellij/execution/actions/StopAction.java
+++ b/platform/lang-impl/src/com/intellij/execution/actions/StopAction.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,14 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package com.intellij.execution.actions;
+import com.intellij.execution.ExecutionBundle;
import com.intellij.execution.ExecutionManager;
import com.intellij.execution.KillableProcess;
+import com.intellij.execution.configurations.RunProfile;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.ui.RunContentDescriptor;
-import com.intellij.execution.ui.RunContentManager;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.progress.ProgressIndicator;
@@ -29,7 +29,7 @@ import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.openapi.ui.popup.JBPopupFactory;
-import com.intellij.openapi.ui.popup.ListItemDescriptor;
+import com.intellij.openapi.ui.popup.ListItemDescriptorAdapter;
import com.intellij.openapi.ui.popup.PopupChooserBuilder;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Pair;
@@ -49,19 +49,20 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-public class StopAction extends DumbAwareAction implements AnAction.TransparentUpdate {
+class StopAction extends DumbAwareAction implements AnAction.TransparentUpdate {
@Override
public void update(final AnActionEvent e) {
boolean enable = false;
Icon icon = getTemplatePresentation().getIcon();
String description = getTemplatePresentation().getDescription();
- final Presentation presentation = e.getPresentation();
-
+ Presentation presentation = e.getPresentation();
if (ActionPlaces.MAIN_MENU.equals(e.getPlace())) {
enable = !getCancellableProcesses(e.getProject()).isEmpty() || !getActiveDescriptors(e.getDataContext()).isEmpty();
+ presentation.setText(getTemplatePresentation().getText());
}
else {
- final ProcessHandler processHandler = getHandler(e.getDataContext());
+ RunContentDescriptor contentDescriptor = e.getData(LangDataKeys.RUN_CONTENT_DESCRIPTOR);
+ ProcessHandler processHandler = contentDescriptor == null ? null : contentDescriptor.getProcessHandler();
if (processHandler != null && !processHandler.isProcessTerminated()) {
if (!processHandler.isProcessTerminating()) {
enable = true;
@@ -72,6 +73,14 @@ public class StopAction extends DumbAwareAction implements AnAction.TransparentU
description = "Kill process";
}
}
+
+ RunProfile runProfile = e.getData(LangDataKeys.RUN_PROFILE);
+ if (runProfile == null && contentDescriptor == null) {
+ presentation.setText(getTemplatePresentation().getText());
+ }
+ else {
+ presentation.setText(ExecutionBundle.message("stop.configuration.action.name", runProfile == null ? contentDescriptor.getDisplayName() : runProfile.getName()));
+ }
}
presentation.setEnabled(enable);
@@ -84,7 +93,8 @@ public class StopAction extends DumbAwareAction implements AnAction.TransparentU
final DataContext dataContext = e.getDataContext();
ProcessHandler activeProcessHandler = getHandler(dataContext);
- List<Pair<TaskInfo, ProgressIndicator>> backgroundTasks = getCancellableProcesses(e.getProject());
+ Project project = e.getProject();
+ List<Pair<TaskInfo, ProgressIndicator>> backgroundTasks = getCancellableProcesses(project);
if (ActionPlaces.MAIN_MENU.equals(e.getPlace())) {
if (activeProcessHandler != null && !activeProcessHandler.isProcessTerminating() && !activeProcessHandler.isProcessTerminated()
&& backgroundTasks.isEmpty()) {
@@ -94,12 +104,14 @@ public class StopAction extends DumbAwareAction implements AnAction.TransparentU
Pair<List<HandlerItem>, HandlerItem>
handlerItems = getItemsList(backgroundTasks, getActiveDescriptors(dataContext), activeProcessHandler);
- if (handlerItems.first.isEmpty()) return;
+ if (handlerItems == null || handlerItems.first.isEmpty()) {
+ return;
+ }
final JBList list = new JBList(handlerItems.first);
if (handlerItems.second != null) list.setSelectedValue(handlerItems.second, true);
- list.setCellRenderer(new GroupedItemsListRenderer(new ListItemDescriptor() {
+ list.setCellRenderer(new GroupedItemsListRenderer(new ListItemDescriptorAdapter() {
@Nullable
@Override
public String getTextFor(Object value) {
@@ -108,12 +120,6 @@ public class StopAction extends DumbAwareAction implements AnAction.TransparentU
@Nullable
@Override
- public String getTooltipFor(Object value) {
- return null;
- }
-
- @Nullable
- @Override
public Icon getIconFor(Object value) {
return value instanceof HandlerItem ? ((HandlerItem)value).icon : null;
}
@@ -122,12 +128,6 @@ public class StopAction extends DumbAwareAction implements AnAction.TransparentU
public boolean hasSeparatorAboveOf(Object value) {
return value instanceof HandlerItem && ((HandlerItem)value).hasSeparator;
}
-
- @Nullable
- @Override
- public String getCaptionAboveOf(Object value) {
- return null;
- }
}));
final PopupChooserBuilder builder = JBPopupFactory.getInstance().createListPopupBuilder(list);
@@ -148,7 +148,8 @@ public class StopAction extends DumbAwareAction implements AnAction.TransparentU
}
}).setRequestFocus(true).createPopup();
- popup.showCenteredInCurrentWindow(e.getProject());
+ assert project != null;
+ popup.showCenteredInCurrentWindow(project);
}
else {
if (activeProcessHandler != null) {
@@ -171,12 +172,15 @@ public class StopAction extends DumbAwareAction implements AnAction.TransparentU
});
}
+ @Nullable
private static Pair<List<HandlerItem>, HandlerItem> getItemsList(List<Pair<TaskInfo, ProgressIndicator>> tasks,
List<RunContentDescriptor> descriptors,
ProcessHandler activeProcessHandler) {
- if (tasks.isEmpty() && descriptors.isEmpty()) return Pair.create(Collections.<HandlerItem>emptyList(), null);
+ if (tasks.isEmpty() && descriptors.isEmpty()) {
+ return null;
+ }
- ArrayList<HandlerItem> items = new ArrayList<HandlerItem>(tasks.size() + descriptors.size());
+ List<HandlerItem> items = new ArrayList<HandlerItem>(tasks.size() + descriptors.size());
HandlerItem selected = null;
for (RunContentDescriptor descriptor : descriptors) {
final ProcessHandler handler = descriptor.getProcessHandler();
@@ -188,7 +192,9 @@ public class StopAction extends DumbAwareAction implements AnAction.TransparentU
}
};
items.add(item);
- if (handler == activeProcessHandler) selected = item;
+ if (handler == activeProcessHandler) {
+ selected = item;
+ }
}
}
@@ -202,7 +208,7 @@ public class StopAction extends DumbAwareAction implements AnAction.TransparentU
});
hasSeparator = false;
}
- return Pair.<List<HandlerItem>, HandlerItem>create(items, selected);
+ return Pair.create(items, selected);
}
private static void stopProcess(ProcessHandler processHandler) {
@@ -220,21 +226,19 @@ public class StopAction extends DumbAwareAction implements AnAction.TransparentU
}
@Nullable
- static ProcessHandler getHandler(final DataContext dataContext) {
- final RunContentDescriptor contentDescriptor = RunContentManager.RUN_CONTENT_DESCRIPTOR.getData(dataContext);
- final ProcessHandler processHandler;
+ static ProcessHandler getHandler(@NotNull DataContext dataContext) {
+ final RunContentDescriptor contentDescriptor = LangDataKeys.RUN_CONTENT_DESCRIPTOR.getData(dataContext);
if (contentDescriptor != null) {
// toolwindow case
- processHandler = contentDescriptor.getProcessHandler();
+ return contentDescriptor.getProcessHandler();
}
else {
// main menu toolbar
final Project project = CommonDataKeys.PROJECT.getData(dataContext);
final RunContentDescriptor selectedContent =
project == null ? null : ExecutionManager.getInstance(project).getContentManager().getSelectedContent();
- processHandler = selectedContent == null ? null : selectedContent.getProcessHandler();
+ return selectedContent == null ? null : selectedContent.getProcessHandler();
}
- return processHandler;
}
@NotNull
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 1a9afd1e25e5..d7f40f35a219 100644
--- a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java
+++ b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java
@@ -616,7 +616,7 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider {
sink.put(OpenFileDescriptor.NAVIGATE_IN_EDITOR, myConsoleEditor);
}
else if (getProject().isInitialized()) {
- sink.put(key, FileEditorManagerEx.getInstanceEx(getProject()).getData(key.getName(), myConsoleEditor, myVirtualFile));
+ sink.put(key, FileEditorManagerEx.getInstanceEx(getProject()).getData(key.getName(), myConsoleEditor, myConsoleEditor.getCaretModel().getCurrentCaret()));
}
}
diff --git a/platform/lang-impl/src/com/intellij/execution/impl/ConfigurationSettingsEditor.java b/platform/lang-impl/src/com/intellij/execution/impl/ConfigurationSettingsEditor.java
index bdae21f781ea..7bae2105014a 100644
--- a/platform/lang-impl/src/com/intellij/execution/impl/ConfigurationSettingsEditor.java
+++ b/platform/lang-impl/src/com/intellij/execution/impl/ConfigurationSettingsEditor.java
@@ -75,16 +75,14 @@ class ConfigurationSettingsEditor extends CompositeSettingsEditor<RunnerAndConfi
myRunnersComponent = new RunnersEditorComponent();
- ProgramRunner[] runners = RunnerRegistry.getInstance().getRegisteredRunners();
final Executor[] executors = ExecutorRegistry.getInstance().getRegisteredExecutors();
for (final Executor executor : executors) {
- for (ProgramRunner runner : runners) {
- if (runner.canRun(executor.getId(), myConfiguration)) {
- JComponent perRunnerSettings = createCompositePerRunnerSettings(executor, runner);
- if (perRunnerSettings != null) {
- myRunnersComponent.addExecutorComponent(executor, perRunnerSettings);
- }
+ ProgramRunner runner = RunnerRegistry.getInstance().getRunner(executor.getId(), myConfiguration);
+ if (runner != null) {
+ JComponent perRunnerSettings = createCompositePerRunnerSettings(executor, runner);
+ if (perRunnerSettings != null) {
+ myRunnersComponent.addExecutorComponent(executor, perRunnerSettings);
}
}
}
diff --git a/platform/lang-impl/src/com/intellij/execution/impl/ExecutionManagerImpl.java b/platform/lang-impl/src/com/intellij/execution/impl/ExecutionManagerImpl.java
index c017284f8e11..29808af0845d 100644
--- a/platform/lang-impl/src/com/intellij/execution/impl/ExecutionManagerImpl.java
+++ b/platform/lang-impl/src/com/intellij/execution/impl/ExecutionManagerImpl.java
@@ -13,13 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package com.intellij.execution.impl;
import com.intellij.CommonBundle;
import com.intellij.execution.*;
import com.intellij.execution.configuration.CompatibilityAwareRunProfile;
-import com.intellij.execution.configurations.*;
+import com.intellij.execution.configurations.RunConfiguration;
+import com.intellij.execution.configurations.RunProfile;
+import com.intellij.execution.configurations.RunProfileState;
import com.intellij.execution.process.ProcessAdapter;
import com.intellij.execution.process.ProcessEvent;
import com.intellij.execution.process.ProcessHandler;
@@ -34,12 +35,12 @@ import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.impl.SimpleDataContext;
import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.components.ProjectComponent;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Trinity;
@@ -47,21 +48,20 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.ui.docking.DockManager;
import com.intellij.util.Alarm;
+import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
-import com.intellij.util.containers.Predicate;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
-import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
-/**
- * @author dyoma
- */
-public class ExecutionManagerImpl extends ExecutionManager implements ProjectComponent {
+public class ExecutionManagerImpl extends ExecutionManager implements Disposable {
public static final Key<Object> EXECUTION_SESSION_ID_KEY = Key.create("EXECUTION_SESSION_ID_KEY");
- private static final Logger LOG = Logger.getInstance("com.intellij.execution.impl.ExecutionManagerImpl");
+
+ private static final Logger LOG = Logger.getInstance(ExecutionManagerImpl.class);
+ private static final ProcessHandler[] EMPTY_PROCESS_HANDLERS = new ProcessHandler[0];
private final Project myProject;
@@ -70,28 +70,12 @@ public class ExecutionManagerImpl extends ExecutionManager implements ProjectCom
private final List<Trinity<RunContentDescriptor, RunnerAndConfigurationSettings, Executor>> myRunningConfigurations =
ContainerUtil.createLockFreeCopyOnWriteList();
- /**
- * reflection
- */
- ExecutionManagerImpl(final Project project) {
+ ExecutionManagerImpl(@NotNull Project project) {
myProject = project;
}
@Override
- public void projectOpened() {
- ((RunContentManagerImpl)getContentManager()).init();
- }
-
- @Override
- public void projectClosed() {
- }
-
- @Override
- public void initComponent() {
- }
-
- @Override
- public void disposeComponent() {
+ public void dispose() {
for (Trinity<RunContentDescriptor, RunnerAndConfigurationSettings, Executor> trinity : myRunningConfigurations) {
Disposer.dispose(trinity.first);
}
@@ -108,112 +92,118 @@ public class ExecutionManagerImpl extends ExecutionManager implements ProjectCom
return myContentManager;
}
+ @NotNull
@Override
public ProcessHandler[] getRunningProcesses() {
- final List<ProcessHandler> handlers = new ArrayList<ProcessHandler>();
+ if (myContentManager == null) return EMPTY_PROCESS_HANDLERS;
+ List<ProcessHandler> handlers = null;
for (RunContentDescriptor descriptor : getContentManager().getAllDescriptors()) {
- final ProcessHandler processHandler = descriptor.getProcessHandler();
+ ProcessHandler processHandler = descriptor.getProcessHandler();
if (processHandler != null) {
+ if (handlers == null) {
+ handlers = new SmartList<ProcessHandler>();
+ }
handlers.add(processHandler);
}
}
- return handlers.toArray(new ProcessHandler[handlers.size()]);
+ return handlers == null ? EMPTY_PROCESS_HANDLERS : handlers.toArray(new ProcessHandler[handlers.size()]);
}
@Override
public void compileAndRun(@NotNull final Runnable startRunnable,
- @NotNull final ExecutionEnvironment env,
+ @NotNull final ExecutionEnvironment environment,
@Nullable final RunProfileState state,
@Nullable final Runnable onCancelRunnable) {
- long id = env.getExecutionId();
+ long id = environment.getExecutionId();
if (id == 0) {
- id = env.assignNewExecutionId();
+ id = environment.assignNewExecutionId();
}
- RunProfile profile = env.getRunProfile();
-
- if (profile instanceof RunConfiguration) {
- final RunConfiguration runConfiguration = (RunConfiguration)profile;
- final RunManagerImpl runManager = RunManagerImpl.getInstanceImpl(myProject);
- final List<BeforeRunTask> activeTasks = new ArrayList<BeforeRunTask>();
- activeTasks.addAll(runManager.getBeforeRunTasks(runConfiguration));
+ RunProfile profile = environment.getRunProfile();
+ if (!(profile instanceof RunConfiguration)) {
+ startRunnable.run();
+ return;
+ }
- DataContext context = env.getDataContext();
+ final RunConfiguration runConfiguration = (RunConfiguration)profile;
+ final List<BeforeRunTask> beforeRunTasks = RunManagerEx.getInstanceEx(myProject).getBeforeRunTasks(runConfiguration);
+ if (beforeRunTasks.isEmpty()) {
+ startRunnable.run();
+ }
+ else {
+ DataContext context = environment.getDataContext();
final DataContext projectContext = context != null ? context : SimpleDataContext.getProjectContext(myProject);
-
- if (!activeTasks.isEmpty()) {
- final long finalId = id;
- final Long executionSessionId = new Long(id);
- ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
- /** @noinspection SSBasedInspection*/
- @Override
- public void run() {
- for (BeforeRunTask task : activeTasks) {
- if (myProject.isDisposed()) {
- return;
- }
- BeforeRunTaskProvider<BeforeRunTask> provider = BeforeRunTaskProvider.getProvider(myProject, task.getProviderId());
- if (provider == null) {
- LOG.warn("Cannot find BeforeRunTaskProvider for id='" + task.getProviderId() + "'");
- continue;
- }
- ExecutionEnvironment taskEnvironment = new ExecutionEnvironmentBuilder(env).setContentToReuse(null).build();
- taskEnvironment.setExecutionId(finalId);
- EXECUTION_SESSION_ID_KEY.set(taskEnvironment, executionSessionId);
- if (!provider.executeTask(projectContext, runConfiguration, taskEnvironment, task)) {
- if (onCancelRunnable != null) {
- SwingUtilities.invokeLater(onCancelRunnable);
- }
- return;
- }
+ final long finalId = id;
+ final Long executionSessionId = new Long(id);
+ ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
+ /** @noinspection SSBasedInspection*/
+ @Override
+ public void run() {
+ for (BeforeRunTask task : beforeRunTasks) {
+ if (myProject.isDisposed()) {
+ return;
}
- // important! Do not use DumbService.smartInvokelater here because it depends on modality state
- // and execution of startRunnable could be skipped if modality state check fails
- SwingUtilities.invokeLater(new Runnable() {
- @Override
- public void run() {
- if (!myProject.isDisposed()) {
- DumbService.getInstance(myProject).runWhenSmart(startRunnable);
- }
+ @SuppressWarnings("unchecked")
+ BeforeRunTaskProvider<BeforeRunTask> provider = BeforeRunTaskProvider.getProvider(myProject, task.getProviderId());
+ if (provider == null) {
+ LOG.warn("Cannot find BeforeRunTaskProvider for id='" + task.getProviderId() + "'");
+ continue;
+ }
+ ExecutionEnvironment taskEnvironment = new ExecutionEnvironmentBuilder(environment).contentToReuse(null).build();
+ taskEnvironment.setExecutionId(finalId);
+ EXECUTION_SESSION_ID_KEY.set(taskEnvironment, executionSessionId);
+ if (!provider.executeTask(projectContext, runConfiguration, taskEnvironment, task)) {
+ if (onCancelRunnable != null) {
+ SwingUtilities.invokeLater(onCancelRunnable);
}
- });
+ return;
+ }
}
- });
- }
- else {
- startRunnable.run();
- }
- }
- else {
- startRunnable.run();
+ // important! Do not use DumbService.smartInvokeLater here because it depends on modality state
+ // and execution of startRunnable could be skipped if modality state check fails
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ if (!myProject.isDisposed()) {
+ DumbService.getInstance(myProject).runWhenSmart(startRunnable);
+ }
+ }
+ });
+ }
+ });
}
}
@Override
- public void startRunProfile(@NotNull final RunProfileStarter starter, @NotNull final RunProfileState state,
- @NotNull final Project project, @NotNull final Executor executor, @NotNull final ExecutionEnvironment env) {
- final RunContentDescriptor reuseContent =
- ExecutionManager.getInstance(project).getContentManager().getReuseContent(env);
+ public void startRunProfile(@NotNull final RunProfileStarter starter,
+ @NotNull final RunProfileState state,
+ @NotNull final ExecutionEnvironment environment) {
+ final Project project = environment.getProject();
+ final RunContentDescriptor reuseContent = getContentManager().getReuseContent(environment);
if (reuseContent != null) {
- reuseContent.setExecutionId(env.getExecutionId());
+ reuseContent.setExecutionId(environment.getExecutionId());
}
- final RunProfile profile = env.getRunProfile();
- project.getMessageBus().syncPublisher(EXECUTION_TOPIC).processStartScheduled(executor.getId(), env);
+ final Executor executor = environment.getExecutor();
+ project.getMessageBus().syncPublisher(EXECUTION_TOPIC).processStartScheduled(executor.getId(), environment);
Runnable startRunnable = new Runnable() {
@Override
public void run() {
- if (project.isDisposed()) return;
+ if (project.isDisposed()) {
+ return;
+ }
+
+ RunProfile profile = environment.getRunProfile();
boolean started = false;
try {
- project.getMessageBus().syncPublisher(EXECUTION_TOPIC).processStarting(executor.getId(), env);
-
- final RunContentDescriptor descriptor = starter.execute(project, executor, state, reuseContent, env);
+ project.getMessageBus().syncPublisher(EXECUTION_TOPIC).processStarting(executor.getId(), environment);
+ final RunContentDescriptor descriptor = starter.execute(project, executor, state, reuseContent, environment);
if (descriptor != null) {
+ environment.setContentToReuse(descriptor);
final Trinity<RunContentDescriptor, RunnerAndConfigurationSettings, Executor> trinity =
- Trinity.create(descriptor, env.getRunnerAndConfigurationSettings(), executor);
+ Trinity.create(descriptor, environment.getRunnerAndConfigurationSettings(), executor);
myRunningConfigurations.add(trinity);
Disposer.register(descriptor, new Disposable() {
@Override
@@ -221,13 +211,13 @@ public class ExecutionManagerImpl extends ExecutionManager implements ProjectCom
myRunningConfigurations.remove(trinity);
}
});
- ExecutionManager.getInstance(project).getContentManager().showRunContent(executor, descriptor, reuseContent);
+ getContentManager().showRunContent(executor, descriptor, reuseContent);
final ProcessHandler processHandler = descriptor.getProcessHandler();
if (processHandler != null) {
if (!processHandler.isStartNotified()) {
processHandler.startNotify();
}
- project.getMessageBus().syncPublisher(EXECUTION_TOPIC).processStarted(executor.getId(), env, processHandler);
+ project.getMessageBus().syncPublisher(EXECUTION_TOPIC).processStarted(executor.getId(), environment, processHandler);
started = true;
processHandler.addProcessListener(new ProcessExecutionListener(project, profile, processHandler));
}
@@ -239,7 +229,7 @@ public class ExecutionManagerImpl extends ExecutionManager implements ProjectCom
}
finally {
if (!started) {
- project.getMessageBus().syncPublisher(EXECUTION_TOPIC).processNotStarted(executor.getId(), env);
+ project.getMessageBus().syncPublisher(EXECUTION_TOPIC).processNotStarted(executor.getId(), environment);
}
}
}
@@ -249,11 +239,11 @@ public class ExecutionManagerImpl extends ExecutionManager implements ProjectCom
startRunnable.run();
}
else {
- compileAndRun(startRunnable, env, state, new Runnable() {
+ compileAndRun(startRunnable, environment, state, new Runnable() {
@Override
public void run() {
if (!project.isDisposed()) {
- project.getMessageBus().syncPublisher(EXECUTION_TOPIC).processNotStarted(executor.getId(), env);
+ project.getMessageBus().syncPublisher(EXECUTION_TOPIC).processNotStarted(executor.getId(), environment);
}
}
});
@@ -261,26 +251,36 @@ public class ExecutionManagerImpl extends ExecutionManager implements ProjectCom
}
@Override
- public void startRunProfile(@NotNull RunProfileStarter starter, @NotNull RunProfileState state, @NotNull ExecutionEnvironment env) {
- startRunProfile(starter, state, env.getProject(), env.getExecutor(), env);
- }
-
- @Override
- public void restartRunProfile(@NotNull final Project project,
- @NotNull final Executor executor,
- @NotNull final ExecutionTarget target,
- @Nullable final RunnerAndConfigurationSettings configuration,
- @Nullable final ProcessHandler processHandler) {
+ public void restartRunProfile(@NotNull Project project,
+ @NotNull Executor executor,
+ @NotNull ExecutionTarget target,
+ @Nullable RunnerAndConfigurationSettings configuration,
+ @Nullable ProcessHandler processHandler) {
+ ExecutionEnvironmentBuilder builder = createEnvironmentBuilder(project, executor, configuration);
if (processHandler != null) {
for (RunContentDescriptor descriptor : getContentManager().getAllDescriptors()) {
- final ProcessHandler handler = descriptor.getProcessHandler();
- if (handler == processHandler) {
- restartRunProfile(project, null, null, null, null, null, executor, target, configuration, descriptor);
- return;
+ if (descriptor.getProcessHandler() == processHandler) {
+ builder.contentToReuse(descriptor);
+ break;
}
}
}
- restartRunProfile(project, null, null, null, null, null, executor, target, configuration, null);
+ restartRunProfile(builder.target(target).build());
+ }
+
+ @NotNull
+ private static ExecutionEnvironmentBuilder createEnvironmentBuilder(@NotNull Project project, @NotNull Executor executor, @Nullable RunnerAndConfigurationSettings configuration) {
+ ExecutionEnvironmentBuilder builder = new ExecutionEnvironmentBuilder(project, executor);
+
+ ProgramRunner runner = RunnerRegistry.getInstance().getRunner(executor.getId(), configuration != null ? configuration.getConfiguration() : null);
+ if (runner == null && configuration != null) {
+ LOG.error("Cannot find runner for " + configuration.getName());
+ }
+ else if (runner != null) {
+ assert configuration != null;
+ builder.runnerAndSettings(runner, configuration);
+ }
+ return builder;
}
@Override
@@ -289,123 +289,89 @@ public class ExecutionManagerImpl extends ExecutionManager implements ProjectCom
@NotNull ExecutionTarget target,
@Nullable RunnerAndConfigurationSettings configuration,
@Nullable RunContentDescriptor currentDescriptor) {
- restartRunProfile(project, null, null, null, null, null, executor, target, configuration, currentDescriptor);
+ ExecutionEnvironmentBuilder builder = createEnvironmentBuilder(project, executor, configuration);
+ restartRunProfile(builder.target(target).contentToReuse(currentDescriptor).build());
}
@Override
public void restartRunProfile(@Nullable ProgramRunner runner,
@NotNull ExecutionEnvironment environment,
@Nullable RunContentDescriptor currentDescriptor) {
- restartRunProfile(environment.getProject(),
- environment.getDataContext(),
- runner,
- environment.getRunProfile(),
- environment.getRunnerSettings(),
- environment.getConfigurationSettings(),
- environment.getExecutor(),
- environment.getExecutionTarget(),
- environment.getRunnerAndConfigurationSettings(), currentDescriptor);
+ ExecutionEnvironmentBuilder builder = new ExecutionEnvironmentBuilder(environment).contentToReuse(currentDescriptor);
+ if (runner != null) {
+ builder.runner(runner);
+ }
+ restartRunProfile(builder.build());
}
+ public static boolean isProcessRunning(@Nullable RunContentDescriptor descriptor) {
+ ProcessHandler processHandler = descriptor == null ? null : descriptor.getProcessHandler();
+ return processHandler != null && !processHandler.isProcessTerminated();
+ }
- private void restartRunProfile(@NotNull final Project project,
- @Nullable final DataContext context,
- @Nullable ProgramRunner r,
- @Nullable final RunProfile runProfile,
- @Nullable final RunnerSettings runnerSettings,
- @Nullable final ConfigurationPerRunnerSettings configurationPerRunnerSettings,
- @NotNull final Executor executor,
- @NotNull final ExecutionTarget target,
- @Nullable final RunnerAndConfigurationSettings configuration,
- @Nullable final RunContentDescriptor currentDescriptor) {
- final ProgramRunner runner = r != null ?
- r :
- RunnerRegistry.getInstance().getRunner(executor.getId(),
- configuration != null && configuration.getConfiguration() != null
- ? configuration.getConfiguration()
- : runProfile
- );
- if (configuration != null && runner == null) {
- LOG.error("Cannot find runner for " + configuration.getName());
- return;
- }
-
- final List<RunContentDescriptor> runningConfigurationsOfTheSameType = new ArrayList<RunContentDescriptor>();
- final List<RunContentDescriptor> runningIncompatibleConfigurations = new ArrayList<RunContentDescriptor>();
+ @Override
+ public void restartRunProfile(@NotNull final ExecutionEnvironment environment) {
+ RunnerAndConfigurationSettings configuration = environment.getRunnerAndConfigurationSettings();
- if (configuration != null) {
- runningIncompatibleConfigurations.addAll(getIncompatibleRunningDescriptors(configuration));
+ List<RunContentDescriptor> runningIncompatible;
+ if (configuration == null) {
+ runningIncompatible = Collections.emptyList();
}
+ else {
+ runningIncompatible = getIncompatibleRunningDescriptors(configuration);
+ }
+
+ RunContentDescriptor contentToReuse = environment.getContentToReuse();
+ final List<RunContentDescriptor> runningOfTheSameType = new SmartList<RunContentDescriptor>();
if (configuration != null && configuration.isSingleton()) {
- runningConfigurationsOfTheSameType.addAll(getRunningDescriptorsOfTheSameConfigType(configuration));
+ runningOfTheSameType.addAll(getRunningDescriptorsOfTheSameConfigType(configuration));
}
- else if (currentDescriptor != null) {
- runningConfigurationsOfTheSameType.add(currentDescriptor);
+ else if (isProcessRunning(contentToReuse)) {
+ runningOfTheSameType.add(contentToReuse);
}
- final List<RunContentDescriptor> runningConfigurationsToStop = ContainerUtil.concat(runningConfigurationsOfTheSameType,
- runningIncompatibleConfigurations);
- if (!runningConfigurationsToStop.isEmpty()) {
+ List<RunContentDescriptor> runningToStop = ContainerUtil.concat(runningOfTheSameType, runningIncompatible);
+ if (!runningToStop.isEmpty()) {
if (configuration != null) {
- if (!runningConfigurationsOfTheSameType.isEmpty()
- && (runningConfigurationsOfTheSameType.size() > 1 ||
- currentDescriptor == null ||
- runningConfigurationsOfTheSameType.get(0) != currentDescriptor) &&
- !userApprovesStopForSameTypeConfigurations(project, configuration.getName(), runningConfigurationsOfTheSameType.size())) {
+ if (!runningOfTheSameType.isEmpty()
+ && (runningOfTheSameType.size() > 1 || contentToReuse == null || runningOfTheSameType.get(0) != contentToReuse) &&
+ !userApprovesStopForSameTypeConfigurations(environment.getProject(), configuration.getName(), runningOfTheSameType.size())) {
return;
}
- if (!runningIncompatibleConfigurations.isEmpty()
- && !userApprovesStopForIncompatibleConfigurations(myProject, configuration.getName(), runningIncompatibleConfigurations)) {
+ if (!runningIncompatible.isEmpty()
+ && !userApprovesStopForIncompatibleConfigurations(myProject, configuration.getName(), runningIncompatible)) {
return;
}
}
- for (RunContentDescriptor descriptor : runningConfigurationsToStop) {
+
+ for (RunContentDescriptor descriptor : runningToStop) {
stop(descriptor);
}
}
- Runnable runnable = new Runnable() {
+ awaitingTerminationAlarm.addRequest(new Runnable() {
@Override
public void run() {
- if (runner != null && ExecutorRegistry.getInstance().isStarting(project, executor.getId(), runner.getRunnerId())) {
+ if (ExecutorRegistry.getInstance().isStarting(environment)) {
awaitingTerminationAlarm.addRequest(this, 100);
return;
}
- for (RunContentDescriptor descriptor : runningConfigurationsOfTheSameType) {
+
+ for (RunContentDescriptor descriptor : runningOfTheSameType) {
ProcessHandler processHandler = descriptor.getProcessHandler();
if (processHandler != null && !processHandler.isProcessTerminated()) {
awaitingTerminationAlarm.addRequest(this, 100);
return;
}
}
- start(project, context, runner, runProfile, runnerSettings, configurationPerRunnerSettings, configuration, executor, target,
- currentDescriptor);
+ start(environment);
}
- };
- awaitingTerminationAlarm.addRequest(runnable, 50);
+ }, 50);
}
- private static void start(@NotNull Project project,
- @Nullable DataContext context,
- @Nullable ProgramRunner runner,
- @Nullable RunProfile runProfile,
- @Nullable RunnerSettings runnerSettings,
- @Nullable ConfigurationPerRunnerSettings configurationPerRunnerSettings,
- @Nullable RunnerAndConfigurationSettings configuration,
- @NotNull Executor executor,
- @NotNull ExecutionTarget target,
- @Nullable RunContentDescriptor descriptor) {
- Runnable restarter = descriptor != null ? descriptor.getRestarter() : null;
- if (runner != null && runProfile != null) {
- ProgramRunnerUtil.executeConfiguration(project, context, configuration, executor, target, descriptor,
- configuration != null && configuration.isEditBeforeRun(), runner, runProfile, false);
- }
- else if (configuration != null) {
- ProgramRunnerUtil.executeConfiguration(project, context, configuration, executor, target, descriptor, true);
- }
- else if (restarter != null) {
- restarter.run();
- }
+ private static void start(@NotNull ExecutionEnvironment environment) {
+ RunnerAndConfigurationSettings settings = environment.getRunnerAndConfigurationSettings();
+ ProgramRunnerUtil.executeConfiguration(environment, settings != null && settings.isEditBeforeRun(), true);
}
private static boolean userApprovesStopForSameTypeConfigurations(Project project, String configName, int instancesCount) {
@@ -505,35 +471,36 @@ public class ExecutionManagerImpl extends ExecutionManager implements ProjectCom
Messages.getQuestionIcon(), option) == Messages.OK;
}
- private List<RunContentDescriptor> getRunningDescriptorsOfTheSameConfigType(
- @NotNull final RunnerAndConfigurationSettings configurationAndSettings) {
- return getRunningDescriptors(new Predicate<RunnerAndConfigurationSettings>() {
+ @NotNull
+ private List<RunContentDescriptor> getRunningDescriptorsOfTheSameConfigType(@NotNull final RunnerAndConfigurationSettings configurationAndSettings) {
+ return getRunningDescriptors(new Condition<RunnerAndConfigurationSettings>() {
@Override
- public boolean apply(@Nullable RunnerAndConfigurationSettings runningConfigurationAndSettings) {
+ public boolean value(@Nullable RunnerAndConfigurationSettings runningConfigurationAndSettings) {
return configurationAndSettings == runningConfigurationAndSettings;
}
});
}
- private List<RunContentDescriptor> getIncompatibleRunningDescriptors(
- @NotNull final RunnerAndConfigurationSettings configurationAndSettings) {
+ @NotNull
+ private List<RunContentDescriptor> getIncompatibleRunningDescriptors(@NotNull RunnerAndConfigurationSettings configurationAndSettings) {
final RunConfiguration configurationToCheckCompatibility = configurationAndSettings.getConfiguration();
- return getRunningDescriptors(new Predicate<RunnerAndConfigurationSettings>() {
+ return getRunningDescriptors(new Condition<RunnerAndConfigurationSettings>() {
@Override
- public boolean apply(@Nullable RunnerAndConfigurationSettings runningConfigurationAndSettings) {
- if (runningConfigurationAndSettings == null) return false;
- RunConfiguration runningConfiguration = runningConfigurationAndSettings.getConfiguration();
- if (runningConfiguration == null || !(runningConfiguration instanceof CompatibilityAwareRunProfile)) return false;
+ public boolean value(@Nullable RunnerAndConfigurationSettings runningConfigurationAndSettings) {
+ RunConfiguration runningConfiguration = runningConfigurationAndSettings == null ? null : runningConfigurationAndSettings.getConfiguration();
+ if (runningConfiguration == null || !(runningConfiguration instanceof CompatibilityAwareRunProfile)) {
+ return false;
+ }
return ((CompatibilityAwareRunProfile)runningConfiguration).mustBeStoppedToRun(configurationToCheckCompatibility);
}
});
}
- private List<RunContentDescriptor> getRunningDescriptors(
- Predicate<RunnerAndConfigurationSettings> condition) {
- List<RunContentDescriptor> result = new ArrayList<RunContentDescriptor>();
+ @NotNull
+ private List<RunContentDescriptor> getRunningDescriptors(@NotNull Condition<RunnerAndConfigurationSettings> condition) {
+ List<RunContentDescriptor> result = new SmartList<RunContentDescriptor>();
for (Trinity<RunContentDescriptor, RunnerAndConfigurationSettings, Executor> trinity : myRunningConfigurations) {
- if (condition.apply(trinity.getSecond())) {
+ if (condition.value(trinity.getSecond())) {
ProcessHandler processHandler = trinity.getFirst().getProcessHandler();
if (processHandler != null && !processHandler.isProcessTerminating() && !processHandler.isProcessTerminated()) {
result.add(trinity.getFirst());
@@ -543,30 +510,27 @@ public class ExecutionManagerImpl extends ExecutionManager implements ProjectCom
return result;
}
- private static void stop(RunContentDescriptor runContentDescriptor) {
- ProcessHandler processHandler = runContentDescriptor != null ? runContentDescriptor.getProcessHandler() : null;
+ private static void stop(@Nullable RunContentDescriptor descriptor) {
+ ProcessHandler processHandler = descriptor != null ? descriptor.getProcessHandler() : null;
if (processHandler == null) {
return;
}
+
if (processHandler instanceof KillableProcess && processHandler.isProcessTerminating()) {
((KillableProcess)processHandler).killProcess();
return;
}
- if (processHandler.detachIsDefault()) {
- processHandler.detachProcess();
- }
- else {
- processHandler.destroyProcess();
+ if (!processHandler.isProcessTerminated()) {
+ if (processHandler.detachIsDefault()) {
+ processHandler.detachProcess();
+ }
+ else {
+ processHandler.destroyProcess();
+ }
}
}
- @Override
- @NotNull
- public String getComponentName() {
- return "ExecutionManager";
- }
-
private static class ProcessExecutionListener extends ProcessAdapter {
private final Project myProject;
private final RunProfile myProfile;
diff --git a/platform/lang-impl/src/com/intellij/execution/impl/ProjectRunConfigurationManager.java b/platform/lang-impl/src/com/intellij/execution/impl/ProjectRunConfigurationManager.java
index deadaad0a0d1..42b9be79890e 100644
--- a/platform/lang-impl/src/com/intellij/execution/impl/ProjectRunConfigurationManager.java
+++ b/platform/lang-impl/src/com/intellij/execution/impl/ProjectRunConfigurationManager.java
@@ -50,7 +50,7 @@ import java.util.Set;
}
)
public class ProjectRunConfigurationManager implements ProjectComponent, PersistentStateComponent<Element> {
- private static final Logger LOG = Logger.getInstance("#com.intellij.execution.impl.ProjectRunConfigurationManager");
+ private static final Logger LOG = Logger.getInstance(ProjectRunConfigurationManager.class);
private final RunManagerImpl myManager;
private List<Element> myUnloadedElements = null;
@@ -150,7 +150,7 @@ public class ProjectRunConfigurationManager implements ProjectComponent, Persist
}
if (myUnloadedElements != null) {
for (Element unloadedElement : myUnloadedElements) {
- element.addContent((Element)unloadedElement.clone());
+ element.addContent(unloadedElement.clone());
}
}
}
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 edf1352a760c..97f36a8fd2b4 100644
--- a/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationBeforeRunProvider.java
+++ b/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationBeforeRunProvider.java
@@ -23,6 +23,7 @@ import com.intellij.execution.process.ProcessAdapter;
import com.intellij.execution.process.ProcessEvent;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.runners.ExecutionEnvironment;
+import com.intellij.execution.runners.ExecutionEnvironmentBuilder;
import com.intellij.execution.runners.ProgramRunner;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.Disposable;
@@ -137,7 +138,7 @@ extends BeforeRunTaskProvider<RunConfigurationBeforeRunProvider.RunConfigurableB
}
@NotNull
- private List<RunnerAndConfigurationSettings> getAvailableConfigurations(RunConfiguration runConfiguration) {
+ private static List<RunnerAndConfigurationSettings> getAvailableConfigurations(RunConfiguration runConfiguration) {
Project project = runConfiguration.getProject();
if (project == null || !project.isInitialized())
return Collections.emptyList();
@@ -164,9 +165,7 @@ extends BeforeRunTaskProvider<RunConfigurationBeforeRunProvider.RunConfigurableB
}
String executorId = DefaultRunExecutor.getRunExecutorInstance().getId();
final ProgramRunner runner = ProgramRunnerUtil.getRunner(executorId, settings);
- if (runner == null)
- return false;
- return runner.canRun(executorId, settings.getConfiguration());
+ return runner != null && runner.canRun(executorId, settings.getConfiguration());
}
@Override
@@ -180,16 +179,17 @@ extends BeforeRunTaskProvider<RunConfigurationBeforeRunProvider.RunConfigurableB
}
final Executor executor = DefaultRunExecutor.getRunExecutorInstance();
final String executorId = executor.getId();
- final ProgramRunner runner = ProgramRunnerUtil.getRunner(executorId, settings);
- if (runner == null)
+ ExecutionEnvironmentBuilder builder = ExecutionEnvironmentBuilder.createOrNull(executor, settings);
+ if (builder == null) {
return false;
- final ExecutionEnvironment environment = new ExecutionEnvironment(executor, runner, settings, myProject);
+ }
+ final ExecutionEnvironment environment = builder.build();
environment.setExecutionId(env.getExecutionId());
if (!ExecutionTargetManager.canRun(settings, env.getExecutionTarget())) {
return false;
}
- if (!runner.canRun(executorId, environment.getRunProfile())) {
+ if (!environment.getRunner().canRun(executorId, environment.getRunProfile())) {
return false;
}
else {
@@ -198,23 +198,27 @@ extends BeforeRunTaskProvider<RunConfigurationBeforeRunProvider.RunConfigurableB
final Disposable disposable = Disposer.newDisposable();
myProject.getMessageBus().connect(disposable).subscribe(ExecutionManager.EXECUTION_TOPIC, new ExecutionAdapter() {
+ @Override
public void processStartScheduled(final String executorIdLocal, final ExecutionEnvironment environmentLocal) {
if (executorId.equals(executorIdLocal) && environment.equals(environmentLocal)) {
targetDone.down();
}
}
+ @Override
public void processNotStarted(final String executorIdLocal, @NotNull final ExecutionEnvironment environmentLocal) {
if (executorId.equals(executorIdLocal) && environment.equals(environmentLocal)) {
targetDone.up();
}
}
+ @Override
public void processStarted(final String executorIdLocal,
@NotNull final ExecutionEnvironment environmentLocal,
@NotNull final ProcessHandler handler) {
if (executorId.equals(executorIdLocal) && environment.equals(environmentLocal)) {
handler.addProcessListener(new ProcessAdapter() {
+ @Override
public void processTerminated(ProcessEvent event) {
result.set(event.getExitCode() == 0);
targetDone.up();
@@ -229,7 +233,7 @@ extends BeforeRunTaskProvider<RunConfigurationBeforeRunProvider.RunConfigurableB
@Override
public void run() {
try {
- runner.execute(environment);
+ environment.getRunner().execute(environment);
}
catch (ExecutionException e) {
targetDone.up();
diff --git a/platform/lang-impl/src/com/intellij/execution/impl/RunDialog.java b/platform/lang-impl/src/com/intellij/execution/impl/RunDialog.java
index 71e205c3f22c..139eb0c4e25b 100644
--- a/platform/lang-impl/src/com/intellij/execution/impl/RunDialog.java
+++ b/platform/lang-impl/src/com/intellij/execution/impl/RunDialog.java
@@ -20,6 +20,7 @@ import com.intellij.execution.ExecutionBundle;
import com.intellij.execution.Executor;
import com.intellij.execution.RunnerAndConfigurationSettings;
import com.intellij.execution.configurations.RunConfiguration;
+import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.openapi.help.HelpManager;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.options.ex.SingleConfigurableEditor;
@@ -111,6 +112,10 @@ public class RunDialog extends DialogWrapper implements RunConfigurable.RunDialo
return editConfiguration(project, configuration, title, null);
}
+ public static boolean editConfiguration(@NotNull ExecutionEnvironment environment, @NotNull String title) {
+ return editConfiguration(environment.getProject(), environment.getRunnerAndConfigurationSettings(), title, environment.getExecutor());
+ }
+
public static boolean editConfiguration(final Project project, final RunnerAndConfigurationSettings configuration, final String title, @Nullable final Executor executor) {
final SingleConfigurationConfigurable<RunConfiguration> configurable = SingleConfigurationConfigurable.editSettings(configuration, executor);
final SingleConfigurableEditor dialog = new SingleConfigurableEditor(project, configurable, IdeModalityType.PROJECT) {
diff --git a/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.java b/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.java
index d3a1e1cb0574..7b54f21503df 100644
--- a/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.java
+++ b/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.java
@@ -19,6 +19,7 @@ package com.intellij.execution.impl;
import com.intellij.ProjectTopics;
import com.intellij.execution.*;
import com.intellij.execution.configurations.*;
+import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.components.NamedComponent;
@@ -106,7 +107,7 @@ public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable,
public final void initializeConfigurationTypes(@NotNull final ConfigurationType[] factories) {
Arrays.sort(factories, new Comparator<ConfigurationType>() {
@Override
- public int compare(final ConfigurationType o1, final ConfigurationType o2) {
+ public int compare(@NotNull final ConfigurationType o1, @NotNull final ConfigurationType o2) {
return o1.getDisplayName().compareTo(o2.getDisplayName());
}
});
@@ -461,7 +462,7 @@ public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable,
// IDEA-63663 Sort run configurations alphabetically if clean checkout
Collections.sort(order, new Comparator<Pair<String, RunnerAndConfigurationSettings>>() {
@Override
- public int compare(Pair<String, RunnerAndConfigurationSettings> o1, Pair<String, RunnerAndConfigurationSettings> o2) {
+ public int compare(@NotNull Pair<String, RunnerAndConfigurationSettings> o1, @NotNull Pair<String, RunnerAndConfigurationSettings> o2) {
boolean temporary1 = o1.getSecond().isTemporary();
boolean temporary2 = o2.getSecond().isTemporary();
if (temporary1 == temporary2) {
@@ -475,7 +476,7 @@ public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable,
else {
Collections.sort(order, new Comparator<Pair<String, RunnerAndConfigurationSettings>>() {
@Override
- public int compare(Pair<String, RunnerAndConfigurationSettings> o1, Pair<String, RunnerAndConfigurationSettings> o2) {
+ public int compare(@NotNull Pair<String, RunnerAndConfigurationSettings> o1, @NotNull Pair<String, RunnerAndConfigurationSettings> o2) {
int i1 = folderNames.indexOf(o1.getSecond().getFolderName());
int i2 = folderNames.indexOf(o2.getSecond().getFolderName());
if (i1 != i2) {
@@ -507,8 +508,12 @@ public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable,
return myConfigurations.values();
}
- public static boolean canRunConfiguration(@NotNull final RunnerAndConfigurationSettings configuration,
- @NotNull final Executor executor) {
+ public static boolean canRunConfiguration(@NotNull ExecutionEnvironment environment) {
+ RunnerAndConfigurationSettings runnerAndConfigurationSettings = environment.getRunnerAndConfigurationSettings();
+ return runnerAndConfigurationSettings != null && canRunConfiguration(runnerAndConfigurationSettings, environment.getExecutor());
+ }
+
+ public static boolean canRunConfiguration(@NotNull RunnerAndConfigurationSettings configuration, @NotNull Executor executor) {
try {
configuration.checkSettings(executor);
}
@@ -567,7 +572,7 @@ public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable,
if (myUnknownElements != null) {
for (Element unloadedElement : myUnknownElements) {
- parentNode.addContent((Element)unloadedElement.clone());
+ parentNode.addContent(unloadedElement.clone());
}
}
}
@@ -647,7 +652,7 @@ public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable,
final Comparator<Element> comparator = new Comparator<Element>() {
@Override
- public int compare(Element a, Element b) {
+ public int compare(@NotNull Element a, @NotNull Element b) {
final boolean aDefault = Boolean.valueOf(a.getAttributeValue("default", "false"));
final boolean bDefault = Boolean.valueOf(b.getAttributeValue("default", "false"));
return aDefault == bDefault ? 0 : aDefault ? -1 : 1;
@@ -666,7 +671,7 @@ public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable,
Collections.sort(sortedElements, comparator); // ensure templates are loaded first!
for (final Element element : sortedElements) {
- RunnerAndConfigurationSettings configurationSettings = null;
+ RunnerAndConfigurationSettings configurationSettings;
try {
configurationSettings = loadConfiguration(element, false);
}
@@ -915,6 +920,7 @@ public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable,
public List<RunnerAndConfigurationSettings> getTempConfigurationsList() {
List<RunnerAndConfigurationSettings> configurations =
ContainerUtil.filter(myConfigurations.values(), new Condition<RunnerAndConfigurationSettings>() {
+ @Override
public boolean value(RunnerAndConfigurationSettings settings) {
return settings.isTemporary();
}
@@ -933,6 +939,7 @@ public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable,
return result;
}
+ @Override
public void makeStable(@NotNull RunnerAndConfigurationSettings settings) {
settings.setTemporary(false);
myRecentlyUsedTemporaries.remove(settings.getConfiguration());
diff --git a/platform/lang-impl/src/com/intellij/execution/impl/RunnerRegistryImpl.java b/platform/lang-impl/src/com/intellij/execution/impl/RunnerRegistryImpl.java
index 08e9541c265f..cefeaf958f0d 100644
--- a/platform/lang-impl/src/com/intellij/execution/impl/RunnerRegistryImpl.java
+++ b/platform/lang-impl/src/com/intellij/execution/impl/RunnerRegistryImpl.java
@@ -51,10 +51,12 @@ public class RunnerRegistryImpl extends RunnerRegistry {
}
@Override
- public ProgramRunner getRunner(@NotNull final String executorId, final RunProfile settings) {
- if (settings == null) return null;
- final ProgramRunner[] runners = getRegisteredRunners();
- for (final ProgramRunner runner : runners) {
+ public ProgramRunner getRunner(@NotNull String executorId, @Nullable RunProfile settings) {
+ if (settings == null) {
+ return null;
+ }
+
+ for (ProgramRunner runner : getRegisteredRunners()) {
if (runner.canRun(executorId, settings)) {
return runner;
}
diff --git a/platform/lang-impl/src/com/intellij/execution/impl/SingleConfigurationConfigurable.java b/platform/lang-impl/src/com/intellij/execution/impl/SingleConfigurationConfigurable.java
index 4c58ab7029b3..4a750f22a15d 100644
--- a/platform/lang-impl/src/com/intellij/execution/impl/SingleConfigurationConfigurable.java
+++ b/platform/lang-impl/src/com/intellij/execution/impl/SingleConfigurationConfigurable.java
@@ -151,12 +151,10 @@ public final class SingleConfigurationConfigurable<Config extends RunConfigurati
if (snapshot != null) {
snapshot.setName(getNameText());
snapshot.checkSettings(myExecutor);
- for (ProgramRunner runner : RunnerRegistry.getInstance().getRegisteredRunners()) {
- for (Executor executor : ExecutorRegistry.getInstance().getRegisteredExecutors()) {
- if (runner.canRun(executor.getId(), snapshot.getConfiguration())) {
- checkConfiguration(runner, snapshot);
- break;
- }
+ for (Executor executor : ExecutorRegistry.getInstance().getRegisteredExecutors()) {
+ ProgramRunner runner = RunnerRegistry.getInstance().getRunner(executor.getId(), snapshot.getConfiguration());
+ if (runner != null) {
+ checkConfiguration(runner, snapshot);
}
}
}
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 b4b3cd919ec4..7bcabebf256a 100644
--- a/platform/lang-impl/src/com/intellij/execution/runners/AbstractConsoleRunnerWithHistory.java
+++ b/platform/lang-impl/src/com/intellij/execution/runners/AbstractConsoleRunnerWithHistory.java
@@ -173,7 +173,7 @@ public abstract class AbstractConsoleRunnerWithHistory<T extends LanguageConsole
return false;
}
- protected void showConsole(Executor defaultExecutor, RunContentDescriptor contentDescriptor) {
+ protected void showConsole(Executor defaultExecutor, @NotNull RunContentDescriptor contentDescriptor) {
// Show in run toolwindow
ExecutionManager.getInstance(myProject).getContentManager().showRunContent(defaultExecutor, contentDescriptor);
}
diff --git a/platform/lang-impl/src/com/intellij/execution/runners/DefaultProgramRunner.java b/platform/lang-impl/src/com/intellij/execution/runners/DefaultProgramRunner.java
index e2f8a5a717fe..5f7321aa8068 100644
--- a/platform/lang-impl/src/com/intellij/execution/runners/DefaultProgramRunner.java
+++ b/platform/lang-impl/src/com/intellij/execution/runners/DefaultProgramRunner.java
@@ -36,10 +36,10 @@ public abstract class DefaultProgramRunner extends GenericProgramRunner {
@NotNull final ExecutionEnvironment env) throws ExecutionException {
FileDocumentManager.getInstance().saveAllDocuments();
ExecutionResult executionResult = state.execute(env.getExecutor(), this);
- if (executionResult == null) return null;
-
- final RunContentBuilder contentBuilder = new RunContentBuilder(this, executionResult, env);
- return contentBuilder.showRunContent(contentToReuse);
+ if (executionResult == null) {
+ return null;
+ }
+ return new RunContentBuilder(executionResult, env).showRunContent(contentToReuse);
}
}
diff --git a/platform/lang-impl/src/com/intellij/execution/runners/FakeRerunAction.java b/platform/lang-impl/src/com/intellij/execution/runners/FakeRerunAction.java
index 45393c328e69..ecc8fa553121 100644
--- a/platform/lang-impl/src/com/intellij/execution/runners/FakeRerunAction.java
+++ b/platform/lang-impl/src/com/intellij/execution/runners/FakeRerunAction.java
@@ -15,33 +15,127 @@
*/
package com.intellij.execution.runners;
+import com.intellij.execution.ExecutionBundle;
+import com.intellij.execution.ExecutorRegistry;
+import com.intellij.execution.impl.ExecutionManagerImpl;
+import com.intellij.execution.process.ProcessHandler;
+import com.intellij.execution.ui.RunContentDescriptor;
+import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.openapi.project.DumbAware;
import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import javax.swing.*;
+import java.awt.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
/**
* @author Roman.Chernyatchik
*/
-public class FakeRerunAction extends AnAction implements DumbAware {
- protected static final List<RestartAction> registry = ContainerUtil.createLockFreeCopyOnWriteList();
+class FakeRerunAction extends AnAction implements DumbAware {
+ @SuppressWarnings("deprecation")
+ static final List<RestartAction> registry = ContainerUtil.createLockFreeCopyOnWriteList();
@Override
- public void actionPerformed(AnActionEvent e) {
- RestartAction action = RestartAction.findActualAction();
- if (action != null && action.isEnabled()) {
- action.actionPerformed(e);
+ public void update(AnActionEvent event) {
+ Presentation presentation = event.getPresentation();
+ ExecutionEnvironment environment = getEnvironment(event);
+ if (environment != null) {
+ presentation.setText(ExecutionBundle.message("rerun.configuration.action.name", environment.getRunProfile().getName()));
+ presentation.setIcon(ExecutionManagerImpl.isProcessRunning(getDescriptor(event)) ? AllIcons.Actions.Restart : environment.getExecutor().getIcon());
+ presentation.setEnabledAndVisible(isEnabled(event));
+ return;
}
+
+ FakeRerunAction action = findActualAction(event);
+ presentation.setEnabled(action != null && action.isEnabled(event));
+ presentation.setVisible(false);
}
@Override
- public void update(AnActionEvent e) {
- final Presentation presentation = e.getPresentation();
- RestartAction action = RestartAction.findActualAction();
- presentation.setEnabled(action != null && action.isEnabled());
- presentation.setVisible(false);
+ public void actionPerformed(AnActionEvent event) {
+ ExecutionEnvironment environment = getEnvironment(event);
+ if (environment != null) {
+ ExecutionUtil.restart(environment);
+ return;
+ }
+
+ FakeRerunAction action = findActualAction(event);
+ if (action != null && action.isEnabled(event)) {
+ action.actionPerformed(event);
+ }
+ }
+
+ @Nullable
+ protected RunContentDescriptor getDescriptor(AnActionEvent event) {
+ return event.getData(LangDataKeys.RUN_CONTENT_DESCRIPTOR);
+ }
+
+ @Nullable
+ protected ExecutionEnvironment getEnvironment(AnActionEvent event) {
+ return event.getData(LangDataKeys.EXECUTION_ENVIRONMENT);
+ }
+
+ protected boolean isEnabled(AnActionEvent event) {
+ RunContentDescriptor descriptor = getDescriptor(event);
+ ProcessHandler processHandler = descriptor == null ? null : descriptor.getProcessHandler();
+ ExecutionEnvironment environment = getEnvironment(event);
+ return environment != null &&
+ !ExecutorRegistry.getInstance().isStarting(environment) &&
+ !(processHandler != null && processHandler.isProcessTerminating());
+ }
+
+ @Nullable
+ private JComponent getRunComponent(@NotNull AnActionEvent event) {
+ RunContentDescriptor descriptor = getDescriptor(event);
+ return descriptor == null ? null : descriptor.getComponent();
+ }
+
+ @Nullable
+ private static FakeRerunAction findActualAction(@NotNull final AnActionEvent event) {
+ if (registry.isEmpty()) {
+ return null;
+ }
+
+ List<FakeRerunAction> candidates = new ArrayList<FakeRerunAction>(registry);
+ Collections.sort(candidates, new Comparator<FakeRerunAction>() {
+ @Override
+ public int compare(@NotNull FakeRerunAction action1, @NotNull FakeRerunAction action2) {
+ boolean isActive1 = action1.isEnabled(event);
+ if (isActive1 != action2.isEnabled(event)) {
+ return isActive1 ? -1 : 1;
+ }
+
+ JComponent component1 = action1.getRunComponent(event);
+ JComponent component2 = action2.getRunComponent(event);
+ Window window1 = component1 == null ? null : SwingUtilities.windowForComponent(component1);
+ Window window2 = component2 == null ? null : SwingUtilities.windowForComponent(component2);
+ if (window1 == null) {
+ return 1;
+ }
+ if (window2 == null) {
+ return -1;
+ }
+
+ boolean showing1 = component1.isShowing();
+ boolean showing2 = component2.isShowing();
+ if (showing1 && !showing2) {
+ return -1;
+ }
+ if (showing2 && !showing1) {
+ return 1;
+ }
+ return (window1.isActive() ? -1 : 1);
+ }
+ });
+ return candidates.get(0);
}
}
diff --git a/platform/lang-impl/src/com/intellij/execution/runners/RerunTestsAction.java b/platform/lang-impl/src/com/intellij/execution/runners/RerunTestsAction.java
index c4e8fd0a3e0d..8d3bf8663598 100644
--- a/platform/lang-impl/src/com/intellij/execution/runners/RerunTestsAction.java
+++ b/platform/lang-impl/src/com/intellij/execution/runners/RerunTestsAction.java
@@ -1,13 +1,11 @@
package com.intellij.execution.runners;
-import com.intellij.execution.ExecutionManager;
-import com.intellij.execution.ExecutorRegistry;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.openapi.Disposable;
-import com.intellij.openapi.actionSystem.*;
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.project.DumbAwareAction;
-import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
@@ -25,41 +23,27 @@ import java.util.List;
* @author Sergey Simonchik
*/
public class RerunTestsAction extends DumbAwareAction implements AnAction.TransparentUpdate {
-
public static final String ID = "RerunTests";
- private static final List<RerunInfo> REGISTRY = ContainerUtil.createLockFreeCopyOnWriteList();
+ private static final List<ExecutionEnvironment> REGISTRY = ContainerUtil.createLockFreeCopyOnWriteList();
- public static void register(@NotNull RunContentDescriptor descriptor,
- @NotNull ExecutionEnvironment env,
- @NotNull ProgramRunner runner) {
- final RerunInfo rerunInfo = new RerunInfo(descriptor, env, runner);
- REGISTRY.add(rerunInfo);
- Disposer.register(descriptor, new Disposable() {
+ public static void register(@NotNull final ExecutionEnvironment environment) {
+ REGISTRY.add(environment);
+ Disposer.register(environment, new Disposable() {
@Override
public void dispose() {
- REGISTRY.remove(rerunInfo);
+ REGISTRY.remove(environment);
}
});
}
@Override
public void actionPerformed(AnActionEvent e) {
- DataContext dataContext = e.getDataContext();
- Project project = CommonDataKeys.PROJECT.getData(dataContext);
- if (project == null) {
- return;
- }
- ExecutionManager executionManager = ExecutionManager.getInstance(project);
- for (RerunInfo rerunInfo : REGISTRY) {
- RunContentDescriptor descriptor = rerunInfo.getDescriptor();
- if (!Disposer.isDisposed(descriptor)) {
- ExecutionEnvironment env = rerunInfo.getEnv();
- ProgramRunner runner = rerunInfo.getRunner();
- ProcessHandler processHandler = descriptor.getProcessHandler();
+ for (ExecutionEnvironment environment : REGISTRY) {
+ if (!Disposer.isDisposed(environment)) {
+ RunContentDescriptor descriptor = environment.getContentToReuse();
+ ProcessHandler processHandler = descriptor == null ? null : descriptor.getProcessHandler();
if (processHandler != null && processHandler.isProcessTerminated()) {
- if (!ExecutorRegistry.getInstance().isStarting(project, env.getExecutor().getId(), runner.getRunnerId())) {
- executionManager.restartRunProfile(runner, env, descriptor);
- }
+ ExecutionUtil.restart(environment);
}
}
}
@@ -67,35 +51,6 @@ public class RerunTestsAction extends DumbAwareAction implements AnAction.Transp
@Override
public void update(AnActionEvent e) {
- Presentation presentation = e.getPresentation();
- presentation.setEnabled(true);
- }
-
- private static class RerunInfo {
-
- private final RunContentDescriptor myDescriptor;
- private final ExecutionEnvironment myEnv;
- private final ProgramRunner myRunner;
-
- public RerunInfo(@NotNull RunContentDescriptor descriptor,
- @NotNull ExecutionEnvironment env,
- @NotNull ProgramRunner runner) {
- myDescriptor = descriptor;
- myEnv = env;
- myRunner = runner;
- }
-
- private RunContentDescriptor getDescriptor() {
- return myDescriptor;
- }
-
- private ExecutionEnvironment getEnv() {
- return myEnv;
- }
-
- private ProgramRunner getRunner() {
- return myRunner;
- }
+ e.getPresentation().setEnabled(true);
}
-
}
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 20b29c2de994..1ab3cee3c8cb 100644
--- a/platform/lang-impl/src/com/intellij/execution/runners/RestartAction.java
+++ b/platform/lang-impl/src/com/intellij/execution/runners/RestartAction.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,129 +15,69 @@
*/
package com.intellij.execution.runners;
-import com.intellij.execution.ExecutionBundle;
-import com.intellij.execution.ExecutionManager;
import com.intellij.execution.Executor;
-import com.intellij.execution.ExecutorRegistry;
-import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.ui.RunContentDescriptor;
-import com.intellij.icons.AllIcons;
import com.intellij.openapi.Disposable;
-import com.intellij.openapi.actionSystem.*;
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.actionSystem.CustomShortcutSet;
+import com.intellij.openapi.actionSystem.IdeActions;
import com.intellij.openapi.keymap.KeymapManager;
import com.intellij.openapi.project.DumbAware;
-import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
-import java.awt.*;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
+@Deprecated
/**
- * @author dyoma
+ * to remove in IDEA 15
*/
public class RestartAction extends FakeRerunAction implements DumbAware, AnAction.TransparentUpdate, Disposable {
-
- private final ProgramRunner myRunner;
- @NotNull private final RunContentDescriptor myDescriptor;
- @NotNull private final Executor myExecutor;
+ private final RunContentDescriptor myDescriptor;
private final ExecutionEnvironment myEnvironment;
- public RestartAction(@NotNull final Executor executor,
- final ProgramRunner runner,
- @NotNull final RunContentDescriptor descriptor,
- @NotNull final ExecutionEnvironment env) {
+ public RestartAction(@NotNull RunContentDescriptor descriptor, @NotNull ExecutionEnvironment environment) {
+ //noinspection deprecation
+ this(environment.getExecutor(), null, descriptor, environment);
+ }
+
+ @Deprecated
+ /**
+ * @deprecated environment must provide runner id
+ * to remove in IDEA 15
+ */
+ public RestartAction(@SuppressWarnings("UnusedParameters") @NotNull Executor executor,
+ @Nullable ProgramRunner runner,
+ @NotNull RunContentDescriptor descriptor,
+ @NotNull ExecutionEnvironment environment) {
Disposer.register(descriptor, this);
- registry.add(this);
+ FakeRerunAction.registry.add(this);
- myEnvironment = env;
+ myEnvironment = runner == null ? environment : RunContentBuilder.fix(environment, runner);
getTemplatePresentation().setEnabled(false);
- myRunner = runner;
myDescriptor = descriptor;
- myExecutor = executor;
- // see IDEADEV-698
-
- if (descriptor.getRestarter() == null) {
- descriptor.setRestarter(new Runnable() {
- @Override
- public void run() {
- restart();
- }
- });
- }
}
@Override
public void dispose() {
- registry.remove(this);
- }
-
- @Nullable
- static RestartAction findActualAction() {
- if (registry.isEmpty())
- return null;
- List<RestartAction> candidates = new ArrayList<RestartAction>(registry);
- Collections.sort(candidates, new Comparator<RestartAction>() {
- @Override
- public int compare(RestartAction action1, RestartAction action2) {
- boolean isActive1 = action1.isEnabled();
- boolean isActive2 = action2.isEnabled();
- if (isActive1 != isActive2)
- return isActive1? - 1 : 1;
- Window window1 = SwingUtilities.windowForComponent(action1.myDescriptor.getComponent());
- Window window2 = SwingUtilities.windowForComponent(action2.myDescriptor.getComponent());
- if (window1 == null)
- return 1;
- if (window2 == null)
- return -1;
- boolean showing1 = action1.myDescriptor.getComponent().isShowing();
- boolean showing2 = action2.myDescriptor.getComponent().isShowing();
- if (showing1 && !showing2)
- return -1;
- if (showing2 && !showing1)
- return 1;
- return (window1.isActive() ? -1 : 1);
- }
- });
- return candidates.get(0);
+ FakeRerunAction.registry.remove(this);
}
@Override
- public void actionPerformed(final AnActionEvent e) {
- restart();
- }
-
- public void restart() {
- Project project = myEnvironment.getProject();
- if (!ExecutorRegistry.getInstance().isStarting(project, myExecutor.getId(), myRunner.getRunnerId()))
- ExecutionManager.getInstance(project).restartRunProfile(myRunner, myEnvironment, myDescriptor);
+ @NotNull
+ protected RunContentDescriptor getDescriptor(AnActionEvent event) {
+ return myDescriptor;
}
@Override
- public void update(final AnActionEvent event) {
- final Presentation presentation = event.getPresentation();
- String name = myEnvironment.getRunProfile().getName();
- ProcessHandler processHandler = myDescriptor.getProcessHandler();
- final boolean isRunning = processHandler != null && !processHandler.isProcessTerminated();
-
- presentation.setText(ExecutionBundle.message("rerun.configuration.action.name", name));
- presentation.setIcon(isRunning ? AllIcons.Actions.Restart : myExecutor.getIcon());
- presentation.setEnabled(isEnabled());
- }
-
- boolean isEnabled() {
- ProcessHandler processHandler = myDescriptor.getProcessHandler();
- boolean isTerminating = processHandler != null && processHandler.isProcessTerminating();
- boolean isStarting = ExecutorRegistry.getInstance().isStarting(myEnvironment.getProject(), myExecutor.getId(), myRunner.getRunnerId());
- return !isStarting && !isTerminating;
+ @NotNull
+ protected ExecutionEnvironment getEnvironment(AnActionEvent event) {
+ return myEnvironment;
}
- public void registerShortcut(final JComponent component) {
+ public void registerShortcut(JComponent component) {
registerCustomShortcutSet(new CustomShortcutSet(KeymapManager.getInstance().getActiveKeymap().getShortcuts(IdeActions.ACTION_RERUN)),
component);
}
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 bb6d206f1eb9..f16f8dadfb45 100644
--- a/platform/lang-impl/src/com/intellij/execution/runners/RunContentBuilder.java
+++ b/platform/lang-impl/src/com/intellij/execution/runners/RunContentBuilder.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,9 +15,6 @@
*/
package com.intellij.execution.runners;
-import com.intellij.diagnostic.logging.LogConsoleManagerBase;
-import com.intellij.diagnostic.logging.LogFilesManager;
-import com.intellij.diagnostic.logging.OutputFileUtil;
import com.intellij.execution.DefaultExecutionResult;
import com.intellij.execution.ExecutionManager;
import com.intellij.execution.ExecutionResult;
@@ -32,7 +29,6 @@ import com.intellij.execution.ui.actions.CloseAction;
import com.intellij.execution.ui.layout.PlaceInGrid;
import com.intellij.icons.AllIcons;
import com.intellij.ide.actions.ContextHelpAction;
-import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
@@ -40,115 +36,91 @@ import com.intellij.openapi.util.Disposer;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.ui.content.Content;
import com.intellij.ui.content.tabs.PinToolwindowTabAction;
+import com.intellij.util.SmartList;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import javax.swing.*;
-import java.util.ArrayList;
import java.util.Collection;
+import java.util.List;
-/**
- * @author dyoma
- */
-public class RunContentBuilder extends LogConsoleManagerBase {
+public class RunContentBuilder extends RunTab {
@NonNls private static final String JAVA_RUNNER = "JavaRunner";
- private final ProgramRunner myRunner;
- private final ArrayList<AnAction> myRunnerActions = new ArrayList<AnAction>();
- private ExecutionResult myExecutionResult;
-
- private final LogFilesManager myManager;
-
- private RunnerLayoutUi myUi;
- private final Executor myExecutor;
+ private final List<AnAction> myRunnerActions = new SmartList<AnAction>();
+ private final ExecutionResult myExecutionResult;
/**
- * @deprecated use {@link #RunContentBuilder(ProgramRunner, com.intellij.execution.ExecutionResult, ExecutionEnvironment)}
+ * @deprecated use {@link #RunContentBuilder(com.intellij.execution.ExecutionResult, ExecutionEnvironment)}
+ * to remove in IDEA 14
*/
+ @SuppressWarnings("UnusedParameters")
public RunContentBuilder(@NotNull Project project,
ProgramRunner runner,
Executor executor,
ExecutionResult executionResult,
@NotNull ExecutionEnvironment environment) {
+ //noinspection deprecation
this(runner, executionResult, environment);
}
+ /**
+ * @deprecated use {@link #RunContentBuilder(com.intellij.execution.ExecutionResult, ExecutionEnvironment)}
+ * to remove in IDEA 15
+ */
public RunContentBuilder(ProgramRunner runner,
ExecutionResult executionResult,
@NotNull ExecutionEnvironment environment) {
- super(environment.getProject(), SearchScopeProvider.createSearchScope(environment.getProject(), environment.getRunProfile()));
- myRunner = runner;
- myExecutor = environment.getExecutor();
- myManager = new LogFilesManager(environment.getProject(), this, this);
+ this(executionResult, fix(environment, runner));
+ }
+
+ public RunContentBuilder(@NotNull ExecutionResult executionResult, @NotNull ExecutionEnvironment environment) {
+ super(environment, getRunnerType(executionResult.getExecutionConsole()));
+
myExecutionResult = executionResult;
- setEnvironment(environment);
+ myUi.getOptions().setMoveToGridActionEnabled(false).setMinimizeActionEnabled(false);
}
- /**
- * @deprecated use {@link #RunContentBuilder(com.intellij.openapi.project.Project, ProgramRunner, com.intellij.execution.Executor, com.intellij.execution.ExecutionResult, ExecutionEnvironment)}
- */
- public RunContentBuilder(final Project project, final ProgramRunner runner, Executor executor) {
- super(project);
- myRunner = runner;
- myExecutor = executor;
- myManager = new LogFilesManager(project, this, this);
+ @NotNull
+ public static ExecutionEnvironment fix(@NotNull ExecutionEnvironment environment, @Nullable ProgramRunner runner) {
+ if (runner == null || runner.equals(environment.getRunner())) {
+ return environment;
+ }
+ else {
+ return new ExecutionEnvironmentBuilder(environment).runner(runner).build();
+ }
}
+ @SuppressWarnings("UnusedDeclaration")
@Deprecated
@NotNull
+ /**
+ * @deprecated to remove in IDEA 15
+ */
public static GlobalSearchScope createSearchScope(Project project, RunProfile runProfile) {
return SearchScopeProvider.createSearchScope(project, runProfile);
}
+ @NotNull
public ExecutionResult getExecutionResult() {
return myExecutionResult;
}
- @Deprecated
- public void setExecutionResult(final ExecutionResult executionResult) {
- myExecutionResult = executionResult;
- }
-
- @Override
- public void setEnvironment(@NotNull final ExecutionEnvironment env) {
- super.setEnvironment(env);
- final RunProfile profile = env.getRunProfile();
- if (profile instanceof RunConfigurationBase) {
- myManager.registerFileMatcher((RunConfigurationBase)profile);
- }
- }
-
public void addAction(@NotNull final AnAction action) {
myRunnerActions.add(action);
}
+ @NotNull
private RunContentDescriptor createDescriptor() {
- if (myExecutionResult == null) {
- throw new IllegalStateException("Missing ExecutionResult");
- }
-
- ExecutionEnvironment environment = getEnvironment();
- if (environment == null) {
- throw new IllegalStateException("Missing ExecutionEnvironment");
- }
-
- final RunProfile profile = environment.getRunProfile();
-
- final ExecutionConsole console = myExecutionResult.getExecutionConsole();
- String runnerType = JAVA_RUNNER;
- if (console instanceof ExecutionConsoleEx) {
- final String id = ((ExecutionConsoleEx)console).getExecutionConsoleId();
- if (id != null) {
- runnerType = JAVA_RUNNER + "." + id;
- }
- }
- myUi = RunnerLayoutUi.Factory.getInstance(getProject()).create(runnerType, myExecutor.getId(), profile.getName(), this);
- myUi.getOptions().setMoveToGridActionEnabled(false).setMinimizeActionEnabled(false);
-
+ final RunProfile profile = getEnvironment().getRunProfile();
if (ApplicationManager.getApplication().isUnitTestMode()) {
- return new MyRunContentDescriptor(profile, myExecutionResult, myUi.getComponent(), this);
+ RunContentDescriptor contentDescriptor = new RunContentDescriptor(profile, myExecutionResult, myUi);
+ Disposer.register(contentDescriptor, this);
+ return contentDescriptor;
}
+ final ExecutionConsole console = myExecutionResult.getExecutionConsole();
if (console != null) {
if (console instanceof ExecutionConsoleEx) {
((ExecutionConsoleEx)console).buildUi(myUi);
@@ -156,19 +128,17 @@ public class RunContentBuilder extends LogConsoleManagerBase {
else {
buildConsoleUiDefault(myUi, console);
}
- if (profile instanceof RunConfigurationBase) {
- myManager.initLogConsoles((RunConfigurationBase)profile, myExecutionResult.getProcessHandler());
- OutputFileUtil.attachDumpListener((RunConfigurationBase)profile, myExecutionResult.getProcessHandler(), console);
- }
+ initLogConsoles(profile, myExecutionResult.getProcessHandler(), console);
}
- MyRunContentDescriptor contentDescriptor = new MyRunContentDescriptor(profile, myExecutionResult, myUi.getComponent(), this);
- myUi.getOptions().setLeftToolbar(createActionToolbar(contentDescriptor, myUi.getComponent()), ActionPlaces.UNKNOWN);
+ RunContentDescriptor contentDescriptor = new RunContentDescriptor(profile, myExecutionResult, myUi);
+ Disposer.register(contentDescriptor, this);
+ myUi.getOptions().setLeftToolbar(createActionToolbar(contentDescriptor), ActionPlaces.UNKNOWN);
if (profile instanceof RunConfigurationBase) {
if (console instanceof ObservableConsoleView && !ApplicationManager.getApplication().isUnitTestMode()) {
((ObservableConsoleView)console).addChangeListener(new ConsoleToFrontListener((RunConfigurationBase)profile,
getProject(),
- myExecutor,
+ getEnvironment().getExecutor(),
contentDescriptor,
myUi),
this);
@@ -178,10 +148,22 @@ public class RunContentBuilder extends LogConsoleManagerBase {
return contentDescriptor;
}
+ @NotNull
+ private static String getRunnerType(@Nullable ExecutionConsole console) {
+ String runnerType = JAVA_RUNNER;
+ if (console instanceof ExecutionConsoleEx) {
+ String id = ((ExecutionConsoleEx)console).getExecutionConsoleId();
+ if (id != null) {
+ return JAVA_RUNNER + '.' + id;
+ }
+ }
+ return runnerType;
+ }
+
public static void buildConsoleUiDefault(RunnerLayoutUi ui, final ExecutionConsole console) {
final Content consoleContent = ui.createContent(ExecutionConsole.CONSOLE_CONTENT_ID, console.getComponent(), "Console",
AllIcons.Debugger.Console,
- console.getPreferredFocusableComponent());
+ console.getPreferredFocusableComponent());
consoleContent.setCloseable(false);
addAdditionalConsoleEditorActions(console, consoleContent);
@@ -191,22 +173,18 @@ public class RunContentBuilder extends LogConsoleManagerBase {
public static void addAdditionalConsoleEditorActions(final ExecutionConsole console, final Content consoleContent) {
final DefaultActionGroup consoleActions = new DefaultActionGroup();
if (console instanceof ConsoleView) {
- AnAction[] actions = ((ConsoleView)console).createConsoleActions();
- for (AnAction goaction: actions) {
- consoleActions.add(goaction);
+ for (AnAction action : ((ConsoleView)console).createConsoleActions()) {
+ consoleActions.add(action);
}
}
consoleContent.setActions(consoleActions, ActionPlaces.UNKNOWN, console.getComponent());
}
- private ActionGroup createActionToolbar(final RunContentDescriptor contentDescriptor, final JComponent component) {
+ @NotNull
+ private ActionGroup createActionToolbar(@NotNull RunContentDescriptor contentDescriptor) {
final DefaultActionGroup actionGroup = new DefaultActionGroup();
-
- final RestartAction restartAction = new RestartAction(myExecutor, myRunner, contentDescriptor, getEnvironment());
- restartAction.registerShortcut(component);
- actionGroup.add(restartAction);
-
+ actionGroup.add(ActionManager.getInstance().getAction(IdeActions.ACTION_RERUN));
if (myExecutionResult instanceof DefaultExecutionResult) {
final AnAction[] actions = ((DefaultExecutionResult)myExecutionResult).getRestartActions();
if (actions != null) {
@@ -217,15 +195,14 @@ public class RunContentBuilder extends LogConsoleManagerBase {
}
}
- final AnAction stopAction = ActionManager.getInstance().getAction(IdeActions.ACTION_STOP_PROGRAM);
- actionGroup.add(stopAction);
+ actionGroup.add(ActionManager.getInstance().getAction(IdeActions.ACTION_STOP_PROGRAM));
if (myExecutionResult instanceof DefaultExecutionResult) {
actionGroup.addAll(((DefaultExecutionResult)myExecutionResult).getAdditionalStopActions());
}
actionGroup.addAll(myExecutionResult.getActions());
- for (final AnAction anAction : myRunnerActions) {
+ for (AnAction anAction : myRunnerActions) {
if (anAction != null) {
actionGroup.add(anAction);
}
@@ -238,9 +215,9 @@ public class RunContentBuilder extends LogConsoleManagerBase {
actionGroup.add(myUi.getOptions().getLayoutActions());
actionGroup.addSeparator();
actionGroup.add(PinToolwindowTabAction.getPinAction());
- actionGroup.add(new CloseAction(myExecutor, contentDescriptor, getProject()));
+ actionGroup.add(new CloseAction(getEnvironment().getExecutor(), contentDescriptor, getProject()));
final String helpId = contentDescriptor.getHelpId();
- actionGroup.add(new ContextHelpAction(helpId != null ? helpId : myExecutor.getHelpId()));
+ actionGroup.add(new ContextHelpAction(helpId != null ? helpId : getEnvironment().getExecutor().getHelpId()));
return actionGroup;
}
@@ -252,14 +229,10 @@ public class RunContentBuilder extends LogConsoleManagerBase {
/**
* @param reuseContent see {@link RunContentDescriptor#myContent}
*/
- public RunContentDescriptor showRunContent(final RunContentDescriptor reuseContent) {
- final RunContentDescriptor descriptor = createDescriptor();
- if (reuseContent != null) {
- descriptor.setAttachedContent(reuseContent.getAttachedContent());
- if (reuseContent.isReuseToolWindowActivation()) {
- descriptor.setActivateToolWindowWhenAdded(reuseContent.isActivateToolWindowWhenAdded());
- }
- }
+ public RunContentDescriptor showRunContent(@Nullable RunContentDescriptor reuseContent) {
+ RunContentDescriptor descriptor = createDescriptor();
+ RunContentManagerImpl.copyContentAndBehavior(descriptor, reuseContent);
+ myRunContentDescriptor = descriptor;
return descriptor;
}
@@ -273,21 +246,6 @@ public class RunContentBuilder extends LogConsoleManagerBase {
return AllIcons.Debugger.Console;
}
- private static class MyRunContentDescriptor extends RunContentDescriptor {
- private final Disposable myAdditionalDisposable;
-
- public MyRunContentDescriptor(final RunProfile profile, final ExecutionResult executionResult, final JComponent component, @NotNull Disposable additionalDisposable) {
- super(executionResult.getExecutionConsole(), executionResult.getProcessHandler(), component, profile.getName(), profile.getIcon());
- myAdditionalDisposable = additionalDisposable;
- }
-
- @Override
- public void dispose() {
- Disposer.dispose(myAdditionalDisposable);
- super.dispose();
- }
- }
-
public static class ConsoleToFrontListener implements ConsoleViewImpl.ChangeListener {
@NotNull private final RunConfigurationBase myRunConfigurationBase;
@NotNull private final Project myProject;
diff --git a/platform/lang-impl/src/com/intellij/execution/runners/RunTab.java b/platform/lang-impl/src/com/intellij/execution/runners/RunTab.java
new file mode 100644
index 000000000000..2edc2098ce15
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/execution/runners/RunTab.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 com.intellij.execution.runners;
+
+import com.intellij.diagnostic.logging.LogConsoleManagerBase;
+import com.intellij.diagnostic.logging.LogFilesManager;
+import com.intellij.diagnostic.logging.OutputFileUtil;
+import com.intellij.execution.configurations.RunConfigurationBase;
+import com.intellij.execution.configurations.RunProfile;
+import com.intellij.execution.configurations.SearchScopeProvider;
+import com.intellij.execution.process.ProcessHandler;
+import com.intellij.execution.ui.ExecutionConsole;
+import com.intellij.execution.ui.RunContentDescriptor;
+import com.intellij.execution.ui.RunnerLayoutUi;
+import com.intellij.openapi.actionSystem.DataProvider;
+import com.intellij.openapi.actionSystem.LangDataKeys;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.search.GlobalSearchScope;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public abstract class RunTab extends LogConsoleManagerBase implements DataProvider {
+ @NotNull
+ protected final RunnerLayoutUi myUi;
+ protected final LogFilesManager myManager;
+ protected RunContentDescriptor myRunContentDescriptor;
+
+ protected RunTab(@NotNull ExecutionEnvironment environment, @NotNull String runnerType) {
+ this(environment.getProject(),
+ SearchScopeProvider.createSearchScope(environment.getProject(), environment.getRunProfile()),
+ runnerType,
+ environment.getExecutor().getId(),
+ environment.getRunProfile().getName());
+
+ setEnvironment(environment);
+ }
+
+ protected RunTab(@NotNull Project project, @NotNull GlobalSearchScope searchScope, @NotNull String runnerType, @NotNull String runnerTitle, @NotNull String sessionName) {
+ super(project, searchScope);
+
+ myManager = new LogFilesManager(project, this, this);
+
+ myUi = RunnerLayoutUi.Factory.getInstance(getProject()).create(runnerType, runnerTitle, sessionName, this);
+ myUi.getContentManager().addDataProvider(this);
+ }
+
+ @Nullable
+ @Override
+ public Object getData(@NonNls String dataId) {
+ if (LangDataKeys.RUN_PROFILE.is(dataId)) {
+ ExecutionEnvironment environment = getEnvironment();
+ return environment == null ? null : environment.getRunProfile();
+ }
+ else if (LangDataKeys.EXECUTION_ENVIRONMENT.is(dataId)) {
+ return getEnvironment();
+ }
+ else if (LangDataKeys.RUN_CONTENT_DESCRIPTOR.is(dataId)) {
+ return myRunContentDescriptor;
+ }
+ return null;
+ }
+
+ @Override
+ public final void setEnvironment(@NotNull ExecutionEnvironment environment) {
+ super.setEnvironment(environment);
+
+ RunProfile profile = environment.getRunProfile();
+ if (profile instanceof RunConfigurationBase) {
+ myManager.registerFileMatcher((RunConfigurationBase)profile);
+ }
+ }
+
+ protected final void initLogConsoles(@NotNull RunProfile runConfiguration, @Nullable ProcessHandler processHandler, @Nullable ExecutionConsole console) {
+ if (runConfiguration instanceof RunConfigurationBase && processHandler != null) {
+ RunConfigurationBase configuration = (RunConfigurationBase)runConfiguration;
+ myManager.initLogConsoles(configuration, processHandler);
+ OutputFileUtil.attachDumpListener(configuration, processHandler, console);
+ }
+ }
+}
diff --git a/platform/lang-impl/src/com/intellij/execution/ui/RunContentManagerImpl.java b/platform/lang-impl/src/com/intellij/execution/ui/RunContentManagerImpl.java
index 73ec463954cd..c9dae095522c 100644
--- a/platform/lang-impl/src/com/intellij/execution/ui/RunContentManagerImpl.java
+++ b/platform/lang-impl/src/com/intellij/execution/ui/RunContentManagerImpl.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.
@@ -46,12 +46,14 @@ import com.intellij.openapi.wm.ToolWindowAnchor;
import com.intellij.openapi.wm.ToolWindowManager;
import com.intellij.openapi.wm.ex.ToolWindowManagerAdapter;
import com.intellij.openapi.wm.ex.ToolWindowManagerEx;
+import com.intellij.ui.AppUIUtil;
import com.intellij.ui.content.*;
import com.intellij.ui.docking.DockManager;
+import com.intellij.util.SmartList;
import com.intellij.util.concurrency.Semaphore;
import com.intellij.util.containers.ContainerUtil;
-import com.intellij.util.containers.HashMap;
-import com.intellij.util.messages.Topic;
+import gnu.trove.THashMap;
+import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -59,60 +61,59 @@ import javax.swing.*;
import java.util.*;
public class RunContentManagerImpl implements RunContentManager, Disposable {
- public static final Topic<RunContentWithExecutorListener> RUN_CONTENT_TOPIC =
- Topic.create("Run Content", RunContentWithExecutorListener.class);
public static final Key<Boolean> ALWAYS_USE_DEFAULT_STOPPING_BEHAVIOUR_KEY = Key.create("ALWAYS_USE_DEFAULT_STOPPING_BEHAVIOUR_KEY");
- private static final Logger LOG = Logger.getInstance("#com.intellij.execution.ui.RunContentManagerImpl");
- private static final Key<RunContentDescriptor> DESCRIPTOR_KEY = new Key<RunContentDescriptor>("Descriptor");
+ private static final Logger LOG = Logger.getInstance(RunContentManagerImpl.class);
+ private static final Key<RunContentDescriptor> DESCRIPTOR_KEY = Key.create("Descriptor");
private final Project myProject;
- private DockableGridContainerFactory myContentFactory;
- private final Map<String, ContentManager> myToolwindowIdToContentManagerMap = new HashMap<String, ContentManager>();
+ private final Map<String, ContentManager> myToolwindowIdToContentManagerMap = new THashMap<String, ContentManager>();
- private final Map<RunContentListener, Disposable> myListeners = new HashMap<RunContentListener, Disposable>();
- private final LinkedList<String> myToolwindowIdZbuffer = new LinkedList<String>();
+ private final Map<RunContentListener, Disposable> myListeners = new THashMap<RunContentListener, Disposable>();
+ private final LinkedList<String> myToolwindowIdZBuffer = new LinkedList<String>();
- public RunContentManagerImpl(Project project, DockManager dockManager) {
+ public RunContentManagerImpl(@NotNull Project project, @NotNull DockManager dockManager) {
myProject = project;
- myContentFactory = new DockableGridContainerFactory();
- dockManager.register(DockableGridContainerFactory.TYPE, myContentFactory);
- Disposer.register(myProject, myContentFactory);
+ DockableGridContainerFactory containerFactory = new DockableGridContainerFactory();
+ dockManager.register(DockableGridContainerFactory.TYPE, containerFactory);
+ Disposer.register(myProject, containerFactory);
+
+ AppUIUtil.invokeOnEdt(new Runnable() {
+ @Override
+ public void run() {
+ init();
+ }
+ }, myProject.getDisposed());
}
- public void init() {
- final Executor[] executors = ExecutorRegistry.getInstance().getRegisteredExecutors();
- for (Executor executor : executors) {
- registerToolwindow(executor);
+ // must be called on EDT
+ private void init() {
+ ToolWindowManagerEx toolWindowManager = ToolWindowManagerEx.getInstanceEx(myProject);
+ if (toolWindowManager == null) {
+ return;
}
- if (ToolWindowManager.getInstance(myProject) == null) return;
+ for (Executor executor : ExecutorRegistry.getInstance().getRegisteredExecutors()) {
+ registerToolwindow(executor, toolWindowManager);
+ }
- // To ensure ToolwindowManager had already initialized in its projectOpened.
- SwingUtilities.invokeLater(new Runnable() {
+ toolWindowManager.addToolWindowManagerListener(new ToolWindowManagerAdapter() {
@Override
- public void run() {
- if (myProject.isDisposed()) return;
- ((ToolWindowManagerEx)ToolWindowManager.getInstance(myProject)).addToolWindowManagerListener(new ToolWindowManagerAdapter() {
- @Override
- public void stateChanged() {
- if (myProject.isDisposed()) return;
-
- ToolWindowManager toolWindowManager = ToolWindowManager.getInstance(myProject);
-
- Set<String> currentWindows = new HashSet<String>();
- String[] toolWindowIds = toolWindowManager.getToolWindowIds();
+ public void stateChanged() {
+ if (myProject.isDisposed()) {
+ return;
+ }
- ContainerUtil.addAll(currentWindows, toolWindowIds);
- myToolwindowIdZbuffer.retainAll(currentWindows);
+ ToolWindowManager toolWindowManager = ToolWindowManager.getInstance(myProject);
+ Set<String> currentWindows = new THashSet<String>();
+ ContainerUtil.addAll(currentWindows, toolWindowManager.getToolWindowIds());
+ myToolwindowIdZBuffer.retainAll(currentWindows);
- final String activeToolWindowId = toolWindowManager.getActiveToolWindowId();
- if (activeToolWindowId != null) {
- if (myToolwindowIdZbuffer.remove(activeToolWindowId)) {
- myToolwindowIdZbuffer.addFirst(activeToolWindowId);
- }
- }
+ final String activeToolWindowId = toolWindowManager.getActiveToolWindowId();
+ if (activeToolWindowId != null) {
+ if (myToolwindowIdZBuffer.remove(activeToolWindowId)) {
+ myToolwindowIdZBuffer.addFirst(activeToolWindowId);
}
- });
+ }
}
});
}
@@ -121,25 +122,15 @@ public class RunContentManagerImpl implements RunContentManager, Disposable {
public void dispose() {
}
- private void unregisterToolwindow(final String id) {
- final ContentManager manager = myToolwindowIdToContentManagerMap.get(id);
- manager.removeAllContents(true);
- myToolwindowIdToContentManagerMap.remove(id);
- myToolwindowIdZbuffer.remove(id);
- }
-
- private void registerToolwindow(@NotNull final Executor executor) {
+ private void registerToolwindow(@NotNull final Executor executor, @NotNull ToolWindowManagerEx toolWindowManager) {
final String toolWindowId = executor.getToolWindowId();
- final ToolWindowManager toolWindowManager = ToolWindowManager.getInstance(myProject);
- if (toolWindowManager == null) return; //headless environment
if (toolWindowManager.getToolWindow(toolWindowId) != null) {
return;
}
- final ToolWindow toolWindow = toolWindowManager.registerToolWindow(toolWindowId, true, ToolWindowAnchor.BOTTOM, this, true);
-
+ ToolWindow toolWindow = toolWindowManager.registerToolWindow(toolWindowId, true, ToolWindowAnchor.BOTTOM, this, true);
final ContentManager contentManager = toolWindow.getContentManager();
- class MyDataProvider implements DataProvider {
+ contentManager.addDataProvider(new DataProvider() {
private int myInsideGetData = 0;
@Override
@@ -157,31 +148,30 @@ public class RunContentManagerImpl implements RunContentManager, Disposable {
myInsideGetData--;
}
}
- }
- contentManager.addDataProvider(new MyDataProvider());
+ });
toolWindow.setIcon(executor.getToolWindowIcon());
new ContentManagerWatcher(toolWindow, contentManager);
contentManager.addContentManagerListener(new ContentManagerAdapter() {
@Override
public void selectionChanged(final ContentManagerEvent event) {
- final Content content = event.getContent();
- final RunContentDescriptor descriptor = content != null ? getRunContentDescriptorByContent(content) : null;
- getSyncPublisher().contentSelected(descriptor, executor);
+ Content content = event.getContent();
+ getSyncPublisher().contentSelected(content == null ? null : getRunContentDescriptorByContent(content), executor);
}
});
myToolwindowIdToContentManagerMap.put(toolWindowId, contentManager);
Disposer.register(contentManager, new Disposable() {
@Override
public void dispose() {
- unregisterToolwindow(toolWindowId);
+ myToolwindowIdToContentManagerMap.remove(toolWindowId).removeAllContents(true);
+ myToolwindowIdZBuffer.remove(toolWindowId);
}
});
- myToolwindowIdZbuffer.addLast(toolWindowId);
+ myToolwindowIdZBuffer.addLast(toolWindowId);
}
private RunContentWithExecutorListener getSyncPublisher() {
- return myProject.getMessageBus().syncPublisher(RUN_CONTENT_TOPIC);
+ return myProject.getMessageBus().syncPublisher(TOPIC);
}
@Override
@@ -193,24 +183,19 @@ public class RunContentManagerImpl implements RunContentManager, Disposable {
toFrontRunContent(requestor, descriptor);
}
-
@Override
public void toFrontRunContent(final Executor requestor, final RunContentDescriptor descriptor) {
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
- final ContentManager contentManager = getContentManagerForRunner(requestor);
-
- final Content content = getRunContentByDescriptor(contentManager, descriptor);
-
- if (contentManager != null && content != null) {
+ ContentManager contentManager = getContentManagerForRunner(requestor);
+ Content content = getRunContentByDescriptor(contentManager, descriptor);
+ if (content != null) {
contentManager.setSelectedContent(content);
-
- final ToolWindow toolWindow = ToolWindowManager.getInstance(myProject).getToolWindow(requestor.getToolWindowId());
- toolWindow.show(null);
+ ToolWindowManager.getInstance(myProject).getToolWindow(requestor.getToolWindowId()).show(null);
}
}
- });
+ }, myProject.getDisposed());
}
@Override
@@ -218,37 +203,25 @@ public class RunContentManagerImpl implements RunContentManager, Disposable {
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
- if (!myProject.isDisposed()) {
- final String toolWindowId = executor.getToolWindowId();
- final ToolWindow toolWindow = ToolWindowManager.getInstance(myProject).getToolWindow(toolWindowId);
- if (toolWindow != null) {
- toolWindow.hide(null);
- }
+ ToolWindow toolWindow = ToolWindowManager.getInstance(myProject).getToolWindow(executor.getToolWindowId());
+ if (toolWindow != null) {
+ toolWindow.hide(null);
}
}
- });
+ }, myProject.getDisposed());
}
@Override
@Nullable
public RunContentDescriptor getSelectedContent(final Executor executor) {
- final ContentManager contentManager = getContentManagerForRunner(executor);
- if (contentManager != null) {
- final Content selectedContent = contentManager.getSelectedContent();
- if (selectedContent != null) {
- final RunContentDescriptor runContentDescriptorByContent = getRunContentDescriptorByContent(selectedContent);
- if (runContentDescriptorByContent != null) {
- return runContentDescriptorByContent;
- }
- }
- }
- return null;
+ final Content selectedContent = getContentManagerForRunner(executor).getSelectedContent();
+ return selectedContent != null ? getRunContentDescriptorByContent(selectedContent) : null;
}
@Override
@Nullable
public RunContentDescriptor getSelectedContent() {
- for (String activeWindow : myToolwindowIdZbuffer) {
+ for (String activeWindow : myToolwindowIdZBuffer) {
final ContentManager contentManager = myToolwindowIdToContentManagerMap.get(activeWindow);
if (contentManager == null) {
continue;
@@ -280,32 +253,30 @@ public class RunContentManagerImpl implements RunContentManager, Disposable {
}
@Override
- public void showRunContent(@NotNull final Executor executor, final RunContentDescriptor descriptor) {
- showRunContent(executor, descriptor, descriptor != null ? descriptor.getExecutionId() : 0L);
+ public void showRunContent(@NotNull Executor executor, @NotNull RunContentDescriptor descriptor) {
+ showRunContent(executor, descriptor, descriptor.getExecutionId());
}
- public void showRunContent(@NotNull final Executor executor, final RunContentDescriptor descriptor, long executionId) {
- if (ApplicationManager.getApplication().isUnitTestMode()) return;
+ public void showRunContent(@NotNull final Executor executor, @NotNull final RunContentDescriptor descriptor, long executionId) {
+ if (ApplicationManager.getApplication().isUnitTestMode()) {
+ return;
+ }
final ContentManager contentManager = getContentManagerForRunner(executor);
- RunContentDescriptor oldDescriptor =
- chooseReuseContentForDescriptor(contentManager, descriptor, executionId, descriptor != null ? descriptor.getDisplayName() : null);
-
+ RunContentDescriptor oldDescriptor = chooseReuseContentForDescriptor(contentManager, descriptor, executionId, descriptor.getDisplayName());
final Content content;
-
- Content oldAttachedContent = oldDescriptor != null ? oldDescriptor.getAttachedContent() : null;
- if (oldDescriptor != null) {
- content = oldAttachedContent;
- getSyncPublisher().contentRemoved(oldDescriptor, executor);
- Disposer.dispose(oldDescriptor); // is of the same category, can be reused
- }
- else if (oldAttachedContent == null || !oldAttachedContent.isValid() /*|| oldAttachedContent.getUserData(MARKED_TO_BE_REUSED) != null */) {
+ if (oldDescriptor == null) {
content = createNewContent(contentManager, descriptor, executor);
- final Icon icon = descriptor.getIcon();
+ Icon icon = descriptor.getIcon();
content.setIcon(icon == null ? executor.getToolWindowIcon() : icon);
- } else {
- content = oldAttachedContent;
}
+ else {
+ content = oldDescriptor.getAttachedContent();
+ LOG.assertTrue(content != null);
+ getSyncPublisher().contentRemoved(oldDescriptor, executor);
+ Disposer.dispose(oldDescriptor); // is of the same category, can be reused
+ }
+
content.setExecutionId(executionId);
content.setComponent(descriptor.getComponent());
content.setPreferredFocusedComponent(descriptor.getPreferredFocusComputable());
@@ -353,10 +324,10 @@ public class RunContentManagerImpl implements RunContentManager, Disposable {
if (!descriptor.isActivateToolWindowWhenAdded()) {
return;
}
+
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
- if (myProject.isDisposed()) return;
ToolWindow window = ToolWindowManager.getInstance(myProject).getToolWindow(executor.getToolWindowId());
// let's activate tool window, but don't move focus
//
@@ -367,14 +338,17 @@ public class RunContentManagerImpl implements RunContentManager, Disposable {
descriptor.getPreferredFocusComputable();
window.activate(null, descriptor.isAutoFocusContent(), descriptor.isAutoFocusContent());
}
- });
+ }, myProject.getDisposed());
}
@Override
@Nullable
@Deprecated
public RunContentDescriptor getReuseContent(final Executor requestor, DataContext dataContext) {
- if (ApplicationManager.getApplication().isUnitTestMode()) return null;
+ if (ApplicationManager.getApplication().isUnitTestMode()) {
+ return null;
+ }
+ //noinspection deprecation
return getReuseContent(requestor, GenericProgramRunner.CONTENT_TO_REUSE_DATA_KEY.getData(dataContext));
}
@@ -382,11 +356,13 @@ public class RunContentManagerImpl implements RunContentManager, Disposable {
@Nullable
@Deprecated
public RunContentDescriptor getReuseContent(Executor requestor, @Nullable RunContentDescriptor contentToReuse) {
- if (ApplicationManager.getApplication().isUnitTestMode()) return null;
- if (contentToReuse != null) return contentToReuse;
-
- final ContentManager contentManager = getContentManagerForRunner(requestor);
- return chooseReuseContentForDescriptor(contentManager, contentToReuse, 0L, null);
+ if (ApplicationManager.getApplication().isUnitTestMode()) {
+ return null;
+ }
+ if (contentToReuse != null) {
+ return contentToReuse;
+ }
+ return chooseReuseContentForDescriptor(getContentManagerForRunner(requestor), null, 0L, null);
}
@Nullable
@@ -400,10 +376,12 @@ public class RunContentManagerImpl implements RunContentManager, Disposable {
public RunContentDescriptor getReuseContent(@NotNull ExecutionEnvironment executionEnvironment) {
if (ApplicationManager.getApplication().isUnitTestMode()) return null;
RunContentDescriptor contentToReuse = executionEnvironment.getContentToReuse();
- if (contentToReuse != null) return contentToReuse;
+ if (contentToReuse != null) {
+ return contentToReuse;
+ }
final ContentManager contentManager = getContentManagerForRunner(executionEnvironment.getExecutor());
- return chooseReuseContentForDescriptor(contentManager, contentToReuse, executionEnvironment.getExecutionId(),
+ return chooseReuseContentForDescriptor(contentManager, null, executionEnvironment.getExecutionId(),
executionEnvironment.toString());
}
@@ -413,14 +391,21 @@ public class RunContentManagerImpl implements RunContentManager, Disposable {
}
@Override
- public void showRunContent(@NotNull final Executor info, RunContentDescriptor descriptor, RunContentDescriptor contentToReuse) {
+ public void showRunContent(@NotNull Executor info, @NotNull RunContentDescriptor descriptor, @Nullable RunContentDescriptor contentToReuse) {
+ copyContentAndBehavior(descriptor, contentToReuse);
+ showRunContent(info, descriptor, descriptor.getExecutionId());
+ }
+
+ public static void copyContentAndBehavior(@NotNull RunContentDescriptor descriptor, @Nullable RunContentDescriptor contentToReuse) {
if (contentToReuse != null) {
- final Content attachedContent = contentToReuse.getAttachedContent();
- if (attachedContent.getManager() != null) {
+ Content attachedContent = contentToReuse.getAttachedContent();
+ if (attachedContent != null && attachedContent.isValid()) {
descriptor.setAttachedContent(attachedContent);
}
+ if (contentToReuse.isReuseToolWindowActivation()) {
+ descriptor.setActivateToolWindowWhenAdded(contentToReuse.isActivateToolWindowWhenAdded());
+ }
}
- showRunContent(info, descriptor, descriptor != null ? descriptor.getExecutionId(): 0L);
}
@Nullable
@@ -436,7 +421,9 @@ public class RunContentManagerImpl implements RunContentManager, Disposable {
}
//Stage two: try to get content from descriptor itself
final Content attachedContent = descriptor.getAttachedContent();
- if (attachedContent != null && attachedContent.isValid() && contentManager.getIndexOfContent(attachedContent) != -1) content = attachedContent;
+ if (attachedContent != null && attachedContent.isValid() && contentManager.getIndexOfContent(attachedContent) != -1) {
+ content = attachedContent;
+ }
}
//Stage three: choose the content with name we prefer
if (content == null) {
@@ -486,6 +473,7 @@ public class RunContentManagerImpl implements RunContentManager, Disposable {
if (contentManager == null) {
LOG.error("Runner " + executor.getId() + " is not registered");
}
+ //noinspection ConstantConditions
return contentManager;
}
@@ -499,26 +487,20 @@ public class RunContentManagerImpl implements RunContentManager, Disposable {
return content;
}
- private static boolean isTerminated(@NotNull final Content content) {
- final RunContentDescriptor descriptor = getRunContentDescriptorByContent(content);
- if (descriptor == null) {
- return true;
- }
- else {
- final ProcessHandler processHandler = descriptor.getProcessHandler();
- return processHandler == null || processHandler.isProcessTerminated();
- }
+ private static boolean isTerminated(@NotNull Content content) {
+ RunContentDescriptor descriptor = getRunContentDescriptorByContent(content);
+ ProcessHandler processHandler = descriptor == null ? null : descriptor.getProcessHandler();
+ return processHandler == null || processHandler.isProcessTerminated();
}
@Nullable
- public static RunContentDescriptor getRunContentDescriptorByContent(@NotNull final Content content) {
+ private static RunContentDescriptor getRunContentDescriptorByContent(@NotNull Content content) {
return content.getUserData(DESCRIPTOR_KEY);
}
-
@Override
@Nullable
- public ToolWindow getToolWindowByDescriptor(@NotNull final RunContentDescriptor descriptor) {
+ public ToolWindow getToolWindowByDescriptor(@NotNull RunContentDescriptor descriptor) {
for (Map.Entry<String, ContentManager> entry : myToolwindowIdToContentManagerMap.entrySet()) {
if (getRunContentByDescriptor(entry.getValue(), descriptor) != null) {
return ToolWindowManager.getInstance(myProject).getToolWindow(entry.getKey());
@@ -528,9 +510,8 @@ public class RunContentManagerImpl implements RunContentManager, Disposable {
}
@Nullable
- private static Content getRunContentByDescriptor(final ContentManager contentManager, final RunContentDescriptor descriptor) {
- final Content[] contents = contentManager.getContents();
- for (final Content content : contents) {
+ private static Content getRunContentByDescriptor(@NotNull ContentManager contentManager, @NotNull RunContentDescriptor descriptor) {
+ for (Content content : contentManager.getContents()) {
if (descriptor.equals(content.getUserData(DESCRIPTOR_KEY))) {
return content;
}
@@ -539,18 +520,18 @@ public class RunContentManagerImpl implements RunContentManager, Disposable {
}
@Override
- public void addRunContentListener(final RunContentListener listener, final Executor executor) {
+ public void addRunContentListener(@NotNull final RunContentListener listener, final Executor executor) {
final Disposable disposable = Disposer.newDisposable();
- myProject.getMessageBus().connect(disposable).subscribe(RUN_CONTENT_TOPIC, new RunContentWithExecutorListener() {
+ myProject.getMessageBus().connect(disposable).subscribe(TOPIC, new RunContentWithExecutorListener() {
@Override
- public void contentSelected(RunContentDescriptor descriptor, @NotNull Executor executor2) {
+ public void contentSelected(@Nullable RunContentDescriptor descriptor, @NotNull Executor executor2) {
if (executor2.equals(executor)) {
listener.contentSelected(descriptor);
}
}
@Override
- public void contentRemoved(RunContentDescriptor descriptor, @NotNull Executor executor2) {
+ public void contentRemoved(@Nullable RunContentDescriptor descriptor, @NotNull Executor executor2) {
if (executor2.equals(executor)) {
listener.contentRemoved(descriptor);
}
@@ -560,16 +541,16 @@ public class RunContentManagerImpl implements RunContentManager, Disposable {
}
@Override
- public void addRunContentListener(final RunContentListener listener) {
+ public void addRunContentListener(@NotNull final RunContentListener listener) {
final Disposable disposable = Disposer.newDisposable();
- myProject.getMessageBus().connect(disposable).subscribe(RUN_CONTENT_TOPIC, new RunContentWithExecutorListener() {
+ myProject.getMessageBus().connect(disposable).subscribe(TOPIC, new RunContentWithExecutorListener() {
@Override
- public void contentSelected(RunContentDescriptor descriptor, @NotNull Executor executor) {
+ public void contentSelected(@Nullable RunContentDescriptor descriptor, @NotNull Executor executor) {
listener.contentSelected(descriptor);
}
@Override
- public void contentRemoved(RunContentDescriptor descriptor, @NotNull Executor executor) {
+ public void contentRemoved(@Nullable RunContentDescriptor descriptor, @NotNull Executor executor) {
listener.contentRemoved(descriptor);
}
});
@@ -582,18 +563,16 @@ public class RunContentManagerImpl implements RunContentManager, Disposable {
if (myToolwindowIdToContentManagerMap.isEmpty()) {
return Collections.emptyList();
}
- final String[] ids = myToolwindowIdToContentManagerMap.keySet().toArray(new String[myToolwindowIdToContentManagerMap.size()]);
- final List<RunContentDescriptor> descriptors = new ArrayList<RunContentDescriptor>();
- for (String id : ids) {
- final ContentManager contentManager = myToolwindowIdToContentManagerMap.get(id);
- for (final Content content : contentManager.getContents()) {
- final RunContentDescriptor descriptor = getRunContentDescriptorByContent(content);
+
+ List<RunContentDescriptor> descriptors = new SmartList<RunContentDescriptor>();
+ for (String id : myToolwindowIdToContentManagerMap.keySet()) {
+ for (Content content : myToolwindowIdToContentManagerMap.get(id).getContents()) {
+ RunContentDescriptor descriptor = getRunContentDescriptorByContent(content);
if (descriptor != null) {
descriptors.add(descriptor);
}
}
}
-
return descriptors;
}
@@ -607,10 +586,9 @@ public class RunContentManagerImpl implements RunContentManager, Disposable {
@Nullable
private RunContentDescriptor getDescriptorBy(ProcessHandler handler, Executor runnerInfo) {
- ContentManager contentManager = getContentManagerForRunner(runnerInfo);
- Content[] contents = contentManager.getContents();
- for (Content content : contents) {
- RunContentDescriptor runContentDescriptor = content.getUserData(DESCRIPTOR_KEY);
+ for (Content content : getContentManagerForRunner(runnerInfo).getContents()) {
+ RunContentDescriptor runContentDescriptor = getRunContentDescriptorByContent(content);
+ assert runContentDescriptor != null;
if (runContentDescriptor.getProcessHandler() == handler) {
return runContentDescriptor;
}
@@ -642,12 +620,11 @@ public class RunContentManagerImpl implements RunContentManager, Disposable {
final Content content = myContent;
try {
- final RunContentDescriptor descriptor = getRunContentDescriptorByContent(content);
-
+ RunContentDescriptor descriptor = getRunContentDescriptorByContent(content);
getSyncPublisher().contentRemoved(descriptor, myExecutor);
-
- if (descriptor != null)
+ if (descriptor != null) {
Disposer.dispose(descriptor);
+ }
}
finally {
content.getManager().removeContentManagerListener(this);
@@ -699,7 +676,6 @@ public class RunContentManagerImpl implements RunContentManager, Disposable {
private boolean closeQuery(boolean modal) {
final RunContentDescriptor descriptor = getRunContentDescriptorByContent(myContent);
-
if (descriptor == null) {
return true;
}
@@ -709,6 +685,7 @@ public class RunContentManagerImpl implements RunContentManager, Disposable {
return true;
}
final boolean destroyProcess;
+ //noinspection deprecation
if (processHandler.isSilentlyDestroyOnClose() || Boolean.TRUE.equals(processHandler.getUserData(ProcessHandler.SILENTLY_DESTROY_ON_CLOSE))) {
destroyProcess = true;
}
@@ -786,7 +763,9 @@ public class RunContentManagerImpl implements RunContentManager, Disposable {
break;
}
try {
+ //noinspection SynchronizeOnThis
synchronized (this) {
+ //noinspection SynchronizeOnThis
wait(2000L);
}
}
diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/GridCellImpl.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/GridCellImpl.java
index b70d37a79e41..301cceee7e19 100644
--- a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/GridCellImpl.java
+++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/GridCellImpl.java
@@ -70,6 +70,7 @@ public class GridCellImpl implements GridCell {
myPlaceInGrid = placeInGrid;
myPlaceholder = placeholder;
myTabs = new JBTabsImpl(myContext.getProject(), myContext.getActionManager(), myContext.getFocusManager(), container) {
+ @SuppressWarnings("UseJBColor")
@Override
protected Color getFocusedTopFillColor() {
return UIUtil.isUnderDarcula() ? ColorUtil.toAlpha(new Color(0x1E2533), 100) : new Color(202, 211, 227);
@@ -88,11 +89,13 @@ public class GridCellImpl implements GridCell {
super.paintBorder(g2d, shape, borderColor);
}
+ @SuppressWarnings("UseJBColor")
@Override
protected Color getFocusedBottomFillColor() {
return UIUtil.isUnderDarcula() ? new Color(0x1E2533) : new Color(0xc2cbdb);
}
+ @SuppressWarnings("UseJBColor")
@Override
public Color getBackground() {
return UIUtil.isUnderDarcula() ? new Color(0x27292A) : super.getBackground();
@@ -239,8 +242,6 @@ public class GridCellImpl implements GridCell {
}
private TabInfo createTabInfoFor(Content content) {
- final JComponent c = content.getComponent();
-
final TabInfo tabInfo = updatePresentation(new TabInfo(new ProviderWrapper(content, myContext)), content)
.setObject(content)
.setPreferredFocusableComponent(content.getPreferredFocusableComponent())
@@ -257,7 +258,10 @@ public class GridCellImpl implements GridCell {
@Nullable
private static TabInfo updatePresentation(TabInfo info, Content content) {
- if (info == null) return info;
+ if (info == null) {
+ return null;
+ }
+
return info.
setIcon(content.getIcon()).
setText(content.getDisplayName()).
@@ -309,7 +313,6 @@ public class GridCellImpl implements GridCell {
}
private static class ProviderWrapper extends NonOpaquePanel implements DataProvider {
-
Content myContent;
ViewContext myContext;
diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/JBRunnerTabs.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/JBRunnerTabs.java
index 8ca416bd5427..d680e8a7e173 100644
--- a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/JBRunnerTabs.java
+++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/JBRunnerTabs.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.
@@ -43,7 +43,7 @@ import java.util.Map;
*/
public class
JBRunnerTabs extends JBTabsImpl {
- public JBRunnerTabs(@Nullable Project project, ActionManager actionManager, IdeFocusManager focusManager, @NotNull Disposable parent) {
+ public JBRunnerTabs(@Nullable Project project, @NotNull ActionManager actionManager, IdeFocusManager focusManager, @NotNull Disposable parent) {
super(project, actionManager, focusManager, parent);
}
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 821d9dbd6bc3..b8225b0c238b 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
@@ -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.
@@ -89,7 +89,7 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
private ContentManager myManager;
private final RunnerLayout myLayoutSettings;
- private final ActionManager myActionManager;
+ @NotNull private final ActionManager myActionManager;
private final String mySessionName;
private final MyComponent myComponent = new MyComponent();
@@ -99,7 +99,7 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
JBRunnerTabs myTabs;
private final Comparator<TabInfo> myTabsComparator = new Comparator<TabInfo>() {
@Override
- public int compare(final TabInfo o1, final TabInfo o2) {
+ public int compare(@NotNull final TabInfo o1, @NotNull final TabInfo o2) {
//noinspection ConstantConditions
TabImpl tab1 = getTabFor(o1);
TabImpl tab2 = getTabFor(o2);
@@ -132,7 +132,7 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
private final Map<String, LayoutAttractionPolicy> myConditionAttractions = new HashMap<String, LayoutAttractionPolicy>();
private ActionGroup myTabPopupActions;
- private ActionGroup myAdditonalFocusActions;
+ private ActionGroup myAdditionalFocusActions;
private final ActionCallback myInitialized = new ActionCallback();
private boolean myToDisposeRemovedContent = true;
@@ -149,7 +149,7 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
private final CopyOnWriteArraySet<Listener> myDockingListeners = new CopyOnWriteArraySet<Listener>();
private final Set<RunnerContentUi> myChildren = new TreeSet<RunnerContentUi>(new Comparator<RunnerContentUi>() {
@Override
- public int compare(RunnerContentUi o1, RunnerContentUi o2) {
+ public int compare(@NotNull RunnerContentUi o1, @NotNull RunnerContentUi o2) {
return o1.myWindow - o2.myWindow;
}
});
@@ -164,7 +164,7 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
@NotNull String sessionName) {
myProject = project;
myRunnerUi = ui;
- myLayoutSettings = settings;
+ myLayoutSettings = settings;
myActionManager = actionManager;
mySessionName = sessionName;
myFocusManager = focusManager;
@@ -190,7 +190,7 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
}
public void setAdditionalFocusActions(final ActionGroup group) {
- myAdditonalFocusActions = group;
+ myAdditionalFocusActions = group;
rebuildTabPopup();
}
@@ -269,7 +269,7 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
});
myTabs.addTabMouseListener(new MouseAdapter() {
@Override
- public void mousePressed(MouseEvent e) {
+ public void mousePressed(@NotNull MouseEvent e) {
if (UIUtil.isCloseClick(e)) {
final TabInfo tabInfo = myTabs.findInfo(e);
final GridImpl grid = tabInfo == null? null : getGridFor(tabInfo);
@@ -299,10 +299,11 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
}
private void rebuildTabPopup() {
+ initUi();
+
myTabs.setPopupGroup(getCellPopupGroup(TAB_POPUP_PLACE), TAB_POPUP_PLACE, true);
- final ArrayList<GridImpl> grids = getGrids();
- for (GridImpl each : grids) {
+ for (GridImpl each : getGrids()) {
each.rebuildTabPopup();
}
}
@@ -325,10 +326,9 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
for (AnAction eachFocus : focusActions) {
group.add(eachFocus);
}
- if (myAdditonalFocusActions != null) {
- final AnAction[] addins = myAdditonalFocusActions.getChildren(event);
- for (AnAction eachAddin : addins) {
- group.add(eachAddin);
+ if (myAdditionalFocusActions != null) {
+ for (AnAction action : myAdditionalFocusActions.getChildren(event)) {
+ group.add(action);
}
}
}
@@ -350,7 +350,7 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
}
@Override
- public void propertyChange(final PropertyChangeEvent evt) {
+ public void propertyChange(@NotNull final PropertyChangeEvent evt) {
Content content = (Content)evt.getSource();
final GridImpl grid = getGridFor(content, false);
if (grid == null) return;
@@ -436,8 +436,8 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
return new ActionCallback.Done();
}
- private void storeDefaultIndices(Content[] contents) {
- int i = 0;
+ private void storeDefaultIndices(@NotNull Content[] contents) {
+ //int i = 0;
for (Content content : contents) {
content.putUserData(RunnerLayout.DEFAULT_INDEX, getStateFor(content).getTab().getDefaultIndex());
//content.putUserData(CONTENT_NUMBER, i++);
@@ -637,8 +637,9 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
myManager.addContentManagerListener(new ContentManagerListener() {
@Override
public void contentAdded(final ContentManagerEvent event) {
- final GridImpl grid = getGridFor(event.getContent(), true);
+ initUi();
+ GridImpl grid = getGridFor(event.getContent(), true);
if (grid == null) {
return;
}
@@ -795,10 +796,12 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
private static void moveFollowingTabs(int index, final JBRunnerTabs tabs) {
for (TabInfo info : tabs.getTabs()) {
- final TabImpl tab = getTabFor(info);
- final int tabIndex = tab != null ? tab.getIndex() : -1;
- if (tabIndex >= index) {
- tab.setIndex(tabIndex + 1);
+ TabImpl tab = getTabFor(info);
+ if (tab != null) {
+ int tabIndex = tab.getIndex();
+ if (tabIndex >= index) {
+ tab.setIndex(tabIndex + 1);
+ }
}
}
}
@@ -1147,7 +1150,7 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
myOriginal = null;
myTopActions = null;
- myAdditonalFocusActions = null;
+ myAdditionalFocusActions = null;
myLeftToolbarActions = null;
}
@@ -1166,7 +1169,7 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
Content[] all = contents.toArray(new Content[contents.size()]);
Arrays.sort(all, new Comparator<Content>() {
@Override
- public int compare(Content content, Content content1) {
+ public int compare(@NotNull Content content, @NotNull Content content1) {
final int i = getStateFor(content).getTab().getDefaultIndex();
final int i1 = getStateFor(content1).getTab().getDefaultIndex();
return i - i1;
@@ -1222,6 +1225,7 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
myMinimizeActionEnabled = enabled;
}
+ @SuppressWarnings("SpellCheckingInspection")
public void setMovetoGridActionEnabled(final boolean enabled) {
myMoveToGridActionEnabled = enabled;
}
@@ -1271,7 +1275,6 @@ 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();
@@ -1293,7 +1296,7 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
private static class MyDropAreaPainter extends AbstractPainter {
private Shape myBoundingBox;
- private Color myColor = ColorUtil.mix(JBColor.BLUE, JBColor.WHITE, .3);
+ private final Color myColor = ColorUtil.mix(JBColor.BLUE, JBColor.WHITE, .3);
@Override
public boolean needsRepaint() {
@@ -1390,6 +1393,7 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
}
}
+ @SuppressWarnings("NullableProblems")
@Override
public String getName() {
return RunnerContentUi.this.getName();
@@ -1575,6 +1579,7 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
return myManager;
}
+ @NotNull
@Override
public ActionManager getActionManager() {
return myActionManager;
@@ -1617,7 +1622,7 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
}
@Override
- public void validate(final Content content, final ActiveRunnable toRestore) {
+ public void validate(Content content, final ActiveRunnable toRestore) {
final TabInfo current = myTabs.getSelectedInfo();
myTabs.getPresentation().setPaintBlocked(true, true);
@@ -1628,6 +1633,7 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
toRestore.run().doWhenDone(new Runnable() {
@Override
public void run() {
+ assert current != null;
myTabs.select(current, true);
myTabs.getPresentation().setPaintBlocked(false, true);
}
@@ -1654,7 +1660,7 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
}
@Override
- public Dimension preferredLayoutSize(final Container parent) {
+ public Dimension preferredLayoutSize(@NotNull final Container parent) {
Dimension size = new Dimension();
Dimension leftSize = myLeft.getPreferredSize();
@@ -1667,7 +1673,7 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
}
@Override
- public void layoutContainer(final Container parent) {
+ public void layoutContainer(@NotNull final Container parent) {
Dimension size = parent.getSize();
Dimension prefSize = parent.getPreferredSize();
if (prefSize.width <= size.width) {
@@ -1806,10 +1812,9 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
@Override
public void dragOutStarted(MouseEvent mouseEvent, TabInfo info) {
- final JComponent component = info.getComponent();
- final Content[] data = CONTENT_KEY.getData((DataProvider)component);
- final List<Content> contents = Arrays.asList(data);
-
+ JComponent component = info.getComponent();
+ Content[] data = CONTENT_KEY.getData((DataProvider)component);
+ assert data != null;
storeDefaultIndices(data);
final Dimension size = info.getComponent().getSize();
@@ -1822,7 +1827,7 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
presentation.setIcon(info.getIcon());
mySession = getDockManager().createDragSession(mouseEvent, new DockableGrid(image, presentation,
size,
- contents, 0));
+ Arrays.asList(data), 0));
}
@Override
diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerLayoutUiImpl.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerLayoutUiImpl.java
index 70d6a3f92819..7475adbcab21 100644
--- a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerLayoutUiImpl.java
+++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerLayoutUiImpl.java
@@ -21,7 +21,6 @@ import com.intellij.execution.ui.layout.LayoutAttractionPolicy;
import com.intellij.execution.ui.layout.LayoutStateDefaults;
import com.intellij.execution.ui.layout.LayoutViewOptions;
import com.intellij.execution.ui.layout.PlaceInGrid;
-import com.intellij.ide.DataManager;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.ActionGroup;
import com.intellij.openapi.actionSystem.ActionManager;
@@ -46,9 +45,8 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
-public class RunnerLayoutUiImpl implements Disposable.Parent, RunnerLayoutUi, LayoutStateDefaults, LayoutViewOptions {
+public class RunnerLayoutUiImpl implements Disposable.Parent, RunnerLayoutUi, LayoutStateDefaults, LayoutViewOptions, DataProvider {
private final RunnerLayout myLayout;
- private final JPanel myContentPanel;
private final RunnerContentUi myContentUI;
private final ContentManager myViewsContentManager;
@@ -63,14 +61,12 @@ public class RunnerLayoutUiImpl implements Disposable.Parent, RunnerLayoutUi, La
Disposer.register(parent, this);
myContentUI = new RunnerContentUi(project, this, ActionManager.getInstance(), IdeFocusManager.getInstance(project), myLayout,
- runnerTitle + " - " + sessionName);
+ runnerTitle + " - " + sessionName);
Disposer.register(this, myContentUI);
- myContentPanel = new MyContent();
myViewsContentManager = getContentFactory().createContentManager(myContentUI.getContentUI(), false, project);
+ myViewsContentManager.addDataProvider(this);
Disposer.register(this, myViewsContentManager);
-
- myContentPanel.add(myViewsContentManager.getComponent(), BorderLayout.CENTER);
}
@Override
@@ -80,7 +76,6 @@ public class RunnerLayoutUiImpl implements Disposable.Parent, RunnerLayoutUi, La
return this;
}
-
@NotNull
@Override
public LayoutStateDefaults initTabDefaults(int id, String text, Icon icon) {
@@ -156,7 +151,7 @@ public class RunnerLayoutUiImpl implements Disposable.Parent, RunnerLayoutUi, La
@Override
@NotNull
public JComponent getComponent() {
- return myContentPanel;
+ return myViewsContentManager.getComponent();
}
private static ContentFactory getContentFactory() {
@@ -380,28 +375,12 @@ public class RunnerLayoutUiImpl implements Disposable.Parent, RunnerLayoutUi, La
return contents;
}
- private class MyContent extends JPanel implements DataProvider {
- public MyContent() {
- super(new BorderLayout());
- }
-
- @Override
- public Object getData(@NonNls String dataId) {
- if (SwitchProvider.KEY.getName().equals(dataId)) {
- return myContentUI;
- }
-
- if (QuickActionProvider.KEY.getName().equals(dataId)) {
- return myContentUI;
- }
-
- if (RunnerContentUi.KEY.getName().equals(dataId)) {
- return myContentUI;
- }
-
- final DataProvider provider = DataManager.getDataProvider(this);
- return provider != null ? provider.getData(dataId) : null;
+ @Nullable
+ @Override
+ public Object getData(@NonNls String dataId) {
+ if (SwitchProvider.KEY.is(dataId) || QuickActionProvider.KEY.is(dataId) || RunnerContentUi.KEY.is(dataId)) {
+ return myContentUI;
}
+ return null;
}
-
}
diff --git a/platform/lang-impl/src/com/intellij/find/FindSettings.java b/platform/lang-impl/src/com/intellij/find/FindSettings.java
index d61fd395eadd..d8c6d73461a1 100644
--- a/platform/lang-impl/src/com/intellij/find/FindSettings.java
+++ b/platform/lang-impl/src/com/intellij/find/FindSettings.java
@@ -128,4 +128,7 @@ public abstract class FindSettings{
public abstract boolean isExceptCommentsAndLiterals();
public abstract void setExceptCommentsAndLiterals(boolean selected);
+
+ public abstract boolean isShowResultsInSeparateView();
+ public abstract void setShowResultsInSeparateView(boolean selected);
}
diff --git a/platform/lang-impl/src/com/intellij/find/actions/ShowUsagesTableCellRenderer.java b/platform/lang-impl/src/com/intellij/find/actions/ShowUsagesTableCellRenderer.java
index d9848fdec4b0..c4445c4ab5d2 100644
--- a/platform/lang-impl/src/com/intellij/find/actions/ShowUsagesTableCellRenderer.java
+++ b/platform/lang-impl/src/com/intellij/find/actions/ShowUsagesTableCellRenderer.java
@@ -77,7 +77,7 @@ class ShowUsagesTableCellRenderer implements TableCellRenderer {
textChunks.setBorder(null);
if (usage == null || usageNode instanceof ShowUsagesAction.StringNode) {
- textChunks.append(value.toString(), SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES);
+ textChunks.append(value != null ? value.toString() : "", SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES);
return textComponentSpanningWholeRow(textChunks, panelBackground, panelForeground, column, list, row);
}
if (usage == ShowUsagesAction.MORE_USAGES_SEPARATOR) {
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 d7f7665a9299..b78ce2c7ead7 100644
--- a/platform/lang-impl/src/com/intellij/find/findInProject/FindInProjectManager.java
+++ b/platform/lang-impl/src/com/intellij/find/findInProject/FindInProjectManager.java
@@ -40,7 +40,6 @@ import org.jetbrains.annotations.NotNull;
public class FindInProjectManager {
private final Project myProject;
- private boolean myToOpenInNewTab = false;
private volatile boolean myIsFindInProgress = false;
public static FindInProjectManager getInstance(Project project) {
@@ -60,12 +59,12 @@ public class FindInProjectManager {
isOpenInNewTabEnabled = false;
}
else {
- toOpenInNewTab[0] = myToOpenInNewTab;
+ toOpenInNewTab[0] = FindSettings.getInstance().isShowResultsInSeparateView();
isOpenInNewTabEnabled = UsageViewManager.getInstance(myProject).getReusableContentsCount() > 0;
}
final FindManager findManager = FindManager.getInstance(myProject);
- final FindModel findModel = (FindModel) findManager.getFindInProjectModel().clone();
+ final FindModel findModel = findManager.getFindInProjectModel().clone();
findModel.setReplaceState(false);
findModel.setOpenInNewTabVisible(true);
findModel.setOpenInNewTabEnabled(isOpenInNewTabEnabled);
@@ -86,7 +85,7 @@ public class FindInProjectManager {
public void run() {
findModel.setOpenInNewTabVisible(false);
if (isOpenInNewTabEnabled) {
- myToOpenInNewTab = toOpenInNewTab[0] = findModel.isOpenInNewTab();
+ FindSettings.getInstance().setShowResultsInSeparateView(toOpenInNewTab[0] = findModel.isOpenInNewTab());
}
startFindInProject(findModel);
@@ -107,8 +106,8 @@ public class FindInProjectManager {
if (manager == null) return;
final FindManager findManager = FindManager.getInstance(myProject);
findManager.getFindInProjectModel().copyFrom(findModel);
- final FindModel findModelCopy = (FindModel)findModel.clone();
- final UsageViewPresentation presentation = FindInProjectUtil.setupViewPresentation(myToOpenInNewTab, findModelCopy);
+ final FindModel findModelCopy = findModel.clone();
+ final UsageViewPresentation presentation = FindInProjectUtil.setupViewPresentation(FindSettings.getInstance().isShowResultsInSeparateView(), findModelCopy);
final boolean showPanelIfOnlyOneUsage = !FindSettings.getInstance().isSkipResultsWithOneUsage();
final FindUsagesProcessPresentation processPresentation = FindInProjectUtil.setupProcessPresentation(myProject, showPanelIfOnlyOneUsage, presentation);
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 c25456da1988..b268e455a67c 100644
--- a/platform/lang-impl/src/com/intellij/find/impl/FindDialog.java
+++ b/platform/lang-impl/src/com/intellij/find/impl/FindDialog.java
@@ -45,10 +45,7 @@ import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiFileFactory;
import com.intellij.psi.search.SearchScope;
-import com.intellij.ui.EditorComboBoxRenderer;
-import com.intellij.ui.EditorTextField;
-import com.intellij.ui.IdeBorderFactory;
-import com.intellij.ui.StateRestoringCheckBox;
+import com.intellij.ui.*;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Consumer;
import com.intellij.util.ui.UIUtil;
@@ -340,6 +337,9 @@ public class FindDialog extends DialogWrapper {
topOptionsPanel.setLayout(new GridLayout(1, 2, UIUtil.DEFAULT_HGAP, 0));
topOptionsPanel.add(createFindOptionsPanel());
optionsPanel.add(topOptionsPanel, gbConstraints);
+
+ JPanel resultsOptionPanel = null;
+
if (myModel.isMultipleFiles()) {
optionsPanel.add(createGlobalScopePanel(), gbConstraints);
gbConstraints.weightx = 1;
@@ -350,7 +350,9 @@ public class FindDialog extends DialogWrapper {
optionsPanel.add(createFilterPanel(),gbConstraints);
myCbToSkipResultsWhenOneUsage = createCheckbox(FindSettings.getInstance().isSkipResultsWithOneUsage(), FindBundle.message("find.options.skip.results.tab.with.one.occurrence.checkbox"));
- optionsPanel.add(myCbToSkipResultsWhenOneUsage, gbConstraints);
+ resultsOptionPanel = createResultsOptionPanel(optionsPanel, gbConstraints);
+ resultsOptionPanel.add(myCbToSkipResultsWhenOneUsage);
+
myCbToSkipResultsWhenOneUsage.setVisible(!myModel.isReplaceState());
}
else {
@@ -374,18 +376,26 @@ public class FindDialog extends DialogWrapper {
}
if (myModel.isOpenInNewTabVisible()){
- JPanel openInNewTabWindowPanel = new JPanel(new BorderLayout());
myCbToOpenInNewTab = new JCheckBox(FindBundle.message("find.open.in.new.tab.checkbox"));
myCbToOpenInNewTab.setFocusable(false);
myCbToOpenInNewTab.setSelected(myModel.isOpenInNewTab());
myCbToOpenInNewTab.setEnabled(myModel.isOpenInNewTabEnabled());
- openInNewTabWindowPanel.add(myCbToOpenInNewTab, BorderLayout.EAST);
- optionsPanel.add(openInNewTabWindowPanel, gbConstraints);
+
+ if (resultsOptionPanel == null) resultsOptionPanel = createResultsOptionPanel(optionsPanel, gbConstraints);
+ resultsOptionPanel.add(myCbToOpenInNewTab);
}
return optionsPanel;
}
+ private static JPanel createResultsOptionPanel(JPanel optionsPanel, GridBagConstraints gbConstraints) {
+ JPanel resultsOptionPanel = new JPanel();
+ resultsOptionPanel.setLayout(new BoxLayout(resultsOptionPanel, BoxLayout.Y_AXIS));
+
+ optionsPanel.add(new HideableTitledPanel(FindBundle.message("results.options.group"), resultsOptionPanel, false), gbConstraints);
+ return resultsOptionPanel;
+ }
+
@NotNull
private JComponent createFilterPanel() {
JPanel filterPanel = new JPanel();
@@ -615,9 +625,11 @@ public class FindDialog extends DialogWrapper {
JLabel searchContextLabel = new JLabel(FindBundle.message("find.context.combo.label"));
searchContextLabel.setLabelFor(mySearchContext);
- searchContextPanel.add(searchContextLabel, BorderLayout.WEST);
-
- searchContextPanel.add(mySearchContext, BorderLayout.CENTER);
+ JPanel panel = new JPanel();
+ panel.setAlignmentX(Component.LEFT_ALIGNMENT);
+ panel.add(searchContextLabel);
+ panel.add(mySearchContext);
+ searchContextPanel.add(panel, BorderLayout.WEST);
if (FindManagerImpl.ourHasSearchInCommentsAndLiterals) {
findOptionsPanel.add(searchContextPanel);
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 23f14c5eb0b4..db82791478f0 100644
--- a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java
+++ b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java
@@ -301,6 +301,7 @@ public class FindInProjectUtil {
}
presentation.setOpenInNewTab(toOpenInNewTab);
presentation.setCodeUsages(false);
+ presentation.setUsageTypeFilteringAvailable(true);
return presentation;
}
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 27e2b7215f25..b7d58e926e30 100644
--- a/platform/lang-impl/src/com/intellij/find/impl/FindManagerImpl.java
+++ b/platform/lang-impl/src/com/intellij/find/impl/FindManagerImpl.java
@@ -387,7 +387,8 @@ public class FindManagerImpl extends FindManager implements PersistentStateCompo
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;
+ // [e.key, e.value] intersect with [input.start, input.end]
+ if (e.getKey() <= input.getStartOffset() && (input.getStartOffset() <= e.getValue() || e.getValue() >= input.getEndOffset())) return false;
if (e.getValue() <= input.getStartOffset()) break;
}
return true;
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 c9c8e3492834..ffe3555ea059 100644
--- a/platform/lang-impl/src/com/intellij/find/impl/FindSettingsImpl.java
+++ b/platform/lang-impl/src/com/intellij/find/impl/FindSettingsImpl.java
@@ -110,6 +110,7 @@ public class FindSettingsImpl extends FindSettings implements PersistentStateCom
@SuppressWarnings({"WeakerAccess"}) public boolean REGULAR_EXPRESSIONS = false;
@SuppressWarnings({"WeakerAccess"}) public boolean LOCAL_REGULAR_EXPRESSIONS = false;
@SuppressWarnings({"WeakerAccess"}) public boolean WITH_SUBDIRECTORIES = true;
+ @SuppressWarnings({"WeakerAccess"}) public boolean SHOW_RESULTS_IN_SEPARATE_VIEW = false;
@SuppressWarnings({"WeakerAccess"}) public String SEARCH_SCOPE = DEFAULT_SEARCH_SCOPE;
@SuppressWarnings({"WeakerAccess"}) public String FILE_MASK;
@@ -409,6 +410,16 @@ public class FindSettingsImpl extends FindSettings implements PersistentStateCom
}
@Override
+ public boolean isShowResultsInSeparateView() {
+ return SHOW_RESULTS_IN_SEPARATE_VIEW;
+ }
+
+ @Override
+ public void setShowResultsInSeparateView(boolean optionValue) {
+ SHOW_RESULTS_IN_SEPARATE_VIEW = optionValue;
+ }
+
+ @Override
public boolean isExceptCommentsAndLiterals() {
return EXCEPT_COMMENTS_AND_STRING_LITERALS;
}
diff --git a/platform/lang-impl/src/com/intellij/formatting/FormatProcessor.java b/platform/lang-impl/src/com/intellij/formatting/FormatProcessor.java
index 7d3c7c649fd2..73358455bdcd 100644
--- a/platform/lang-impl/src/com/intellij/formatting/FormatProcessor.java
+++ b/platform/lang-impl/src/com/intellij/formatting/FormatProcessor.java
@@ -180,6 +180,7 @@ class FormatProcessor {
}
private int getRightMargin(Block rootBlock) {
+ Language language = null;
if (rootBlock instanceof ASTBlock) {
ASTNode node = ((ASTBlock)rootBlock).getNode();
if (node != null) {
@@ -187,12 +188,12 @@ class FormatProcessor {
if (psiElement.isValid()) {
PsiFile psiFile = psiElement.getContainingFile();
if (psiFile != null) {
- return mySettings.getRightMargin(psiFile.getViewProvider().getBaseLanguage());
+ language = psiFile.getViewProvider().getBaseLanguage();
}
}
}
}
- return mySettings.RIGHT_MARGIN;
+ return mySettings.getRightMargin(language);
}
private LeafBlockWrapper getLastBlock() {
diff --git a/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java b/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java
index 7b40b786ff7a..5b32caed587d 100644
--- a/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java
+++ b/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java
@@ -112,26 +112,27 @@ 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;
+ if (blockWithParent != null) {
+ Block parentBlock = blockWithParent.first;
+ Block targetBlock = blockWithParent.second;
+ if (parentBlock != null && targetBlock != null) {
+ Block prevBlock = findPreviousSibling(parentBlock, targetBlock);
+ if (prevBlock != null) {
+ SpacingImpl spacing = (SpacingImpl)parentBlock.getSpacing(prevBlock, targetBlock);
+ if (spacing != null) {
+ int minSpaces = spacing.getMinSpaces();
+ if (minSpaces > 0) {
+ return minSpaces;
+ }
+ }
+ }
+ }
}
- return Math.max(spacing.getMinSpaces(), 0);
+ return 0;
}
- private static Couple<Block> getBlockAtOffset(Block parent, Block block, int offset) {
+ @Nullable
+ private static Couple<Block> getBlockAtOffset(@Nullable Block parent, @NotNull Block block, int offset) {
TextRange textRange = block.getTextRange();
int startOffset = textRange.getStartOffset();
int endOffset = textRange.getEndOffset();
@@ -150,7 +151,8 @@ public class FormatterImpl extends FormatterEx
return null;
}
- private static Block findPreviousSibling(Block parent, Block block) {
+ @Nullable
+ private static Block findPreviousSibling(@NotNull Block parent, Block block) {
Block result = null;
for (Block subBlock : parent.getSubBlocks()) {
if (subBlock == block) {
@@ -568,6 +570,7 @@ public class FormatterImpl extends FormatterEx
final TextRange affectedRange) {
final FormattingDocumentModel documentModel = model.getDocumentModel();
final Block block = model.getRootBlock();
+ if (block.getTextRange().isEmpty()) return null; // handing empty document case
final FormatProcessor processor = buildProcessorAndWrapBlocks(
documentModel, block, settings, indentOptions, new FormatTextRanges(affectedRange, true), offset
);
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 d704e738efa3..bfd00da9107d 100644
--- a/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java
+++ b/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java
@@ -18,9 +18,11 @@ package com.intellij.ide.actions;
import com.intellij.codeInsight.navigation.NavigationUtil;
import com.intellij.execution.Executor;
import com.intellij.execution.ExecutorRegistry;
+import com.intellij.execution.RunnerAndConfigurationSettings;
import com.intellij.execution.actions.ChooseRunConfigurationPopup;
import com.intellij.execution.actions.ExecutorProvider;
import com.intellij.execution.executors.DefaultRunExecutor;
+import com.intellij.execution.impl.RunDialog;
import com.intellij.featureStatistics.FeatureUsageTracker;
import com.intellij.icons.AllIcons;
import com.intellij.ide.DataManager;
@@ -116,7 +118,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
* @author Konstantin Bulenkov
*/
@SuppressWarnings("FieldAccessedSynchronizedAndUnsynchronized")
-public class SearchEverywhereAction extends AnAction implements CustomComponentAction, DumbAware{
+public class SearchEverywhereAction extends AnAction implements CustomComponentAction, DumbAware, DataProvider, RightAlignedToolbarAction {
public static final String SE_HISTORY_KEY = "SearchEverywhereHistoryKey";
public static final int SEARCH_FIELD_COLUMNS = 25;
private static final int MAX_CLASSES = 6;
@@ -321,6 +323,12 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
}
+ @Nullable
+ @Override
+ public Object getData(@NonNls String dataId) {
+ return null;
+ }
+
private static String getShortcut() {
String shortcutText;
final Shortcut[] shortcuts = KeymapManager.getInstance().getActiveKeymap().getShortcuts(IdeActions.ACTION_SEARCH_EVERYWHERE);
@@ -673,6 +681,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
panel.add(myPopupField, BorderLayout.CENTER);
panel.add(topPanel, BorderLayout.NORTH);
panel.setBorder(IdeBorderFactory.createEmptyBorder(3, 5, 4, 5));
+ DataManager.registerDataProvider(panel, this);
final ComponentPopupBuilder builder = JBPopupFactory.getInstance().createComponentPopupBuilder(panel, editor);
myBalloon = builder
.setCancelOnClickOutside(true)
@@ -695,7 +704,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
});
Component parent = UIUtil.findUltimateParent(window);
- registerDataProvider(panel);
+ registerDataProvider(panel, e.getProject());
final RelativePoint showPoint;
if (me != null) {
final Component label = me.getComponent();
@@ -773,7 +782,12 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
storage.setValues(SE_HISTORY_KEY, newValues);
}
- private void registerDataProvider(JPanel panel) {
+ public Executor getExecutor() {
+ return ourShiftIsPressed.get() ? DefaultRunExecutor.getRunExecutorInstance()
+ : ExecutorRegistry.getInstance().getExecutorById(ToolWindowId.DEBUG);
+ }
+
+ private void registerDataProvider(JPanel panel, final Project project) {
DataManager.registerDataProvider(panel, new DataProvider() {
@Nullable
@Override
@@ -783,6 +797,29 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
return value;
} else if (CommonDataKeys.VIRTUAL_FILE.is(dataId) && value instanceof VirtualFile) {
return value;
+ } else if (CommonDataKeys.NAVIGATABLE.is(dataId)) {
+ if (value instanceof Navigatable) return value;
+ if (value instanceof ChooseRunConfigurationPopup.ItemWrapper) {
+ final Object config = ((ChooseRunConfigurationPopup.ItemWrapper)value).getValue();
+ if (config instanceof RunnerAndConfigurationSettings) {
+ return new Navigatable() {
+ @Override
+ public void navigate(boolean requestFocus) {
+ RunDialog.editConfiguration(project, (RunnerAndConfigurationSettings)config, "Edit Configuration", getExecutor());
+ }
+
+ @Override
+ public boolean canNavigate() {
+ return true;
+ }
+
+ @Override
+ public boolean canNavigateToSource() {
+ return true;
+ }
+ };
+ }
+ }
}
return null;
}
diff --git a/platform/lang-impl/src/com/intellij/ide/actions/SelectInAction.java b/platform/lang-impl/src/com/intellij/ide/actions/SelectInAction.java
index 7efdfb14249f..55d532106a56 100644
--- a/platform/lang-impl/src/com/intellij/ide/actions/SelectInAction.java
+++ b/platform/lang-impl/src/com/intellij/ide/actions/SelectInAction.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.
@@ -54,7 +54,7 @@ public class SelectInAction extends AnAction implements DumbAware {
}
}
- private static void invoke(DataContext dataContext, SelectInContext context) {
+ private static void invoke(@NotNull DataContext dataContext, @NotNull SelectInContext context) {
final List<SelectInTarget> targetVector = Arrays.asList(getSelectInManager(context.getProject()).getTargets());
ListPopup popup;
if (targetVector.isEmpty()) {
@@ -71,10 +71,10 @@ public class SelectInAction extends AnAction implements DumbAware {
}
private static class SelectInActionsStep extends BaseListPopupStep<SelectInTarget> {
- private final SelectInContext mySelectInContext;
+ @NotNull private final SelectInContext mySelectInContext;
private final List<SelectInTarget> myVisibleTargets;
- public SelectInActionsStep(@NotNull final Collection<SelectInTarget> targetVector, SelectInContext selectInContext) {
+ public SelectInActionsStep(@NotNull final Collection<SelectInTarget> targetVector, @NotNull SelectInContext selectInContext) {
mySelectInContext = selectInContext;
myVisibleTargets = new ArrayList<SelectInTarget>();
for (SelectInTarget target : targetVector) {
diff --git a/platform/lang-impl/src/com/intellij/ide/commander/CommanderPanel.java b/platform/lang-impl/src/com/intellij/ide/commander/CommanderPanel.java
index b5af4621705d..03a5a7fd806a 100644
--- a/platform/lang-impl/src/com/intellij/ide/commander/CommanderPanel.java
+++ b/platform/lang-impl/src/com/intellij/ide/commander/CommanderPanel.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.
@@ -607,6 +607,7 @@ public class CommanderPanel extends JPanel {
}
}
+ @NotNull
@Override
public PsiDirectory[] getDirectories() {
PsiDirectory directory = getDirectory();
diff --git a/platform/lang-impl/src/com/intellij/ide/favoritesTreeView/FavoritesProjectViewPane.java b/platform/lang-impl/src/com/intellij/ide/favoritesTreeView/FavoritesProjectViewPane.java
index c76416e5a4b1..df2a1bf83962 100644
--- a/platform/lang-impl/src/com/intellij/ide/favoritesTreeView/FavoritesProjectViewPane.java
+++ b/platform/lang-impl/src/com/intellij/ide/favoritesTreeView/FavoritesProjectViewPane.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.
@@ -131,6 +131,7 @@ public class FavoritesProjectViewPane extends AbstractProjectViewPane {
return subId;
}
+ @NotNull
@Override
public ActionCallback updateFromRoot(boolean restoreExpandedPaths) {
return ((FavoritesViewTreeBuilder)getTreeBuilder()).updateFromRootCB();
diff --git a/platform/lang-impl/src/com/intellij/ide/favoritesTreeView/FavoritesTreeViewPanel.java b/platform/lang-impl/src/com/intellij/ide/favoritesTreeView/FavoritesTreeViewPanel.java
index f97eb9e2a8df..4d72b483a39c 100644
--- a/platform/lang-impl/src/com/intellij/ide/favoritesTreeView/FavoritesTreeViewPanel.java
+++ b/platform/lang-impl/src/com/intellij/ide/favoritesTreeView/FavoritesTreeViewPanel.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.
@@ -777,6 +777,7 @@ public class FavoritesTreeViewPanel extends JPanel implements DataProvider, Dock
return selectedNodeElements[0] instanceof PsiDirectory ? new PsiDirectory[]{(PsiDirectory)selectedNodeElements[0]} : null;
}
+ @NotNull
@Override
public PsiDirectory[] getDirectories() {
final PsiDirectory[] directories = getSelectedDirectories();
diff --git a/platform/lang-impl/src/com/intellij/ide/impl/ProjectViewSelectInGroupTarget.java b/platform/lang-impl/src/com/intellij/ide/impl/ProjectViewSelectInGroupTarget.java
index 8b96157234d8..a0fb4f5d389d 100644
--- a/platform/lang-impl/src/com/intellij/ide/impl/ProjectViewSelectInGroupTarget.java
+++ b/platform/lang-impl/src/com/intellij/ide/impl/ProjectViewSelectInGroupTarget.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.
@@ -37,7 +37,7 @@ import java.util.LinkedHashSet;
public class ProjectViewSelectInGroupTarget implements CompositeSelectInTarget, DumbAware {
@Override
@NotNull
- public Collection<SelectInTarget> getSubTargets(SelectInContext context) {
+ public Collection<SelectInTarget> getSubTargets(@NotNull SelectInContext context) {
return ProjectView.getInstance(context.getProject()).getSelectInTargets();
}
diff --git a/platform/lang-impl/src/com/intellij/ide/impl/ProjectViewSelectInTarget.java b/platform/lang-impl/src/com/intellij/ide/impl/ProjectViewSelectInTarget.java
index 8902939c1de5..b510dc98bf1f 100644
--- a/platform/lang-impl/src/com/intellij/ide/impl/ProjectViewSelectInTarget.java
+++ b/platform/lang-impl/src/com/intellij/ide/impl/ProjectViewSelectInTarget.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.
@@ -55,12 +55,13 @@ public abstract class ProjectViewSelectInTarget extends SelectInTargetPsiWrapper
select(myProject, selector, getMinorViewId(), mySubId, virtualFile, requestFocus);
}
+ @NotNull
public static ActionCallback select(@NotNull Project project,
- final Object toSelect,
- @Nullable final String viewId,
- @Nullable final String subviewId,
- final VirtualFile virtualFile,
- final boolean requestFocus) {
+ final Object toSelect,
+ @Nullable final String viewId,
+ @Nullable final String subviewId,
+ final VirtualFile virtualFile,
+ final boolean requestFocus) {
final ActionCallback result = new ActionCallback();
@@ -86,7 +87,8 @@ public abstract class ProjectViewSelectInTarget extends SelectInTargetPsiWrapper
if (requestFocus) {
projectViewToolWindow.activate(runnable, false);
- } else {
+ }
+ else {
projectViewToolWindow.show(runnable);
}
@@ -96,7 +98,7 @@ public abstract class ProjectViewSelectInTarget extends SelectInTargetPsiWrapper
@Override
@NotNull
- public Collection<SelectInTarget> getSubTargets(SelectInContext context) {
+ public Collection<SelectInTarget> getSubTargets(@NotNull SelectInContext context) {
List<SelectInTarget> result = new ArrayList<SelectInTarget>();
AbstractProjectViewPane pane = ProjectView.getInstance(myProject).getProjectViewPaneById(getMinorViewId());
int index = 0;
diff --git a/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarIdeView.java b/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarIdeView.java
index 13ab984a7620..5a32f4d0531b 100644
--- a/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarIdeView.java
+++ b/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarIdeView.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.
@@ -22,6 +22,7 @@ import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.Navigatable;
import com.intellij.psi.*;
+import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
@@ -48,6 +49,7 @@ public final class NavBarIdeView implements IdeView {
myPanel.hideHint();
}
+ @NotNull
@Override
public PsiDirectory[] getDirectories() {
final PsiDirectory dir = myPanel.getSelectedElement(PsiDirectory.class);
diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/ProjectView.java b/platform/lang-impl/src/com/intellij/ide/projectView/ProjectView.java
index cad0cf728c9a..d82a7c0a9b4b 100644
--- a/platform/lang-impl/src/com/intellij/ide/projectView/ProjectView.java
+++ b/platform/lang-impl/src/com/intellij/ide/projectView/ProjectView.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.
@@ -23,6 +23,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.ActionCallback;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
@@ -34,14 +35,15 @@ public abstract class ProjectView {
public abstract void select(Object element, VirtualFile file, boolean requestFocus);
+ @NotNull
public abstract ActionCallback selectCB(Object element, VirtualFile file, boolean requestFocus);
@Nullable
public abstract PsiElement getParentOfCurrentSelection();
// show pane identified by id using default(or currently selected) subId
- public abstract void changeView(String viewId);
- public abstract void changeView(String viewId, String subId);
+ public abstract void changeView(@NotNull String viewId);
+ public abstract void changeView(@NotNull String viewId, String subId);
public abstract void changeView();
@@ -55,19 +57,19 @@ public abstract class ProjectView {
public abstract boolean isHideEmptyMiddlePackages(String paneId);
- public abstract void setHideEmptyPackages(boolean hideEmptyPackages, String paneId);
+ public abstract void setHideEmptyPackages(boolean hideEmptyPackages, @NotNull String paneId);
public abstract boolean isShowLibraryContents(String paneId);
- public abstract void setShowLibraryContents(boolean showLibraryContents, String paneId);
+ public abstract void setShowLibraryContents(boolean showLibraryContents, @NotNull String paneId);
public abstract boolean isShowModules(String paneId);
- public abstract void setShowModules(boolean showModules, String paneId);
+ public abstract void setShowModules(boolean showModules, @NotNull String paneId);
- public abstract void addProjectPane(final AbstractProjectViewPane pane);
+ public abstract void addProjectPane(@NotNull AbstractProjectViewPane pane);
- public abstract void removeProjectPane(AbstractProjectViewPane instance);
+ public abstract void removeProjectPane(@NotNull AbstractProjectViewPane pane);
public abstract AbstractProjectViewPane getProjectViewPaneById(String id);
@@ -75,7 +77,7 @@ public abstract class ProjectView {
public abstract boolean isAbbreviatePackageNames(String paneId);
- public abstract void setAbbreviatePackageNames(boolean abbreviatePackageNames, String paneId);
+ public abstract void setAbbreviatePackageNames(boolean abbreviatePackageNames, @NotNull String paneId);
/**
* e.g. {@link com.intellij.ide.projectView.impl.ProjectViewPane#ID}
@@ -86,11 +88,13 @@ public abstract class ProjectView {
public abstract void selectPsiElement(PsiElement element, boolean requestFocus);
public abstract boolean isSortByType(String paneId);
- public abstract void setSortByType(String paneId, final boolean sortByType);
+ public abstract void setSortByType(@NotNull String paneId, final boolean sortByType);
public abstract AbstractProjectViewPane getCurrentProjectViewPane();
+ @NotNull
public abstract Collection<String> getPaneIds();
+ @NotNull
public abstract Collection<SelectInTarget> getSelectInTargets();
}
diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/AbstractProjectViewPSIPane.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/AbstractProjectViewPSIPane.java
index d8bab8db9224..593d2576f370 100644
--- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/AbstractProjectViewPSIPane.java
+++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/AbstractProjectViewPSIPane.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.
@@ -156,6 +156,7 @@ public abstract class AbstractProjectViewPSIPane extends AbstractProjectViewPane
CustomizationUtil.installPopupHandler(myTree, IdeActions.GROUP_PROJECT_VIEW_POPUP, ActionPlaces.PROJECT_VIEW_POPUP);
}
+ @NotNull
@Override
public final ActionCallback updateFromRoot(boolean restoreExpandedPaths) {
final ArrayList<Object> pathsToExpand = new ArrayList<Object>();
@@ -190,6 +191,7 @@ public abstract class AbstractProjectViewPSIPane extends AbstractProjectViewPane
selectCB(element, file, requestFocus);
}
+ @NotNull
public ActionCallback selectCB(Object element, VirtualFile file, boolean requestFocus) {
if (file != null) {
return ((BaseProjectTreeBuilder)getTreeBuilder()).select(element, file, requestFocus);
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 c4708c48d19f..636824bd4896 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
@@ -204,9 +204,11 @@ public abstract class AbstractProjectViewPane implements DataProvider, Disposabl
myTreeStructure = null;
}
+ @NotNull
public abstract ActionCallback updateFromRoot(boolean restoreExpandedPaths);
public abstract void select(Object element, VirtualFile file, boolean requestFocus);
+
public void selectModule(final Module module, final boolean requestFocus) {
doSelectModuleOrGroup(module, requestFocus);
}
@@ -482,6 +484,7 @@ public abstract class AbstractProjectViewPane implements DataProvider, Disposabl
return myTree;
}
+ @NotNull
public PsiDirectory[] getSelectedDirectories() {
List<PsiDirectory> directories = ContainerUtil.newArrayList();
for (PsiDirectoryNode node : getSelectedNodes(PsiDirectoryNode.class)) {
@@ -541,6 +544,7 @@ public abstract class AbstractProjectViewPane implements DataProvider, Disposabl
return PsiDirectory.EMPTY_ARRAY;
}
+ @NotNull
protected PsiDirectory[] getSelectedDirectoriesInAmbiguousCase(@NotNull final DefaultMutableTreeNode node) {
final Object userObject = node.getUserObject();
if (userObject instanceof AbstractModuleNode) {
diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/FavoritesViewToolWindowFactory.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/FavoritesViewToolWindowFactory.java
index 17aa1b673f0c..451ae64b0bbb 100644
--- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/FavoritesViewToolWindowFactory.java
+++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/FavoritesViewToolWindowFactory.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.
@@ -24,13 +24,14 @@ import com.intellij.openapi.wm.ToolWindowFactory;
import com.intellij.openapi.wm.ex.ToolWindowEx;
import com.intellij.ui.content.Content;
import com.intellij.ui.content.ContentManager;
+import org.jetbrains.annotations.NotNull;
/**
* @author Konstantin Bulenkov
*/
public class FavoritesViewToolWindowFactory implements ToolWindowFactory, DumbAware {
@Override
- public void createToolWindowContent(Project project, ToolWindow toolWindow) {
+ public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindow toolWindow) {
if (toolWindow != null) {
final ContentManager contentManager = toolWindow.getContentManager();
final FavoritesTreeViewPanel panel = new FavoritesPanel(project).getPanel();
diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewImpl.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewImpl.java
index a8c7c0aa98a0..4172abdb1798 100644
--- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewImpl.java
+++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewImpl.java
@@ -40,7 +40,10 @@ import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
-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.components.StoragePathMacros;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.extensions.Extensions;
@@ -49,7 +52,7 @@ import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.TextEditor;
import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx;
import com.intellij.openapi.module.Module;
-import com.intellij.openapi.module.ModuleUtil;
+import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.*;
@@ -70,13 +73,15 @@ import com.intellij.openapi.wm.ex.ToolWindowManagerEx;
import com.intellij.openapi.wm.impl.content.ToolWindowContentUi;
import com.intellij.psi.*;
import com.intellij.psi.impl.file.PsiDirectoryFactory;
-import com.intellij.psi.util.PsiUtilBase;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.ui.AutoScrollFromSourceHandler;
import com.intellij.ui.AutoScrollToSourceHandler;
import com.intellij.ui.GuiUtils;
import com.intellij.ui.components.JBList;
-import com.intellij.ui.content.*;
+import com.intellij.ui.content.Content;
+import com.intellij.ui.content.ContentManager;
+import com.intellij.ui.content.ContentManagerAdapter;
+import com.intellij.ui.content.ContentManagerEvent;
import com.intellij.ui.switcher.QuickActionProvider;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IJSwingUtilities;
@@ -114,7 +119,7 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
private final CopyPasteDelegator myCopyPasteDelegator;
private boolean isInitialized;
private boolean myExtensionsLoaded = false;
- private final Project myProject;
+ @NotNull private final Project myProject;
// + options
private final Map<String, Boolean> myFlattenPackages = new THashMap<String, Boolean>();
@@ -134,7 +139,6 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
private final Map<String, Boolean> myAutoscrollToSource = new THashMap<String, Boolean>();
private final Map<String, Boolean> myAutoscrollFromSource = new THashMap<String, Boolean>();
private static final boolean ourAutoscrollFromSourceDefaults = false;
- private static final boolean ourShowStructureDefaults = false;
private String myCurrentViewId;
private String myCurrentViewSubId;
@@ -172,7 +176,6 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
@NonNls private static final String ELEMENT_AUTOSCROLL_TO_SOURCE = "autoscrollToSource";
@NonNls private static final String ELEMENT_AUTOSCROLL_FROM_SOURCE = "autoscrollFromSource";
@NonNls private static final String ELEMENT_SORT_BY_TYPE = "sortByType";
- @NonNls private static final String ELEMENT_FOLDERS_ALWAYS_ON_TOP = "foldersAlwaysOnTop";
private static final String ATTRIBUTE_ID = "id";
private JPanel myViewContentPanel;
@@ -191,7 +194,7 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
private ContentManager myContentManager;
private boolean myFoldersAlwaysOnTop = true;
- public ProjectViewImpl(Project project, final FileEditorManager fileEditorManager, final ToolWindowManagerEx toolWindowManager) {
+ public ProjectViewImpl(@NotNull Project project, final FileEditorManager fileEditorManager, final ToolWindowManagerEx toolWindowManager) {
myProject = project;
constructUi();
@@ -221,16 +224,16 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
}
};
myAutoScrollToSourceHandler = new AutoScrollToSourceHandler() {
- @Override
- protected boolean isAutoScrollMode() {
- return isAutoscrollToSource(myCurrentViewId);
- }
+ @Override
+ protected boolean isAutoScrollMode() {
+ return isAutoscrollToSource(myCurrentViewId);
+ }
- @Override
- protected void setAutoScrollMode(boolean state) {
- setAutoscrollToSource(state, myCurrentViewId);
- }
- };
+ @Override
+ protected void setAutoScrollMode(boolean state) {
+ setAutoscrollToSource(state, myCurrentViewId);
+ }
+ };
toolWindowManager.addToolWindowManagerListener(new ToolWindowManagerAdapter(){
private boolean toolWindowVisible;
@@ -268,16 +271,15 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
}
@Override
+ @NotNull
public List<AnAction> getActions(boolean originalProvider) {
ArrayList<AnAction> result = new ArrayList<AnAction>();
DefaultActionGroup views = new DefaultActionGroup("Change View", true);
- boolean lastWasHeader = false;
boolean lastHeaderHadKids = false;
for (int i = 0; i < myContentManager.getContentCount(); i++) {
Content each = myContentManager.getContent(i);
if (each != null) {
-
if (each.getUserData(SUB_ID_KEY) == null) {
if (lastHeaderHadKids) {
views.add(new Separator());
@@ -291,12 +293,11 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
}
}
}
- } else {
+ }
+ else {
lastHeaderHadKids = true;
}
- lastWasHeader = each.getUserData(SUB_ID_KEY) == null;
-
views.add(new ChangeViewAction(each.getUserData(ID_KEY), each.getUserData(SUB_ID_KEY)));
}
}
@@ -304,13 +305,14 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
result.add(new Separator());
- ArrayList<AnAction> secondary = new ArrayList<AnAction>();
+ List<AnAction> secondary = new ArrayList<AnAction>();
if (myActionGroup != null) {
AnAction[] kids = myActionGroup.getChildren(null);
for (AnAction each : kids) {
if (myActionGroup.isPrimary(each)) {
result.add(each);
- } else {
+ }
+ else {
secondary.add(each);
}
}
@@ -325,7 +327,7 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
private final String myId;
private final String mySubId;
- private ChangeViewAction(String id, String subId) {
+ private ChangeViewAction(@NotNull String id, String subId) {
myId = id;
mySubId = subId;
}
@@ -348,7 +350,7 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
}
@Override
- public synchronized void addProjectPane(final AbstractProjectViewPane pane) {
+ public synchronized void addProjectPane(@NotNull final AbstractProjectViewPane pane) {
myUninitializedPanes.add(pane);
SelectInTarget selectInTarget = pane.createSelectInTarget();
if (selectInTarget != null) {
@@ -360,7 +362,8 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
}
@Override
- public synchronized void removeProjectPane(AbstractProjectViewPane pane) {
+ public synchronized void removeProjectPane(@NotNull AbstractProjectViewPane pane) {
+ ApplicationManager.getApplication().assertIsDispatchThread();
myUninitializedPanes.remove(pane);
//assume we are completely initialized here
String idToRemove = pane.getId();
@@ -425,7 +428,8 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
myUninitializedPanes.clear();
}
- private void doAddPane(final AbstractProjectViewPane newPane) {
+ private void doAddPane(@NotNull final AbstractProjectViewPane newPane) {
+ ApplicationManager.getApplication().assertIsDispatchThread();
int index;
final ContentManager manager = myContentManager;
for (index = 0; index < manager.getContentCount(); index++) {
@@ -473,7 +477,7 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
Disposer.register(this, newPane);
}
- private void showPane(AbstractProjectViewPane newPane) {
+ private void showPane(@NotNull AbstractProjectViewPane newPane) {
AbstractProjectViewPane currentPane = getCurrentProjectViewPane();
PsiElement selectedPsiElement = null;
if (currentPane != null) {
@@ -550,30 +554,26 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
myActionGroup.remove(collapseAction);
}
}
- ((ToolWindowEx)window).setTitleActions(new AnAction[] {scrollAction, collapseAction});
+ ((ToolWindowEx)window).setTitleActions(scrollAction, collapseAction);
}
// public for tests
- public synchronized void setupImpl(final ToolWindow toolWindow) {
+ public synchronized void setupImpl(@NotNull ToolWindow toolWindow) {
setupImpl(toolWindow, true);
}
// public for tests
- public synchronized void setupImpl(final ToolWindow toolWindow, final boolean loadPaneExtensions) {
+ public synchronized void setupImpl(@NotNull ToolWindow toolWindow, final boolean loadPaneExtensions) {
+ ApplicationManager.getApplication().assertIsDispatchThread();
myActionGroup = new DefaultActionGroup();
myAutoScrollFromSourceHandler.install();
- if (toolWindow != null) {
- myContentManager = toolWindow.getContentManager();
- if (!ApplicationManager.getApplication().isUnitTestMode()) {
- toolWindow.setContentUiType(ToolWindowContentUiType.COMBO, null);
- ((ToolWindowEx)toolWindow).setAdditionalGearActions(myActionGroup);
- toolWindow.getComponent().putClientProperty(ToolWindowContentUi.HIDE_ID_LABEL, "true");
- }
- } else {
- final ContentFactory contentFactory = ServiceManager.getService(ContentFactory.class);
- myContentManager = contentFactory.createContentManager(false, myProject);
+ myContentManager = toolWindow.getContentManager();
+ if (!ApplicationManager.getApplication().isUnitTestMode()) {
+ toolWindow.setContentUiType(ToolWindowContentUiType.COMBO, null);
+ ((ToolWindowEx)toolWindow).setAdditionalGearActions(myActionGroup);
+ toolWindow.getComponent().putClientProperty(ToolWindowContentUi.HIDE_ID_LABEL, "true");
}
GuiUtils.replaceJSplitPaneWithIDEASplitter(myPanel);
@@ -655,11 +655,11 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
}
class FlattenPackagesDependableAction extends PaneOptionAction {
- FlattenPackagesDependableAction(Map<String, Boolean> optionsMap,
- final String text,
- final String description,
- final Icon icon,
- boolean optionDefaultValue) {
+ FlattenPackagesDependableAction(@NotNull Map<String, Boolean> optionsMap,
+ @NotNull String text,
+ @NotNull String description,
+ @NotNull Icon icon,
+ boolean optionDefaultValue) {
super(optionsMap, text, description, icon, optionDefaultValue);
}
@@ -782,15 +782,15 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
}
}
+ @NotNull
@Override
public ActionCallback selectCB(Object element, VirtualFile file, boolean requestFocus) {
final AbstractProjectViewPane viewPane = getCurrentProjectViewPane();
if (viewPane != null && viewPane instanceof AbstractProjectViewPSIPane) {
- return ((AbstractProjectViewPSIPane) viewPane).selectCB(element, file, requestFocus);
- } else {
- select(element, file, requestFocus);
- return new ActionCallback.Done();
+ return ((AbstractProjectViewPSIPane)viewPane).selectCB(element, file, requestFocus);
}
+ select(element, file, requestFocus);
+ return new ActionCallback.Done();
}
@Override
@@ -844,10 +844,10 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
private final Map<String, Boolean> myOptionsMap;
private final boolean myOptionDefaultValue;
- PaneOptionAction(Map<String, Boolean> optionsMap,
- final String text,
- final String description,
- final Icon icon,
+ PaneOptionAction(@NotNull Map<String, Boolean> optionsMap,
+ @NotNull String text,
+ @NotNull String description,
+ Icon icon,
boolean optionDefaultValue) {
super(text, description, icon);
myOptionsMap = optionsMap;
@@ -946,6 +946,7 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
}
}
+ @NotNull
private PsiElement[] getElementsToDelete() {
final AbstractProjectViewPane viewPane = getCurrentProjectViewPane();
PsiElement[] elements = viewPane.getSelectedPSIElements();
@@ -1038,7 +1039,7 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
if (virtualFiles == null || virtualFiles.length <= 1) return null;
final Set<Module> modules = new HashSet<Module>();
for (VirtualFile virtualFile : virtualFiles) {
- modules.add(ModuleUtil.findModuleForFile(virtualFile, myProject));
+ modules.add(ModuleUtilCore.findModuleForFile(virtualFile, myProject));
}
return modules.size() == 1 ? modules.iterator().next() : null;
}
@@ -1157,7 +1158,7 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
return null;
}
- private void detachLibrary(final LibraryOrderEntry orderEntry, final Project project) {
+ private void detachLibrary(@NotNull final LibraryOrderEntry orderEntry, @NotNull Project project) {
final Module module = orderEntry.getOwnerModule();
String message = IdeBundle.message("detach.library.from.module", orderEntry.getPresentableName(), module.getName());
String title = IdeBundle.message("detach.library");
@@ -1230,7 +1231,7 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
* otherwise VirtualFileArrayRule will return all module's content roots when just one of them is selected
*/
@Nullable
- private Module moduleBySingleContentRoot(VirtualFile file) {
+ private Module moduleBySingleContentRoot(@NotNull VirtualFile file) {
if (ProjectRootsUtil.isModuleContentRoot(file, myProject)) {
Module module = ProjectRootManager.getInstance(myProject).getFileIndex().getModuleForFile(file);
if (module != null && !module.isDisposed() && ModuleRootManager.getInstance(module).getContentRoots().length == 1) {
@@ -1241,8 +1242,9 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
return null;
}
- private <T> List<T> getSelectedElements(Class<T> klass) {
- ArrayList<T> result = new ArrayList<T>();
+ @NotNull
+ private <T> List<T> getSelectedElements(@NotNull Class<T> klass) {
+ List<T> result = new ArrayList<T>();
final AbstractProjectViewPane viewPane = getCurrentProjectViewPane();
if (viewPane == null) return result;
final Object[] elements = viewPane.getSelectedElements();
@@ -1276,6 +1278,7 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
}
}
+ @NotNull
@Override
public PsiDirectory[] getDirectories() {
final AbstractProjectViewPane viewPane = getCurrentProjectViewPane();
@@ -1295,12 +1298,12 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
@Override
public void selectPsiElement(PsiElement element, boolean requestFocus) {
if (element == null) return;
- VirtualFile virtualFile = PsiUtilBase.getVirtualFile(element);
+ VirtualFile virtualFile = PsiUtilCore.getVirtualFile(element);
select(element, virtualFile, requestFocus);
}
- private static void readOption(Element node, Map<String, Boolean> options) {
+ private static void readOption(Element node, @NotNull Map<String, Boolean> options) {
if (node == null) return;
List attributes = node.getAttributes();
for (final Object attribute1 : attributes) {
@@ -1309,7 +1312,7 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
}
}
- private static void writeOption(Element parentNode, Map<String, Boolean> optionsForPanes, String optionName) {
+ private static void writeOption(@NotNull Element parentNode, @NotNull Map<String, Boolean> optionsForPanes, @NotNull String optionName) {
Element e = new Element(optionName);
for (Map.Entry<String, Boolean> entry : optionsForPanes.entrySet()) {
final String key = entry.getKey();
@@ -1354,7 +1357,7 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
}
}
- private void readPaneState(Element panesElement) {
+ private void readPaneState(@NotNull Element panesElement) {
@SuppressWarnings({"unchecked"})
final List<Element> paneElements = panesElement.getChildren(ELEMENT_PANE);
@@ -1412,7 +1415,7 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
return parentNode;
}
- private void writePaneState(Element panesElement) {
+ private void writePaneState(@NotNull Element panesElement) {
for (AbstractProjectViewPane pane : myId2Pane.values()) {
Element paneElement = new Element(ELEMENT_PANE);
paneElement.setAttribute(ATTRIBUTE_ID, pane.getId());
@@ -1425,7 +1428,7 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
panesElement.addContent(paneElement);
}
for (Element element : myUninitializedPaneState.values()) {
- panesElement.addContent((Element) element.clone());
+ panesElement.addContent(element.clone());
}
}
@@ -1496,10 +1499,11 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
}
@Override
- public void setShowLibraryContents(boolean showLibraryContents, String paneId) {
+ public void setShowLibraryContents(boolean showLibraryContents, @NotNull String paneId) {
setPaneOption(myShowLibraryContents, showLibraryContents, paneId, true);
}
+ @NotNull
public ActionCallback setShowLibraryContentsCB(boolean showLibraryContents, String paneId) {
return setPaneOption(myShowLibraryContents, showLibraryContents, paneId, true);
}
@@ -1510,21 +1514,22 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
}
@Override
- public void setShowModules(boolean showModules, String paneId) {
+ public void setShowModules(boolean showModules, @NotNull String paneId) {
setPaneOption(myShowModules, showModules, paneId, true);
}
@Override
- public void setHideEmptyPackages(boolean hideEmptyPackages, String paneId) {
+ public void setHideEmptyPackages(boolean hideEmptyPackages, @NotNull String paneId) {
setPaneOption(myHideEmptyPackages, hideEmptyPackages, paneId, true);
}
@Override
- public void setAbbreviatePackageNames(boolean abbreviatePackageNames, String paneId) {
+ public void setAbbreviatePackageNames(boolean abbreviatePackageNames, @NotNull String paneId) {
setPaneOption(myAbbreviatePackageNames, abbreviatePackageNames, paneId, true);
}
- private ActionCallback setPaneOption(Map<String, Boolean> optionsMap, boolean value, String paneId, final boolean updatePane) {
+ @NotNull
+ private ActionCallback setPaneOption(@NotNull Map<String, Boolean> optionsMap, boolean value, String paneId, final boolean updatePane) {
optionsMap.put(paneId, value ? Boolean.TRUE : Boolean.FALSE);
if (updatePane) {
final AbstractProjectViewPane pane = getProjectViewPaneById(paneId);
@@ -1535,7 +1540,7 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
return new ActionCallback.Done();
}
- private static boolean getPaneOptionValue(Map<String, Boolean> optionsMap, String paneId, boolean defaultValue) {
+ private static boolean getPaneOptionValue(@NotNull Map<String, Boolean> optionsMap, String paneId, boolean defaultValue) {
final Boolean value = optionsMap.get(paneId);
return value == null ? defaultValue : value.booleanValue();
}
@@ -1573,7 +1578,7 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
private static class SelectionInfo {
private final Object[] myElements;
- private SelectionInfo(Object[] elements) {
+ private SelectionInfo(@NotNull Object[] elements) {
myElements = elements;
}
@@ -1600,6 +1605,7 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
}
}
+ @NotNull
public static SelectionInfo create(final AbstractProjectViewPane viewPane) {
List<Object> selectedElements = Collections.emptyList();
if (viewPane != null) {
@@ -1621,7 +1627,7 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
private class MyAutoScrollFromSourceHandler extends AutoScrollFromSourceHandler {
private MyAutoScrollFromSourceHandler() {
- super(ProjectViewImpl.this.myProject,ProjectViewImpl.this.myViewContentPanel, ProjectViewImpl.this);
+ super(ProjectViewImpl.this.myProject, myViewContentPanel, ProjectViewImpl.this);
}
@Override
@@ -1631,7 +1637,8 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
if (fileEditor instanceof TextEditor) {
Editor editor = ((TextEditor)fileEditor).getEditor();
selectElementAtCaretNotLosingFocus(editor);
- } else {
+ }
+ else {
final VirtualFile file = FileEditorManagerEx.getInstanceEx(myProject).getFile(fileEditor);
if (file != null) {
final PsiFile psiFile = PsiManager.getInstance(myProject).findFile(file);
@@ -1679,19 +1686,19 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
}
}
- private void selectElementAtCaretNotLosingFocus(final Editor editor) {
+ private void selectElementAtCaretNotLosingFocus(@NotNull Editor editor) {
if (IJSwingUtilities.hasFocus(getCurrentProjectViewPane().getComponentToFocus())) return;
selectElementAtCaret(editor);
}
- private void selectElementAtCaret(Editor editor) {
+ private void selectElementAtCaret(@NotNull Editor editor) {
final PsiFile file = PsiDocumentManager.getInstance(myProject).getPsiFile(editor.getDocument());
if (file == null) return;
scrollFromFile(file, editor);
}
- private void scrollFromFile(PsiFile file, @Nullable Editor editor) {
+ private void scrollFromFile(@NotNull PsiFile file, @Nullable Editor editor) {
final MySelectInContext selectInContext = new MySelectInContext(file, editor);
final SelectInTarget target = mySelectInTargets.get(getCurrentViewId());
@@ -1719,10 +1726,10 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
}
private class MySelectInContext implements SelectInContext {
- private final PsiFile myPsiFile;
+ @NotNull private final PsiFile myPsiFile;
@Nullable private final Editor myEditor;
- private MySelectInContext(final PsiFile psiFile, @Nullable Editor editor) {
+ private MySelectInContext(@NotNull PsiFile psiFile, @Nullable Editor editor) {
myPsiFile = psiFile;
myEditor = editor;
}
@@ -1733,13 +1740,14 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
return myProject;
}
+ @NotNull
private PsiFile getPsiFile() {
return myPsiFile;
}
@Override
+ @NotNull
public FileEditorProvider getFileEditorProvider() {
- if (myPsiFile == null) return null;
return new FileEditorProvider() {
@Override
public FileEditor openFileEditor() {
@@ -1748,6 +1756,7 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
};
}
+ @NotNull
private PsiElement getPsiElement() {
PsiElement e = null;
if (myEditor != null) {
@@ -1780,7 +1789,7 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
}
@Override
- public void setSortByType(String paneId, final boolean sortByType) {
+ public void setSortByType(@NotNull String paneId, final boolean sortByType) {
setPaneOption(mySortByType, sortByType, paneId, false);
final AbstractProjectViewPane pane = getProjectViewPaneById(paneId);
pane.installComparator();
@@ -1788,8 +1797,7 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
private class SortByTypeAction extends ToggleAction {
private SortByTypeAction() {
- super(IdeBundle.message("action.sort.by.type"), IdeBundle.message("action.sort.by.type"),
- AllIcons.ObjectBrowser.SortByType);
+ super(IdeBundle.message("action.sort.by.type"), IdeBundle.message("action.sort.by.type"), AllIcons.ObjectBrowser.SortByType);
}
@Override
@@ -1845,11 +1853,13 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
}
}
+ @NotNull
@Override
public Collection<String> getPaneIds() {
return myId2Pane.keySet();
}
+ @NotNull
@Override
public Collection<SelectInTarget> getSelectInTargets() {
ensurePanesLoaded();
diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewToolWindowFactory.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewToolWindowFactory.java
index 192f5966c489..f4b3803a63d0 100644
--- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewToolWindowFactory.java
+++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewToolWindowFactory.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.
@@ -23,13 +23,14 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.wm.ToolWindow;
import com.intellij.openapi.wm.ToolWindowFactoryEx;
+import org.jetbrains.annotations.NotNull;
/**
* @author yole
*/
public class ProjectViewToolWindowFactory implements ToolWindowFactoryEx, DumbAware {
@Override
- public void createToolWindowContent(Project project, ToolWindow toolWindow) {
+ public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindow toolWindow) {
((ProjectViewImpl) ProjectView.getInstance(project)).setupImpl(toolWindow);
}
diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/ShowModulesAction.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/ShowModulesAction.java
index 6e53e96725b5..370b7a335bf4 100644
--- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/ShowModulesAction.java
+++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/ShowModulesAction.java
@@ -24,6 +24,7 @@ import com.intellij.openapi.actionSystem.ToggleAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.util.PlatformUtils;
+import org.jetbrains.annotations.NotNull;
/**
* @author anna
@@ -43,6 +44,7 @@ public abstract class ShowModulesAction extends ToggleAction {
return ProjectView.getInstance(myProject).isShowModules(getId());
}
+ @NotNull
protected abstract String getId();
@Override
diff --git a/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeTreeViewPanel.java b/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeTreeViewPanel.java
index 2fbbdc7ea348..9daf15441dbf 100644
--- a/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeTreeViewPanel.java
+++ b/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeTreeViewPanel.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.
@@ -252,7 +252,7 @@ public class ScopeTreeViewPanel extends JPanel implements Disposable {
public void selectScope(final NamedScope scope) {
refreshScope(scope);
- if (scope != DefaultScopesProvider.getAllScope() && scope != null) {
+ if (scope != CustomScopesProviderEx.getAllScope() && scope != null) {
CURRENT_SCOPE_NAME = scope.getName();
}
}
@@ -323,7 +323,7 @@ public class ScopeTreeViewPanel extends JPanel implements Disposable {
public void refreshScope(@Nullable NamedScope scope) {
FileTreeModelBuilder.clearCaches(myProject);
if (scope == null) { //was deleted
- scope = DefaultScopesProvider.getAllScope();
+ scope = CustomScopesProviderEx.getAllScope();
}
LOG.assertTrue(scope != null);
final NamedScopesHolder holder = NamedScopesHolder.getHolder(myProject, scope.getName(), myDependencyValidationManager);
@@ -364,7 +364,7 @@ public class ScopeTreeViewPanel extends JPanel implements Disposable {
protected NamedScope getCurrentScope() {
NamedScope scope = NamedScopesHolder.getScope(myProject, CURRENT_SCOPE_NAME);
if (scope == null) {
- scope = DefaultScopesProvider.getAllScope();
+ scope = CustomScopesProviderEx.getAllScope();
}
LOG.assertTrue(scope != null);
return scope;
@@ -888,6 +888,7 @@ public class ScopeTreeViewPanel extends JPanel implements Disposable {
return null;
}
+ @NotNull
@Override
public PsiDirectory[] getDirectories() {
PsiDirectory directory = getDirectory();
diff --git a/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeViewPane.java b/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeViewPane.java
index 5c929e99b736..dc47793401e0 100644
--- a/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeViewPane.java
+++ b/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeViewPane.java
@@ -162,6 +162,7 @@ public class ScopeViewPane extends AbstractProjectViewPane {
public void addToolbarActions(DefaultActionGroup actionGroup) {
actionGroup.add(ActionManager.getInstance().getAction("ScopeView.EditScopes"));
actionGroup.addAction(new ShowModulesAction(myProject){
+ @NotNull
@Override
protected String getId() {
return ScopeViewPane.this.getId();
@@ -169,6 +170,7 @@ public class ScopeViewPane extends AbstractProjectViewPane {
}).setAsSecondary(true);
}
+ @NotNull
@Override
public ActionCallback updateFromRoot(boolean restoreExpandedPaths) {
saveExpandedPaths();
@@ -249,14 +251,13 @@ public class ScopeViewPane extends AbstractProjectViewPane {
if (data != null) {
return data;
}
- return myViewPanel != null ? myViewPanel.getData(dataId) : null;
+ return myViewPanel == null ? null : myViewPanel.getData(dataId);
}
@NotNull
@Override
public ActionCallback getReady(@NotNull Object requestor) {
final ActionCallback callback = myViewPanel.getActionCallback();
- return myViewPanel == null ? new ActionCallback.Rejected() :
- callback != null ? callback : new ActionCallback.Done();
+ return callback == null ? new ActionCallback.Done() : callback;
}
}
diff --git a/platform/lang-impl/src/com/intellij/ide/structureView/impl/StructureViewToolWindowFactory.java b/platform/lang-impl/src/com/intellij/ide/structureView/impl/StructureViewToolWindowFactory.java
index b05193bf858a..c06cd2cb5d59 100644
--- a/platform/lang-impl/src/com/intellij/ide/structureView/impl/StructureViewToolWindowFactory.java
+++ b/platform/lang-impl/src/com/intellij/ide/structureView/impl/StructureViewToolWindowFactory.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,13 +22,14 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.wm.ToolWindow;
import com.intellij.openapi.wm.ToolWindowFactory;
import com.intellij.openapi.wm.ex.ToolWindowEx;
+import org.jetbrains.annotations.NotNull;
/**
* @author yole
*/
public class StructureViewToolWindowFactory implements ToolWindowFactory, DumbAware {
@Override
- public void createToolWindowContent(Project project, ToolWindow toolWindow) {
+ public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindow toolWindow) {
StructureViewFactoryImpl factory = (StructureViewFactoryImpl)StructureViewFactory.getInstance(project);
factory.initToolWindow((ToolWindowEx)toolWindow);
}
diff --git a/platform/lang-impl/src/com/intellij/ide/todo/TodoToolWindowFactory.java b/platform/lang-impl/src/com/intellij/ide/todo/TodoToolWindowFactory.java
index ad5368672fec..4217f5ace393 100644
--- a/platform/lang-impl/src/com/intellij/ide/todo/TodoToolWindowFactory.java
+++ b/platform/lang-impl/src/com/intellij/ide/todo/TodoToolWindowFactory.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,13 +20,14 @@ import com.intellij.openapi.wm.ToolWindowFactory;
import com.intellij.openapi.wm.ToolWindow;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.components.ServiceManager;
+import org.jetbrains.annotations.NotNull;
/**
* @author yole
*/
public class TodoToolWindowFactory implements ToolWindowFactory {
@Override
- public void createToolWindowContent(Project project, ToolWindow toolWindow) {
+ public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindow toolWindow) {
TodoView todoView = ServiceManager.getService(project, TodoView.class);
todoView.initToolWindow(toolWindow);
}
diff --git a/platform/lang-impl/src/com/intellij/ide/util/MemberChooser.java b/platform/lang-impl/src/com/intellij/ide/util/MemberChooser.java
index 80099b35c3d8..54ae97d446b5 100644
--- a/platform/lang-impl/src/com/intellij/ide/util/MemberChooser.java
+++ b/platform/lang-impl/src/com/intellij/ide/util/MemberChooser.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.
@@ -47,8 +47,6 @@ import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.*;
import java.awt.*;
import java.awt.event.*;
-import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
import java.util.*;
import java.util.List;
@@ -536,9 +534,9 @@ public class MemberChooser<T extends ClassMember> extends DialogWrapper implemen
protected void doSort() {
Pair<ElementNode, List<ElementNode>> pair = storeSelection();
- Enumeration<ParentNode> children = getRootNodeChildren();
+ Enumeration<TreeNode> children = getRootNodeChildren();
while (children.hasMoreElements()) {
- ParentNode classNode = children.nextElement();
+ ParentNode classNode = (ParentNode)children.nextElement();
sortNode(classNode, myComparator);
myTreeModel.nodeStructureChanged(classNode);
}
@@ -547,10 +545,10 @@ public class MemberChooser<T extends ClassMember> extends DialogWrapper implemen
}
private static void sortNode(ParentNode node, final Comparator<ElementNode> sortComparator) {
- ArrayList<MemberNode> arrayList = new ArrayList<MemberNode>();
- Enumeration<MemberNode> children = node.children();
+ ArrayList<ElementNode> arrayList = new ArrayList<ElementNode>();
+ Enumeration<TreeNode> children = node.children();
while (children.hasMoreElements()) {
- arrayList.add(children.nextElement());
+ arrayList.add((ElementNode)children.nextElement());
}
Collections.sort(arrayList, sortComparator);
@@ -571,16 +569,16 @@ public class MemberChooser<T extends ClassMember> extends DialogWrapper implemen
DefaultMutableTreeNode root = getRootNode();
if (!myShowClasses || myContainerNodes.isEmpty()) {
List<ParentNode> otherObjects = new ArrayList<ParentNode>();
- Enumeration<ParentNode> children = getRootNodeChildren();
+ Enumeration<TreeNode> children = getRootNodeChildren();
ParentNode newRoot = new ParentNode(null, new MemberChooserObjectBase(getAllContainersNodeName()), new Ref<Integer>(0));
while (children.hasMoreElements()) {
- final ParentNode nextElement = children.nextElement();
+ final ParentNode nextElement = (ParentNode)children.nextElement();
if (nextElement instanceof ContainerNode) {
final ContainerNode containerNode = (ContainerNode)nextElement;
- Enumeration<MemberNode> memberNodes = containerNode.children();
+ Enumeration<TreeNode> memberNodes = containerNode.children();
List<MemberNode> memberNodesList = new ArrayList<MemberNode>();
while (memberNodes.hasMoreElements()) {
- memberNodesList.add(memberNodes.nextElement());
+ memberNodesList.add((MemberNode)memberNodes.nextElement());
}
for (MemberNode memberNode : memberNodesList) {
newRoot.add(memberNode);
@@ -595,13 +593,13 @@ public class MemberChooser<T extends ClassMember> extends DialogWrapper implemen
if (newRoot.children().hasMoreElements()) root.add(newRoot);
}
else {
- Enumeration<ParentNode> children = getRootNodeChildren();
+ Enumeration<TreeNode> children = getRootNodeChildren();
while (children.hasMoreElements()) {
- ParentNode allClassesNode = children.nextElement();
- Enumeration<MemberNode> memberNodes = allClassesNode.children();
+ ParentNode allClassesNode = (ParentNode)children.nextElement();
+ Enumeration<TreeNode> memberNodes = allClassesNode.children();
ArrayList<MemberNode> arrayList = new ArrayList<MemberNode>();
while (memberNodes.hasMoreElements()) {
- arrayList.add(memberNodes.nextElement());
+ arrayList.add((MemberNode)memberNodes.nextElement());
}
Collections.sort(arrayList, myComparator);
for (MemberNode memberNode : arrayList) {
@@ -626,7 +624,7 @@ public class MemberChooser<T extends ClassMember> extends DialogWrapper implemen
return IdeBundle.message("node.memberchooser.all.classes");
}
- private Enumeration<ParentNode> getRootNodeChildren() {
+ private Enumeration<TreeNode> getRootNodeChildren() {
return getRootNode().children();
}
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 ccf63a429346..267333399dbd 100644
--- a/platform/lang-impl/src/com/intellij/lang/parser/GeneratedParserUtilBase.java
+++ b/platform/lang-impl/src/com/intellij/lang/parser/GeneratedParserUtilBase.java
@@ -933,7 +933,8 @@ public class GeneratedParserUtilBase {
for (Pair<PsiBuilder.Marker, Integer> pair : siblingList) {
if (pair.second != rating || parenPair != null && pair.first == parenPair.second) break main;
if (++count >= MAX_CHILDREN_IN_TREE) {
- final PsiBuilder.Marker parentMarker = pair.first.precede();
+ PsiBuilder.Marker parentMarker = pair.first.precede();
+ parentMarker.setCustomEdgeTokenBinders(WhitespacesBinders.GREEDY_LEFT_BINDER, null);
while (count-- > 0) {
siblingList.removeFirst();
}
@@ -986,6 +987,7 @@ public class GeneratedParserUtilBase {
else {
if (marker == null) {
marker = builder_.mark();
+ marker.setCustomEdgeTokenBinders(WhitespacesBinders.GREEDY_LEFT_BINDER, null);
}
final boolean result = (!parenList.isEmpty() || eatMoreCondition.parse(builder_, level + 1)) && parser.parse(builder_, level + 1);
if (result) {
diff --git a/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectWordAtCaretAction.java b/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectWordAtCaretAction.java
index b70189f5140a..0cf8e9e984d0 100644
--- a/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectWordAtCaretAction.java
+++ b/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectWordAtCaretAction.java
@@ -35,6 +35,7 @@ import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.text.CharArrayUtil;
+import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
@@ -45,18 +46,13 @@ public class SelectWordAtCaretAction extends TextComponentEditorAction implement
setInjectedContext(true);
}
- @Override
- public EditorActionHandler getHandler() {
- return new Handler(super.getHandler());
- }
-
private static class DefaultHandler extends EditorActionHandler {
private DefaultHandler() {
super(true);
}
@Override
- public void execute(Editor editor, DataContext dataContext) {
+ public void doExecute(Editor editor, @Nullable Caret caret, DataContext dataContext) {
int lineNumber = editor.getCaretModel().getLogicalPosition().line;
int caretOffset = editor.getCaretModel().getOffset();
Document document = editor.getDocument();
@@ -94,23 +90,24 @@ public class SelectWordAtCaretAction extends TextComponentEditorAction implement
}
}
- private static class Handler extends EditorActionHandler {
+ public static class Handler extends EditorActionHandler {
private final EditorActionHandler myDefaultHandler;
- private Handler(EditorActionHandler defaultHandler) {
+ public Handler(EditorActionHandler defaultHandler) {
super(true);
myDefaultHandler = defaultHandler;
+
}
@Override
- public void execute(Editor editor, DataContext dataContext) {
+ public void doExecute(Editor editor, @Nullable Caret caret, DataContext dataContext) {
final IndentGuideDescriptor guide = editor.getIndentsModel().getCaretIndentGuide();
final SelectionModel selectionModel = editor.getSelectionModel();
if (guide != null && !selectionModel.hasSelection() && !selectionModel.hasBlockSelection() && isWhitespaceAtCaret(editor)) {
selectWithGuide(editor, guide);
}
else {
- myDefaultHandler.execute(editor, dataContext);
+ myDefaultHandler.execute(editor, caret, dataContext);
}
}
diff --git a/platform/lang-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorPsiDataProvider.java b/platform/lang-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorPsiDataProvider.java
index 1f911936637a..7400e982b5a0 100644
--- a/platform/lang-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorPsiDataProvider.java
+++ b/platform/lang-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorPsiDataProvider.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,9 +19,12 @@ package com.intellij.openapi.fileEditor.impl.text;
import com.intellij.codeInsight.TargetElementUtilBase;
import com.intellij.ide.IdeView;
import com.intellij.ide.util.EditorHelper;
+import com.intellij.injected.editor.EditorWindow;
+import com.intellij.injected.editor.InjectedCaret;
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.editor.ex.EditorEx;
import com.intellij.openapi.fileEditor.EditorDataProvider;
import com.intellij.openapi.project.IndexNotReadyException;
import com.intellij.openapi.project.Project;
@@ -42,45 +45,64 @@ import static com.intellij.util.containers.ContainerUtil.addIfNotNull;
public class TextEditorPsiDataProvider implements EditorDataProvider {
@Override
@Nullable
- public Object getData(@NotNull final String dataId, @NotNull final Editor e, @NotNull final VirtualFile file) {
- if (!file.isValid()) return null;
+ public Object getData(@NotNull final String dataId, @NotNull final Editor e, @NotNull final Caret caret) {
+ if (!(e instanceof EditorEx)) {
+ return null;
+ }
+ VirtualFile file = ((EditorEx)e).getVirtualFile();
+ if (file == null || !file.isValid()) return null;
+ Project project = e.getProject();
if (dataId.equals(injectedId(EDITOR.getName()))) {
- if (PsiDocumentManager.getInstance(e.getProject()).isUncommited(e.getDocument())) {
+ if (project == null || PsiDocumentManager.getInstance(project).isUncommited(e.getDocument())) {
return e;
}
else {
- return InjectedLanguageUtil.getEditorForInjectedLanguageNoCommit(e, getPsiFile(e, file));
+ return InjectedLanguageUtil.getEditorForInjectedLanguageNoCommit(e, caret, getPsiFile(e, file));
}
}
+ if (HOST_EDITOR.is(dataId)) {
+ return e instanceof EditorWindow ? ((EditorWindow)e).getDelegate() : e;
+ }
+ if (CARET.is(dataId)) {
+ return caret;
+ }
+ if (dataId.equals(injectedId(CARET.getName()))) {
+ Editor editor = (Editor)getData(injectedId(EDITOR.getName()), e, caret);
+ assert editor != null;
+ return getInjectedCaret(editor, caret);
+ }
if (dataId.equals(injectedId(PSI_ELEMENT.getName()))) {
- return getPsiElementIn((Editor)getData(injectedId(EDITOR.getName()), e, file), file);
+ Editor editor = (Editor)getData(injectedId(EDITOR.getName()), e, caret);
+ assert editor != null;
+ Caret injectedCaret = getInjectedCaret(editor, caret);
+ return getPsiElementIn(editor, injectedCaret, file);
}
if (PSI_ELEMENT.is(dataId)){
- return getPsiElementIn(e, file);
+ return getPsiElementIn(e, caret, file);
}
if (dataId.equals(injectedId(LANGUAGE.getName()))) {
- PsiFile psiFile = (PsiFile)getData(injectedId(PSI_FILE.getName()), e, file);
- Editor editor = (Editor)getData(injectedId(EDITOR.getName()), e, file);
+ PsiFile psiFile = (PsiFile)getData(injectedId(PSI_FILE.getName()), e, caret);
+ Editor editor = (Editor)getData(injectedId(EDITOR.getName()), e, caret);
if (psiFile == null || editor == null) return null;
- return getLanguageAtCurrentPositionInEditor(editor, psiFile);
+ Caret injectedCaret = getInjectedCaret(editor, caret);
+ return getLanguageAtCurrentPositionInEditor(injectedCaret, psiFile);
}
if (LANGUAGE.is(dataId)) {
final PsiFile psiFile = getPsiFile(e, file);
if (psiFile == null) return null;
- return getLanguageAtCurrentPositionInEditor(e, psiFile);
+ return getLanguageAtCurrentPositionInEditor(caret, psiFile);
}
if (dataId.equals(injectedId(VIRTUAL_FILE.getName()))) {
- PsiFile psiFile = (PsiFile)getData(injectedId(PSI_FILE.getName()), e, file);
+ PsiFile psiFile = (PsiFile)getData(injectedId(PSI_FILE.getName()), e, caret);
if (psiFile == null) return null;
return psiFile.getVirtualFile();
}
if (dataId.equals(injectedId(PSI_FILE.getName()))) {
- Editor editor = (Editor)getData(injectedId(EDITOR.getName()), e, file);
+ Editor editor = (Editor)getData(injectedId(EDITOR.getName()), e, caret);
if (editor == null) {
return null;
}
- final Project project = editor.getProject();
if (project == null) {
return null;
}
@@ -90,7 +112,7 @@ public class TextEditorPsiDataProvider implements EditorDataProvider {
return getPsiFile(e, file);
}
if (IDE_VIEW.is(dataId)) {
- final PsiFile psiFile = PsiManager.getInstance(e.getProject()).findFile(file);
+ final PsiFile psiFile = project == null ? null : PsiManager.getInstance(project).findFile(file);
final PsiDirectory psiDirectory = psiFile != null ? psiFile.getParent() : null;
if (psiDirectory != null && psiDirectory.isPhysical()) {
return new IdeView() {
@@ -103,6 +125,7 @@ public class TextEditorPsiDataProvider implements EditorDataProvider {
}
}
+ @NotNull
@Override
public PsiDirectory[] getDirectories() {
return new PsiDirectory[]{psiDirectory};
@@ -116,20 +139,32 @@ public class TextEditorPsiDataProvider implements EditorDataProvider {
}
}
if (CONTEXT_LANGUAGES.is(dataId)) {
- return computeLanguages(e, file);
+ return computeLanguages(e, caret);
}
return null;
}
- private static Language getLanguageAtCurrentPositionInEditor(final Editor editor, final PsiFile psiFile) {
- final SelectionModel selectionModel = editor.getSelectionModel();
- int caretOffset = editor.getCaretModel().getOffset();
- int mostProbablyCorrectLanguageOffset = caretOffset == selectionModel.getSelectionStart() ||
- caretOffset == selectionModel.getSelectionEnd()
- ? selectionModel.getSelectionStart()
+ @NotNull
+ private static Caret getInjectedCaret(@NotNull Editor editor, @NotNull Caret hostCaret) {
+ if (!(editor instanceof EditorWindow) || hostCaret instanceof InjectedCaret) {
+ return hostCaret;
+ }
+ for (Caret caret : editor.getCaretModel().getAllCarets()) {
+ if (((InjectedCaret)caret).getDelegate() == hostCaret) {
+ return caret;
+ }
+ }
+ throw new IllegalArgumentException("Cannot find injected caret corresponding to " + hostCaret);
+ }
+
+ private static Language getLanguageAtCurrentPositionInEditor(Caret caret, final PsiFile psiFile) {
+ int caretOffset = caret.getOffset();
+ int mostProbablyCorrectLanguageOffset = caretOffset == caret.getSelectionStart() ||
+ caretOffset == caret.getSelectionEnd()
+ ? caret.getSelectionStart()
: caretOffset;
- if (selectionModel.hasSelection()) {
- return getLanguageAtOffset(psiFile, mostProbablyCorrectLanguageOffset, selectionModel.getSelectionEnd());
+ if (caret.hasSelection()) {
+ return getLanguageAtOffset(psiFile, mostProbablyCorrectLanguageOffset, caret.getSelectionEnd());
}
return PsiUtilCore.getLanguageAtOffset(psiFile, mostProbablyCorrectLanguageOffset);
@@ -148,12 +183,13 @@ public class TextEditorPsiDataProvider implements EditorDataProvider {
}
@Nullable
- private static PsiElement getPsiElementIn(@NotNull Editor editor, @NotNull VirtualFile file) {
+ private static PsiElement getPsiElementIn(@NotNull Editor editor, @NotNull Caret caret, @NotNull VirtualFile file) {
final PsiFile psiFile = getPsiFile(editor, file);
if (psiFile == null) return null;
try {
- return TargetElementUtilBase.findTargetElement(editor, TargetElementUtilBase.getInstance().getReferenceSearchFlags());
+ TargetElementUtilBase util = TargetElementUtilBase.getInstance();
+ return util.findTargetElement(editor, util.getReferenceSearchFlags(), caret.getOffset());
}
catch (IndexNotReadyException e) {
return null;
@@ -173,13 +209,13 @@ public class TextEditorPsiDataProvider implements EditorDataProvider {
return psiFile != null && psiFile.isValid() ? psiFile : null;
}
- private Language[] computeLanguages(@NotNull Editor editor, @NotNull VirtualFile file) {
+ private Language[] computeLanguages(@NotNull Editor editor, @NotNull Caret caret) {
LinkedHashSet<Language> set = new LinkedHashSet<Language>(4);
- Language injectedLanguage = (Language)getData(injectedId(LANGUAGE.getName()), editor, file);
+ Language injectedLanguage = (Language)getData(injectedId(LANGUAGE.getName()), editor, caret);
addIfNotNull(injectedLanguage, set);
- Language language = (Language)getData(LANGUAGE.getName(), editor, file);
+ Language language = (Language)getData(LANGUAGE.getName(), editor, caret);
addIfNotNull(language, set);
- PsiFile psiFile = (PsiFile)getData(PSI_FILE.getName(), editor, file);
+ PsiFile psiFile = (PsiFile)getData(PSI_FILE.getName(), editor, caret);
if (psiFile != null) {
addIfNotNull(psiFile.getViewProvider().getBaseLanguage(), set);
}
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 09e489b3d1df..c753efb145e8 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,14 +25,16 @@ 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.*;
+import com.intellij.openapi.roots.ModuleRootAdapter;
+import com.intellij.openapi.roots.ModuleRootEvent;
+import com.intellij.openapi.roots.ModuleRootManager;
+import com.intellij.openapi.roots.OrderEntry;
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;
@@ -42,8 +44,6 @@ 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 {
@@ -206,96 +206,4 @@ public class DirectoryIndexImpl extends DirectoryIndex {
LOG.error("Directory index is already disposed for " + myProject);
}
}
-
- @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/ui/configuration/ContentRootPanel.java b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentRootPanel.java
index bc10302c9c43..71b9ebcd205d 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
@@ -45,6 +45,7 @@ import org.jetbrains.jps.model.JpsElement;
import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
import javax.swing.*;
+import javax.swing.border.EmptyBorder;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import java.awt.*;
@@ -102,6 +103,7 @@ public abstract class ContentRootPanel extends JPanel {
public void initUI() {
myHeader = createHeader();
+ myHeader.setBorder(new EmptyBorder(0, 8, 0, 0));
this.add(myHeader, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 8, 0), 0, 0));
addFolderGroupComponents();
@@ -198,7 +200,7 @@ public abstract class ContentRootPanel extends JPanel {
final Font labelFont = UIUtil.getLabelFont();
titleLabel.setFont(labelFont.deriveFont(Font.BOLD));
titleLabel.setOpaque(false);
- titleLabel.setBorder(BorderFactory.createEmptyBorder(0, 2, 0, 0));
+ titleLabel.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0));
registerTextComponent(titleLabel, foregroundColor);
final JPanel groupPanel = new JPanel(new BorderLayout());
diff --git a/platform/lang-impl/src/com/intellij/platform/templates/github/DownloadUtil.java b/platform/lang-impl/src/com/intellij/platform/templates/github/DownloadUtil.java
index e4889af6a591..bbffc7c98ba4 100644
--- a/platform/lang-impl/src/com/intellij/platform/templates/github/DownloadUtil.java
+++ b/platform/lang-impl/src/com/intellij/platform/templates/github/DownloadUtil.java
@@ -176,9 +176,6 @@ public class DownloadUtil {
URLConnection urlConnection = HttpConfigurable.getInstance().openConnection(location);
HttpURLConnection httpURLConnection = ObjectUtils.tryCast(urlConnection, HttpURLConnection.class);
try {
- int timeout = (int) TimeUnit.MINUTES.toMillis(2);
- urlConnection.setConnectTimeout(timeout);
- urlConnection.setReadTimeout(timeout);
urlConnection.connect();
InputStream in = urlConnection.getInputStream();
int contentLength = urlConnection.getContentLength();
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
index c69a3e5566a2..602de3c8dba5 100644
--- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ScopesOrderDialog.java
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ScopesOrderDialog.java
@@ -64,7 +64,7 @@ public class ScopesOrderDialog extends DialogWrapper {
ListUtil.moveSelectedItemsUp(myOptionsList);
}
}).disableRemoveAction().disableAddAction().createPanel();
- final JLabel descr = new JLabel("<html><p>If file appears in two or more scopes, it will be" +
+ 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));
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 2da5c80a758b..81d0bf651688 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
@@ -16,7 +16,6 @@
package com.intellij.profile.codeInspection.ui;
-import com.intellij.CommonBundle;
import com.intellij.codeHighlighting.HighlightDisplayLevel;
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
@@ -62,7 +61,6 @@ import com.intellij.profile.codeInspection.ui.table.ScopesAndSeveritiesTable;
import com.intellij.psi.search.scope.packageSet.NamedScope;
import com.intellij.ui.*;
import com.intellij.ui.components.JBLabel;
-import com.intellij.ui.treeStructure.Tree;
import com.intellij.util.Alarm;
import com.intellij.util.Function;
import com.intellij.util.config.StorageAccessors;
@@ -85,8 +83,6 @@ import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import java.awt.*;
-import java.awt.event.InputEvent;
-import java.awt.event.KeyEvent;
import java.io.IOException;
import java.io.StringReader;
import java.util.*;
@@ -811,7 +807,7 @@ public class SingleInspectionProfilePanel extends JPanel {
}
}
final JTable scopesAndScopesAndSeveritiesTable =
- new ScopesAndSeveritiesTable(new ScopesAndSeveritiesTable.TableSettings(nodes, mySelectedProfile, myTreeTable, project) {
+ new ScopesAndSeveritiesTable(new ScopesAndSeveritiesTable.TableSettings(nodes, mySelectedProfile, project) {
@Override
protected void onScopeChosen(@NotNull final ScopeToolState state) {
setConfigPanel(configPanelAnchor, state);
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 92cb62f0f800..5607816ad13c 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
@@ -64,8 +64,8 @@ public class InspectionsConfigTreeTable extends TreeTable {
final TableColumn isEnabledColumn = getColumnModel().getColumn(IS_ENABLED_COLUMN);
isEnabledColumn.setMaxWidth(20);
- isEnabledColumn.setCellRenderer(new ThreeStateCheckBoxRenderer(false));
- isEnabledColumn.setCellEditor(new ThreeStateCheckBoxRenderer(true));
+ isEnabledColumn.setCellRenderer(new ThreeStateCheckBoxRenderer());
+ isEnabledColumn.setCellEditor(new ThreeStateCheckBoxRenderer());
addMouseMotionListener(new MouseAdapter() {
@Override
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 3b2c36bf7d34..385b764af027 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
@@ -20,11 +20,9 @@ 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;
@@ -36,12 +34,12 @@ import com.intellij.profile.codeInspection.ui.inspectionsTree.InspectionConfigTr
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 com.intellij.util.ui.EmptyIcon;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -63,7 +61,7 @@ public class ScopesAndSeveritiesTable extends JBTable {
public static final HighlightSeverity MIXED_FAKE_SEVERITY = new HighlightSeverity("Mixed", -1);
@SuppressWarnings("UnusedDeclaration")
- public static final HighlightDisplayLevel MIXED_FAKE_LEVEL = new HighlightDisplayLevel(MIXED_FAKE_SEVERITY, AllIcons.Actions.Help);
+ public static final HighlightDisplayLevel MIXED_FAKE_LEVEL = new HighlightDisplayLevel(MIXED_FAKE_SEVERITY, EmptyIcon.create(12));
private final static int SCOPE_ENABLED_COLUMN = 0;
private final static int SCOPE_NAME_COLUMN = 1;
@@ -76,8 +74,8 @@ public class ScopesAndSeveritiesTable extends JBTable {
final TableColumn scopeEnabledColumn = columnModel.getColumn(SCOPE_ENABLED_COLUMN);
scopeEnabledColumn.setMaxWidth(30);
- scopeEnabledColumn.setCellRenderer(new ThreeStateCheckBoxRenderer(false));
- scopeEnabledColumn.setCellEditor(new ThreeStateCheckBoxRenderer(true));
+ scopeEnabledColumn.setCellRenderer(new ThreeStateCheckBoxRenderer());
+ scopeEnabledColumn.setCellEditor(new ThreeStateCheckBoxRenderer());
final TableColumn severityColumn = columnModel.getColumn(SEVERITY_COLUMN);
severityColumn.setCellRenderer(SeverityRenderer.create(tableSettings.getInspectionProfile()));
@@ -113,12 +111,10 @@ public class ScopesAndSeveritiesTable extends JBTable {
private final List<String> myKeyNames;
private final List<HighlightDisplayKey> myKeys;
private final InspectionProfileImpl myInspectionProfile;
- private final TreeTable myTreeTable;
private final Project myProject;
protected TableSettings(final List<InspectionConfigTreeNode> nodes,
final InspectionProfileImpl inspectionProfile,
- final TreeTable treeTable,
final Project project) {
myNodes = nodes;
myKeys = new ArrayList<HighlightDisplayKey>(myNodes.size());
@@ -130,7 +126,6 @@ public class ScopesAndSeveritiesTable extends JBTable {
}
myInspectionProfile = inspectionProfile;
- myTreeTable = treeTable;
myProject = project;
}
@@ -150,10 +145,6 @@ public class ScopesAndSeveritiesTable extends JBTable {
return myInspectionProfile;
}
- public TreeTable getTreeTable() {
- return myTreeTable;
- }
-
public Project getProject() {
return myProject;
}
@@ -186,8 +177,6 @@ public class ScopesAndSeveritiesTable extends JBTable {
private static class MyTableModel extends AbstractTableModel implements EditableModel {
private final InspectionProfileImpl myInspectionProfile;
private final List<String> myKeyNames;
- private final List<InspectionConfigTreeNode> myNodes;
- private final TreeTable myTreeTable;
private final Project myProject;
private final TableSettings myTableSettings;
private final List<HighlightDisplayKey> myKeys;
@@ -202,8 +191,6 @@ public class ScopesAndSeveritiesTable extends JBTable {
myInspectionProfile = tableSettings.getInspectionProfile();
myKeys = tableSettings.getKeys();
myKeyNames = tableSettings.getKeyNames();
- myNodes = tableSettings.getNodes();
- myTreeTable = tableSettings.getTreeTable();
myScopeComparator = new ScopeOrderComparator(myInspectionProfile);
refreshAggregatedScopes();
}
@@ -263,7 +250,7 @@ public class ScopesAndSeveritiesTable extends JBTable {
case SCOPE_ENABLED_COLUMN:
return isEnabled(rowIndex);
case SCOPE_NAME_COLUMN:
- return rowIndex == lastRowIndex() ? "Everywhere else" : getScope(rowIndex).getName();
+ return rowIndex == lastRowIndex() ? "Everywhere else" : getScopeName(rowIndex);
case SEVERITY_COLUMN:
return getSeverityState(rowIndex);
default:
@@ -275,13 +262,17 @@ public class ScopesAndSeveritiesTable extends JBTable {
return getScopeToolState(rowIndex).getExistedStates().get(0).getScope(myProject);
}
+ private String getScopeName(final int rowIndex) {
+ return getScopeToolState(rowIndex).getExistedStates().get(0).getScopeName();
+ }
+
@NotNull
private SeverityState getSeverityState(final int rowIndex) {
final ExistedScopesStatesAndNonExistNames existedScopesStatesAndNonExistNames = getScopeToolState(rowIndex);
if (!existedScopesStatesAndNonExistNames.getNonExistNames().isEmpty()) {
return new SeverityState(MIXED_FAKE_SEVERITY, false);
}
- return new SeverityState(ScopesAndSeveritiesTable.getSeverity(existedScopesStatesAndNonExistNames.getExistedStates()), true);
+ return new SeverityState(getSeverity(existedScopesStatesAndNonExistNames.getExistedStates()), true);
}
@Nullable
@@ -361,7 +352,7 @@ public class ScopesAndSeveritiesTable extends JBTable {
LOG.error("no display level found for name " + severityState.getSeverity().getName());
return;
}
- final String scopeName = rowIndex == lastRowIndex() ? null : getScope(rowIndex).getName();
+ final String scopeName = rowIndex == lastRowIndex() ? null : getScopeName(rowIndex);
myInspectionProfile.setErrorLevel(myKeys, level, scopeName, myProject);
}
else if (columnIndex == SCOPE_ENABLED_COLUMN) {
@@ -417,7 +408,6 @@ public class ScopesAndSeveritiesTable extends JBTable {
}
};
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);
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 455e2a60cd19..9e2a4ead10f1 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
@@ -27,6 +27,7 @@ import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import java.awt.*;
import java.awt.event.*;
+import java.util.ArrayList;
import java.util.EventObject;
import java.util.List;
@@ -37,7 +38,7 @@ public class ThreeStateCheckBoxRenderer extends ThreeStateCheckBox implements Ta
private final List<CellEditorListener> myListeners = new SmartList<CellEditorListener>();
- public ThreeStateCheckBoxRenderer(final boolean isEditor) {
+ public ThreeStateCheckBoxRenderer() {
setThirdStateEnabled(false);
setHorizontalAlignment(CENTER);
setVerticalAlignment(CENTER);
@@ -95,7 +96,7 @@ public class ThreeStateCheckBoxRenderer extends ThreeStateCheckBox implements Ta
@Override
public boolean stopCellEditing() {
final ChangeEvent e = new ChangeEvent(this);
- for (final CellEditorListener listener : myListeners) {
+ for (final CellEditorListener listener : new ArrayList<CellEditorListener>(myListeners)) {
listener.editingStopped(e);
}
return true;
@@ -104,7 +105,7 @@ public class ThreeStateCheckBoxRenderer extends ThreeStateCheckBox implements Ta
@Override
public void cancelCellEditing() {
final ChangeEvent e = new ChangeEvent(this);
- for (final CellEditorListener listener : myListeners) {
+ for (final CellEditorListener listener : new ArrayList<CellEditorListener>(myListeners)) {
listener.editingCanceled(e);
}
}
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/DocumentCommitThread.java b/platform/lang-impl/src/com/intellij/psi/impl/DocumentCommitThread.java
index c8793c085a58..32a2e38384d9 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/DocumentCommitThread.java
+++ b/platform/lang-impl/src/com/intellij/psi/impl/DocumentCommitThread.java
@@ -18,8 +18,8 @@ package com.intellij.psi.impl;
import com.intellij.codeInsight.daemon.impl.DaemonProgressIndicator;
import com.intellij.ide.startup.impl.StartupManagerImpl;
import com.intellij.openapi.Disposable;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.application.ex.ApplicationManagerEx;
+import com.intellij.openapi.application.ApplicationAdapter;
+import com.intellij.openapi.application.ex.ApplicationEx;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
@@ -54,17 +54,44 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run
private final Queue<CommitTask> documentsToCommit = new Queue<CommitTask>(10);
private final List<CommitTask> documentsToApplyInEDT = new ArrayList<CommitTask>(10); // guarded by documentsToCommit
+ private final ApplicationEx myApplication;
private volatile boolean isDisposed;
private CommitTask currentTask; // guarded by documentsToCommit
private volatile boolean threadFinished;
- private volatile boolean myEnabled = true; // true if we can do commits. set to false temporarily during the write action.
+ private volatile boolean myEnabled; // true if we can do commits. set to false temporarily during the write action.
public static DocumentCommitThread getInstance() {
return ServiceManager.getService(DocumentCommitThread.class);
}
- public DocumentCommitThread() {
- log("Starting thread",null, false);
+ public DocumentCommitThread(final ApplicationEx application) {
+ myApplication = application;
+ // install listener in EDT to avoid missing events in case we are inside write action right now
+ application.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ application.addApplicationListener(new ApplicationAdapter() {
+ private int runningWriteActions;
+
+ @Override
+ public void beforeWriteActionStart(Object action) {
+ if (runningWriteActions++ == 0) {
+ disable("Write action started: " + action);
+ }
+ }
+
+ @Override
+ public void writeActionFinished(Object action) {
+ if (--runningWriteActions == 0) {
+ enable("Write action finished: " + action);
+ }
+ }
+ }, DocumentCommitThread.this);
+
+ enable("Listener installed, started");
+ }
+ });
+ log("Starting thread", null, false);
new Thread(this, "Document commit thread").start();
}
@@ -88,14 +115,14 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run
}
}
- public void disable(@NonNls Object reason) {
+ private void disable(@NonNls Object reason) {
// write action has just started, all commits are useless
cancel(reason);
myEnabled = false;
log("Disabled", null, false, reason);
}
- public void enable(Object reason) {
+ private void enable(@NonNls Object reason) {
myEnabled = true;
wakeUpQueue();
log("Enabled", null, false, reason);
@@ -107,7 +134,7 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run
}
}
- private void cancel(@NonNls Object reason) {
+ private void cancel(@NonNls @NotNull Object reason) {
startNewTask(null, reason);
}
@@ -126,7 +153,7 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run
doQueue(project, document, reason);
}
- private void doQueue(Project project, Document document, Object reason) {
+ private void doQueue(@NotNull Project project, @NotNull Document document, @NotNull Object reason) {
synchronized (documentsToCommit) {
ProgressIndicator indicator = new DaemonProgressIndicator();
CommitTask newTask = new CommitTask(document, project, indicator, reason);
@@ -193,7 +220,6 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run
public void clearQueue() {
cancelAll();
log.setLength(0);
- disable("end of test");
wakeUpQueue();
}
@@ -303,9 +329,9 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run
}
if (success) {
- assert !ApplicationManager.getApplication().isDispatchThread();
+ assert !myApplication.isDispatchThread();
UIUtil.invokeLaterIfNeeded(finishRunnable);
- log("Invoked later finishRunnable", task, false, success, finishRunnable, indicator);
+ log("Invoked later finishRunnable", task, false, finishRunnable, indicator);
}
}
catch (ProcessCanceledException e) {
@@ -334,7 +360,7 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run
@Override
public void commitSynchronously(@NotNull Document document, @NotNull Project project) {
assert !isDisposed;
- ApplicationManager.getApplication().assertWriteAccessAllowed();
+ myApplication.assertWriteAccessAllowed();
if (!project.isInitialized() && !project.isDefault()) {
@NonNls String s = project + "; Disposed: "+project.isDisposed()+"; Open: "+project.isOpen();
@@ -380,7 +406,7 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run
return new ProgressIndicatorBase();
}
- private void startNewTask(CommitTask task, Object reason) {
+ private void startNewTask(@Nullable CommitTask task, @NotNull Object reason) {
synchronized (documentsToCommit) { // sync to prevent overwriting
CommitTask cur = currentTask;
if (cur != null) {
@@ -388,19 +414,19 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run
}
currentTask = task;
}
+ log("new task started", task, false, reason);
}
// returns finish commit Runnable (to be invoked later in EDT), or null on failure
@Nullable
- private Runnable commitUnderProgress(@NotNull final CommitTask task,
- final boolean synchronously) {
+ private Runnable commitUnderProgress(@NotNull final CommitTask task, final boolean synchronously) {
final Project project = task.project;
final Document document = task.document;
final List<Processor<Document>> finishProcessors = new SmartList<Processor<Document>>();
Runnable runnable = new Runnable() {
@Override
public void run() {
- ApplicationManager.getApplication().assertReadAccessAllowed();
+ myApplication.assertReadAccessAllowed();
if (project.isDisposed()) return;
final PsiDocumentManagerImpl documentManager = (PsiDocumentManagerImpl)PsiDocumentManager.getInstance(project);
@@ -424,14 +450,12 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run
}
};
if (synchronously) {
- ApplicationManager.getApplication().assertWriteAccessAllowed();
+ myApplication.assertWriteAccessAllowed();
runnable.run();
}
- else {
- if (!ApplicationManagerEx.getApplicationEx().tryRunReadAction(runnable)) {
- log("Could not start read action", task, synchronously, ApplicationManager.getApplication().isReadAccessAllowed(), Thread.currentThread());
- return null;
- }
+ else if (!myApplication.tryRunReadAction(runnable)) {
+ log("Could not start read action", task, synchronously, myApplication.isReadAccessAllowed(), Thread.currentThread());
+ return null;
}
boolean canceled = task.indicator.isCanceled();
@@ -443,7 +467,7 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run
Runnable finishRunnable = new Runnable() {
@Override
public void run() {
- ApplicationManager.getApplication().assertIsDispatchThread();
+ myApplication.assertIsDispatchThread();
Project project = task.project;
if (project.isDisposed()) return;
@@ -525,4 +549,27 @@ public class DocumentCommitThread extends DocumentCommitProcessor implements Run
}
return result[0];
}
+
+ @TestOnly
+ boolean isEnabled() {
+ return myEnabled;
+ }
+
+ @TestOnly
+ public void waitUntilAllCommitted(long timeout) throws InterruptedException {
+ if (!myEnabled) {
+ throw new IllegalStateException("DocumentCommitThread is disabled");
+ }
+ int attempts = 0;
+ int delay = 100;
+ synchronized (documentsToCommit) {
+ while(!documentsToCommit.isEmpty() || currentTask != null) {
+ documentsToCommit.wait(delay);
+ if (delay * attempts > timeout) {
+ throw new RuntimeException("timeout");
+ }
+ attempts++;
+ }
+ }
+ }
}
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java
index 63b8a6af86e1..16926b18b834 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java
+++ b/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java
@@ -19,7 +19,6 @@ package com.intellij.psi.impl;
import com.intellij.AppTopics;
import com.intellij.injected.editor.DocumentWindow;
import com.intellij.injected.editor.EditorWindowImpl;
-import com.intellij.openapi.application.ApplicationAdapter;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.SettingsSavingComponent;
import com.intellij.openapi.editor.Document;
@@ -33,7 +32,10 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectLocator;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.*;
+import com.intellij.psi.FileViewProvider;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiManager;
+import com.intellij.psi.SmartPointerManager;
import com.intellij.psi.impl.source.PostprocessReformattingAspect;
import com.intellij.util.FileContentUtil;
import com.intellij.util.Processor;
@@ -79,18 +81,6 @@ public class PsiDocumentManagerImpl extends PsiDocumentManagerBase implements Se
documentCommitThread.queueCommit(project, doc, "Bulk update finished");
}
});
- ApplicationManager.getApplication().addApplicationListener(new ApplicationAdapter() {
- @Override
- public void beforeWriteActionStart(Object action) {
- documentCommitThread.disable("Write action started: " + action);
- }
-
- @Override
- public void writeActionFinished(Object action) {
- documentCommitThread.enable("Write action finished: " + action);
- }
- }, project);
- documentCommitThread.enable("project open");
}
@Nullable
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeFormatterFacade.java b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeFormatterFacade.java
index fa1dd9e86b4a..c7b9bf3a3adf 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeFormatterFacade.java
+++ b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeFormatterFacade.java
@@ -391,14 +391,15 @@ public class CodeFormatterFacade {
/**
- * Inspects all lines of the given document and wraps all of them that exceed {@link CodeStyleSettings#RIGHT_MARGIN right margin}.
+ * Inspects all lines of the given document and wraps all of them that exceed {@link CodeStyleSettings#getRightMargin(com.intellij.lang.Language)}
+ * right margin}.
* <p/>
* I.e. the algorithm is to do the following for every line:
* <p/>
* <pre>
* <ol>
* <li>
- * Check if the line exceeds {@link CodeStyleSettings#RIGHT_MARGIN right margin}. Go to the next line in the case of
+ * Check if the line exceeds {@link CodeStyleSettings#getRightMargin(com.intellij.lang.Language)} right margin}. Go to the next line in the case of
* negative answer;
* </li>
* <li>Determine line wrap position; </li>
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerImpl.java
index 767152fc1e2b..d51ef1216a59 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerImpl.java
+++ b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerImpl.java
@@ -181,7 +181,7 @@ public class CodeStyleManagerImpl extends CodeStyleManager {
transformAllChildren(treeElement);
final CodeFormatterFacade codeFormatter = new CodeFormatterFacade(getSettings(), file.getLanguage());
- LOG.assertTrue(file.isValid());
+ LOG.assertTrue(file.isValid(), "File name: " + file.getName() + " , class: " + file.getClass().getSimpleName());
if (editor == null) {
editor = PsiUtilBase.findEditor(file);
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedFileViewProvider.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedFileViewProvider.java
index f4a6d576e6b8..58a9463b755d 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedFileViewProvider.java
+++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedFileViewProvider.java
@@ -61,7 +61,7 @@ public class InjectedFileViewProvider extends SingleRootFileViewProvider impleme
@NotNull Language language) {
super(psiManager, (VirtualFile)virtualFile, true, language);
myDocumentWindow = documentWindow;
- myProject = documentWindow.getShreds().get(0).getHost().getProject();
+ myProject = documentWindow.getShreds().getHostPointer().getProject();
}
@Override
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 fdc434d8d11a..647ace567d5d 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
@@ -24,7 +24,6 @@ import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.editor.SelectionModel;
import com.intellij.openapi.editor.impl.EditorImpl;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
@@ -38,6 +37,7 @@ import com.intellij.psi.impl.PsiParameterizedCachedValue;
import com.intellij.psi.impl.source.DummyHolder;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.*;
+import com.intellij.testFramework.LightVirtualFile;
import com.intellij.util.containers.ConcurrentList;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
@@ -93,7 +93,12 @@ public class InjectedLanguageUtil {
public static Place getShreds(@NotNull FileViewProvider viewProvider) {
if (!(viewProvider instanceof InjectedFileViewProvider)) return null;
InjectedFileViewProvider myFileViewProvider = (InjectedFileViewProvider)viewProvider;
- return ((DocumentWindowImpl)myFileViewProvider.getDocument()).getShreds();
+ return getShreds(myFileViewProvider.getDocument());
+ }
+
+ @NotNull
+ public static Place getShreds(@NotNull DocumentWindow document) {
+ return ((DocumentWindowImpl)document).getShreds();
}
public static void enumerate(@NotNull DocumentWindow documentWindow,
@@ -162,6 +167,13 @@ public class InjectedLanguageUtil {
return getEditorForInjectedLanguageNoCommit(editor, file, offset);
}
+ public static Editor getEditorForInjectedLanguageNoCommit(@Nullable Editor editor, @Nullable Caret caret, @Nullable PsiFile file) {
+ if (editor == null || file == null || editor instanceof EditorWindow || caret == null) return editor;
+
+ PsiFile injectedFile = findInjectedPsiNoCommit(file, caret.getOffset());
+ return getInjectedEditorForInjectedFile(editor, caret, injectedFile);
+ }
+
public static Caret getCaretForInjectedLanguageNoCommit(@Nullable Caret caret, @Nullable PsiFile file) {
if (caret == null || file == null || caret instanceof InjectedCaret) return caret;
@@ -212,17 +224,21 @@ public class InjectedLanguageUtil {
@NotNull
public static Editor getInjectedEditorForInjectedFile(@NotNull Editor hostEditor, @Nullable final PsiFile injectedFile) {
+ return getInjectedEditorForInjectedFile(hostEditor, hostEditor.getCaretModel().getCurrentCaret(), injectedFile);
+ }
+
+ @NotNull
+ public static Editor getInjectedEditorForInjectedFile(@NotNull Editor hostEditor, @NotNull Caret hostCaret, @Nullable final PsiFile injectedFile) {
if (injectedFile == null || hostEditor instanceof EditorWindow || hostEditor.isDisposed()) return hostEditor;
Project project = hostEditor.getProject();
if (project == null) project = injectedFile.getProject();
Document document = PsiDocumentManager.getInstance(project).getDocument(injectedFile);
if (!(document instanceof DocumentWindowImpl)) return hostEditor;
DocumentWindowImpl documentWindow = (DocumentWindowImpl)document;
- SelectionModel selectionModel = hostEditor.getSelectionModel();
- if (selectionModel.hasSelection()) {
- int selstart = selectionModel.getSelectionStart();
+ if (hostCaret.hasSelection()) {
+ int selstart = hostCaret.getSelectionStart();
if (selstart != -1) {
- int selend = Math.max(selstart, selectionModel.getSelectionEnd());
+ int selend = Math.max(selstart, hostCaret.getSelectionEnd());
if (!documentWindow.containsRange(selstart, selend)) {
// selection spreads out the injected editor range
return hostEditor;
@@ -573,4 +589,29 @@ public class InjectedLanguageUtil {
});
return ref.get();
}
+
+ @Nullable
+ public static PsiLanguageInjectionHost findInjectionHost(@Nullable PsiElement psi) {
+ if (psi == null) return null;
+ PsiFile containingFile = psi.getContainingFile().getOriginalFile(); // * formatting
+ PsiElement fileContext = containingFile.getContext(); // * quick-edit-handler
+ if (fileContext instanceof PsiLanguageInjectionHost) return (PsiLanguageInjectionHost)fileContext;
+ Place shreds = getShreds(containingFile.getViewProvider()); // * injection-registrar
+ if (shreds == null) {
+ VirtualFile virtualFile = PsiUtilCore.getVirtualFile(containingFile);
+ if (virtualFile instanceof LightVirtualFile) {
+ virtualFile = ((LightVirtualFile)virtualFile).getOriginalFile(); // * dynamic files-from-text
+ }
+ if (virtualFile instanceof VirtualFileWindow) {
+ shreds = getShreds(((VirtualFileWindow)virtualFile).getDocumentWindow());
+ }
+ }
+ return shreds != null ? shreds.getHostPointer().getElement() : null;
+ }
+
+ @Nullable
+ public static PsiLanguageInjectionHost findInjectionHost(@Nullable VirtualFile virtualFile) {
+ return virtualFile instanceof VirtualFileWindow ?
+ getShreds(((VirtualFileWindow)virtualFile).getDocumentWindow()).getHostPointer().getElement() : null;
+ }
}
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/MultiHostRegistrarImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/MultiHostRegistrarImpl.java
index 183af7374072..e520eea741be 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/MultiHostRegistrarImpl.java
+++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/MultiHostRegistrarImpl.java
@@ -389,7 +389,7 @@ public class MultiHostRegistrarImpl implements MultiHostRegistrar, ModificationT
"\nLeaf texts concatenated:'"+ patcher.catLeafs +"';" +
"\nFile root: "+parsedNode+
"\nLanguage: "+parsedNode.getPsi().getLanguage()+
- "\nHost file: "+ shreds.get(0).getHost().getContainingFile().getVirtualFile()
+ "\nHost file: "+ shreds.getHostPointer().getVirtualFile()
;
DebugUtil.startPsiModification("injection leaf patching");
try {
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/Place.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/Place.java
index afaf499b9bb9..f6be385077c2 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/Place.java
+++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/Place.java
@@ -17,6 +17,7 @@
package com.intellij.psi.impl.source.tree.injected;
import com.intellij.psi.PsiLanguageInjectionHost;
+import com.intellij.psi.SmartPsiElementPointer;
import com.intellij.util.SmartList;
import org.jetbrains.annotations.NotNull;
@@ -30,6 +31,11 @@ public class Place extends SmartList<PsiLanguageInjectionHost.Shred> {
super(shreds);
}
+ @NotNull
+ public SmartPsiElementPointer<PsiLanguageInjectionHost> getHostPointer() {
+ return ((ShredImpl)get(0)).getSmartPointer();
+ }
+
public boolean isValid() {
for (PsiLanguageInjectionHost.Shred shred : this) {
if (!shred.isValid()) {
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/ShredImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/ShredImpl.java
index aea41ab16f72..5c60a1c2254f 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/ShredImpl.java
+++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/ShredImpl.java
@@ -45,6 +45,7 @@ class ShredImpl implements PsiLanguageInjectionHost.Shred {
assert relevantRangeInHost.isValid();
}
+ @NotNull
public SmartPsiElementPointer<PsiLanguageInjectionHost> getSmartPointer() {
return hostElementPointer;
}
diff --git a/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java b/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java
index d791f14aa841..493d1d6cd519 100644
--- a/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java
+++ b/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java
@@ -302,7 +302,7 @@ public class StubIndexImpl extends StubIndex implements ApplicationComponent, Pe
return true;
}
- private static void forceRebuild(@NotNull Throwable e) {
+ public void forceRebuild(@NotNull Throwable e) {
LOG.info(e);
FileBasedIndex.getInstance().scheduleRebuild(StubUpdatingIndex.INDEX_ID, e);
}
diff --git a/platform/lang-impl/src/com/intellij/refactoring/changeSignature/MethodNodeBase.java b/platform/lang-impl/src/com/intellij/refactoring/changeSignature/MethodNodeBase.java
index 36e5352e0f8e..782ff452fbf4 100644
--- a/platform/lang-impl/src/com/intellij/refactoring/changeSignature/MethodNodeBase.java
+++ b/platform/lang-impl/src/com/intellij/refactoring/changeSignature/MethodNodeBase.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.
@@ -15,6 +15,7 @@
*/
package com.intellij.refactoring.changeSignature;
+import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Iconable;
@@ -88,7 +89,12 @@ public abstract class MethodNodeBase<M extends PsiElement> extends CheckedTreeNo
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
@Override
public void run() {
- callers.set(computeCallers());
+ ApplicationManager.getApplication().runReadAction(new Runnable() {
+ @Override
+ public void run() {
+ callers.set(computeCallers());
+ }
+ });
}
}, RefactoringBundle.message("caller.chooser.looking.for.callers"), true, myProject)) {
myCancelCallback.run();
diff --git a/platform/lang-impl/src/com/intellij/refactoring/inline/GenericInlineHandler.java b/platform/lang-impl/src/com/intellij/refactoring/inline/GenericInlineHandler.java
index dd5d9a42ed91..cbeefc786612 100644
--- a/platform/lang-impl/src/com/intellij/refactoring/inline/GenericInlineHandler.java
+++ b/platform/lang-impl/src/com/intellij/refactoring/inline/GenericInlineHandler.java
@@ -184,7 +184,7 @@ public class GenericInlineHandler {
}
}
else {
- conflicts.putValue(referenceElement, "Cannot inline reference from " + language.getID());
+ conflicts.putValue(referenceElement, "Cannot inline reference from " + language.getDisplayName());
}
}
diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/RenameProcessor.java b/platform/lang-impl/src/com/intellij/refactoring/rename/RenameProcessor.java
index 7e8ec09f3e23..a34d30dc5401 100644
--- a/platform/lang-impl/src/com/intellij/refactoring/rename/RenameProcessor.java
+++ b/platform/lang-impl/src/com/intellij/refactoring/rename/RenameProcessor.java
@@ -320,11 +320,7 @@ public class RenameProcessor extends BaseRefactoringProcessor {
protected boolean isPreviewUsages(UsageInfo[] usages) {
if (myForceShowPreview) return true;
if (super.isPreviewUsages(usages)) return true;
- if (UsageViewUtil.hasNonCodeUsages(usages)) {
- WindowManager.getInstance().getStatusBar(myProject)
- .setInfo(RefactoringBundle.message("occurrences.found.in.comments.strings.and.non.java.files"));
- return true;
- }
+ if (UsageViewUtil.reportNonRegularUsages(usages, myProject)) return true;
return false;
}
diff --git a/platform/lang-impl/src/com/intellij/refactoring/safeDelete/SafeDeleteProcessor.java b/platform/lang-impl/src/com/intellij/refactoring/safeDelete/SafeDeleteProcessor.java
index e6acbaa4adda..b8f069d5f142 100644
--- a/platform/lang-impl/src/com/intellij/refactoring/safeDelete/SafeDeleteProcessor.java
+++ b/platform/lang-impl/src/com/intellij/refactoring/safeDelete/SafeDeleteProcessor.java
@@ -26,7 +26,6 @@ import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Ref;
-import com.intellij.openapi.wm.WindowManager;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.searches.ReferencesSearch;
@@ -40,7 +39,9 @@ import com.intellij.refactoring.safeDelete.usageInfo.SafeDeleteCustomUsageInfo;
import com.intellij.refactoring.safeDelete.usageInfo.SafeDeleteReferenceSimpleDeleteUsageInfo;
import com.intellij.refactoring.safeDelete.usageInfo.SafeDeleteReferenceUsageInfo;
import com.intellij.refactoring.safeDelete.usageInfo.SafeDeleteUsageInfo;
-import com.intellij.refactoring.util.*;
+import com.intellij.refactoring.util.NonCodeSearchDescriptionLocation;
+import com.intellij.refactoring.util.RefactoringUIUtil;
+import com.intellij.refactoring.util.TextOccurrencesUtil;
import com.intellij.usageView.UsageInfo;
import com.intellij.usageView.UsageViewDescriptor;
import com.intellij.usageView.UsageViewUtil;
@@ -352,8 +353,7 @@ public class SafeDeleteProcessor extends BaseRefactoringProcessor {
@Override
protected boolean isPreviewUsages(UsageInfo[] usages) {
- if(myPreviewNonCodeUsages && (UsageViewUtil.hasNonCodeUsages(usages) || UsageViewUtil.hasUsagesInGeneratedCode(usages, myProject))) {
- WindowManager.getInstance().getStatusBar(myProject).setInfo(RefactoringBundle.message("occurrences.found.in.comments.strings.non.java.files.and.generated.code"));
+ if(myPreviewNonCodeUsages && UsageViewUtil.reportNonRegularUsages(usages, myProject)) {
return true;
}
diff --git a/platform/lang-impl/src/com/intellij/tools/BaseToolManager.java b/platform/lang-impl/src/com/intellij/tools/BaseToolManager.java
index c848939cf398..478f60eed51a 100644
--- a/platform/lang-impl/src/com/intellij/tools/BaseToolManager.java
+++ b/platform/lang-impl/src/com/intellij/tools/BaseToolManager.java
@@ -1,6 +1,6 @@
/*
- * 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.
@@ -33,10 +33,10 @@ import java.util.List;
public abstract class BaseToolManager<T extends Tool> implements ExportableApplicationComponent {
- private final ActionManagerEx myActionManager;
+ @NotNull private final ActionManagerEx myActionManager;
private final SchemesManager<ToolsGroup<T>, ToolsGroup<T>> mySchemesManager;
- public BaseToolManager(ActionManagerEx actionManagerEx, SchemesManagerFactory factory) {
+ public BaseToolManager(@NotNull ActionManagerEx actionManagerEx, SchemesManagerFactory factory) {
myActionManager = actionManagerEx;
mySchemesManager = factory.createSchemesManager(
diff --git a/platform/lang-impl/src/com/intellij/tools/ScanSourceCommentsAction.java b/platform/lang-impl/src/com/intellij/tools/ScanSourceCommentsAction.java
index be3fa32182de..53d15d581927 100644
--- a/platform/lang-impl/src/com/intellij/tools/ScanSourceCommentsAction.java
+++ b/platform/lang-impl/src/com/intellij/tools/ScanSourceCommentsAction.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,7 +22,7 @@ package com.intellij.tools;
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.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileTypes.LanguageFileType;
import com.intellij.openapi.progress.ProgressIndicator;
@@ -107,19 +107,24 @@ public class ScanSourceCommentsAction extends AnAction {
descriptor.addFile(file);
}
- private void scanCommentsInFile(Project project, final VirtualFile vFile) {
+ private void scanCommentsInFile(final Project project, final VirtualFile vFile) {
if (!vFile.isDirectory() && vFile.getFileType() instanceof LanguageFileType) {
- PsiFile psiFile = PsiManager.getInstance(project).findFile(vFile);
- if (psiFile == null) return;
-
- for (PsiFile root : psiFile.getViewProvider().getAllFiles()) {
- root.accept(new PsiRecursiveElementWalkingVisitor() {
- @Override
- public void visitComment(PsiComment comment) {
- commentFound(vFile, comment.getText());
+ ApplicationManager.getApplication().runReadAction(new Runnable() {
+ @Override
+ public void run() {
+ PsiFile psiFile = PsiManager.getInstance(project).findFile(vFile);
+ if (psiFile == null) return;
+
+ for (PsiFile root : psiFile.getViewProvider().getAllFiles()) {
+ root.accept(new PsiRecursiveElementWalkingVisitor() {
+ @Override
+ public void visitComment(PsiComment comment) {
+ commentFound(vFile, comment.getText());
+ }
+ });
}
- });
- }
+ }
+ });
}
}
diff --git a/platform/lang-impl/src/com/intellij/tools/Tool.java b/platform/lang-impl/src/com/intellij/tools/Tool.java
index 760fb5901e65..8077bf530e37 100644
--- a/platform/lang-impl/src/com/intellij/tools/Tool.java
+++ b/platform/lang-impl/src/com/intellij/tools/Tool.java
@@ -17,7 +17,6 @@
package com.intellij.tools;
import com.intellij.execution.ExecutionException;
-import com.intellij.execution.RunnerRegistry;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.configurations.PathEnvironmentVariableUtil;
import com.intellij.execution.executors.DefaultRunExecutor;
@@ -274,15 +273,11 @@ public class Tool implements SchemeElement {
FileDocumentManager.getInstance().saveAllDocuments();
try {
if (isUseConsole()) {
- final ToolRunProfile profile = new ToolRunProfile(this, dataContext);
- final ProgramRunner runner = RunnerRegistry.getInstance().getRunner(DefaultRunExecutor.EXECUTOR_ID, profile);
- assert runner != null;
-
- ExecutionEnvironment executionEnvironment = new ExecutionEnvironmentBuilder(project, DefaultRunExecutor.getRunExecutorInstance())
- .setRunProfile(profile)
- .build();
- executionEnvironment.setExecutionId(executionId);
- runner.execute(executionEnvironment, new ProgramRunner.Callback() {
+ ExecutionEnvironment environment = ExecutionEnvironmentBuilder.create(project,
+ DefaultRunExecutor.getRunExecutorInstance(),
+ new ToolRunProfile(this, dataContext)).build();
+ environment.setExecutionId(executionId);
+ environment.getRunner().execute(environment, new ProgramRunner.Callback() {
@Override
public void processStarted(RunContentDescriptor descriptor) {
ProcessHandler processHandler = descriptor.getProcessHandler();
diff --git a/platform/lang-impl/src/com/intellij/ui/DuplicateNodeRenderer.java b/platform/lang-impl/src/com/intellij/ui/DuplicateNodeRenderer.java
index 3083ffed6de9..663dccce5ed8 100644
--- a/platform/lang-impl/src/com/intellij/ui/DuplicateNodeRenderer.java
+++ b/platform/lang-impl/src/com/intellij/ui/DuplicateNodeRenderer.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.
@@ -21,6 +21,7 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import java.awt.*;
import java.util.Enumeration;
@@ -84,9 +85,9 @@ public class DuplicateNodeRenderer {
private static Rectangle getExpandedNodesRect(JTree tree, DefaultMutableTreeNode node, TreePath path) {
Rectangle rect = tree.getRowBounds(tree.getRowForPath(path));
if (tree.isExpanded(path)) {
- Enumeration<DefaultMutableTreeNode> children = node.children();
+ Enumeration<TreeNode> children = node.children();
while (children.hasMoreElements()) {
- DefaultMutableTreeNode child = children.nextElement();
+ DefaultMutableTreeNode child = (DefaultMutableTreeNode)children.nextElement();
TreePath childPath = path.pathByAddingChild(child);
assert !path.equals(childPath) : path+";"+child;
rect = union(rect, getExpandedNodesRect(tree, child, childPath));
diff --git a/platform/lang-impl/src/com/intellij/ui/popup/PopupPositionManager.java b/platform/lang-impl/src/com/intellij/ui/popup/PopupPositionManager.java
index ea9a263d5713..81d09d7886f8 100644
--- a/platform/lang-impl/src/com/intellij/ui/popup/PopupPositionManager.java
+++ b/platform/lang-impl/src/com/intellij/ui/popup/PopupPositionManager.java
@@ -53,7 +53,7 @@ public class PopupPositionManager {
@Nullable final Editor editor,
@Nullable DataContext dataContext) {
final LookupEx lookup = LookupManager.getActiveLookup(editor);
- if (lookup != null && lookup.getCurrentItem() != null) {
+ if (lookup != null && lookup.getCurrentItem() != null && lookup.getComponent().isShowing()) {
new PositionAdjuster(lookup.getComponent()).adjust(hint);
lookup.addLookupListener(new LookupAdapter() {
@Override
diff --git a/platform/lang-impl/src/com/intellij/ui/tabs/ColorSelectionComponent.java b/platform/lang-impl/src/com/intellij/ui/tabs/ColorSelectionComponent.java
index a7721a8b826f..bfa1e14ec88e 100644
--- a/platform/lang-impl/src/com/intellij/ui/tabs/ColorSelectionComponent.java
+++ b/platform/lang-impl/src/com/intellij/ui/tabs/ColorSelectionComponent.java
@@ -96,24 +96,24 @@ public class ColorSelectionComponent extends JPanel {
}
@Nullable
- private ColorButton getSelectedButtonInner() {
+ public String getSelectedColorName() {
for (String name : myColorToButtonMap.keySet()) {
ColorButton button = myColorToButtonMap.get(name);
- if (button.isSelected()) return button;
+ if (!button.isSelected()) continue;
+ if (button instanceof CustomColorButton) return ColorUtil.toHex(button.getColor());
+ return name;
}
return null;
}
@Nullable
- public String getSelectedColorName() {
- ColorButton button = getSelectedButtonInner();
- return button == null? null : button instanceof CustomColorButton ? ColorUtil.toHex(button.getColor()) : button.getText();
- }
-
- @Nullable
public Color getSelectedColor() {
- ColorButton button = getSelectedButtonInner();
- return button == null? null : button.getColor();
+ for (String name : myColorToButtonMap.keySet()) {
+ ColorButton button = myColorToButtonMap.get(name);
+ if (!button.isSelected()) continue;
+ return button.getColor();
+ }
+ return null;
}
public void initDefault(@NotNull FileColorManager manager, @Nullable String selectedColorName) {
diff --git a/platform/lang-impl/src/com/intellij/ui/tabs/FileColorManagerImpl.java b/platform/lang-impl/src/com/intellij/ui/tabs/FileColorManagerImpl.java
index a60889bb9f93..c65af1ecdb4f 100644
--- a/platform/lang-impl/src/com/intellij/ui/tabs/FileColorManagerImpl.java
+++ b/platform/lang-impl/src/com/intellij/ui/tabs/FileColorManagerImpl.java
@@ -18,24 +18,25 @@ package com.intellij.ui.tabs;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.openapi.components.*;
-import com.intellij.openapi.components.StoragePathMacros;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
-import com.intellij.psi.PsiManager;
import com.intellij.ui.ColorUtil;
import com.intellij.ui.FileColorManager;
+import com.intellij.ui.JBColor;
import com.intellij.ui.LightColors;
-import com.intellij.util.containers.hash.LinkedHashMap;
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.UIUtil;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
-import java.util.*;
+import java.util.Collection;
+import java.util.Collections;
import java.util.List;
+import java.util.Map;
/**
* @author spleaner
@@ -52,25 +53,14 @@ public class FileColorManagerImpl extends FileColorManager implements Persistent
private final FileColorsModel myModel;
private FileColorSharedConfigurationManager mySharedConfigurationManager;
- private static final Map<String, Color> ourDefaultColors;
- private static final Map<String, Color> ourDefaultDarkColors;
-
- static {
- ourDefaultColors = new LinkedHashMap<String, Color>();
- ourDefaultColors.put("Blue", new Color(0xdcf0ff));
- ourDefaultColors.put("Green", new Color(231, 250, 219));
- ourDefaultColors.put("Orange", new Color(246, 224, 202));
- ourDefaultColors.put("Rose", new Color(242, 206, 202));
- ourDefaultColors.put("Violet", new Color(222, 213, 241));
- ourDefaultColors.put("Yellow", new Color(255, 255, 228));
- ourDefaultDarkColors = new LinkedHashMap<String, Color>();
- ourDefaultDarkColors.put("Blue", new Color(0x2B3557));
- ourDefaultDarkColors.put("Green", new Color(0x2A3B2C));
- ourDefaultDarkColors.put("Orange", new Color(0x823B1C));
- ourDefaultDarkColors.put("Rose", new Color(0x542F3A));
- ourDefaultDarkColors.put("Violet", new Color(0x4f4056));
- ourDefaultDarkColors.put("Yellow", new Color(0x494539));
- }
+ private static final Map<String, Color> ourDefaultColors = ContainerUtil.<String, Color>immutableMapBuilder()
+ .put("Blue", new JBColor(new Color(0xdcf0ff), new Color(0x2B3557)))
+ .put("Green", new JBColor(new Color(231, 250, 219), new Color(0x2A3B2C)))
+ .put("Orange", new JBColor(new Color(246, 224, 202), new Color(0x823B1C)))
+ .put("Rose", new JBColor(new Color(242, 206, 202), new Color(0x542F3A)))
+ .put("Violet", new JBColor(new Color(222, 213, 241), new Color(0x4f4056)))
+ .put("Yellow", new JBColor(new Color(255, 255, 228), new Color(0x494539)))
+ .build();
public FileColorManagerImpl(@NotNull final Project project) {
myProject = project;
@@ -133,7 +123,7 @@ public class FileColorManagerImpl extends FileColorManager implements Persistent
@SuppressWarnings({"MethodMayBeStatic"})
@Nullable
public Color getColor(@NotNull final String name) {
- final Color color = UIUtil.isUnderDarcula() ? ourDefaultDarkColors.get(name) : ourDefaultColors.get(name);
+ Color color = ourDefaultColors.get(name);
return color == null ? ColorUtil.fromHex(name, null) : color;
}
@@ -151,8 +141,7 @@ public class FileColorManagerImpl extends FileColorManager implements Persistent
@Override
@SuppressWarnings({"MethodMayBeStatic"})
public Collection<String> getColorNames() {
- final Set<String> names = ourDefaultColors.keySet();
- final List<String> sorted = new ArrayList<String>(names);
+ List<String> sorted = ContainerUtil.newArrayList(ourDefaultColors.keySet());
Collections.sort(sorted);
return sorted;
}
diff --git a/platform/lang-impl/src/com/intellij/usageView/UsageViewUtil.java b/platform/lang-impl/src/com/intellij/usageView/UsageViewUtil.java
index ca230c790e65..4dee56707ae0 100644
--- a/platform/lang-impl/src/com/intellij/usageView/UsageViewUtil.java
+++ b/platform/lang-impl/src/com/intellij/usageView/UsageViewUtil.java
@@ -24,10 +24,13 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.GeneratedSourcesFilter;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.wm.StatusBar;
+import com.intellij.openapi.wm.WindowManager;
import com.intellij.psi.ElementDescriptionUtil;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiReference;
+import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.util.MoveRenameUsageInfo;
import com.intellij.refactoring.util.NonCodeUsageInfo;
import com.intellij.usages.Usage;
@@ -179,4 +182,17 @@ public class UsageViewUtil {
}
return usageInfos;
}
+
+ public static boolean reportNonRegularUsages(UsageInfo[] usages, final Project project) {
+ boolean inGeneratedCode = hasUsagesInGeneratedCode(usages, project);
+ if (hasNonCodeUsages(usages) || inGeneratedCode) {
+ StatusBar statusBar = WindowManager.getInstance().getStatusBar(project);
+ if (statusBar != null) {
+ statusBar.setInfo(inGeneratedCode ? RefactoringBundle.message("occurrences.found.in.comments.strings.non.java.files.and.generated.code")
+ : RefactoringBundle.message("occurrences.found.in.comments.strings.and.non.java.files"));
+ }
+ return true;
+ }
+ return false;
+ }
}
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 85077380ea6e..da85132806e5 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java
@@ -531,7 +531,8 @@ public class FileBasedIndexImpl extends FileBasedIndex {
extension.hasSnapshotMapping() && IdIndex.ourSnapshotMappingsEnabled
? createInputsIndexExternalizer(extension, indexId, extension.getKeyDescriptor())
: null;
- index = new MapReduceIndex<K, V, FileContent>(indexId, extension.getIndexer(), storage, externalizer, extension.getValueExternalizer());
+ index = new MapReduceIndex<K, V, FileContent>(
+ indexId, extension.getIndexer(), storage, externalizer, extension.getValueExternalizer(), extension instanceof PsiDependentIndex);
}
index.setInputIdToDataKeysIndex(new Factory<PersistentHashMap<Integer, Collection<K>>>() {
@Override
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 6427765295c5..0060cb2fb159 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/MapReduceIndex.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/MapReduceIndex.java
@@ -17,10 +17,14 @@
package com.intellij.util.indexing;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream;
import com.intellij.openapi.util.io.ByteSequence;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiFile;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.*;
import com.intellij.util.io.*;
@@ -50,6 +54,7 @@ public class MapReduceIndex<Key, Value, Input> implements UpdatableIndex<Key,Val
private final DataExternalizer<Value> myValueExternalizer;
private final DataExternalizer<Collection<Key>> mySnapshotIndexExternalizer;
+ private final boolean myIsPsiBackedIndex;
private PersistentHashMap<Integer, Collection<Key>> myInputsIndex;
private PersistentHashMap<Integer, ByteSequence> myContents;
@@ -75,14 +80,16 @@ public class MapReduceIndex<Key, Value, Input> implements UpdatableIndex<Key,Val
public MapReduceIndex(@Nullable final ID<Key, Value> indexId,
DataIndexer<Key, Value, Input> indexer,
@NotNull IndexStorage<Key, Value> storage) throws IOException {
- this(indexId, indexer, storage, null, null);
+ this(indexId, indexer, storage, null, null, false);
}
public MapReduceIndex(@Nullable final ID<Key, Value> indexId,
DataIndexer<Key, Value, Input> indexer,
@NotNull IndexStorage<Key, Value> storage,
DataExternalizer<Collection<Key>> snapshotIndexExternalizer,
- DataExternalizer<Value> valueDataExternalizer) throws IOException {
+ DataExternalizer<Value> valueDataExternalizer,
+ boolean psiBasedIndex
+ ) throws IOException {
myIndexId = indexId;
myIndexer = indexer;
myStorage = storage;
@@ -91,6 +98,7 @@ public class MapReduceIndex<Key, Value, Input> implements UpdatableIndex<Key,Val
mySnapshotIndexExternalizer = snapshotIndexExternalizer;
myValueExternalizer = valueDataExternalizer;
myContents = createContentsIndex();
+ myIsPsiBackedIndex = psiBasedIndex;
}
private PersistentHashMap<Integer, ByteSequence> createContentsIndex() throws IOException {
@@ -557,7 +565,34 @@ public class MapReduceIndex<Key, Value, Input> implements UpdatableIndex<Key,Val
return result;
}
- private static Integer getHashOfContent(FileContent content) throws IOException {
+ private Integer getHashOfContent(FileContent content) throws IOException {
+ if (myIsPsiBackedIndex && myHasSnapshotMapping && content instanceof FileContentImpl) {
+ // psi backed index should use existing psi to build index value (FileContentImpl.getPsiFileAccountingForUnsavedDocument())
+ // so we should use different bytes to calculate hash(Id)
+ Integer previouslyCalculatedUncommittedHashId = content.getUserData(ourSavedUncommittedHashIdKey);
+
+ if (previouslyCalculatedUncommittedHashId == null) {
+ Document document = FileDocumentManager.getInstance().getCachedDocument(content.getFile());
+
+ if (document != null) { // if document is not committed
+ PsiDocumentManager psiDocumentManager = PsiDocumentManager.getInstance(content.getProject());
+
+ if (psiDocumentManager.isUncommited(document)) {
+ PsiFile file = psiDocumentManager.getCachedPsiFile(document);
+ Charset charset = ((FileContentImpl)content).getCharset();
+
+ if (file != null) {
+ previouslyCalculatedUncommittedHashId = ContentHashesSupport
+ .calcContentHashIdWithFileType(file.getText().getBytes(charset), charset,
+ content.getFileType());
+ content.putUserData(ourSavedUncommittedHashIdKey, previouslyCalculatedUncommittedHashId);
+ }
+ }
+ }
+ }
+ if (previouslyCalculatedUncommittedHashId != null) return previouslyCalculatedUncommittedHashId;
+ }
+
Integer previouslyCalculatedContentHashId = content.getUserData(ourSavedContentHashIdKey);
if (previouslyCalculatedContentHashId == null) {
byte[] hash = content instanceof FileContentImpl ? ((FileContentImpl)content).getHash():null;
@@ -616,6 +651,7 @@ public class MapReduceIndex<Key, Value, Input> implements UpdatableIndex<Key,Val
}
private static final com.intellij.openapi.util.Key<Integer> ourSavedContentHashIdKey = com.intellij.openapi.util.Key.create("saved.content.hash.id");
+ private static final com.intellij.openapi.util.Key<Integer> ourSavedUncommittedHashIdKey = com.intellij.openapi.util.Key.create("saved.uncommitted.hash.id");
protected void updateWithMap(final int inputId,
int savedInputId, @NotNull Map<Key, Value> newData,
diff --git a/platform/platform-api/src/com/intellij/execution/process/AnsiEscapeDecoder.java b/platform/platform-api/src/com/intellij/execution/process/AnsiEscapeDecoder.java
index 0ecf7c8a6dd0..58a8e40db2d6 100644
--- a/platform/platform-api/src/com/intellij/execution/process/AnsiEscapeDecoder.java
+++ b/platform/platform-api/src/com/intellij/execution/process/AnsiEscapeDecoder.java
@@ -19,80 +19,105 @@ import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.util.List;
+import java.util.regex.Pattern;
/**
+ * See <a href="http://en.wikipedia.org/wiki/ANSI_escape_code">ANSI escape code</a>.
+ *
* @author traff
*/
public class AnsiEscapeDecoder {
- private static final char TEXT_ATTRS_PREFIX_CH = '\u001B';
- private static final String TEXT_ATTRS_PREFIX = Character.toString(TEXT_ATTRS_PREFIX_CH) + "[";
- private static final String TEXT_ATTRS_PATTERN = "m" + TEXT_ATTRS_PREFIX_CH + "\\[";
+ private static final char ESC_CHAR = '\u001B'; // Escape sequence start character
+ private static final String CSI = ESC_CHAR + "["; // "Control Sequence Initiator"
+ private static final Pattern INNER_PATTERN = Pattern.compile(Pattern.quote("m" + CSI));
- private Key myCurrentColor;
+ private Key myCurrentTextAttributes;
/**
* Parses ansi-color codes from text and sends text fragments with color attributes to textAcceptor
*
- * @param text
- * @param outputType
- * @param textAcceptor if implements ColoredTextAcceptor then it will receive text fragments with color attributes
- * if implements ColoredChunksAcceptor then it will receive list of pairs <text, attribute>
+ * @param text a string with ANSI escape sequences
+ * @param outputType stdout/stderr/system (from {@link ProcessOutputTypes})
+ * @param textAcceptor receives text fragments with color attributes.
+ * It can implement ColoredChunksAcceptor to receive list of pairs (text, attribute).
*/
- public void escapeText(String text, Key outputType, ColoredTextAcceptor textAcceptor) {
- final List<Pair<String, Key>> textChunks = ContainerUtil.newArrayList();
+ public void escapeText(@NotNull String text, @NotNull Key outputType, @NotNull ColoredTextAcceptor textAcceptor) {
+ List<Pair<String, Key>> chunks = null;
int pos = 0;
while (true) {
- int macroPos = text.indexOf(TEXT_ATTRS_PREFIX, pos);
- if (macroPos < 0) break;
- if (pos != macroPos) {
- textChunks.add(Pair.create(text.substring(pos, macroPos), getCurrentOutputAttributes(outputType)));
+ int escSeqBeginInd = text.indexOf(CSI, pos);
+ if (escSeqBeginInd < 0) {
+ break;
}
- final int macroEndPos = getEndMacroPos(text, macroPos);
- if (macroEndPos < 0) {
+ if (pos < escSeqBeginInd) {
+ chunks = processTextChunk(chunks, text.substring(pos, escSeqBeginInd), outputType, textAcceptor);
+ }
+ final int escSeqEndInd = findEscSeqEndIndex(text, escSeqBeginInd);
+ if (escSeqEndInd < 0) {
break;
}
+ String escSeq = text.substring(escSeqBeginInd, escSeqEndInd);
// this is a simple fix for RUBY-8996:
// we replace several consecutive escape sequences with one which contains all these sequences
- final String colorAttribute = text.substring(macroPos, macroEndPos).replaceAll(TEXT_ATTRS_PATTERN, ";");
- myCurrentColor = ColoredOutputTypeRegistry.getInstance().getOutputKey(colorAttribute);
- pos = macroEndPos;
+ String colorAttribute = INNER_PATTERN.matcher(escSeq).replaceAll(";");
+ myCurrentTextAttributes = ColoredOutputTypeRegistry.getInstance().getOutputKey(colorAttribute);
+ pos = escSeqEndInd;
}
if (pos < text.length()) {
- textChunks.add(Pair.create(text.substring(pos), getCurrentOutputAttributes(outputType)));
+ chunks = processTextChunk(chunks, text.substring(pos), outputType, textAcceptor);
}
- if (textAcceptor instanceof ColoredChunksAcceptor) {
- ((ColoredChunksAcceptor)textAcceptor).coloredChunksAvailable(textChunks);
- }
- else {
- coloredTextAvailable(textChunks, textAcceptor);
+ if (chunks != null && textAcceptor instanceof ColoredChunksAcceptor) {
+ ((ColoredChunksAcceptor)textAcceptor).coloredChunksAvailable(chunks);
}
}
- // selects all consecutive escape sequences
- private static int getEndMacroPos(final String text, int macroPos) {
- int endMacroPos = text.indexOf('m', macroPos);
- while (endMacroPos >= 0) {
- endMacroPos += 1;
- macroPos = text.indexOf(TEXT_ATTRS_PREFIX, endMacroPos);
- if (macroPos != endMacroPos) {
+ /*
+ * Selects all consecutive escape sequences and returns escape sequence end index (exclusive).
+ * If the escape sequence isn't finished, returns -1.
+ */
+ private static int findEscSeqEndIndex(@NotNull String text, int escSeqBeginInd) {
+ escSeqBeginInd = text.indexOf('m', escSeqBeginInd);
+ while (escSeqBeginInd >= 0) {
+ escSeqBeginInd++;
+ if (!text.regionMatches(escSeqBeginInd, CSI, 0, CSI.length())) {
break;
}
- endMacroPos = text.indexOf('m', macroPos);
+ escSeqBeginInd = text.indexOf('m', escSeqBeginInd);
+ }
+ return escSeqBeginInd;
+ }
+
+ @Nullable
+ private List<Pair<String, Key>> processTextChunk(@Nullable List<Pair<String, Key>> buffer,
+ @NotNull String text,
+ @NotNull Key outputType,
+ @NotNull ColoredTextAcceptor textAcceptor) {
+ Key attributes = getCurrentOutputAttributes(outputType);
+ if (textAcceptor instanceof ColoredChunksAcceptor) {
+ if (buffer == null) {
+ buffer = ContainerUtil.newArrayListWithCapacity(1);
+ }
+ buffer.add(Pair.create(text, attributes));
+ }
+ else {
+ textAcceptor.coloredTextAvailable(text, attributes);
}
- return endMacroPos;
+ return buffer;
}
- protected Key getCurrentOutputAttributes(final Key outputType) {
+ @NotNull
+ protected Key getCurrentOutputAttributes(@NotNull Key outputType) {
if (outputType == ProcessOutputTypes.STDERR || outputType == ProcessOutputTypes.SYSTEM) {
return outputType;
}
- return myCurrentColor != null ? myCurrentColor : outputType;
+ return myCurrentTextAttributes != null ? myCurrentTextAttributes : outputType;
}
- public void coloredTextAvailable(@NotNull final List<Pair<String, Key>> textChunks, ColoredTextAcceptor textAcceptor) {
- for (final Pair<String, Key> textChunk : textChunks) {
+ public void coloredTextAvailable(@NotNull List<Pair<String, Key>> textChunks, ColoredTextAcceptor textAcceptor) {
+ for (Pair<String, Key> textChunk : textChunks) {
textAcceptor.coloredTextAvailable(textChunk.getFirst(), textChunk.getSecond());
}
}
diff --git a/platform/platform-api/src/com/intellij/execution/process/CapturingAnsiEscapesAwareProcessHandler.java b/platform/platform-api/src/com/intellij/execution/process/CapturingAnsiEscapesAwareProcessHandler.java
index c76e79a0bfd6..96544b8ba83c 100644
--- a/platform/platform-api/src/com/intellij/execution/process/CapturingAnsiEscapesAwareProcessHandler.java
+++ b/platform/platform-api/src/com/intellij/execution/process/CapturingAnsiEscapesAwareProcessHandler.java
@@ -44,7 +44,8 @@ public class CapturingAnsiEscapesAwareProcessHandler extends CapturingProcessHan
private static class AnsiEscapesAwareAdapter extends CapturingProcessAdapter implements AnsiEscapeDecoder.ColoredTextAcceptor {
private final AnsiEscapeDecoder myAnsiEscapeDecoder = new AnsiEscapeDecoder() {
@Override
- protected Key getCurrentOutputAttributes(Key outputType) {
+ @NotNull
+ protected Key getCurrentOutputAttributes(@NotNull Key outputType) {
return outputType; //we don't need color information - only stdout and stderr keys are added to output in CapturingProcessAdapter
}
};
diff --git a/platform/platform-api/src/com/intellij/execution/process/ColoredOutputTypeRegistry.java b/platform/platform-api/src/com/intellij/execution/process/ColoredOutputTypeRegistry.java
index 7fff03827fb4..be9dccb0dbca 100644
--- a/platform/platform-api/src/com/intellij/execution/process/ColoredOutputTypeRegistry.java
+++ b/platform/platform-api/src/com/intellij/execution/process/ColoredOutputTypeRegistry.java
@@ -8,6 +8,7 @@ import com.intellij.openapi.editor.markup.EffectType;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.util.Key;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import java.awt.*;
import java.util.HashMap;
@@ -73,6 +74,7 @@ public class ColoredOutputTypeRegistry {
see full doc at http://en.wikipedia.org/wiki/ANSI_escape_code
*/
+ @NotNull
public Key getOutputKey(@NonNls String attribute) {
final Key key = myRegisteredKeys.get(attribute);
if (key != null) {
diff --git a/platform/platform-api/src/com/intellij/ide/CompositeSelectInTarget.java b/platform/platform-api/src/com/intellij/ide/CompositeSelectInTarget.java
index 7facb6f990f8..e493770d6605 100644
--- a/platform/platform-api/src/com/intellij/ide/CompositeSelectInTarget.java
+++ b/platform/platform-api/src/com/intellij/ide/CompositeSelectInTarget.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.
@@ -25,5 +25,5 @@ import java.util.Collection;
*/
public interface CompositeSelectInTarget extends SelectInTarget{
@NotNull
- Collection<SelectInTarget> getSubTargets(SelectInContext context);
+ Collection<SelectInTarget> getSubTargets(@NotNull SelectInContext context);
}
diff --git a/platform/platform-api/src/com/intellij/ide/SelectInTarget.java b/platform/platform-api/src/com/intellij/ide/SelectInTarget.java
index 3e5f9d0e87bd..e7d834ac2268 100644
--- a/platform/platform-api/src/com/intellij/ide/SelectInTarget.java
+++ b/platform/platform-api/src/com/intellij/ide/SelectInTarget.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.
@@ -21,6 +21,7 @@ import org.jetbrains.annotations.Nullable;
public interface SelectInTarget {
ExtensionPointName<SelectInTarget> EP_NAME = new ExtensionPointName<SelectInTarget>("com.intellij.selectInTarget");
+ @Override
String toString();
/**
diff --git a/platform/platform-api/src/com/intellij/openapi/actionSystem/AbbreviationManager.java b/platform/platform-api/src/com/intellij/openapi/actionSystem/AbbreviationManager.java
index 78db7cf0ed5c..1e03a3482ad4 100644
--- a/platform/platform-api/src/com/intellij/openapi/actionSystem/AbbreviationManager.java
+++ b/platform/platform-api/src/com/intellij/openapi/actionSystem/AbbreviationManager.java
@@ -15,7 +15,7 @@
*/
package com.intellij.openapi.actionSystem;
-import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.components.ServiceManager;
import java.util.List;
import java.util.Set;
@@ -26,11 +26,16 @@ import java.util.Set;
*/
public abstract class AbbreviationManager {
public static AbbreviationManager getInstance() {
- return ApplicationManager.getApplication().getComponent(AbbreviationManager.class);
+ return ServiceManager.getService(AbbreviationManager.class);
}
+
public abstract Set<String> getAbbreviations();
+
public abstract Set<String> getAbbreviations(String actionId);
+
public abstract List<String> findActions(String abbreviation);
+
public abstract void register(String abbreviation, String actionId);
+
public abstract void remove(String abbreviation, String actionId);
}
diff --git a/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/CaretSpecificDataContext.java b/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/CaretSpecificDataContext.java
new file mode 100644
index 000000000000..e53cc48e4d5a
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/CaretSpecificDataContext.java
@@ -0,0 +1,47 @@
+/*
+ * 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.openapi.actionSystem.CommonDataKeys;
+import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.actionSystem.DataContextWrapper;
+import com.intellij.openapi.editor.Caret;
+import com.intellij.openapi.fileEditor.FileEditorManager;
+import com.intellij.openapi.project.Project;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class CaretSpecificDataContext extends DataContextWrapper {
+ private final Caret myCaret;
+
+ public CaretSpecificDataContext(@NotNull DataContext delegate, @NotNull Caret caret) {
+ super(delegate);
+ myCaret = caret;
+ }
+
+ @Nullable
+ @Override
+ public Object getData(@NonNls String dataId) {
+ Project project = (Project)super.getData(CommonDataKeys.PROJECT.getName());
+ if (project == null) {
+ return null;
+ }
+ FileEditorManager fm = FileEditorManager.getInstance(project);
+ Object data = fm == null ? null : fm.getData(dataId, myCaret.getEditor(), myCaret);
+ return data == null ? super.getData(dataId) : data;
+ }
+}
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 945c52022984..d93a508f97bd 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,13 +26,14 @@ import org.jetbrains.annotations.Nullable;
import java.awt.event.KeyEvent;
+import static com.intellij.openapi.actionSystem.CommonDataKeys.EDITOR;
import static com.intellij.openapi.actionSystem.CommonDataKeys.PROJECT;
public abstract class EditorAction extends AnAction implements DumbAware {
private EditorActionHandler myHandler;
private boolean myHandlersLoaded;
- public EditorActionHandler getHandler() {
+ public final EditorActionHandler getHandler() {
ensureHandlersLoaded();
return myHandler;
}
@@ -46,6 +47,7 @@ public abstract class EditorAction extends AnAction implements DumbAware {
ensureHandlersLoaded();
EditorActionHandler tmp = myHandler;
myHandler = newHandler;
+ myHandler.setWorksInInjected(isInInjectedContext());
return tmp;
}
@@ -58,12 +60,22 @@ public abstract class EditorAction extends AnAction implements DumbAware {
final EditorActionHandlerBean handlerBean = extensions[i];
if (handlerBean.action.equals(id)) {
myHandler = handlerBean.getHandler(myHandler);
+ myHandler.setWorksInInjected(isInInjectedContext());
}
}
}
}
@Override
+ public void setInjectedContext(boolean worksInInjected) {
+ super.setInjectedContext(worksInInjected);
+ // we assume that this method is called in constructor at the point
+ // where the chain of handlers is not initialized yet
+ // and it's enough to pass the flag to the default handler only
+ myHandler.setWorksInInjected(isInInjectedContext());
+ }
+
+ @Override
public final void actionPerformed(AnActionEvent e) {
DataContext dataContext = e.getDataContext();
Editor editor = getEditor(dataContext);
@@ -72,7 +84,7 @@ public abstract class EditorAction extends AnAction implements DumbAware {
@Nullable
protected Editor getEditor(@NotNull DataContext dataContext) {
- return CommonDataKeys.EDITOR.getData(dataContext);
+ return EDITOR.getData(dataContext);
}
public final void actionPerformed(final Editor editor, @NotNull final DataContext dataContext) {
@@ -102,7 +114,7 @@ public abstract class EditorAction extends AnAction implements DumbAware {
}
public void update(Editor editor, Presentation presentation, DataContext dataContext) {
- presentation.setEnabled(getHandler().isEnabled(editor, dataContext));
+ presentation.setEnabled(getHandler().isEnabled(editor, null, dataContext));
}
public void updateForKeyboardAccess(Editor editor, Presentation presentation, DataContext dataContext) {
diff --git a/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorActionHandler.java b/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorActionHandler.java
index c43fd13d8bef..294622ce1916 100644
--- a/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorActionHandler.java
+++ b/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorActionHandler.java
@@ -15,7 +15,7 @@
*/
package com.intellij.openapi.editor.actionSystem;
-import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.CaretAction;
import com.intellij.openapi.editor.Editor;
@@ -35,7 +35,9 @@ import org.jetbrains.annotations.Nullable;
*/
public abstract class EditorActionHandler {
private final boolean myRunForEachCaret;
+ private boolean myWorksInInjected;
private boolean inExecution;
+ private boolean inCheck;
protected EditorActionHandler() {
this(false);
@@ -46,17 +48,92 @@ public abstract class EditorActionHandler {
}
/**
- * Checks if the action handler is currently enabled.
- *
- * @param editor the editor in which the action is invoked.
- * @param dataContext the data context for the action.
- * @return true if the action is enabled, false otherwise
+ * @deprecated Implementations should override
+ * {@link #isEnabledForCaret(com.intellij.openapi.editor.Editor, com.intellij.openapi.editor.Caret, com.intellij.openapi.actionSystem.DataContext)}
+ * instead,
+ * client code should invoke
+ * {@link #isEnabled(com.intellij.openapi.editor.Editor, com.intellij.openapi.editor.Caret, com.intellij.openapi.actionSystem.DataContext)}
+ * instead.
*/
- public boolean isEnabled(Editor editor, DataContext dataContext) {
- return true;
+ public boolean isEnabled(Editor editor, final DataContext dataContext) {
+ if (inCheck) {
+ return true;
+ }
+ inCheck = true;
+ try {
+ if (editor == null) {
+ return false;
+ }
+ Editor hostEditor = dataContext == null ? null : CommonDataKeys.HOST_EDITOR.getData(dataContext);
+ if (hostEditor == null) {
+ hostEditor = editor;
+ }
+ final boolean[] result = new boolean[1];
+ final CaretTask check = new CaretTask() {
+ @Override
+ public void perform(@NotNull Caret caret, @Nullable DataContext dataContext) {
+ result[0] = true;
+ }
+ };
+ if (myRunForEachCaret) {
+ hostEditor.getCaretModel().runForEachCaret(new CaretAction() {
+ @Override
+ public void perform(Caret caret) {
+ doIfEnabled(caret, dataContext, check);
+ }
+ });
+ }
+ else {
+ doIfEnabled(hostEditor.getCaretModel().getCurrentCaret(), dataContext, check);
+ }
+ return result[0];
+ }
+ finally {
+ inCheck = false;
+ }
+ }
+
+ private void doIfEnabled(@NotNull Caret hostCaret, @Nullable DataContext context, @NotNull CaretTask task) {
+ DataContext caretContext = context == null ? null : new CaretSpecificDataContext(context, hostCaret);
+ if (myWorksInInjected && caretContext != null) {
+ DataContext injectedCaretContext = AnActionEvent.getInjectedDataContext(caretContext);
+ Caret injectedCaret = CommonDataKeys.CARET.getData(injectedCaretContext);
+ if (injectedCaret != null && injectedCaret != hostCaret && isEnabledForCaret(injectedCaret.getEditor(), injectedCaret, injectedCaretContext)) {
+ task.perform(injectedCaret, injectedCaretContext);
+ return;
+ }
+ }
+ if (isEnabledForCaret(hostCaret.getEditor(), hostCaret, caretContext)) {
+ task.perform(hostCaret, caretContext);
+ }
}
/**
+ * Implementations can override this method to define whether handler is enabled for a specific caret in a given editor.
+ */
+ protected boolean isEnabledForCaret(@NotNull Editor editor, @NotNull Caret caret, DataContext dataContext) {
+ if (inCheck) {
+ return true;
+ }
+ inCheck = true;
+ try {
+ //noinspection deprecation
+ return isEnabled(editor, dataContext);
+ }
+ finally {
+ inCheck = false;
+ }
+ }
+
+ /**
+ * If <code>caret</code> is <code>null</code>, checks whether handler is enabled in general (i.e. enabled for at least one caret in editor),
+ * if <code>caret</code> is not <code>null</code>, checks whether it's enabled for specified caret.
+ */
+ public final boolean isEnabled(@NotNull Editor editor, @Nullable Caret caret, DataContext dataContext) {
+ //noinspection deprecation
+ return caret == null ? isEnabled(editor, dataContext) : isEnabledForCaret(editor, caret, dataContext);
+ }
+ /**
* @deprecated To implement action logic, override
* {@link #doExecute(com.intellij.openapi.editor.Editor, com.intellij.openapi.editor.Caret, com.intellij.openapi.actionSystem.DataContext)},
* to invoke the handler, call
@@ -112,22 +189,49 @@ public abstract class EditorActionHandler {
* @param editor the editor in which the action is invoked.
* @param dataContext the data context for the action.
*/
- public final void execute(@NotNull final Editor editor, @Nullable Caret contextCaret, final DataContext dataContext) {
+ public final void execute(@NotNull Editor editor, @Nullable final Caret contextCaret, final DataContext dataContext) {
+ Editor hostEditor = dataContext == null ? null : CommonDataKeys.HOST_EDITOR.getData(dataContext);
+ if (hostEditor == null) {
+ hostEditor = editor;
+ }
if (contextCaret == null && runForAllCarets()) {
- editor.getCaretModel().runForEachCaret(new CaretAction() {
+ hostEditor.getCaretModel().runForEachCaret(new CaretAction() {
@Override
public void perform(Caret caret) {
- doExecute(editor, caret, dataContext);
+ doIfEnabled(caret, dataContext, new CaretTask() {
+ @Override
+ public void perform(@NotNull Caret caret, @Nullable DataContext dataContext) {
+ doExecute(caret.getEditor(), caret, dataContext);
+ }
+ });
}
}, true);
}
else {
- doExecute(editor, contextCaret, dataContext);
+ if (contextCaret == null) {
+ doIfEnabled(hostEditor.getCaretModel().getCurrentCaret(), dataContext, new CaretTask() {
+ @Override
+ public void perform(@NotNull Caret caret, @Nullable DataContext dataContext) {
+ doExecute(caret.getEditor(), null, dataContext);
+ }
+ });
+ }
+ else {
+ doExecute(editor, contextCaret, dataContext);
+ }
}
}
+ void setWorksInInjected(boolean worksInInjected) {
+ myWorksInInjected = worksInInjected;
+ }
+
public DocCommandGroupId getCommandGroupId(Editor editor) {
// by default avoid merging two consequential commands, and, in the same time, pass along the Document
return DocCommandGroupId.noneGroupId(editor.getDocument());
}
+
+ private interface CaretTask {
+ void perform(@NotNull Caret caret, @Nullable DataContext dataContext);
+ }
}
diff --git a/platform/platform-api/src/com/intellij/openapi/fileEditor/EditorDataProvider.java b/platform/platform-api/src/com/intellij/openapi/fileEditor/EditorDataProvider.java
index 7dfec0240c1f..90d05360be0e 100644
--- a/platform/platform-api/src/com/intellij/openapi/fileEditor/EditorDataProvider.java
+++ b/platform/platform-api/src/com/intellij/openapi/fileEditor/EditorDataProvider.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,14 +15,14 @@
*/
package com.intellij.openapi.fileEditor;
+import com.intellij.openapi.editor.Caret;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.vfs.VirtualFile;
/**
* @author peter
*/
public interface EditorDataProvider {
- @Nullable Object getData(@NotNull String dataId, @NotNull Editor e, @NotNull VirtualFile file);
+ @Nullable Object getData(@NotNull String dataId, @NotNull Editor e, @NotNull Caret caret);
}
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 b9589574059d..86e719eef48d 100644
--- a/platform/platform-api/src/com/intellij/openapi/fileEditor/FileEditorManager.java
+++ b/platform/platform-api/src/com/intellij/openapi/fileEditor/FileEditorManager.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,6 +16,7 @@
package com.intellij.openapi.fileEditor;
import com.intellij.openapi.Disposable;
+import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
@@ -184,6 +185,13 @@ public abstract class FileEditorManager {
public abstract void registerExtraEditorDataProvider(@NotNull EditorDataProvider provider, Disposable parentDisposable);
/**
+ * Returns data associated with given editor/caret context. Data providers are registered via
+ * {@link #registerExtraEditorDataProvider(EditorDataProvider, com.intellij.openapi.Disposable)} method.
+ */
+ @Nullable
+ public abstract Object getData(@NotNull String dataId, @NotNull Editor editor, @NotNull Caret caret);
+
+ /**
* Selects a specified file editor tab for the specified editor.
* @param file a file to switch the file editor tab for. The function does nothing if the file is not currently open in the editor.
* @param fileEditorProviderId the ID of the file editor to open; matches the return value of
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 c02f27af5d4b..f35d76fff51c 100644
--- a/platform/platform-api/src/com/intellij/openapi/ui/ComboBoxTableRenderer.java
+++ b/platform/platform-api/src/com/intellij/openapi/ui/ComboBoxTableRenderer.java
@@ -117,7 +117,7 @@ public class ComboBoxTableRenderer<T> extends JLabel implements TableCellRendere
public Component getTableCellEditorComponent(JTable table, final Object value, boolean isSelected, final int row, final int column) {
@SuppressWarnings("unchecked") final T t = (T)value;
myValue = t;
- customizeComponent(t, table, isSelected);
+ customizeComponent(t, table, true);
//noinspection SSBasedInspection
SwingUtilities.invokeLater(new Runnable() {
diff --git a/platform/platform-api/src/com/intellij/openapi/ui/ComponentWithActions.java b/platform/platform-api/src/com/intellij/openapi/ui/ComponentWithActions.java
index d6310f508ed0..889fb2786188 100644
--- a/platform/platform-api/src/com/intellij/openapi/ui/ComponentWithActions.java
+++ b/platform/platform-api/src/com/intellij/openapi/ui/ComponentWithActions.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.
@@ -41,11 +41,11 @@ public interface ComponentWithActions {
boolean isContentBuiltIn();
class Impl implements ComponentWithActions {
- private ActionGroup myToolbar;
- private String myToolbarPlace;
- private JComponent myToolbarContext;
- private JComponent mySearchComponent;
- private JComponent myComponent;
+ private final ActionGroup myToolbar;
+ private final String myToolbarPlace;
+ private final JComponent myToolbarContext;
+ private final JComponent mySearchComponent;
+ private final JComponent myComponent;
public Impl(final ActionGroup toolbar, final String toolbarPlace, final JComponent toolbarContext,
final JComponent searchComponent,
@@ -57,6 +57,7 @@ public interface ComponentWithActions {
myComponent = component;
}
+ @Override
public boolean isContentBuiltIn() {
return false;
}
@@ -65,22 +66,27 @@ public interface ComponentWithActions {
this(null, null, null, null, component);
}
+ @Override
public ActionGroup getToolbarActions() {
return myToolbar;
}
+ @Override
public JComponent getSearchComponent() {
return mySearchComponent;
}
+ @Override
public String getToolbarPlace() {
return myToolbarPlace;
}
+ @Override
public JComponent getToolbarContextComponent() {
return myToolbarContext;
}
+ @Override
@NotNull
public JComponent getComponent() {
return myComponent;
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 6c13964d5789..a262ea0a3b85 100644
--- a/platform/platform-api/src/com/intellij/openapi/ui/MasterDetailsComponent.java
+++ b/platform/platform-api/src/com/intellij/openapi/ui/MasterDetailsComponent.java
@@ -122,7 +122,7 @@ public abstract class MasterDetailsComponent implements Configurable, DetailsCom
private boolean myHasDeletedItems;
protected AutoScrollToSourceHandler myAutoScrollHandler;
- private boolean myToReInitWholePanel = true;
+ protected boolean myToReInitWholePanel = true;
protected MasterDetailsComponent() {
this(new MasterDetailsState());
@@ -139,7 +139,7 @@ public abstract class MasterDetailsComponent implements Configurable, DetailsCom
reInitWholePanelIfNeeded();
}
- private void reInitWholePanelIfNeeded() {
+ protected void reInitWholePanelIfNeeded() {
if (!myToReInitWholePanel) return;
myWholePanel = new JPanel(new BorderLayout()) {
@@ -177,7 +177,8 @@ public abstract class MasterDetailsComponent implements Configurable, DetailsCom
decorator.setActionGroup(group);
}
//left.add(myNorthPanel, BorderLayout.NORTH);
- myMaster = decorator.setPanelBorder(new EmptyBorder(0, 0, 0, 0)).createPanel();
+ myMaster = decorator.setAsUsualTopToolbar().setPanelBorder(new EmptyBorder(0, 0, 0, 0)).createPanel();
+ myNorthPanel.setVisible(false);
} else {
left.add(myNorthPanel, BorderLayout.NORTH);
myMaster = ScrollPaneFactory.createScrollPane(myTree);
@@ -280,6 +281,7 @@ public abstract class MasterDetailsComponent implements Configurable, DetailsCom
}
private void initToolbar() {
+ if (Registry.is("ide.new.project.settings")) return;
DefaultActionGroup group = createToolbarActionGroup();
if (group != null) {
final JComponent component = ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, group, true).getComponent();
diff --git a/platform/platform-api/src/com/intellij/openapi/ui/PanelWithText.java b/platform/platform-api/src/com/intellij/openapi/ui/PanelWithText.java
index 172772139ccf..fc6c3c6686cd 100644
--- a/platform/platform-api/src/com/intellij/openapi/ui/PanelWithText.java
+++ b/platform/platform-api/src/com/intellij/openapi/ui/PanelWithText.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.
@@ -36,7 +36,7 @@ public class PanelWithText extends JPanel {
public PanelWithText(String text) {
super(new GridBagLayout());
- setBorder(BorderFactory.createEtchedBorder());
+ //setBorder(BorderFactory.createEtchedBorder());
myLabel.setText(XmlStringUtil.wrapInHtml(text));
add(myLabel, new GridBagConstraints(0, 0, 1, 1, 1, 1, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(8,8,8,8), 0, 0));
}
diff --git a/platform/platform-api/src/com/intellij/openapi/ui/popup/ListItemDescriptorAdapter.java b/platform/platform-api/src/com/intellij/openapi/ui/popup/ListItemDescriptorAdapter.java
new file mode 100644
index 000000000000..e11e70c74b98
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/openapi/ui/popup/ListItemDescriptorAdapter.java
@@ -0,0 +1,44 @@
+/*
+ * 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.openapi.ui.popup;
+
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+
+public abstract class ListItemDescriptorAdapter<T> implements ListItemDescriptor<T> {
+ @Nullable
+ @Override
+ public String getCaptionAboveOf(T value) {
+ return null;
+ }
+
+ @Nullable
+ @Override
+ public String getTooltipFor(T value) {
+ return null;
+ }
+
+ @Override
+ public Icon getIconFor(T value) {
+ return null;
+ }
+
+ @Override
+ public boolean hasSeparatorAboveOf(T value) {
+ return false;
+ }
+} \ No newline at end of file
diff --git a/platform/platform-api/src/com/intellij/openapi/vfs/VfsUtil.java b/platform/platform-api/src/com/intellij/openapi/vfs/VfsUtil.java
index 3cd467048e98..254f7749fb25 100644
--- a/platform/platform-api/src/com/intellij/openapi/vfs/VfsUtil.java
+++ b/platform/platform-api/src/com/intellij/openapi/vfs/VfsUtil.java
@@ -51,7 +51,9 @@ import java.util.*;
public class VfsUtil extends VfsUtilCore {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vfs.VfsUtil");
- public static final char VFS_PATH_SEPARATOR = '/';
+
+ /** @deprecated incorrect name, use {@link #VFS_SEPARATOR_CHAR} (to be removed in IDEA 15) */
+ public static final char VFS_PATH_SEPARATOR = VFS_SEPARATOR_CHAR;
public static void saveText(@NotNull VirtualFile file, @NotNull String text) throws IOException {
Charset charset = file.getCharset();
@@ -585,7 +587,7 @@ public class VfsUtil extends VfsUtilCore {
if (url == null) {
return null;
}
- final int index = url.lastIndexOf(VFS_PATH_SEPARATOR);
+ final int index = url.lastIndexOf(VfsUtil.VFS_SEPARATOR_CHAR);
return index < 0 ? null : url.substring(0, index);
}
@@ -598,12 +600,12 @@ public class VfsUtil extends VfsUtilCore {
if (urlOrPath == null) {
return null;
}
- final int index = urlOrPath.lastIndexOf(VFS_PATH_SEPARATOR);
+ final int index = urlOrPath.lastIndexOf(VfsUtil.VFS_SEPARATOR_CHAR);
return index < 0 ? null : urlOrPath.substring(index+1);
}
@NotNull
- public static List<VirtualFile> markDirty(boolean recursive, boolean reloadChildren, VirtualFile... files) {
+ public static List<VirtualFile> markDirty(boolean recursive, boolean reloadChildren, @NotNull VirtualFile... files) {
List<VirtualFile> list = ContainerUtil.filter(Condition.NOT_NULL, files);
if (list.isEmpty()) {
return Collections.emptyList();
@@ -626,7 +628,7 @@ public class VfsUtil extends VfsUtilCore {
return list;
}
- public static void markDirtyAndRefresh(boolean async, boolean recursive, boolean reloadChildren, VirtualFile... files) {
+ public static void markDirtyAndRefresh(boolean async, boolean recursive, boolean reloadChildren, @NotNull VirtualFile... files) {
List<VirtualFile> list = markDirty(recursive, reloadChildren, files);
if (list.isEmpty()) return;
LocalFileSystem.getInstance().refreshFiles(list, async, recursive, null);
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 6c40a04f5831..38dcb877e030 100644
--- a/platform/platform-api/src/com/intellij/openapi/wm/FocusCommand.java
+++ b/platform/platform-api/src/com/intellij/openapi/wm/FocusCommand.java
@@ -192,7 +192,7 @@ public abstract class FocusCommand extends ActiveRunnable implements Expirable {
LOG.info("We could not request focus in window on " + myToFocus.getClass().getName());
LOG.info(myAllocation);
}
- if (!SystemInfo.isMac || isForced() ) {
+ if (isForced()) {
myToFocus.requestFocus();
if (shouldLogFocuses) {
LOG.info("Force request focus on " + myToFocus.getClass().getName());
@@ -217,10 +217,6 @@ public abstract class FocusCommand extends ActiveRunnable implements Expirable {
if (myToFocus == null) {
return true;
}
- if (SwingUtilities.getWindowAncestor(myToFocus) == null) {
- clear();
- return true;
- }
return false;
}
diff --git a/platform/platform-api/src/com/intellij/openapi/wm/IdeFocusManager.java b/platform/platform-api/src/com/intellij/openapi/wm/IdeFocusManager.java
index d8f7e86d4b9e..6b4852319899 100644
--- a/platform/platform-api/src/com/intellij/openapi/wm/IdeFocusManager.java
+++ b/platform/platform-api/src/com/intellij/openapi/wm/IdeFocusManager.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.
@@ -163,9 +163,8 @@ public abstract class IdeFocusManager implements FocusRequestor {
public abstract void toFront(JComponent c);
public static IdeFocusManager getInstance(@Nullable Project project) {
- if (project == null) return getGlobalInstance();
+ if (project == null || project.isDisposed() || !project.isInitialized()) return getGlobalInstance();
- if (project.isDisposed() || !project.isInitialized()) return getGlobalInstance();
return project.getComponent(IdeFocusManager.class);
}
diff --git a/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowFactory.java b/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowFactory.java
index 477ff28baef6..cc198e18a140 100644
--- a/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowFactory.java
+++ b/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowFactory.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.openapi.wm;
import com.intellij.openapi.project.Project;
+import org.jetbrains.annotations.NotNull;
/**
* Performs lazy initialization of a toolwindow registered in plugin.xml.
@@ -25,5 +26,5 @@ import com.intellij.openapi.project.Project;
* @see ToolWindowEP
*/
public interface ToolWindowFactory {
- void createToolWindowContent(Project project, ToolWindow toolWindow);
+ void createToolWindowContent(@NotNull Project project, @NotNull ToolWindow toolWindow);
}
diff --git a/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowManager.java b/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowManager.java
index 0e7ddb332151..b616429a11c8 100644
--- a/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowManager.java
+++ b/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowManager.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.
@@ -47,16 +47,25 @@ public abstract class ToolWindowManager {
* @return tool window
* @deprecated {@link com.intellij.openapi.wm.ToolWindowManager#registerToolWindow(String, boolean, ToolWindowAnchor)}
*/
- public abstract ToolWindow registerToolWindow(@NotNull String id,@NotNull JComponent component,@NotNull ToolWindowAnchor anchor);
+ @Deprecated
+ @NotNull
+ public abstract ToolWindow registerToolWindow(@NotNull String id, @NotNull JComponent component, @NotNull ToolWindowAnchor anchor);
/**
* @deprecated {@link com.intellij.openapi.wm.ToolWindowManager#registerToolWindow(String, boolean, ToolWindowAnchor)}
*/
- public abstract ToolWindow registerToolWindow(@NotNull String id,@NotNull JComponent component,@NotNull ToolWindowAnchor anchor, Disposable parentDisposable);
+ @Deprecated
+ @NotNull
+ public abstract ToolWindow registerToolWindow(@NotNull String id,
+ @NotNull JComponent component,
+ @NotNull ToolWindowAnchor anchor,
+ @NotNull Disposable parentDisposable);
/**
* @deprecated {@link com.intellij.openapi.wm.ToolWindowManager#registerToolWindow(String, boolean, ToolWindowAnchor)}
*/
+ @Deprecated
+ @NotNull
public abstract ToolWindow registerToolWindow(@NotNull String id,
@NotNull JComponent component,
@NotNull ToolWindowAnchor anchor,
@@ -65,6 +74,8 @@ public abstract class ToolWindowManager {
/**
* @deprecated {@link com.intellij.openapi.wm.ToolWindowManager#registerToolWindow(String, boolean, ToolWindowAnchor)}
*/
+ @Deprecated
+ @NotNull
public abstract ToolWindow registerToolWindow(@NotNull String id,
@NotNull JComponent component,
@NotNull ToolWindowAnchor anchor,
@@ -72,12 +83,16 @@ public abstract class ToolWindowManager {
boolean canWorkInDumbMode,
boolean canCloseContents);
+ @NotNull
public abstract ToolWindow registerToolWindow(@NotNull String id, boolean canCloseContent, @NotNull ToolWindowAnchor anchor);
+ @NotNull
public abstract ToolWindow registerToolWindow(@NotNull String id, boolean canCloseContent, @NotNull ToolWindowAnchor anchor, boolean secondary);
+ @NotNull
public abstract ToolWindow registerToolWindow(@NotNull String id, boolean canCloseContent, @NotNull ToolWindowAnchor anchor, Disposable parentDisposable, boolean canWorkInDumbMode);
+ @NotNull
public ToolWindow registerToolWindow(@NotNull final String id,
final boolean canCloseContent,
@NotNull final ToolWindowAnchor anchor,
@@ -102,6 +117,7 @@ public abstract class ToolWindowManager {
/**
* @return array of <code>id</code>s of all registered tool windows.
*/
+ @NotNull
public abstract String[] getToolWindowIds();
/**
@@ -120,11 +136,12 @@ public abstract class ToolWindowManager {
/**
* Puts specified runnable to the tail of current command queue.
*/
- public abstract void invokeLater(Runnable runnable);
+ public abstract void invokeLater(@NotNull Runnable runnable);
/**
* Utility method for quick access to the focus manager
*/
+ @NotNull
public abstract IdeFocusManager getFocusManager();
public abstract void notifyByBalloon(@NotNull final String toolWindowId, @NotNull final MessageType type, @NotNull final String htmlBody);
diff --git a/platform/platform-api/src/com/intellij/ui/components/JBScrollPane.java b/platform/platform-api/src/com/intellij/ui/components/JBScrollPane.java
index 83944a51755d..97a42176a25b 100644
--- a/platform/platform-api/src/com/intellij/ui/components/JBScrollPane.java
+++ b/platform/platform-api/src/com/intellij/ui/components/JBScrollPane.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.ui.components;
import com.intellij.openapi.wm.IdeGlassPane;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.util.ArrayUtil;
+import com.intellij.util.ReflectionUtil;
import com.intellij.util.ui.ButtonlessScrollBarUI;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -29,7 +30,6 @@ import javax.swing.plaf.ScrollPaneUI;
import javax.swing.plaf.basic.BasicScrollBarUI;
import java.awt.*;
import java.awt.event.MouseEvent;
-import java.lang.reflect.Method;
public class JBScrollPane extends JScrollPane {
private int myViewportBorderWidth = -1;
@@ -302,9 +302,7 @@ public class JBScrollPane extends JScrollPane {
if (ui instanceof BasicScrollBarUI) {
BasicScrollBarUI bui = (BasicScrollBarUI)ui;
try {
- Method m = BasicScrollBarUI.class.getDeclaredMethod("getThumbBounds", ArrayUtil.EMPTY_CLASS_ARRAY);
- m.setAccessible(true);
- Rectangle rect = (Rectangle)m.invoke(bui);
+ Rectangle rect = (Rectangle)ReflectionUtil.getDeclaredMethod(BasicScrollBarUI.class, "getThumbBounds", ArrayUtil.EMPTY_CLASS_ARRAY).invoke(bui);
Point point = SwingUtilities.convertPoint(e.getComponent(), e.getX(), e.getY(), bar);
return !rect.contains(point);
}
diff --git a/platform/platform-api/src/com/intellij/ui/content/ContentManagerEvent.java b/platform/platform-api/src/com/intellij/ui/content/ContentManagerEvent.java
index 9aae91aaba42..31fe871d0a05 100644
--- a/platform/platform-api/src/com/intellij/ui/content/ContentManagerEvent.java
+++ b/platform/platform-api/src/com/intellij/ui/content/ContentManagerEvent.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,10 @@ package com.intellij.ui.content;
import java.util.EventObject;
public class ContentManagerEvent extends EventObject {
- private Content myContent;
- private int myIndex;
+ private final Content myContent;
+ private final int myIndex;
private boolean myConsumed;
- private ContentOperation myOperation;
+ private final ContentOperation myOperation;
public ContentManagerEvent(Object source, Content content, int index, ContentOperation operation) {
super(source);
@@ -54,7 +54,7 @@ public class ContentManagerEvent extends EventObject {
return myOperation;
}
- public static enum ContentOperation {
+ public enum ContentOperation {
add, remove, undefined
}
-} \ No newline at end of file
+}
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 435c4358959f..bda230eb767e 100644
--- a/platform/platform-api/src/com/intellij/ui/table/JBTable.java
+++ b/platform/platform-api/src/com/intellij/ui/table/JBTable.java
@@ -52,7 +52,6 @@ public class JBTable extends JTable implements ComponentWithEmptyText, Component
private Integer myMinRowHeight;
private boolean myStriped;
- private boolean isTypeAhead = true;
private AsyncProcessIcon myBusyIcon;
private boolean myBusy;
@@ -69,6 +68,8 @@ public class JBTable extends JTable implements ComponentWithEmptyText, Component
public JBTable(final TableModel model, final TableColumnModel columnModel) {
super(model, columnModel);
+ setSurrendersFocusOnKeystroke(true);
+
myEmptyText = new StatusText(this) {
@Override
protected boolean isStatusVisible() {
@@ -421,7 +422,10 @@ public class JBTable extends JTable implements ComponentWithEmptyText, Component
return false;
}
- if (e instanceof KeyEvent && UIUtil.isReallyTypedEvent((KeyEvent)e)) {
+ if (e instanceof KeyEvent) {
+ // do not start editing in autoStartsEdit mode on Ctrl-Z and other non-typed events
+ if (!UIUtil.isReallyTypedEvent((KeyEvent)e)) return false;
+
SpeedSearchSupply supply = SpeedSearchSupply.getSupply(this);
if (supply != null && supply.isPopupActive()) {
return false;
@@ -449,20 +453,43 @@ public class JBTable extends JTable implements ComponentWithEmptyText, Component
add(editorComp);
editorComp.validate();
- IdeFocusManager.findInstanceByComponent(this).requestFocus(editorComp, false);
+ if (surrendersFocusOnKeyStroke()) {
+ // this replaces focus request in JTable.processKeyBinding
+ final IdeFocusManager focusManager = IdeFocusManager.findInstanceByComponent(this);
+ focusManager.setTypeaheadEnabled(false);
+ focusManager.requestFocus(editorComp, true).doWhenProcessed(new Runnable() {
+ @Override
+ public void run() {
+ focusManager.setTypeaheadEnabled(true);
+ }
+ });
+ }
setCellEditor(editor);
setEditingRow(row);
setEditingColumn(column);
editor.addCellEditorListener(this);
- if (isTypeAhead) {
- JTableCellEditorHelper.typeAhead(this, e, row, column);
- }
+
return true;
}
return false;
}
+ /**
+ * Always returns false.
+ * If you're interested in value of JTable.surrendersFocusOnKeystroke property, call JBTable.surrendersFocusOnKeyStroke()
+ * @return false
+ * @see #surrendersFocusOnKeyStroke
+ */
+ @Override
+ public boolean getSurrendersFocusOnKeystroke() {
+ return false; // prevents JTable.processKeyBinding from requesting editor component to be focused
+ }
+
+ public boolean surrendersFocusOnKeyStroke() {
+ return super.getSurrendersFocusOnKeystroke();
+ }
+
private static boolean isTableDecorationSupported() {
return UIUtil.isUnderAlloyLookAndFeel()
|| UIUtil.isUnderNativeMacLookAndFeel()
@@ -472,10 +499,6 @@ public class JBTable extends JTable implements ComponentWithEmptyText, Component
|| UIUtil.isUnderWindowsLookAndFeel();
}
- public void disableTypeAheadInCellEditors() {
- isTypeAhead = false;
- }
-
@NotNull
@Override
public Component prepareRenderer(@NotNull TableCellRenderer renderer, int row, int column) {
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 a842f623ac45..43f06bff2850 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
@@ -49,7 +49,7 @@ public class JBEditorTabs extends JBTabsImpl {
private JBEditorTabsPainter myDefaultPainter = new DefaultEditorTabsPainter();
- public JBEditorTabs(@Nullable Project project, ActionManager actionManager, IdeFocusManager focusManager, @NotNull Disposable parent) {
+ public JBEditorTabs(@Nullable Project project, @NotNull ActionManager actionManager, IdeFocusManager focusManager, @NotNull Disposable parent) {
super(project, actionManager, focusManager, parent);
}
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 60898a6e9bd8..326192072c4b 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
@@ -28,6 +28,7 @@ import com.intellij.openapi.wm.*;
import com.intellij.ui.*;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.ui.awt.RelativeRectangle;
+import com.intellij.ui.components.OrphanGuardian;
import com.intellij.ui.switcher.QuickActionProvider;
import com.intellij.ui.switcher.SwitchProvider;
import com.intellij.ui.switcher.SwitchTarget;
@@ -36,6 +37,7 @@ import com.intellij.ui.tabs.impl.singleRow.SingleRowLayout;
import com.intellij.ui.tabs.impl.singleRow.SingleRowPassInfo;
import com.intellij.ui.tabs.impl.table.TableLayout;
import com.intellij.ui.tabs.impl.table.TablePassInfo;
+import com.intellij.util.Consumer;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.Animator;
@@ -69,7 +71,7 @@ public class JBTabsImpl extends JComponent
public static final Color MAC_AQUA_BG_COLOR = Gray._200;
- final ActionManager myActionManager;
+ @NotNull final ActionManager myActionManager;
private final List<TabInfo> myVisibleInfos = new ArrayList<TabInfo>();
private final Map<TabInfo, Integer> myHiddenInfos = new HashMap<TabInfo, Integer>();
@@ -153,8 +155,8 @@ public class JBTabsImpl extends JComponent
private JBTabsPosition myPosition = JBTabsPosition.top;
private final TabsBorder myBorder = new TabsBorder(this);
- private BaseNavigationAction myNextAction;
- private BaseNavigationAction myPrevAction;
+ private final BaseNavigationAction myNextAction;
+ private final BaseNavigationAction myPrevAction;
private boolean myTabDraggingEnabled;
private DragHelper myDragHelper;
@@ -172,6 +174,7 @@ public class JBTabsImpl extends JComponent
private Runnable myDeferredFocusRequest;
private boolean myAlwaysPaintSelectedTab;
+ private int myFirstTabOffset;
public JBTabsImpl(@NotNull Project project) {
this(project, project);
@@ -185,7 +188,7 @@ public class JBTabsImpl extends JComponent
this(project, ActionManager.getInstance(), focusManager, parent);
}
- public JBTabsImpl(@Nullable Project project, ActionManager actionManager, IdeFocusManager focusManager, @NotNull Disposable parent) {
+ public JBTabsImpl(@Nullable Project project, @NotNull ActionManager actionManager, IdeFocusManager focusManager, @NotNull Disposable parent) {
myProject = project;
myActionManager = actionManager;
myFocusManager = focusManager != null ? focusManager : IdeFocusManager.getGlobalInstance();
@@ -197,13 +200,11 @@ public class JBTabsImpl extends JComponent
myNavigationActions = new DefaultActionGroup();
- if (myActionManager != null) {
- myNextAction = new SelectNextAction(this, myActionManager);
- myPrevAction = new SelectPreviousAction(this, myActionManager);
+ myNextAction = new SelectNextAction(this, myActionManager);
+ myPrevAction = new SelectPreviousAction(this, myActionManager);
- myNavigationActions.add(myNextAction);
- myNavigationActions.add(myPrevAction);
- }
+ myNavigationActions.add(myNextAction);
+ myNavigationActions.add(myPrevAction);
setUiDecorator(null);
@@ -315,6 +316,16 @@ public class JBTabsImpl extends JComponent
}
}
};
+ putClientProperty(OrphanGuardian.CLIENT_PROPERTY_KEY, new OrphanGuardian() {
+
+ @Override
+ public void iterateOrphans(Consumer<JComponent> consumer) {
+ for (TabInfo info : getVisibleInfos()) {
+ if (info == mySelectedInfo) continue;
+ consumer.consume(info.getComponent());
+ }
+ }
+ });
}
protected SingleRowLayout createSingleRowLayout() {
@@ -451,14 +462,14 @@ public class JBTabsImpl extends JComponent
}
private void addTimerUpdate() {
- if (myActionManager != null && !myListenerAdded) {
+ if (!myListenerAdded) {
myActionManager.addTimerListener(500, this);
myListenerAdded = true;
}
}
private void removeTimerUpdate() {
- if (myActionManager != null && myListenerAdded) {
+ if (myListenerAdded) {
myActionManager.removeTimerListener(this);
myListenerAdded = false;
}
@@ -492,6 +503,14 @@ public class JBTabsImpl extends JComponent
myDropInfoIndex = dropInfoIndex;
}
+ public int getFirstTabOffset() {
+ return myFirstTabOffset;
+ }
+
+ public void setFirstTabOffset(int firstTabOffset) {
+ myFirstTabOffset = firstTabOffset;
+ }
+
class TabActionsAutoHideListener extends MouseMotionAdapter implements Weighted {
private TabLabel myCurrentOverLabel;
@@ -1399,7 +1418,7 @@ public class JBTabsImpl extends JComponent
final ActionGroup group = info.getGroup();
final JComponent side = info.getSideComponent();
- if (group != null && myTabs.myActionManager != null) {
+ if (group != null) {
final String place = info.getPlace();
ActionToolbar toolbar =
myTabs.myActionManager.createActionToolbar(place != null ? place : ActionPlaces.UNKNOWN, group, myTabs.myHorizontalSide);
@@ -1604,7 +1623,7 @@ public class JBTabsImpl extends JComponent
return 3;
}
- public static int getGhostTabLength() {
+ public int getGhostTabLength() {
return 15;
}
@@ -2561,6 +2580,7 @@ public class JBTabsImpl extends JComponent
}
private void updateContainer(boolean forced, final boolean layoutNow) {
+ if (myProject != null && !myProject.isOpen()) return;
for (TabInfo each : new ArrayList<TabInfo>(myVisibleInfos)) {
final JComponent eachComponent = each.getComponent();
if (getSelectedInfo() == each && getSelectedInfo() != null) {
@@ -2746,8 +2766,7 @@ public class JBTabsImpl extends JComponent
}
private static boolean isChanged(Object oldObject, Object newObject) {
- if (oldObject == null && newObject == null) return false;
- return oldObject != null && !oldObject.equals(newObject) || newObject != null && !newObject.equals(oldObject);
+ return !Comparing.equal(oldObject, newObject);
}
@Override
@@ -2785,12 +2804,11 @@ public class JBTabsImpl extends JComponent
}
private abstract static class BaseNavigationAction extends AnAction {
-
private final ShadowAction myShadow;
- private final ActionManager myActionManager;
+ @NotNull private final ActionManager myActionManager;
private final JBTabsImpl myTabs;
- protected BaseNavigationAction(final String copyFromID, JBTabsImpl tabs, ActionManager mgr) {
+ protected BaseNavigationAction(@NotNull String copyFromID, @NotNull JBTabsImpl tabs, @NotNull ActionManager mgr) {
myActionManager = mgr;
myTabs = tabs;
myShadow = new ShadowAction(this, myActionManager.getAction(copyFromID), tabs);
@@ -2858,7 +2876,7 @@ public class JBTabsImpl extends JComponent
private static class SelectNextAction extends BaseNavigationAction {
- private SelectNextAction(JBTabsImpl tabs, ActionManager mgr) {
+ private SelectNextAction(JBTabsImpl tabs, @NotNull ActionManager mgr) {
super(IdeActions.ACTION_NEXT_TAB, tabs, mgr);
}
@@ -2874,7 +2892,7 @@ public class JBTabsImpl extends JComponent
}
private static class SelectPreviousAction extends BaseNavigationAction {
- private SelectPreviousAction(JBTabsImpl tabs, ActionManager mgr) {
+ private SelectPreviousAction(JBTabsImpl tabs, @NotNull ActionManager mgr) {
super(IdeActions.ACTION_PREVIOUS_TAB, tabs, mgr);
}
@@ -3351,7 +3369,7 @@ public class JBTabsImpl extends JComponent
return myVisibleInfos.isEmpty();
}
- public static int getInterTabSpaceLength() {
+ public int getInterTabSpaceLength() {
return 1;
}
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 4e5925d2a2ee..6bd2e1aa52bf 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
@@ -209,6 +209,7 @@ public class SingleRowLayout extends TabLayout {
protected void prepareLayoutPassInfo(SingleRowPassInfo data, TabInfo selected) {
data.insets = myTabs.getLayoutInsets();
+ data.insets.left += myTabs.getFirstTabOffset();
final JBTabsImpl.Toolbar selectedToolbar = myTabs.myInfo2Toolbar.get(selected);
data.hToolbar = selectedToolbar != null && myTabs.myHorizontalSide && !selectedToolbar.isEmpty() ? selectedToolbar : null;
@@ -216,7 +217,7 @@ public class SingleRowLayout extends TabLayout {
data.toFitLength = getStrategy().getToFitLength(data);
if (myTabs.isGhostsAlwaysVisible()) {
- data.toFitLength -= JBTabsImpl.getGhostTabLength() * 2 + (JBTabsImpl.getInterTabSpaceLength() * 2);
+ data.toFitLength -= myTabs.getGhostTabLength() * 2 + (myTabs.getInterTabSpaceLength() * 2);
}
}
@@ -236,9 +237,9 @@ public class SingleRowLayout extends TabLayout {
private void layoutLabelsAndGhosts(final SingleRowPassInfo data) {
if (data.firstGhostVisible || myTabs.isGhostsAlwaysVisible()) {
- data.firstGhost = getStrategy().getLayoutRect(data, data.position, JBTabsImpl.getGhostTabLength());
+ data.firstGhost = getStrategy().getLayoutRect(data, data.position, myTabs.getGhostTabLength());
myTabs.layout(myLeftGhost, data.firstGhost);
- data.position += getStrategy().getLengthIncrement(data.firstGhost.getSize()) + JBTabsImpl.getInterTabSpaceLength();
+ data.position += getStrategy().getLengthIncrement(data.firstGhost.getSize()) + myTabs.getInterTabSpaceLength();
}
int deltaToFit = 0;
@@ -275,9 +276,9 @@ public class SingleRowLayout extends TabLayout {
boolean continueLayout = applyTabLayout(data, label, length, deltaToFit);
data.position = getStrategy().getMaxPosition(label.getBounds());
- data.position += JBTabsImpl.getInterTabSpaceLength();
+ data.position += myTabs.getInterTabSpaceLength();
- totalLength = getStrategy().getMaxPosition(label.getBounds()) - positionStart + JBTabsImpl.getInterTabSpaceLength();
+ totalLength = getStrategy().getMaxPosition(label.getBounds()) - positionStart + myTabs.getInterTabSpaceLength();
if (!continueLayout) {
layoutStopped = true;
}
@@ -288,7 +289,7 @@ public class SingleRowLayout extends TabLayout {
}
if (data.lastGhostVisible || myTabs.isGhostsAlwaysVisible()) {
- data.lastGhost = getStrategy().getLayoutRect(data, data.position, JBTabsImpl.getGhostTabLength());
+ data.lastGhost = getStrategy().getLayoutRect(data, data.position, myTabs.getGhostTabLength());
myTabs.layout(myRightGhost, data.lastGhost);
}
}
@@ -366,7 +367,7 @@ public class SingleRowLayout extends TabLayout {
protected int getRequiredLength(TabInfo eachInfo) {
TabLabel label = myTabs.myInfo2Label.get(eachInfo);
return getStrategy().getLengthIncrement(label != null ? label.getPreferredSize() : new Dimension())
- + (myTabs.isEditorTabs() ? JBTabsImpl.getInterTabSpaceLength() : 0);
+ + (myTabs.isEditorTabs() ? myTabs.getInterTabSpaceLength() : 0);
}
@@ -417,13 +418,13 @@ public class SingleRowLayout extends TabLayout {
if (!data.firstGhostVisible && isFirstSide) {
data.firstGhostVisible = !myTabs.isEditorTabs();
if (!myTabs.isGhostsAlwaysVisible() && !myTabs.isEditorTabs()) {
- data.toFitLength -= JBTabsImpl.getGhostTabLength();
+ data.toFitLength -= myTabs.getGhostTabLength();
}
}
else if (!data.lastGhostVisible && !isFirstSide) {
data.lastGhostVisible = !myTabs.isEditorTabs();
if (!myTabs.isGhostsAlwaysVisible() && !myTabs.isEditorTabs()) {
- data.toFitLength -= JBTabsImpl.getGhostTabLength();
+ data.toFitLength -= myTabs.getGhostTabLength();
}
}
}
diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/table/TableLayout.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/table/TableLayout.java
index 1326531e2465..9b313783dea7 100644
--- a/platform/platform-api/src/com/intellij/ui/tabs/impl/table/TableLayout.java
+++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/table/TableLayout.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.
@@ -56,8 +56,8 @@ public class TableLayout extends TabLayout {
eachX = data.toFitRec.x;
}
myTabs.layout(eachLabel, eachX, 0, size.width, 1);
- eachX += size.width + JBTabsImpl.getInterTabSpaceLength();
- data.requiredWidth += size.width + JBTabsImpl.getInterTabSpaceLength();
+ eachX += size.width + myTabs.getInterTabSpaceLength();
+ data.requiredWidth += size.width + myTabs.getInterTabSpaceLength();
}
int selectedRow = -1;
@@ -84,7 +84,7 @@ public class TableLayout extends TabLayout {
if (myTabs.getSelectedInfo() == eachInfo) {
selectedRow = eachRow;
}
- eachX += size.width + JBTabsImpl.getInterTabSpaceLength();
+ eachX += size.width + myTabs.getInterTabSpaceLength();
}
else {
eachTableRow = new TableRow(data);
@@ -161,9 +161,9 @@ public class TableLayout extends TabLayout {
label.setAlignmentToCenter(deltaToFit > 0);
boolean lastCell = i == eachRow.myColumns.size() - 1;
- eachX += width + (lastCell ? 0 : JBTabsImpl.getInterTabSpaceLength());
+ eachX += width + (lastCell ? 0 : myTabs.getInterTabSpaceLength());
}
- eachY += myTabs.myHeaderFitSize.height - 1 + JBTabsImpl.getInterTabSpaceLength() - (row < data.table.size() - 1 ? tabUnderlineFix : 0);
+ eachY += myTabs.myHeaderFitSize.height - 1 + myTabs.getInterTabSpaceLength() - (row < data.table.size() - 1 ? tabUnderlineFix : 0);
row++;
}
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 0975876055b2..c8c50bc94680 100644
--- a/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java
+++ b/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java
@@ -283,7 +283,7 @@ public class Tree extends JTree implements ComponentWithEmptyText, ComponentWith
if (myBusyIcon != null) {
if (myBusy) {
- if (hasFocus()) {
+ if (shouldShowBusyIconIfNeeded()) {
myBusyIcon.resume();
myBusyIcon.setToolTipText("Update is in progress. Click to cancel");
}
@@ -305,6 +305,11 @@ public class Tree extends JTree implements ComponentWithEmptyText, ComponentWith
}
}
+ protected boolean shouldShowBusyIconIfNeeded() {
+ // http://youtrack.jetbrains.com/issue/IDEA-101422 "Rotating wait symbol in Project list whenever typing"
+ return hasFocus();
+ }
+
protected boolean paintNodes() {
return false;
}
@@ -429,7 +434,6 @@ public class Tree extends JTree implements ComponentWithEmptyText, ComponentWith
}
final Method method = ReflectionUtil.getDeclaredMethod(aClass, "isLocationInExpandControl", TreePath.class, int.class, int.class);
if (method != null) {
- method.setAccessible(true);
return (Boolean)method.invoke(ui, path, x, y);
}
}
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 0bcb416c7334..d51891a8ffe4 100644
--- a/platform/platform-api/src/com/intellij/util/net/HttpConfigurable.java
+++ b/platform/platform-api/src/com/intellij/util/net/HttpConfigurable.java
@@ -65,7 +65,7 @@ import java.util.*;
)
public class HttpConfigurable implements PersistentStateComponent<HttpConfigurable>, ApplicationComponent,
ExportableApplicationComponent {
- public static final int CONNECTION_TIMEOUT = SystemProperties.getIntProperty("connection.timeout", 10000);
+ public static final int CONNECTION_TIMEOUT = SystemProperties.getIntProperty("idea.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;
@@ -350,8 +350,6 @@ public class HttpConfigurable implements PersistentStateComponent<HttpConfigurab
final URLConnection connection = openConnection(url);
try {
- connection.setConnectTimeout(CONNECTION_TIMEOUT);
- connection.setReadTimeout(CONNECTION_TIMEOUT);
connection.connect();
connection.getInputStream();
}
@@ -387,6 +385,10 @@ public class HttpConfigurable implements PersistentStateComponent<HttpConfigurab
throw ioe;
}
}
+ if (urlConnection != null) {
+ urlConnection.setReadTimeout(CONNECTION_TIMEOUT);
+ urlConnection.setConnectTimeout(CONNECTION_TIMEOUT);
+ }
return urlConnection;
}
diff --git a/platform/platform-api/src/com/intellij/util/ui/AsyncProcessIcon.java b/platform/platform-api/src/com/intellij/util/ui/AsyncProcessIcon.java
index 3c3b42721b58..3d467232b3e3 100644
--- a/platform/platform-api/src/com/intellij/util/ui/AsyncProcessIcon.java
+++ b/platform/platform-api/src/com/intellij/util/ui/AsyncProcessIcon.java
@@ -71,7 +71,7 @@ public class AsyncProcessIcon extends AnimatedIcon {
return icons;
}
- public void updateLocation(JComponent container) {
+ public void updateLocation(final JComponent container) {
final Rectangle rec = container.getVisibleRect();
final Dimension iconSize = getPreferredSize();
@@ -79,7 +79,14 @@ public class AsyncProcessIcon extends AnimatedIcon {
final Rectangle newBounds = new Rectangle(rec.x + rec.width - iconSize.width, rec.y, iconSize.width, iconSize.height);
if (!newBounds.equals(getBounds())) {
setBounds(newBounds);
- container.repaint();
+ // painting problems with scrollpane
+ // repaint shouldn't be called from paint method
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ container.repaint();
+ }
+ });
}
}
diff --git a/platform/platform-api/src/com/intellij/util/ui/ButtonlessScrollBarUI.java b/platform/platform-api/src/com/intellij/util/ui/ButtonlessScrollBarUI.java
index 57f9cfca8a54..d73e21e8dc3a 100644
--- a/platform/platform-api/src/com/intellij/util/ui/ButtonlessScrollBarUI.java
+++ b/platform/platform-api/src/com/intellij/util/ui/ButtonlessScrollBarUI.java
@@ -23,6 +23,7 @@ import com.intellij.ui.Gray;
import com.intellij.ui.JBColor;
import com.intellij.ui.LightColors;
import com.intellij.ui.components.JBScrollPane;
+import com.intellij.util.ReflectionUtil;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
@@ -316,28 +317,21 @@ public class ButtonlessScrollBarUI extends BasicScrollBarUI {
resetMacScrollbarFadeout();
}
+ private static final Method setValueFrom = ReflectionUtil.getDeclaredMethod(TrackListener.class, "setValueFrom", MouseEvent.class);
+ static {
+ LOG.assertTrue(setValueFrom != null, "Cannot get TrackListener.setValueFrom method");
+ }
+
@Override
protected TrackListener createTrackListener() {
return new TrackListener() {
- private Method mySetValueFrom;
-
- {
- try {
- mySetValueFrom = TrackListener.class.getDeclaredMethod("setValueFrom", MouseEvent.class);
- mySetValueFrom.setAccessible(true);
- }
- catch (Exception e) {
- LOG.error("Cannot get TrackListener.setValueFrom method", e);
- }
- }
-
@Override
public void mousePressed(MouseEvent e) {
if (scrollbar.isEnabled()
&& SwingUtilities.isLeftMouseButton(e)
&& !getThumbBounds().contains(e.getPoint())
&& NSScrollerHelper.getClickBehavior() == NSScrollerHelper.ClickBehavior.JumpToSpot
- && mySetValueFrom != null) {
+ && setValueFrom != null) {
switch (scrollbar.getOrientation()) {
case Adjustable.VERTICAL:
@@ -349,7 +343,7 @@ public class ButtonlessScrollBarUI extends BasicScrollBarUI {
}
isDragging = true;
try {
- mySetValueFrom.invoke(this, e);
+ setValueFrom.invoke(this, e);
}
catch (Exception ex) {
LOG.error(ex);
diff --git a/platform/platform-api/src/com/intellij/util/ui/JTableCellEditorHelper.java b/platform/platform-api/src/com/intellij/util/ui/JTableCellEditorHelper.java
deleted file mode 100644
index 733fec87e0b6..000000000000
--- a/platform/platform-api/src/com/intellij/util/ui/JTableCellEditorHelper.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright 2000-2011 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.DataManager;
-import com.intellij.openapi.actionSystem.CommonDataKeys;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
-import com.intellij.openapi.editor.Editor;
-
-import javax.swing.*;
-import java.awt.*;
-import java.awt.event.KeyEvent;
-import java.util.EventObject;
-
-/**
- * @author Konstantin Bulenkov
- */
-public class JTableCellEditorHelper {
- private JTableCellEditorHelper() {}
-
- public static void typeAhead(final JTable table, final EventObject e, final int row, final int column) {
- if (e instanceof KeyEvent) {
- final Runnable r = new Runnable() {
- @Override
- public void run() {
- if (table.getEditingColumn() != column && table.getEditingRow() != row) return;
-
- Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
- if (focusOwner == null || !SwingUtilities.isDescendingFrom(focusOwner, table)) return;
-
- KeyEvent keyEvent = (KeyEvent)e;
- if (Character.isDefined(keyEvent.getKeyChar())) {
- try {
- selectAll(focusOwner);
-
- Robot r = new Robot();
- r.keyPress(keyEvent.getKeyCode());
- r.keyRelease(keyEvent.getKeyCode());
- }
- catch (AWTException e1) {
- return;
- }
- } else {
- selectAll(focusOwner);
- }
- }
- };
-
- SwingUtilities.invokeLater(r);
- }
- }
-
- private static void selectAll(Component component) {
- if (component instanceof TextComponent) {
- ((TextComponent)component).selectAll();
- } else {
- Editor editor = CommonDataKeys.EDITOR.getData(DataManager.getInstance().getDataContext(component));
- if (editor != null) {
- editor.getSelectionModel().setSelection(0, editor.getDocument().getTextLength());
- }
- }
- }
-}
diff --git a/platform/platform-impl/src/com/intellij/errorreport/itn/ITNProxy.java b/platform/platform-impl/src/com/intellij/errorreport/itn/ITNProxy.java
index 142b3924f96a..ec112437520b 100644
--- a/platform/platform-impl/src/com/intellij/errorreport/itn/ITNProxy.java
+++ b/platform/platform-impl/src/com/intellij/errorreport/itn/ITNProxy.java
@@ -181,8 +181,6 @@ public class ITNProxy {
private static HttpURLConnection post(URL url, byte[] bytes) throws IOException {
HttpURLConnection connection = (HttpURLConnection)HttpConfigurable.getInstance().openConnection(url.toString());
- connection.setReadTimeout(10 * 1000);
- connection.setConnectTimeout(10 * 1000);
connection.setRequestMethod(HTTP_POST);
connection.setDoInput(true);
connection.setDoOutput(true);
diff --git a/platform/platform-impl/src/com/intellij/help/impl/HelpManagerImpl.java b/platform/platform-impl/src/com/intellij/help/impl/HelpManagerImpl.java
index ac197b192284..340fbb9ae186 100644
--- a/platform/platform-impl/src/com/intellij/help/impl/HelpManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/help/impl/HelpManagerImpl.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.
@@ -49,18 +49,17 @@ public class HelpManagerImpl extends HelpManager {
private Object myFXHelpBrowser = null;
public void invokeHelp(@Nullable String id) {
-
if (myHelpSet == null) {
myHelpSet = createHelpSet();
}
- if (SystemInfo.isJavaVersionAtLeast("1.7.0.40") && Registry.is("ide.help.fxbrowser")) {
- showHelpInFXBrowser(id);
+ if (MacHelpUtil.isApplicable() && MacHelpUtil.invokeHelp(id)) {
return;
}
- if (MacHelpUtil.isApplicable()) {
- if (MacHelpUtil.invokeHelp(id)) return;
+ if (SystemInfo.isJavaVersionAtLeast("1.7.0.40") && Registry.is("ide.help.fxbrowser")) {
+ showHelpInFXBrowser(id);
+ return;
}
if (myHelpSet == null) {
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 a73295c90f74..27fd6f52e4a6 100644
--- a/platform/platform-impl/src/com/intellij/help/impl/MacHelpUtil.java
+++ b/platform/platform-impl/src/com/intellij/help/impl/MacHelpUtil.java
@@ -28,20 +28,20 @@ import org.jetbrains.annotations.Nullable;
*/
public class MacHelpUtil {
static boolean invokeHelp(@NonNls @Nullable String id) {
- id = id == null || "top".equals(id) ? "startpage" : id;
+ if (id == null || "top".equals(id)) id = "startpage";
- final ID mainBundle = Foundation.invoke("NSBundle", "mainBundle");
- final ID helpBundle = Foundation.invoke(mainBundle, "objectForInfoDictionaryKey:", Foundation.nsString("CFBundleHelpBookName"));
+ ID mainBundle = Foundation.invoke("NSBundle", "mainBundle");
+ ID helpBundle = Foundation.invoke(mainBundle, "objectForInfoDictionaryKey:", Foundation.nsString("CFBundleHelpBookName"));
if (helpBundle.equals(ID.NIL)) {
return false;
}
- final ID helpManager = Foundation.invoke("NSHelpManager", "sharedHelpManager");
+
+ ID helpManager = Foundation.invoke("NSHelpManager", "sharedHelpManager");
Foundation.invoke(helpManager, "openHelpAnchor:inBook:", Foundation.nsString(id), helpBundle);
return true;
}
static boolean isApplicable() {
- return SystemInfo.isMac && Registry.is("ide.mac.show.native.help") && !PlatformUtils.isCidr() && !PlatformUtils
- .isIdeaCommunity();
+ 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 c8699c083ef4..a7d07c9fa1e8 100644
--- a/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java
+++ b/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java
@@ -590,7 +590,6 @@ public class IdeEventQueue extends EventQueue {
final Method setActive = ReflectionUtil.findMethod(ReflectionUtil.getClassDeclaredMethods(KeyboardFocusManager.class, false), resetMethod, Window.class);
if (setActive != null) {
try {
- setActive.setAccessible(true);
setActive.invoke(mgr, (Window)showingWindow);
}
catch (Exception exc) {
@@ -630,7 +629,6 @@ public class IdeEventQueue extends EventQueue {
if (showingWindow == null) {
Method getNativeFocusOwner = ReflectionUtil.getDeclaredMethod(KeyboardFocusManager.class, "getNativeFocusOwner");
if (getNativeFocusOwner != null) {
- getNativeFocusOwner.setAccessible(true);
try {
Object owner = getNativeFocusOwner.invoke(mgr);
if (owner instanceof Component) {
@@ -744,10 +742,7 @@ public class IdeEventQueue extends EventQueue {
&& !(e instanceof KeyEvent && ((KeyEvent)e).getKeyCode() == KeyEvent.VK_ALT)) {
try {
if (stickyAltField == null) {
- stickyAltField = Class
- .forName("com.sun.java.swing.plaf.windows.WindowsRootPaneUI$AltProcessor")
- .getDeclaredField("menuCanceledOnPress");
- stickyAltField.setAccessible(true);
+ stickyAltField = ReflectionUtil.getDeclaredField(Class.forName("com.sun.java.swing.plaf.windows.WindowsRootPaneUI$AltProcessor"), "menuCanceledOnPress");
}
stickyAltField.set(null, true);
}
diff --git a/platform/platform-impl/src/com/intellij/ide/SwingCleanuper.java b/platform/platform-impl/src/com/intellij/ide/SwingCleanuper.java
index dd969f32ac04..baefe3db672d 100644
--- a/platform/platform-impl/src/com/intellij/ide/SwingCleanuper.java
+++ b/platform/platform-impl/src/com/intellij/ide/SwingCleanuper.java
@@ -139,8 +139,7 @@ public final class SwingCleanuper implements ApplicationComponent{
focusManager.setGlobalCurrentFocusCycleRoot(null); //Remove focus leaks
try {
- final Method m = KeyboardFocusManager.class.getDeclaredMethod("setGlobalFocusOwner", Component.class);
- m.setAccessible(true);
+ final Method m = ReflectionUtil.getDeclaredMethod(KeyboardFocusManager.class,"setGlobalFocusOwner", Component.class);
m.invoke(focusManager, new Object[]{null});
}
catch (Exception e) {
@@ -169,7 +168,6 @@ public final class SwingCleanuper implements ApplicationComponent{
if (SystemInfo.isMac) {
try {
field = ReflectionUtil.findField(AccessibleContext.class, Object.class, "nativeAXResource");
- field.setAccessible(true);
}
catch (NoSuchFieldException ignored) {
}
@@ -228,7 +226,6 @@ public final class SwingCleanuper implements ApplicationComponent{
Object resource = myNativeAXResourceField.get(ac);
if (resource != null && resource.getClass().getName().equals("apple.awt.CAccessible")) {
Field accessible = ReflectionUtil.findField(resource.getClass(), Accessible.class, "accessible");
- accessible.setAccessible(true);
accessible.set(resource, null);
}
}
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/CreateLauncherScriptAction.java b/platform/platform-impl/src/com/intellij/ide/actions/CreateLauncherScriptAction.java
index b76839fbffe4..411f2d9d93bb 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/CreateLauncherScriptAction.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/CreateLauncherScriptAction.java
@@ -45,6 +45,7 @@ import static java.util.Arrays.asList;
*/
public class CreateLauncherScriptAction extends DumbAwareAction {
private static final Logger LOG = Logger.getInstance("#com.intellij.ide.actions.CreateLauncherScriptAction");
+ private static final String CONTENTS = "/Contents";
public static boolean isAvailable() {
return SystemInfo.isUnix;
@@ -137,6 +138,8 @@ public class CreateLauncherScriptAction extends DumbAwareAction {
// for Macs just use "*.app"
final String productName = ApplicationNamesInfo.getInstance().getProductName().toLowerCase();
runPath += "/bin/" + productName + ".sh";
+ } else if (runPath.endsWith(CONTENTS)) {
+ runPath = runPath.substring(0, runPath.length() - CONTENTS.length());
}
String launcherContents = ExecUtil.loadTemplate(CreateLauncherScriptAction.class.getClassLoader(), "launcher.py",
newHashMap(asList("$CONFIG_PATH$", "$RUN_PATH$"),
diff --git a/platform/platform-impl/src/com/intellij/ide/customize/CustomizeFeaturedPluginsStepPanel.java b/platform/platform-impl/src/com/intellij/ide/customize/CustomizeFeaturedPluginsStepPanel.java
index c7c729c89424..786a5825e783 100644
--- a/platform/platform-impl/src/com/intellij/ide/customize/CustomizeFeaturedPluginsStepPanel.java
+++ b/platform/platform-impl/src/com/intellij/ide/customize/CustomizeFeaturedPluginsStepPanel.java
@@ -50,7 +50,7 @@ public class CustomizeFeaturedPluginsStepPanel extends AbstractCustomizeWizardSt
public final AtomicBoolean myCanceled = new AtomicBoolean(false);
- public CustomizeFeaturedPluginsStepPanel() throws OfflineException {
+ public CustomizeFeaturedPluginsStepPanel(PluginGroups pluginGroups) throws OfflineException {
setLayout(new GridLayout(1, 1));
JPanel gridPanel = new JPanel(new GridLayout(0, 3));
JBScrollPane scrollPane =
@@ -58,9 +58,9 @@ public class CustomizeFeaturedPluginsStepPanel extends AbstractCustomizeWizardSt
scrollPane.getVerticalScrollBar().setUnitIncrement(10);
scrollPane.setBorder(null);
- Map<String, String> config = PluginGroups.getInstance().getFeaturedPlugins();
+ Map<String, String> config = pluginGroups.getFeaturedPlugins();
boolean isEmptyOrOffline = true;
- List<IdeaPluginDescriptor> pluginsFromRepository = PluginGroups.getInstance().getPluginsFromRepository();
+ List<IdeaPluginDescriptor> pluginsFromRepository = pluginGroups.getPluginsFromRepository();
for (Map.Entry<String, String> entry : config.entrySet()) {
JPanel groupPanel = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
@@ -263,5 +263,5 @@ public class CustomizeFeaturedPluginsStepPanel extends AbstractCustomizeWizardSt
return "New plugins can also be downloaded in " + CommonBundle.settingsTitle() + " | Plugins";
}
- static class OfflineException extends Exception {};
+ public static class OfflineException extends Exception {};
}
diff --git a/platform/platform-impl/src/com/intellij/ide/customize/CustomizeIDEWizardDialog.java b/platform/platform-impl/src/com/intellij/ide/customize/CustomizeIDEWizardDialog.java
index 1b0644a3a20f..be37f9d9d7f6 100644
--- a/platform/platform-impl/src/com/intellij/ide/customize/CustomizeIDEWizardDialog.java
+++ b/platform/platform-impl/src/com/intellij/ide/customize/CustomizeIDEWizardDialog.java
@@ -16,6 +16,7 @@
package com.intellij.ide.customize;
import com.intellij.ide.startup.StartupActionScriptManager;
+import com.intellij.idea.Main;
import com.intellij.openapi.application.ApplicationNamesInfo;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.util.SystemInfo;
@@ -62,6 +63,26 @@ public class CustomizeIDEWizardDialog extends DialogWrapper implements ActionLis
System.setProperty(StartupActionScriptManager.STARTUP_WIZARD_MODE, "true");
}
+ public static void showCustomSteps(String stepsProviderName) {
+ final CustomizeIDEWizardStepsProvider provider;
+
+ try {
+ Class<CustomizeIDEWizardStepsProvider> providerClass = (Class<CustomizeIDEWizardStepsProvider>)Class.forName(stepsProviderName);
+ provider = providerClass.newInstance();
+ }
+ catch (Throwable e) {
+ Main.showMessage("Start Failed", e);
+ return;
+ }
+
+ new CustomizeIDEWizardDialog() {
+ @Override
+ protected void initSteps() {
+ provider.initSteps(this, mySteps);
+ }
+ }.show();
+ }
+
@Override
protected void dispose() {
System.clearProperty(StartupActionScriptManager.STARTUP_WIZARD_MODE);
@@ -73,9 +94,11 @@ public class CustomizeIDEWizardDialog extends DialogWrapper implements ActionLis
if (SystemInfo.isMac) {
mySteps.add(new CustomizeKeyboardSchemeStepPanel());
}
- mySteps.add(new CustomizePluginsStepPanel());
+
+ PluginGroups pluginGroups = new PluginGroups();
+ mySteps.add(new CustomizePluginsStepPanel(pluginGroups));
try {
- mySteps.add(new CustomizeFeaturedPluginsStepPanel());
+ mySteps.add(new CustomizeFeaturedPluginsStepPanel(pluginGroups));
}
catch (CustomizeFeaturedPluginsStepPanel.OfflineException e) {
//skip featured step if we're offline
diff --git a/platform/platform-impl/src/com/intellij/ide/customize/CustomizeIDEWizardStepsProvider.java b/platform/platform-impl/src/com/intellij/ide/customize/CustomizeIDEWizardStepsProvider.java
new file mode 100644
index 000000000000..ceea34db05fd
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/ide/customize/CustomizeIDEWizardStepsProvider.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.ide.customize;
+
+import java.util.List;
+
+/**
+ * @author Alexander Lobas
+ */
+public interface CustomizeIDEWizardStepsProvider {
+ void initSteps(CustomizeIDEWizardDialog wizardDialog, List<AbstractCustomizeWizardStep> steps);
+} \ No newline at end of file
diff --git a/platform/platform-impl/src/com/intellij/ide/customize/CustomizeKeyboardSchemeStepPanel.java b/platform/platform-impl/src/com/intellij/ide/customize/CustomizeKeyboardSchemeStepPanel.java
index 2b35ebe7a6fc..53b215516c09 100644
--- a/platform/platform-impl/src/com/intellij/ide/customize/CustomizeKeyboardSchemeStepPanel.java
+++ b/platform/platform-impl/src/com/intellij/ide/customize/CustomizeKeyboardSchemeStepPanel.java
@@ -94,6 +94,6 @@ public class CustomizeKeyboardSchemeStepPanel extends AbstractCustomizeWizardSte
@Override
public String getHTMLFooter() {
- return "Keymap scheme can be later changed in " + CommonBundle.settingsTitle() + " | Keymap";
+ return "Keymap scheme can be changed later in " + CommonBundle.settingsTitle() + " | Keymap";
}
}
diff --git a/platform/platform-impl/src/com/intellij/ide/customize/CustomizePluginsStepPanel.java b/platform/platform-impl/src/com/intellij/ide/customize/CustomizePluginsStepPanel.java
index 9bd14b69cb47..8924c09780dd 100644
--- a/platform/platform-impl/src/com/intellij/ide/customize/CustomizePluginsStepPanel.java
+++ b/platform/platform-impl/src/com/intellij/ide/customize/CustomizePluginsStepPanel.java
@@ -19,7 +19,6 @@ import com.intellij.ide.plugins.PluginManager;
import com.intellij.openapi.application.ApplicationNamesInfo;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.VerticalFlowLayout;
-import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.util.Pair;
import com.intellij.ui.ColorUtil;
import com.intellij.ui.JBCardLayout;
@@ -52,9 +51,11 @@ public class CustomizePluginsStepPanel extends AbstractCustomizeWizardStep imple
private static final String CUSTOMIZE_COMMAND = "Customize";
private final JBCardLayout myCardLayout;
private final IdSetPanel myCustomizePanel;
+ private final PluginGroups myPluginGroups;
- public CustomizePluginsStepPanel() {
+ public CustomizePluginsStepPanel(PluginGroups pluginGroups) {
+ myPluginGroups = pluginGroups;
myCardLayout = new JBCardLayout();
setLayout(myCardLayout);
JPanel gridPanel = new JPanel(new GridLayout(0, COLS));
@@ -66,8 +67,8 @@ public class CustomizePluginsStepPanel extends AbstractCustomizeWizardStep imple
add(scrollPane, MAIN);
add(myCustomizePanel, CUSTOMIZE);
- Map<String, Pair<String, List<String>>> groups = PluginGroups.getInstance().getTree();
- for (final Map.Entry<String, Pair<String, List<String>>> entry : groups.entrySet()) {
+ Map<String, Pair<Icon, List<String>>> groups = pluginGroups.getTree();
+ for (final Map.Entry<String, Pair<Icon, List<String>>> entry : groups.entrySet()) {
final String group = entry.getKey();
if (PluginGroups.CORE.equals(group)) continue;
@@ -89,10 +90,10 @@ public class CustomizePluginsStepPanel extends AbstractCustomizeWizardStep imple
return isGroupEnabled(group);
}
};
- groupPanel.add(new JLabel(IconLoader.getIcon(entry.getValue().getFirst())), gbc);
+ groupPanel.add(new JLabel(entry.getValue().getFirst()), gbc);
//gbc.insets.bottom = 5;
groupPanel.add(titleLabel, gbc);
- JLabel descriptionLabel = new JLabel(PluginGroups.getInstance().getDescription(group), SwingConstants.CENTER) {
+ JLabel descriptionLabel = new JLabel(pluginGroups.getDescription(group), SwingConstants.CENTER) {
@Override
public Dimension getPreferredSize() {
Dimension size = super.getPreferredSize();
@@ -116,7 +117,7 @@ public class CustomizePluginsStepPanel extends AbstractCustomizeWizardStep imple
gbc.weighty = 0;
JPanel buttonsPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 10, 5));
buttonsPanel.setOpaque(false);
- if (PluginGroups.getInstance().getSets(group).size() == 1) {
+ if (pluginGroups.getSets(group).size() == 1) {
buttonsPanel.add(createLink(SWITCH_COMMAND + ":" + group, getGroupSwitchTextProvider(group)));
}
else {
@@ -152,11 +153,11 @@ public class CustomizePluginsStepPanel extends AbstractCustomizeWizardStep imple
if (SWITCH_COMMAND.equals(command)) {
boolean enabled = isGroupEnabled(group);
- List<IdSet> sets = PluginGroups.getInstance().getSets(group);
+ List<IdSet> sets = myPluginGroups.getSets(group);
for (IdSet idSet : sets) {
String[] ids = idSet.getIds();
for (String id : ids) {
- PluginGroups.getInstance().setPluginEnabledWithDependencies(id, !enabled);
+ myPluginGroups.setPluginEnabledWithDependencies(id, !enabled);
}
}
repaint();
@@ -190,17 +191,17 @@ public class CustomizePluginsStepPanel extends AbstractCustomizeWizardStep imple
@Override
public String getText() {
return (isGroupEnabled(group) ? "Disable" : "Enable") +
- (PluginGroups.getInstance().getSets(group).size() > 1 ? " All" : "");
+ (myPluginGroups.getSets(group).size() > 1 ? " All" : "");
}
};
}
private boolean isGroupEnabled(String group) {
- List<IdSet> sets = PluginGroups.getInstance().getSets(group);
+ List<IdSet> sets = myPluginGroups.getSets(group);
for (IdSet idSet : sets) {
String[] ids = idSet.getIds();
for (String id : ids) {
- if (PluginGroups.getInstance().isPluginEnabled(id)) return true;
+ if (myPluginGroups.isPluginEnabled(id)) return true;
}
}
return false;
@@ -229,7 +230,7 @@ public class CustomizePluginsStepPanel extends AbstractCustomizeWizardStep imple
@Override
public boolean beforeOkAction() {
try {
- PluginManager.saveDisabledPlugins(PluginGroups.getInstance().getDisabledPluginIds(), false);
+ PluginManager.saveDisabledPlugins(myPluginGroups.getDisabledPluginIds(), false);
}
catch (IOException ignored) {
}
@@ -269,9 +270,9 @@ public class CustomizePluginsStepPanel extends AbstractCustomizeWizardStep imple
public void linkSelected(LinkLabel aSource, String command) {
if (myGroup == null) return;
boolean enable = "enable".equals(command);
- List<IdSet> idSets = PluginGroups.getInstance().getSets(myGroup);
+ List<IdSet> idSets = myPluginGroups.getSets(myGroup);
for (IdSet set : idSets) {
- PluginGroups.getInstance().setIdSetEnabled(set, enable);
+ myPluginGroups.setIdSetEnabled(set, enable);
}
CustomizePluginsStepPanel.this.repaint();
}
@@ -280,19 +281,19 @@ public class CustomizePluginsStepPanel extends AbstractCustomizeWizardStep imple
myGroup = group;
myTitleLabel.setText("<html><body><h2 style=\"text-align:left;\">" + group + "</h2></body></html>");
myContentPanel.removeAll();
- List<IdSet> idSets = PluginGroups.getInstance().getSets(group);
+ List<IdSet> idSets = myPluginGroups.getSets(group);
for (final IdSet set : idSets) {
- final JCheckBox checkBox = new JCheckBox(set.getTitle(), PluginGroups.getInstance().isIdSetAllEnabled(set));
+ final JCheckBox checkBox = new JCheckBox(set.getTitle(), myPluginGroups.isIdSetAllEnabled(set));
checkBox.setModel(new JToggleButton.ToggleButtonModel() {
@Override
public boolean isSelected() {
- return PluginGroups.getInstance().isIdSetAllEnabled(set);
+ return myPluginGroups.isIdSetAllEnabled(set);
}
});
checkBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
- PluginGroups.getInstance().setIdSetEnabled(set, !checkBox.isSelected());
+ myPluginGroups.setIdSetEnabled(set, !checkBox.isSelected());
CustomizePluginsStepPanel.this.repaint();
}
});
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 1af2fb883efb..b369e49f8bca 100644
--- a/platform/platform-impl/src/com/intellij/ide/customize/CustomizeUIThemeStepPanel.java
+++ b/platform/platform-impl/src/com/intellij/ide/customize/CustomizeUIThemeStepPanel.java
@@ -34,12 +34,12 @@ import java.util.LinkedHashMap;
import java.util.Map;
public class CustomizeUIThemeStepPanel extends AbstractCustomizeWizardStep {
+ protected static final String DEFAULT = "Default";
+ protected static final String DARCULA = "Darcula";
+ protected static final String INTELLIJ = "IntelliJ";
+ protected static final String ALLOY = "Alloy. IDEA Theme";
+ protected static final String GTK = "GTK+";
- private static final String DEFAULT = "Default";
- private static final String DARCULA = "Darcula";
- private static final String INTELLIJ = "IntelliJ";
- private static final String ALLOY = "Alloy. IDEA Theme";
- private static final String GTK = "GTK+";
private boolean myInitial = true;
private boolean myColumnMode;
private JLabel myPreviewLabel;
@@ -49,24 +49,8 @@ public class CustomizeUIThemeStepPanel extends AbstractCustomizeWizardStep {
setLayout(new BorderLayout(10, 10));
IconLoader.activate();
- if (SystemInfo.isMac) {
- myLafNames.put(DEFAULT, IconLoader.getIcon("/lafs/OSXAqua.png"));
- myLafNames.put(DARCULA, IconLoader.getIcon("/lafs/OSXDarcula.png"));
- }
- else if (SystemInfo.isWindows) {
- //if (PlatformUtils.isIdeaCommunity()) {
- myLafNames.put(INTELLIJ, IconLoader.getIcon("/lafs/WindowsIntelliJ.png"));
- //}
- //else {
- // myLafNames.put(ALLOY, IconLoader.getIcon("/lafs/WindowsAlloy.png"));
- //}
- myLafNames.put(DARCULA, IconLoader.getIcon("/lafs/WindowsDarcula.png"));
- }
- else {
- myLafNames.put(INTELLIJ, IconLoader.getIcon("/lafs/LinuxIntelliJ.png"));
- myLafNames.put(DARCULA, IconLoader.getIcon("/lafs/LinuxDarcula.png"));
- myLafNames.put(GTK, IconLoader.getIcon("/lafs/LinuxGTK.png"));
- }
+ initLafs();
+
myColumnMode = myLafNames.size() > 2;
JPanel buttonsPanel = new JPanel(new GridLayout(myColumnMode ? myLafNames.size() : 1, myColumnMode ? 1 : myLafNames.size(), 5, 5));
ButtonGroup group = new ButtonGroup();
@@ -111,6 +95,31 @@ public class CustomizeUIThemeStepPanel extends AbstractCustomizeWizardStep {
myInitial = false;
}
+ protected void initLafs() {
+ if (SystemInfo.isMac) {
+ addLaf(DEFAULT, "/lafs/OSXAqua.png");
+ addLaf(DARCULA, "/lafs/OSXDarcula.png");
+ }
+ else if (SystemInfo.isWindows) {
+ //if (PlatformUtils.isIdeaCommunity()) {
+ addLaf(INTELLIJ,"/lafs/WindowsIntelliJ.png");
+ //}
+ //else {
+ // addLaf(ALLOY, "/lafs/WindowsAlloy.png");
+ //}
+ addLaf(DARCULA, "/lafs/WindowsDarcula.png");
+ }
+ else {
+ addLaf(INTELLIJ, "/lafs/LinuxIntelliJ.png");
+ addLaf(DARCULA, "/lafs/LinuxDarcula.png");
+ addLaf(GTK, "/lafs/LinuxGTK.png");
+ }
+ }
+
+ protected final void addLaf(String name, String icon) {
+ myLafNames.put(name, IconLoader.getIcon(icon));
+ }
+
@Override
public Dimension getPreferredSize() {
Dimension size = super.getPreferredSize();
@@ -118,7 +127,6 @@ public class CustomizeUIThemeStepPanel extends AbstractCustomizeWizardStep {
return size;
}
-
@Override
public String getTitle() {
return "UI Themes";
diff --git a/platform/platform-impl/src/com/intellij/ide/customize/IdSet.java b/platform/platform-impl/src/com/intellij/ide/customize/IdSet.java
index 47f8863b9ceb..fb406d21359a 100644
--- a/platform/platform-impl/src/com/intellij/ide/customize/IdSet.java
+++ b/platform/platform-impl/src/com/intellij/ide/customize/IdSet.java
@@ -28,7 +28,7 @@ class IdSet {
String myTitle;
String[] myIds;
- IdSet(String description) {
+ IdSet(final PluginGroups pluginGroups, String description) {
int i = description.indexOf(":");
if (i > 0) {
myTitle = description.substring(0, i);
@@ -38,7 +38,7 @@ class IdSet {
myIds = ContainerUtil.filter(myIds, new Condition<String>() {
@Override
public boolean value(String id) {
- return PluginGroups.getInstance().findPlugin(id) != null;
+ return pluginGroups.findPlugin(id) != null;
}
}).toArray(new String[]{});
@@ -47,7 +47,7 @@ class IdSet {
}
if (myTitle == null && myIds.length>0) {
//noinspection ConstantConditions
- myTitle = PluginGroups.getInstance().findPlugin(myIds[0]).getName();
+ myTitle = pluginGroups.findPlugin(myIds[0]).getName();
}
if (myTitle != null) {
for (String skipWord : BLACK_LIST) {
diff --git a/platform/platform-impl/src/com/intellij/ide/customize/PluginGroups.java b/platform/platform-impl/src/com/intellij/ide/customize/PluginGroups.java
index 930901d55105..b17805579869 100644
--- a/platform/platform-impl/src/com/intellij/ide/customize/PluginGroups.java
+++ b/platform/platform-impl/src/com/intellij/ide/customize/PluginGroups.java
@@ -16,7 +16,6 @@
package com.intellij.ide.customize;
import com.intellij.ide.plugins.IdeaPluginDescriptor;
-import com.intellij.ide.plugins.PluginManager;
import com.intellij.ide.plugins.PluginManagerCore;
import com.intellij.ide.plugins.RepositoryHelper;
import com.intellij.idea.StartupUtil;
@@ -27,19 +26,18 @@ import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.ContainerUtil;
+import icons.PlatformImplIcons;
import org.jetbrains.annotations.Nullable;
+import javax.swing.*;
import java.io.File;
import java.util.*;
-class PluginGroups {
+public class PluginGroups {
static final String CORE = "Core";
private static final int MAX_DESCR_LENGTH = 55;
-
- private static PluginGroups instance = null;
-
- final Map<String, Pair<String, List<String>>> myTree = new LinkedHashMap<String, Pair<String, List<String>>>();
+ final Map<String, Pair<Icon, List<String>>> myTree = new LinkedHashMap<String, Pair<Icon, List<String>>>();
final Map<String, String> myFeaturedPlugins = new LinkedHashMap<String, String>();
private final Map<String, List<IdSet>> myGroups = new LinkedHashMap<String, List<IdSet>>();
@@ -50,15 +48,7 @@ class PluginGroups {
private boolean myInitialized = false;
private Set<String> myFeaturedIds = new HashSet<String>();
-
- static synchronized PluginGroups getInstance() {
- if (instance == null) {
- instance = new PluginGroups();
- }
- return instance;
- }
-
- private PluginGroups() {
+ public PluginGroups() {
myAllPlugins = PluginManagerCore.loadDescriptors(null);
try {
myPluginsFromRepository.addAll(RepositoryHelper.loadPluginsFromRepository(null));
@@ -68,8 +58,12 @@ class PluginGroups {
}
PluginManagerCore.loadDisabledPlugins(new File(PathManager.getConfigPath()).getPath(), myDisabledPluginIds);
+ initGroups(myTree, myFeaturedPlugins);
+ }
- myTree.put(CORE, Pair.create((String)null, Arrays.asList(
+ protected void
+ initGroups(Map<String, Pair<Icon, List<String>>> tree, Map<String, String> featuredPlugins) {
+ tree.put(CORE, Pair.create((Icon)null, Arrays.asList(
"com.intellij.copyright",
"com.intellij.java-i18n",
"org.intellij.intelliLang",
@@ -78,7 +72,7 @@ class PluginGroups {
"Type Migration",
"ZKM"
)));
- myTree.put("Java Frameworks", Pair.create("/plugins/JavaFrameworks.png", Arrays.asList(
+ tree.put("Java Frameworks", Pair.create(PlatformImplIcons.JavaFrameworks, Arrays.asList(
"com.intellij.appengine",
"org.intellij.grails",
"com.intellij.gwt",
@@ -113,12 +107,12 @@ class PluginGroups {
"com.intellij.aspectj",
"Osmorc"
)));
- myTree.put("Build Tools", Pair.create("/plugins/BuildTools.png", Arrays.asList(
+ tree.put("Build Tools", Pair.create(PlatformImplIcons.BuildTools, Arrays.asList(
"AntSupport",
"Maven:org.jetbrains.idea.maven,org.jetbrains.idea.maven.ext",
"org.jetbrains.plugins.gradle"
)));
- myTree.put("Web Development", Pair.create("/plugins/WebDevelopment.png", Arrays.asList(
+ tree.put("Web Development", Pair.create(PlatformImplIcons.WebDevelopment, Arrays.asList(
"HTML:HtmlTools,QuirksMode,W3Validators",
"org.jetbrains.plugins.haml",
"com.jetbrains.plugins.jade",
@@ -132,24 +126,17 @@ class PluginGroups {
"com.intellij.plugins.html.instantEditing",
"com.jetbrains.restClient"
)));
- myTree.put("Version Controls", Pair.create("/plugins/VersionControls.png", Arrays.asList(
- "ClearcasePlugin",
- "CVS",
- "Git4Idea",
- "org.jetbrains.plugins.github",
- "hg4idea",
- "PerforceDirectPlugin",
- "Subversion",
- "TFS"
- )));
- myTree.put("Test Tools", Pair.create("/plugins/TestTools.png", Arrays.asList(
+
+ addVcsGroup(tree);
+
+ tree.put("Test Tools", Pair.create(PlatformImplIcons.TestTools, Arrays.asList(
"JUnit",
"TestNG-J",
"cucumber-java",
"cucumber",
"Coverage:Coverage,Emma"
)));
- myTree.put("Application Servers", Pair.create("/plugins/ApplicationServers.png", Arrays.asList(
+ tree.put("Application Servers", Pair.create(PlatformImplIcons.ApplicationServers, Arrays.asList(
"com.intellij.javaee.view",
"Geronimo",
"GlassFish",
@@ -162,7 +149,7 @@ class PluginGroups {
"com.intellij.dmserver",
"JSR45Plugin"
)));
- myTree.put("Clouds", Pair.create("/plugins/Clouds.png", Arrays.asList(
+ tree.put("Clouds", Pair.create(PlatformImplIcons.Clouds, Arrays.asList(
"CloudFoundry",
"CloudBees",
"Heroku",
@@ -170,16 +157,16 @@ class PluginGroups {
)));
//myTree.put("Groovy", Arrays.asList("org.intellij.grails"));
//TODO Scala -> Play 2.x (Play 2.0 Support)
- myTree.put("Swing", Pair.create("/plugins/Swing.png", Arrays.asList(
+ tree.put("Swing", Pair.create(PlatformImplIcons.Swing, Arrays.asList(
"com.intellij.uiDesigner"//TODO JavaFX?
)));
- myTree.put("Android", Pair.create("/plugins/Android.png", Arrays.asList(
+ tree.put("Android", Pair.create(PlatformImplIcons.Android, Arrays.asList(
"org.jetbrains.android",
"com.intellij.android-designer")));
- myTree.put("Database Tools", Pair.create("/plugins/DatabaseTools.png", Arrays.asList(
+ tree.put("Database Tools", Pair.create(PlatformImplIcons.DatabaseTools, Arrays.asList(
"com.intellij.database"
)));
- myTree.put("Other Tools", Pair.create("/plugins/OtherTools.png", Arrays.asList(
+ tree.put("Other Tools", Pair.create(PlatformImplIcons.OtherTools, Arrays.asList(
"ByteCodeViewer",
"com.intellij.dsm",
"org.jetbrains.idea.eclipse",
@@ -190,27 +177,63 @@ class PluginGroups {
"org.jetbrains.plugins.yaml",
"XSLT and XPath:XPathView,XSLT-Debugger"
)));
- myTree.put("Plugin Development", Pair.create("/plugins/PluginDevelopment.png", Arrays.asList("DevKit")));
+ tree.put("Plugin Development", Pair.create(PlatformImplIcons.PluginDevelopment, Arrays.asList("DevKit")));
+
+ featuredPlugins.put("Scala", "Custom Languages:Plugin for Scala language support:org.intellij.scala");
+ featuredPlugins.put("Live Edit Tool",
+ "Web Development:Provides live edit HTML/CSS/JavaScript:com.intellij.plugins.html.instantEditing");
+ addVimPlugin(featuredPlugins);
+ featuredPlugins.put("NodeJS", "JavaScript:Node.js integration:NodeJS");
+ featuredPlugins.put("Atlassian Connector",
+ "Tools Integration:Integration for Atlassian JIRA, Bamboo, Cricible, FishEye:atlassian-idea-plugin");
+ }
- myFeaturedPlugins.put("Scala", "Custom Languages:Plugin for Scala language support:org.intellij.scala");
- myFeaturedPlugins.put("Live Edit Tool", "Web Development:Provides live edit HTML/CSS/JavaScript:com.intellij.plugins.html.instantEditing");
- myFeaturedPlugins.put("IdeaVIM", "Editor:Vim emulation plug-in for IDEs based on the IntelliJ platform:IdeaVIM");
- myFeaturedPlugins.put("NodeJS", "JavaScript:Node.js integration:NodeJS");
- myFeaturedPlugins.put("Atlassian Connector", "Tools Integration:Integration for Atlassian JIRA, Bamboo, Cricible, FishEye:atlassian-idea-plugin");
+ protected static void addVcsGroup(Map<String, Pair<Icon, List<String>>> tree) {
+ tree.put("Version Controls", Pair.create(PlatformImplIcons.VersionControls, Arrays.asList(
+ "ClearcasePlugin",
+ "CVS",
+ "Git4Idea",
+ "org.jetbrains.plugins.github",
+ "hg4idea",
+ "PerforceDirectPlugin",
+ "Subversion",
+ "TFS"
+ )));
+ }
+ protected static void addVimPlugin(Map<String, String> featuredPlugins) {
+ featuredPlugins.put("IdeaVIM", "Editor:Vim emulation plug-in for IDEs based on the IntelliJ platform:IdeaVIM");
+ }
+
+ protected static void addLuaPlugin(Map<String, String> featuredPlugins) {
+ featuredPlugins.put("Lua", "Custom Languages:Lua language integration:Lua");
+ }
+
+ protected static void addMarkdownPlugin(Map<String, String> featuredPlugins) {
+ featuredPlugins.put("Markdown", "Custom Languages:Markdown language integration:net.nicoulaj.idea.markdown");
+ }
+
+ protected static void addConfigurationServerPlugin(Map<String, String> featuredPlugins) {
+ featuredPlugins.put("Configuration Server",
+ "Team Work:Supports sharing settings between installations of IntelliJ Platform based products used by the same developer on different computers:IdeaServerPlugin");
+ }
+
+ protected static void addTeamCityPlugin(Map<String, String> featuredPlugins) {
+ featuredPlugins.put("TeamCity Integration",
+ "Tools Integration:Integration with JetBrains TeamCity - innovative solution for continuous integration and build management:Jetbrains TeamCity Plugin");
}
private void initIfNeed() {
if (myInitialized) return;
myInitialized = true;
- for (Map.Entry<String, Pair<String, List<String>>> entry : myTree.entrySet()) {
+ for (Map.Entry<String, Pair<Icon, List<String>>> entry : myTree.entrySet()) {
final String group = entry.getKey();
if (CORE.equals(group)) continue;
List<IdSet> idSets = new ArrayList<IdSet>();
StringBuilder description = new StringBuilder();
for (String idDescription : entry.getValue().getSecond()) {
- IdSet idSet = new IdSet(idDescription);
+ IdSet idSet = new IdSet(this, idDescription);
String idSetTitle = idSet.getTitle();
if (idSetTitle == null) continue;
idSets.add(idSet);
@@ -230,7 +253,7 @@ class PluginGroups {
}
}
- Map<String, Pair<String, List<String>>> getTree() {
+ Map<String, Pair<Icon, List<String>>> getTree() {
initIfNeed();
return myTree;
}
@@ -302,7 +325,8 @@ class PluginGroups {
void setFeaturedPluginEnabled(String pluginId, boolean enabled) {
if (enabled) {
myFeaturedIds.add(pluginId);
- } else {
+ }
+ else {
myFeaturedIds.remove(pluginId);
}
StartupUtil.setFeaturedPluginsToInstall(myFeaturedIds);
diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/PasswordSafeException.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/PasswordSafeException.java
index 00b529933f68..20d7d5188efb 100644
--- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/PasswordSafeException.java
+++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/PasswordSafeException.java
@@ -19,22 +19,29 @@ package com.intellij.ide.passwordSafe;
* The exception that is thrown when password safe is not available (unable to ask for master password)
*/
public class PasswordSafeException extends Exception {
- /**
- * The constructor
- *
- * @param message the message
- * @param cause the cause
- */
+
+ private static final long MIN_INTERVAL = 1000L;
+
+ private long myTimeMillis = System.currentTimeMillis();
+
public PasswordSafeException(String message, Throwable cause) {
super(message, cause);
}
- /**
- * The constructor
- *
- * @param message the message
- */
public PasswordSafeException(String message) {
super(message);
}
+
+ public long getTimeMillis() {
+ return myTimeMillis;
+ }
+
+ public boolean justHappened() {
+ long timeMillis = System.currentTimeMillis();
+ if (timeMillis - myTimeMillis < MIN_INTERVAL) {
+ myTimeMillis = timeMillis;
+ return true;
+ }
+ return false;
+ }
}
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 a0b001824d90..8bfa859d5ceb 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,6 +43,7 @@ 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.
*/
+ @NotNull
protected abstract byte[] key(@Nullable Project project, @NotNull Class requestor) throws PasswordSafeException;
@Nullable
diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/EncryptionUtil.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/EncryptionUtil.java
index 01fef01cecb1..7bbb8bc80789 100644
--- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/EncryptionUtil.java
+++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/impl/providers/EncryptionUtil.java
@@ -15,6 +15,8 @@
*/
package com.intellij.ide.passwordSafe.impl.providers;
+import org.jetbrains.annotations.NotNull;
+
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
@@ -115,7 +117,7 @@ public class EncryptionUtil {
* @param rawKey the raw key to encrypt
* @return the encrypted key
*/
- public static byte[] encryptKey(byte[] password, byte[] rawKey) {
+ public static byte[] encryptKey(@NotNull byte[] password, byte[] rawKey) {
try {
Cipher c = Cipher.getInstance(ENCRYPT_KEY_ALGORITHM);
c.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(password, SECRET_KEY_ALGORITHM), CBC_SALT_KEY);
@@ -130,12 +132,12 @@ public class EncryptionUtil {
* Create encrypted db key
*
* @param password the password to protect the key
- * @param requester the requester for the key
- * @param key the key within requester
+ * @param requestor the requestor for the key
+ * @param key the key within requestor
* @return the key to use in the database
*/
- public static byte[] dbKey(byte[] password, Class requester, String key) {
- return encryptKey(password, rawKey(requester, key));
+ public static byte[] dbKey(@NotNull byte[] password, Class requestor, String key) {
+ return encryptKey(password, rawKey(requestor, key));
}
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 840159270a8d..6b0b9814698b 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
@@ -22,12 +22,14 @@ 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.ide.passwordSafe.impl.providers.masterKey.windows.WindowsCryptUtils;
-import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
+import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.util.ThrowableComputable;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NotNull;
@@ -36,7 +38,6 @@ import org.jetbrains.annotations.Nullable;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;
-import java.util.concurrent.atomic.AtomicReference;
/**
* The password safe that stores information in configuration file encrypted by master password
@@ -44,13 +45,11 @@ import java.util.concurrent.atomic.AtomicReference;
public class MasterKeyPasswordSafe extends BasePasswordSafeProvider {
private static final String TEST_PASSWORD_KEY = "TEST_PASSWORD:";
private static final String TEST_PASSWORD_VALUE = "test password";
- final PasswordDatabase database;
- /**
- * The key to use to encrypt data
- */
- private transient final PasswordSafeTimed<AtomicReference<byte[]>> key = new PasswordSafeTimed<AtomicReference<byte[]>>() {
- protected AtomicReference<byte[]> compute() {
- return new AtomicReference<byte[]>();
+
+ private final PasswordDatabase myDatabase;
+ private transient final PasswordSafeTimed<Ref<Object>> myKey = new PasswordSafeTimed<Ref<Object>>() {
+ protected Ref<Object> compute() {
+ return Ref.create();
}
@Override
@@ -60,11 +59,7 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider {
};
public MasterKeyPasswordSafe(PasswordDatabase database) {
- this.database = database;
- }
-
- protected boolean isTestMode() {
- return false;
+ this.myDatabase = database;
}
/**
@@ -74,15 +69,15 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider {
* @param encrypt if the password should be encrypted an stored is master database
*/
void resetMasterPassword(String password, boolean encrypt) {
- key.get().set(EncryptionUtil.genPasswordKey(password));
- database.clear();
+ myKey.get().set(EncryptionUtil.genPasswordKey(password));
+ myDatabase.clear();
try {
storePassword(null, MasterKeyPasswordSafe.class, testKey(password), TEST_PASSWORD_VALUE);
if (encrypt) {
- database.setPasswordInfo(encryptPassword(password));
+ myDatabase.setPasswordInfo(encryptPassword(password));
}
else {
- database.setPasswordInfo(ArrayUtil.EMPTY_BYTE_ARRAY);
+ myDatabase.setPasswordInfo(ArrayUtil.EMPTY_BYTE_ARRAY);
}
}
catch (PasswordSafeException e) {
@@ -97,8 +92,8 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider {
* @return true, if password is a correct one
*/
boolean setMasterPassword(String password) {
- byte[] savedKey = key.get().get();
- key.get().set(EncryptionUtil.genPasswordKey(password));
+ Object savedKey = myKey.get().get();
+ myKey.get().set(EncryptionUtil.genPasswordKey(password));
String rc;
try {
rc = getPassword(null, MasterKeyPasswordSafe.class, testKey(password));
@@ -107,7 +102,7 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider {
throw new IllegalStateException("There should be no problem with password at this point", e);
}
if (!TEST_PASSWORD_VALUE.equals(rc)) {
- key.get().set(savedKey);
+ myKey.get().set(savedKey);
return false;
}
else {
@@ -127,11 +122,11 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider {
if (!setMasterPassword(oldPassword)) {
return false;
}
- byte[] oldKey = key.get().get(); // set right in the previous call
+ byte[] oldKey = (byte[])myKey.get().get(); // set right in the previous call
byte[] newKey = EncryptionUtil.genPasswordKey(newPassword);
ByteArrayWrapper testKey = new ByteArrayWrapper(EncryptionUtil.dbKey(oldKey, MasterKeyPasswordSafe.class, testKey(oldPassword)));
HashMap<ByteArrayWrapper, byte[]> oldDb = new HashMap<ByteArrayWrapper, byte[]>();
- database.copyTo(oldDb);
+ myDatabase.copyTo(oldDb);
HashMap<ByteArrayWrapper, byte[]> newDb = new HashMap<ByteArrayWrapper, byte[]>();
for (Map.Entry<ByteArrayWrapper, byte[]> e : oldDb.entrySet()) {
if (testKey.equals(e.getKey())) {
@@ -141,9 +136,9 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider {
String decryptedText = EncryptionUtil.decryptText(oldKey, e.getValue());
newDb.put(new ByteArrayWrapper(EncryptionUtil.encryptKey(newKey, decryptedKey)), EncryptionUtil.encryptText(newKey, decryptedText));
}
- synchronized (database.getDbLock()) {
+ synchronized (myDatabase.getDbLock()) {
resetMasterPassword(newPassword, encrypt);
- database.putAll(newDb);
+ myDatabase.putAll(newDb);
}
return true;
}
@@ -153,65 +148,92 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider {
return TEST_PASSWORD_KEY + password;
}
+ @NotNull
@Override
protected byte[] key(@Nullable final Project project, @NotNull final Class requestor) throws PasswordSafeException {
- Application application = ApplicationManager.getApplication();
- if (!isTestMode() && application.isHeadlessEnvironment()) {
+ Object key = myKey.get().get();
+ if (key instanceof byte[]) return (byte[])key;
+ if (key instanceof PasswordSafeException && ((PasswordSafeException)key).justHappened()) throw (PasswordSafeException)key;
+
+ if (isPasswordEncrypted()) {
+ try {
+ setMasterPassword(decryptPassword(myDatabase.getPasswordInfo()));
+ key = myKey.get().get();
+ if (key instanceof byte[]) return (byte[])key;
+ }
+ catch (PasswordSafeException e) {
+ // ignore exception and ask password
+ }
+ }
+
+ if (ApplicationManager.getApplication().isHeadlessEnvironment()) {
throw new MasterPasswordUnavailableException("The provider is not available in headless environment");
}
- final Ref<byte[]> result = Ref.create(key.get().get());
- if (result.isNull()) {
- if (isPasswordEncrypted()) {
+
+ if (myDatabase.isEmpty()) {
+ if (!MasterPasswordDialog.resetMasterPasswordDialog(project, this, requestor).showAndGet()) {
+ throw new MasterPasswordUnavailableException("Master password is required to store passwords in the database.");
+ }
+ }
+
+ key = invokeAndWait(new ThrowableComputable<Object, PasswordSafeException>() {
+ @Override
+ public Object compute() throws PasswordSafeException {
+ Object key = myKey.get().get();
+ if (key instanceof byte[] || key instanceof PasswordSafeException && ((PasswordSafeException)key).justHappened()) {
+ return key;
+ }
try {
- setMasterPassword(decryptPassword(database.getPasswordInfo()));
- result.set(key.get().get());
+ MasterPasswordDialog.askPassword(project, MasterKeyPasswordSafe.this, requestor);
}
catch (PasswordSafeException e) {
- // ignore exception and ask password
+ myKey.get().set(e);
+ throw e;
}
+ return myKey.get().get();
+ }
+ }, project == null ? Condition.FALSE : project.getDisposed());
+ if (key instanceof byte[]) return (byte[])key;
+ if (key instanceof PasswordSafeException) throw (PasswordSafeException)key;
+
+ throw new AssertionError();
+ }
+
+ private static final Object ourEDTLock = new Object();
+ public <T, E extends Throwable> T invokeAndWait(@NotNull final ThrowableComputable<T, E> computable, @NotNull final Condition expired) throws E {
+ if (ApplicationManager.getApplication().isDispatchThread()) {
+ return computable.compute();
+ }
+ final Ref<Throwable> exRef = Ref.create();
+ final Ref<T> ref = Ref.create();
+ synchronized (ourEDTLock) {
+ if (expired.value(null)) {
+ throw new ProcessCanceledException();
}
- if (result.isNull()) {
- final Ref<PasswordSafeException> ex = new Ref<PasswordSafeException>();
- application.invokeAndWait(new Runnable() {
- public void run() {
- result.set(key.get().get());
- if (result.isNull()) {
- try {
- if (isTestMode()) {
- throw new MasterPasswordUnavailableException("Master password must be specified in test mode.");
- }
- if (database.isEmpty()) {
- if (!MasterPasswordDialog.resetMasterPasswordDialog(project, MasterKeyPasswordSafe.this, requestor).showAndGet()) {
- throw new MasterPasswordUnavailableException("Master password is required to store passwords in the database.");
- }
- }
- else {
- MasterPasswordDialog.askPassword(project, MasterKeyPasswordSafe.this, requestor);
- }
- result.set(key.get().get());
- }
- catch (PasswordSafeException e) {
- ex.set(e);
- }
- catch (Exception e) {
- //noinspection ThrowableInstanceNeverThrown
- ex.set(new MasterPasswordUnavailableException("The problem with retrieving the password", e));
- }
- }
+ ApplicationManager.getApplication().invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ if (expired.value(null)) {
+ exRef.set(new ProcessCanceledException());
+ return;
+ }
+
+ try {
+ ref.set(computable.compute());
+ }
+ catch (Throwable e) {
+ exRef.set(e);
}
- }, ModalityState.any());
- //noinspection ThrowableResultOfMethodCallIgnored
- if (ex.get() != null) {
- throw ex.get();
}
- }
+ }, ModalityState.any());
}
- return result.get();
+ if (!exRef.isNull()) throw (E)exRef.get();
+ return ref.get();
}
@Override
public String getPassword(@Nullable Project project, @NotNull Class requestor, String key) throws PasswordSafeException {
- if (database.isEmpty()) {
+ if (myDatabase.isEmpty()) {
return null;
}
return super.getPassword(project, requestor, key);
@@ -219,7 +241,7 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider {
@Override
public void removePassword(@Nullable Project project, @NotNull Class requester, String key) throws PasswordSafeException {
- if (database.isEmpty()) {
+ if (myDatabase.isEmpty()) {
return;
}
super.removePassword(project, requester, key);
@@ -227,17 +249,17 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider {
@Override
protected byte[] getEncryptedPassword(byte[] key) {
- return database.get(key);
+ return myDatabase.get(key);
}
@Override
protected void removeEncryptedPassword(byte[] key) {
- database.remove(key);
+ myDatabase.remove(key);
}
@Override
protected void storeEncryptedPassword(byte[] key, byte[] encryptedPassword) {
- database.put(key, encryptedPassword);
+ myDatabase.put(key, encryptedPassword);
}
@Override
@@ -303,11 +325,11 @@ public class MasterKeyPasswordSafe extends BasePasswordSafeProvider {
public boolean isPasswordEncrypted() {
if (!isOsProtectedPasswordSupported()) return false;
- byte[] i = database.getPasswordInfo();
- return i != null && i.length > 0;
+ byte[] info = myDatabase.getPasswordInfo();
+ return info != null && info.length > 0;
}
public boolean isEmpty() {
- return database.isEmpty();
+ return myDatabase.isEmpty();
}
}
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 4989789b4ec0..5057b0ee48d6 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
@@ -57,6 +57,7 @@ public class MemoryPasswordSafe extends BasePasswordSafeProvider {
return Registry.intValue("passwordSafe.memorySafe.ttl");
}
+ @NotNull
@Override
protected byte[] key(Project project, @NotNull Class requestor) {
if (key.get() == null) {
diff --git a/platform/platform-impl/src/com/intellij/ide/passwordSafe/ui/PasswordPromptComponent.java b/platform/platform-impl/src/com/intellij/ide/passwordSafe/ui/PasswordPromptComponent.java
index 6ea43344bda4..b31599816435 100644
--- a/platform/platform-impl/src/com/intellij/ide/passwordSafe/ui/PasswordPromptComponent.java
+++ b/platform/platform-impl/src/com/intellij/ide/passwordSafe/ui/PasswordPromptComponent.java
@@ -18,6 +18,7 @@ package com.intellij.ide.passwordSafe.ui;
import com.intellij.ide.passwordSafe.config.PasswordSafeSettings;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.ui.DialogUtil;
import com.intellij.util.ui.UIUtil;
import javax.swing.*;
@@ -49,7 +50,10 @@ public class PasswordPromptComponent {
setTargetProviderType(type);
setUserInputVisible(showUserName);
if (passwordPrompt != null) myPasswordLabel.setText(passwordPrompt);
- if (rememberPrompt != null) myRememberCheckBox.setText(rememberPrompt);
+ if (rememberPrompt != null) {
+ myRememberCheckBox.setText(rememberPrompt);
+ DialogUtil.registerMnemonic(myRememberCheckBox);
+ }
}
public JComponent getComponent() {
diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginInstaller.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginInstaller.java
index b093773bc0fb..366e4e1cf4ef 100644
--- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginInstaller.java
+++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginInstaller.java
@@ -30,10 +30,7 @@ import com.intellij.ui.GuiUtils;
import com.intellij.util.ArrayUtil;
import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
/**
* @author stathik
@@ -45,6 +42,19 @@ public class PluginInstaller {
private PluginInstaller() { }
public static boolean prepareToInstall(List<PluginNode> pluginsToInstall, List<IdeaPluginDescriptor> allPlugins) {
+ HashSet<PluginNode> dependant = new HashSet<PluginNode>();
+ boolean install = prepareToInstall(pluginsToInstall, allPlugins, dependant);
+ for (PluginNode node : dependant) {
+ if (!pluginsToInstall.contains(node)) {
+ pluginsToInstall.add(node);
+ }
+ }
+ return install;
+ }
+
+ private static boolean prepareToInstall(List<PluginNode> pluginsToInstall,
+ List<IdeaPluginDescriptor> allPlugins,
+ Set<PluginNode> installedDependant) {
ProgressIndicator pi = ProgressManager.getInstance().getProgressIndicator();
final List<PluginId> pluginIds = new ArrayList<PluginId>();
@@ -58,7 +68,7 @@ public class PluginInstaller {
if (pi != null) pi.setText(pluginNode.getName());
try {
- result |= prepareToInstall(pluginNode, pluginIds, allPlugins);
+ result |= prepareToInstall(pluginNode, pluginIds, allPlugins, installedDependant);
}
catch (IOException e) {
String title = IdeBundle.message("title.plugin.error");
@@ -72,7 +82,9 @@ public class PluginInstaller {
private static boolean prepareToInstall(final PluginNode pluginNode,
final List<PluginId> pluginIds,
- List<IdeaPluginDescriptor> allPlugins) throws IOException {
+ List<IdeaPluginDescriptor> allPlugins,
+ Set<PluginNode> installedDependant) throws IOException {
+ installedDependant.add(pluginNode);
// check for dependent plugins at first.
if (pluginNode.getDepends() != null && pluginNode.getDepends().size() > 0) {
// prepare plugins list for install
@@ -122,7 +134,7 @@ public class PluginInstaller {
return false;
}
if (proceed[0]) {
- if (!prepareToInstall(depends, allPlugins)) {
+ if (!prepareToInstall(depends, allPlugins, installedDependant)) {
return false;
}
}
@@ -152,7 +164,7 @@ public class PluginInstaller {
return false;
}
if (proceed[0]) {
- if (!prepareToInstall(optionalDeps, allPlugins)) {
+ if (!prepareToInstall(optionalDeps, allPlugins, installedDependant)) {
return false;
}
}
diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerConfigurable.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerConfigurable.java
index 1fcf23e79614..cc683ecb7075 100644
--- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerConfigurable.java
+++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerConfigurable.java
@@ -34,15 +34,7 @@ import javax.swing.*;
import javax.swing.table.TableModel;
import java.util.List;
-/**
- * Created by IntelliJ IDEA.
- * User: stathik
- * Date: Oct 26, 2003
- * Time: 9:30:44 PM
- * To change this template use Options | File Templates.
- */
public class PluginManagerConfigurable extends BaseConfigurable implements SearchableConfigurable, Configurable.NoScroll {
-
@NonNls private static final String POSTPONE = "&Postpone";
public static final String ID = "preferences.pluginManager";
public static final String DISPLAY_NAME = IdeBundle.message("title.plugins");
@@ -68,10 +60,12 @@ public class PluginManagerConfigurable extends BaseConfigurable implements Searc
return myPluginManagerMain.getPluginTable();
}
+ @Override
public String getDisplayName() {
return DISPLAY_NAME;
}
+ @Override
public void reset() {
myPluginManagerMain.reset();
//if (myAvailable) {
@@ -92,10 +86,12 @@ public class PluginManagerConfigurable extends BaseConfigurable implements Searc
getSplitterProportions().restoreSplitterProportions(myPluginManagerMain.getMainPanel());
}
+ @Override
public String getHelpTopic() {
return ID;
}
+ @Override
public void disposeUIResources() {
if (myPluginManagerMain != null) {
getSplitterProportions().saveSplitterProportions(myPluginManagerMain.getMainPanel());
@@ -124,6 +120,7 @@ public class PluginManagerConfigurable extends BaseConfigurable implements Searc
return myAvailable ? myUISettings.getAvailableSplitterProportionsData() : myUISettings.getSplitterProportionsData();
}
+ @Override
public JComponent createComponent() {
return getOrCreatePanel().getMainPanel();
}
@@ -132,6 +129,7 @@ public class PluginManagerConfigurable extends BaseConfigurable implements Searc
return new InstalledPluginsManagerMain(myUISettings);
}
+ @Override
public void apply() throws ConfigurationException {
final String applyMessage = myPluginManagerMain.apply();
if (applyMessage != null) {
@@ -186,18 +184,22 @@ public class PluginManagerConfigurable extends BaseConfigurable implements Searc
if (response == Messages.YES) app.restart(true);
}
+ @Override
public boolean isModified() {
return myPluginManagerMain != null && myPluginManagerMain.isModified();
}
+ @Override
@NotNull
public String getId() {
return getHelpTopic();
}
+ @Override
@Nullable
public Runnable enableSearch(final String option) {
return new Runnable(){
+ @Override
public void run() {
if (myPluginManagerMain == null) return;
myPluginManagerMain.filter(option);
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 931458ff8bc0..e7601a6b0fc0 100644
--- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java
+++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java
@@ -85,6 +85,8 @@ import static com.intellij.openapi.util.text.StringUtil.isEmptyOrSpaces;
*/
public abstract class PluginManagerMain implements Disposable {
public static final String JETBRAINS_VENDOR = "JetBrains";
+ public static final NotificationGroup PLUGIN_LIFECYCLE_NOTIFICATION_GROUP =
+ new NotificationGroup("Plugins Lifecycle Group", NotificationDisplayType.STICKY_BALLOON, true);
public static Logger LOG = Logger.getInstance("#com.intellij.ide.plugins.PluginManagerMain");
@NonNls private static final String TEXT_PREFIX = "<html><head>" +
@@ -652,7 +654,7 @@ public abstract class PluginManagerMain implements Disposable {
message += "<br><a href=";
message += restartCapable ? "\"restart\">Restart now" : "\"shutdown\">Shutdown";
message += "</a>";
- new NotificationGroup("Plugins Lifecycle Group", NotificationDisplayType.STICKY_BALLOON, true)
+ PLUGIN_LIFECYCLE_NOTIFICATION_GROUP
.createNotification(title,
XmlStringUtil.wrapInHtml(message), NotificationType.INFORMATION,
new NotificationListener() {
diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerUISettings.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerUISettings.java
index d5e320a77837..0f0b5189a7f7 100644
--- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerUISettings.java
+++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerUISettings.java
@@ -17,7 +17,6 @@ package com.intellij.ide.plugins;
import com.intellij.ide.ui.SplitterProportionsDataImpl;
import com.intellij.openapi.components.*;
-import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.PerformInBackgroundOption;
import com.intellij.openapi.ui.SplitterProportionsData;
import com.intellij.openapi.util.JDOMExternalizableStringList;
@@ -39,7 +38,6 @@ import javax.swing.*;
}
)
public class PluginManagerUISettings implements PersistentStateComponent<Element>, PerformInBackgroundOption {
- private static final Logger LOG = Logger.getInstance("#com.intellij.ide.plugins.PluginManagerUISettings");
private static final SkipDefaultValuesSerializationFilters FILTERS = new SkipDefaultValuesSerializationFilters();
public int AVAILABLE_SORT_COLUMN_ORDER = SortOrder.ASCENDING.ordinal();
@@ -65,6 +63,7 @@ public class PluginManagerUISettings implements PersistentStateComponent<Element
return ServiceManager.getService(PluginManagerUISettings.class);
}
+ @Override
public Element getState() {
Element element = new Element("state");
XmlSerializer.serializeInto(this, element, FILTERS);
@@ -76,6 +75,7 @@ public class PluginManagerUISettings implements PersistentStateComponent<Element
return element;
}
+ @Override
public void loadState(final Element element) {
XmlSerializer.deserializeInto(this, element);
XmlSerializer.deserializeInto(mySplitterProportionsData, element);
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 ec763a8d5a76..c03eca88ade3 100644
--- a/platform/platform-impl/src/com/intellij/ide/plugins/RepositoryHelper.java
+++ b/platform/platform-impl/src/com/intellij/ide/plugins/RepositoryHelper.java
@@ -23,6 +23,7 @@ import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.application.ex.ApplicationInfoEx;
import com.intellij.openapi.application.impl.ApplicationInfoImpl;
import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.util.BuildNumber;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.PathUtil;
import com.intellij.util.net.HttpConfigurable;
@@ -45,9 +46,14 @@ public class RepositoryHelper {
@NonNls public static final String PLUGIN_LIST_FILE = "availables.xml";
public static List<IdeaPluginDescriptor> loadPluginsFromRepository(@Nullable ProgressIndicator indicator) throws Exception {
+ return loadPluginsFromRepository(indicator, null);
+ }
+
+ public static List<IdeaPluginDescriptor> loadPluginsFromRepository(@Nullable ProgressIndicator indicator,
+ BuildNumber buildnumber) throws Exception {
ApplicationInfoEx appInfo = ApplicationInfoImpl.getShadowInstance();
- String url = appInfo.getPluginsListUrl() + "?build=" + appInfo.getApiVersion();
+ String url = appInfo.getPluginsListUrl() + "?build=" + (buildnumber != null ? buildnumber.asString() : appInfo.getApiVersion());
if (indicator != null) {
indicator.setText2(IdeBundle.message("progress.connecting.to.plugin.manager", appInfo.getPluginManagerUrl()));
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/AppearanceConfigurable.java b/platform/platform-impl/src/com/intellij/ide/ui/AppearanceConfigurable.java
index c60ddc44748d..cc6e16aba6c2 100644
--- a/platform/platform-impl/src/com/intellij/ide/ui/AppearanceConfigurable.java
+++ b/platform/platform-impl/src/com/intellij/ide/ui/AppearanceConfigurable.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.
@@ -70,7 +70,7 @@ public class AppearanceConfigurable extends BaseConfigurable implements Searchab
myComponent.myLafComboBox.setModel(new DefaultComboBoxModel(LafManager.getInstance().getInstalledLookAndFeels()));
myComponent.myLafComboBox.setRenderer(new LafComboBoxRenderer());
- Dictionary<Integer, JLabel> delayDictionary = new Hashtable<Integer, JLabel>();
+ Dictionary<Integer, JComponent> delayDictionary = new Hashtable<Integer, JComponent>();
delayDictionary.put(new Integer(0), new JLabel("0"));
delayDictionary.put(new Integer(1200), new JLabel("1200"));
//delayDictionary.put(new Integer(2400), new JLabel("2400"));
@@ -94,7 +94,7 @@ public class AppearanceConfigurable extends BaseConfigurable implements Searchab
myComponent.myAlphaModeRatioSlider.setSize(100, 50);
@SuppressWarnings({"UseOfObsoleteCollectionType"})
- Dictionary<Integer, JLabel> dictionary = new Hashtable<Integer, JLabel>();
+ Dictionary<Integer, JComponent> dictionary = new Hashtable<Integer, JComponent>();
dictionary.put(new Integer(0), new JLabel("0%"));
dictionary.put(new Integer(50), new JLabel("50%"));
dictionary.put(new Integer(100), new JLabel("100%"));
diff --git a/platform/platform-impl/src/com/intellij/ide/util/TipDialog.java b/platform/platform-impl/src/com/intellij/ide/util/TipDialog.java
index 0744e377e6c5..3d84e6d7431c 100644
--- a/platform/platform-impl/src/com/intellij/ide/util/TipDialog.java
+++ b/platform/platform-impl/src/com/intellij/ide/util/TipDialog.java
@@ -1,4 +1,3 @@
-
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
@@ -33,6 +32,12 @@ import java.awt.event.ActionEvent;
public class TipDialog extends DialogWrapper{
private TipPanel myTipPanel;
+ @Nullable
+ @Override
+ protected String getDimensionServiceKey() {
+ return getClass().getName();
+ }
+
public TipDialog(){
super(WindowManagerEx.getInstanceEx().findVisibleFrame(), true);
initialize();
@@ -52,9 +57,6 @@ public class TipDialog extends DialogWrapper{
setHorizontalStretch(1.33f);
setVerticalStretch(1.25f);
init();
- if (getPeer() instanceof DialogWrapperPeerImpl) {
- ((DialogWrapperPeerImpl)getPeer()).setAutoRequestFocus(false);
- }
}
@NotNull
diff --git a/platform/platform-impl/src/com/intellij/notification/EventLogToolWindowFactory.java b/platform/platform-impl/src/com/intellij/notification/EventLogToolWindowFactory.java
index 1fd6c340d073..32b03f3deb2b 100644
--- a/platform/platform-impl/src/com/intellij/notification/EventLogToolWindowFactory.java
+++ b/platform/platform-impl/src/com/intellij/notification/EventLogToolWindowFactory.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.content.Content;
import com.intellij.ui.content.ContentFactory;
import com.intellij.ui.content.ContentManager;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import javax.swing.event.AncestorEvent;
@@ -44,7 +45,7 @@ import javax.swing.event.AncestorEvent;
*/
public class EventLogToolWindowFactory implements ToolWindowFactory, DumbAware {
@Override
- public void createToolWindowContent(final Project project, ToolWindow toolWindow) {
+ public void createToolWindowContent(@NotNull final Project project, @NotNull ToolWindow toolWindow) {
EventLog.getProjectComponent(project).initDefaultContent();
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/AbbreviationManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/AbbreviationManagerImpl.java
index a7b2e7bc9d02..0d116c7a927f 100644
--- a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/AbbreviationManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/AbbreviationManagerImpl.java
@@ -38,40 +38,33 @@ import java.util.*;
)}
)
public class AbbreviationManagerImpl extends AbbreviationManager implements
- ExportableApplicationComponent, PersistentStateComponent<Element> {
+ ExportableComponent, PersistentStateComponent<Element> {
private final Map<String, List<String>> myAbbreviation2ActionId = new THashMap<String, List<String>>();
private final Map<String, LinkedHashSet<String>> myActionId2Abbreviations = new THashMap<String, LinkedHashSet<String>>();
private final Map<String, LinkedHashSet<String>> myPluginsActionId2Abbreviations = new THashMap<String, LinkedHashSet<String>>();
- @Override
- public void initComponent() {
-
- }
-
- @Override
- public void disposeComponent() {
-
- }
-
- @NotNull
- @Override
- public String getComponentName() {
- return "AbbreviationManager";
- }
-
@Nullable
@Override
public Element getState() {
final Element actions = new Element("actions");
- final Element abbreviations = new Element("abbreviations");
- actions.addContent(abbreviations);
+ if (myActionId2Abbreviations.isEmpty()) {
+ return actions;
+ }
+
+ Element abbreviations = null;
for (String key : myActionId2Abbreviations.keySet()) {
final LinkedHashSet<String> abbrs = myActionId2Abbreviations.get(key);
final LinkedHashSet<String> pluginAbbrs = myPluginsActionId2Abbreviations.get(key);
if (abbrs == pluginAbbrs || (abbrs != null && abbrs.equals(pluginAbbrs))) {
continue;
}
+
if (abbrs != null) {
+ if (abbreviations == null) {
+ abbreviations = new Element("abbreviations");
+ actions.addContent(abbreviations);
+ }
+
final Element action = new Element("action");
action.setAttribute("id", key);
abbreviations.addContent(action);
diff --git a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionManagerImpl.java
index 78043075b166..723956ef9daa 100644
--- a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionManagerImpl.java
@@ -49,6 +49,7 @@ import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.openapi.wm.IdeFrame;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ObjectUtils;
+import com.intellij.util.ReflectionUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import com.intellij.util.messages.MessageBusConnection;
@@ -66,7 +67,6 @@ import javax.swing.*;
import javax.swing.Timer;
import java.awt.*;
import java.awt.event.*;
-import java.lang.reflect.Constructor;
import java.util.*;
import java.util.List;
@@ -259,9 +259,8 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat
Object obj;
String className = stub.getClassName();
try {
- Constructor<?> constructor = Class.forName(className, true, stub.getLoader()).getDeclaredConstructor();
- constructor.setAccessible(true);
- obj = constructor.newInstance();
+ Class<?> aClass = Class.forName(className, true, stub.getLoader());
+ obj = ReflectionUtil.newInstance(aClass);
}
catch (ClassNotFoundException e) {
PluginId pluginId = stub.getPluginId();
diff --git a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionToolbarImpl.java b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionToolbarImpl.java
index a0b495726f30..529d5ba1c62f 100644
--- a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionToolbarImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionToolbarImpl.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.
@@ -65,6 +65,8 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.actionSystem.impl.ActionToolbarImpl");
private static final List<ActionToolbarImpl> ourToolbars = new LinkedList<ActionToolbarImpl>();
+ private static final String RIGHT_ALIGN_KEY = "RIGHT_ALIGN";
+
public static void updateAllToolbarsImmediately() {
for (ActionToolbarImpl toolbar : new ArrayList<ActionToolbarImpl>(ourToolbars)) {
toolbar.updateActionsImmediately();
@@ -107,7 +109,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
private final ActionButtonLook myButtonLook = null;
private final ActionButtonLook myMinimalButtonLook = new InplaceActionButtonLook();
private final DataManager myDataManager;
- protected final ActionManagerEx myActionManager;
+ @NotNull protected final ActionManagerEx myActionManager;
private Rectangle myAutoPopupRec;
@@ -135,7 +137,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
@NotNull final ActionGroup actionGroup,
final boolean horizontal,
DataManager dataManager,
- ActionManagerEx actionManager,
+ @NotNull ActionManagerEx actionManager,
KeymapManagerEx keymapManager) {
this(place, actionGroup, horizontal, false, dataManager, actionManager, keymapManager, false);
}
@@ -144,7 +146,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
final boolean horizontal,
final boolean decorateButtons,
DataManager dataManager,
- ActionManagerEx actionManager,
+ @NotNull ActionManagerEx actionManager,
KeymapManagerEx keymapManager) {
this(place, actionGroup, horizontal, decorateButtons, dataManager, actionManager, keymapManager, false);
}
@@ -154,7 +156,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
final boolean horizontal,
final boolean decorateButtons,
DataManager dataManager,
- ActionManagerEx actionManager,
+ @NotNull ActionManagerEx actionManager,
KeymapManagerEx keymapManager,
boolean updateActionsNow) {
super(null);
@@ -272,11 +274,16 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
}
private void fillToolBar(final List<AnAction> actions, boolean layoutSecondaries) {
+ final List<AnAction> rightAligned = new ArrayList<AnAction>();
if (myAddSeparatorFirst) {
add(new MySeparator());
}
for (int i = 0; i < actions.size(); i++) {
final AnAction action = actions.get(i);
+ if (action instanceof RightAlignedToolbarAction) {
+ rightAligned.add(action);
+ continue;
+ }
// if (action instanceof Separator && isNavBar()) {
// continue;
// }
@@ -311,18 +318,23 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
add(mySecondaryActionsButton);
}
- if ((ActionPlaces.MAIN_TOOLBAR.equals(myPlace) || ActionPlaces.NAVIGATION_BAR_TOOLBAR.equals(myPlace))) {
- final AnAction searchEverywhereAction = ActionManager.getInstance().getAction("SearchEverywhere");
- if (searchEverywhereAction != null) {
- try {
- final CustomComponentAction searchEveryWhereAction = (CustomComponentAction)searchEverywhereAction;
- final JComponent searchEverywhere = searchEveryWhereAction.createCustomComponent(searchEverywhereAction.getTemplatePresentation());
- searchEverywhere.putClientProperty("SEARCH_EVERYWHERE", Boolean.TRUE);
- add(searchEverywhere);
- }
- catch (Exception ignore) {}
- }
- }
+ for (AnAction action : rightAligned) {
+ JComponent button = action instanceof CustomComponentAction ? getCustomComponent(action) : createToolbarButton(action);
+ button.putClientProperty(RIGHT_ALIGN_KEY, Boolean.TRUE);
+ add(button);
+ }
+ //if ((ActionPlaces.MAIN_TOOLBAR.equals(myPlace) || ActionPlaces.NAVIGATION_BAR_TOOLBAR.equals(myPlace))) {
+ // final AnAction searchEverywhereAction = ActionManager.getInstance().getAction("SearchEverywhere");
+ // if (searchEverywhereAction != null) {
+ // try {
+ // final CustomComponentAction searchEveryWhereAction = (CustomComponentAction)searchEverywhereAction;
+ // final JComponent searchEverywhere = searchEveryWhereAction.createCustomComponent(searchEverywhereAction.getTemplatePresentation());
+ // searchEverywhere.putClientProperty("SEARCH_EVERYWHERE", Boolean.TRUE);
+ // add(searchEverywhere);
+ // }
+ // catch (Exception ignore) {}
+ // }
+ //}
}
private JComponent getCustomComponent(AnAction action) {
@@ -730,14 +742,18 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
throw new IllegalStateException("unknown layoutPolicy: " + myLayoutPolicy);
}
+
if (getComponentCount() > 0 && size2Fit.width < Integer.MAX_VALUE) {
- final Component component = getComponent(getComponentCount() - 1);
- if (component instanceof JComponent && ((JComponent)component).getClientProperty("SEARCH_EVERYWHERE") == Boolean.TRUE) {
- int max = 0;
- for (int i = 0; i < bounds.size() - 2; i++) {
- max = Math.max(max, bounds.get(i).height);
+ int maxHeight = 0;
+ for (int i = 0; i < bounds.size() - 2; i++) {
+ maxHeight = Math.max(maxHeight, bounds.get(i).height);
+ }
+
+ for (int i = getComponentCount() - 1, j = 1; i > 0; i--, j++) {
+ final Component component = getComponent(i);
+ if (component instanceof JComponent && ((JComponent)component).getClientProperty(RIGHT_ALIGN_KEY) == Boolean.TRUE) {
+ bounds.set(bounds.size() - j, new Rectangle(size2Fit.width - j * 25, 0, 25, maxHeight));
}
- bounds.set(bounds.size() - 1, new Rectangle(size2Fit.width - 25, 0, 25, max));
}
}
}
@@ -1185,7 +1201,7 @@ public class ActionToolbarImpl extends JPanel implements ActionToolbar {
final ActionGroup actionGroup,
final boolean horizontal,
final DataManager dataManager,
- final ActionManagerEx actionManager,
+ @NotNull ActionManagerEx actionManager,
final KeymapManagerEx keymapManager,
JComponent parent) {
super(place, actionGroup, horizontal, false, dataManager, actionManager, keymapManager, true);
diff --git a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java
index 7c8acbc4c25c..46fae517170d 100644
--- a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java
@@ -781,7 +781,7 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
}
@Override
- public void restart(boolean exitConfirmed) {
+ public void restart(final boolean exitConfirmed) {
exit(false, exitConfirmed, true, true);
}
@@ -801,7 +801,7 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
exiting = true;
try {
- if (!force && getDefaultModalityState() != ModalityState.NON_MODAL) {
+ if (!force && !exitConfirmed && getDefaultModalityState() != ModalityState.NON_MODAL) {
return;
}
@@ -1067,8 +1067,7 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
private static Thread getEventQueueThread() {
EventQueue eventQueue = Toolkit.getDefaultToolkit().getSystemEventQueue();
try {
- Method method = EventQueue.class.getDeclaredMethod("getDispatchThread");
- method.setAccessible(true);
+ Method method = ReflectionUtil.getDeclaredMethod(EventQueue.class, "getDispatchThread");
return (Thread)method.invoke(eventQueue);
}
catch (Exception e) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/application/impl/ModalityInvokatorImpl.java b/platform/platform-impl/src/com/intellij/openapi/application/impl/ModalityInvokatorImpl.java
index ab2be68b70bd..de7a7e76aa70 100644
--- a/platform/platform-impl/src/com/intellij/openapi/application/impl/ModalityInvokatorImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/application/impl/ModalityInvokatorImpl.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.
@@ -27,23 +27,27 @@ import com.intellij.openapi.util.Condition;
import org.jetbrains.annotations.NotNull;
public class ModalityInvokatorImpl implements ModalityInvokator {
+ @NotNull
@Override
- public ActionCallback invokeLater(Runnable runnable) {
+ public ActionCallback invokeLater(@NotNull Runnable runnable) {
return invokeLater(runnable, ApplicationManager.getApplication().getDisposed());
}
+ @NotNull
@Override
- public ActionCallback invokeLater(final Runnable runnable, @NotNull final Condition expired) {
+ public ActionCallback invokeLater(@NotNull final Runnable runnable, @NotNull final Condition expired) {
return LaterInvocator.invokeLater(runnable, expired);
}
+ @NotNull
@Override
- public ActionCallback invokeLater(final Runnable runnable, @NotNull final ModalityState state, @NotNull final Condition expired) {
+ public ActionCallback invokeLater(@NotNull final Runnable runnable, @NotNull final ModalityState state, @NotNull final Condition expired) {
return LaterInvocator.invokeLater(runnable, state, expired);
}
+ @NotNull
@Override
- public ActionCallback invokeLater(Runnable runnable, @NotNull ModalityState state) {
+ public ActionCallback invokeLater(@NotNull Runnable runnable, @NotNull ModalityState state) {
return invokeLater(runnable, state, ApplicationManager.getApplication().getDisposed());
}
} \ No newline at end of file
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/EditorLinePainter.java b/platform/platform-impl/src/com/intellij/openapi/editor/EditorLinePainter.java
new file mode 100644
index 000000000000..420a0fdf23a7
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/EditorLinePainter.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.editor;
+
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collection;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public abstract class EditorLinePainter {
+ public static final ExtensionPointName<EditorLinePainter> EP_NAME = ExtensionPointName.create("com.intellij.editor.linePainter");
+
+ public abstract Collection<LineExtensionInfo> getLineExtensions(@NotNull Project project, @NotNull VirtualFile file, int lineNumber);
+}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/LineExtensionInfo.java b/platform/platform-impl/src/com/intellij/openapi/editor/LineExtensionInfo.java
new file mode 100644
index 000000000000..f84502097b10
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/LineExtensionInfo.java
@@ -0,0 +1,71 @@
+/*
+ * 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.editor.markup.EffectType;
+import org.intellij.lang.annotations.JdkConstants;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.awt.*;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public class LineExtensionInfo {
+ @NotNull private final String myText;
+ @Nullable private final Color myColor;
+ @Nullable private final EffectType myEffectType;
+ @Nullable private final Color myEffectColor;
+ @JdkConstants.FontStyle private final int myFontType;
+
+ public LineExtensionInfo(@NotNull String text,
+ @Nullable Color color,
+ @Nullable EffectType effectType,
+ @Nullable Color effectColor,
+ @JdkConstants.FontStyle int fontType) {
+ myText = text;
+ myColor = color;
+ myEffectType = effectType;
+ myEffectColor = effectColor;
+ myFontType = fontType;
+ }
+
+ @NotNull
+ public String getText() {
+ return myText;
+ }
+
+ @Nullable
+ public Color getColor() {
+ return myColor;
+ }
+
+ @Nullable
+ public EffectType getEffectType() {
+ return myEffectType;
+ }
+
+ @Nullable
+ public Color getEffectColor() {
+ return myEffectColor;
+ }
+
+ @JdkConstants.FontStyle
+ public int getFontType() {
+ return myFontType;
+ }
+}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/EnterAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/EnterAction.java
index cc7b2177cd91..ea2107632122 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/EnterAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/EnterAction.java
@@ -30,6 +30,8 @@ import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.actionSystem.EditorAction;
import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler;
import com.intellij.util.ui.MacUIUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
public class EnterAction extends EditorAction {
public EnterAction() {
@@ -43,13 +45,13 @@ public class EnterAction extends EditorAction {
}
@Override
- public void executeWriteAction(Editor editor, DataContext dataContext) {
+ public void executeWriteAction(Editor editor, @Nullable Caret caret, DataContext dataContext) {
CommandProcessor.getInstance().setCurrentCommandName(EditorBundle.message("typing.command.name"));
insertNewLineAtCaret(editor);
}
@Override
- public boolean isEnabled(Editor editor, DataContext dataContext) {
+ public boolean isEnabledForCaret(@NotNull Editor editor, @NotNull Caret caret, DataContext dataContext) {
return !editor.isOneLineMode();
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/IndentSelectionAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/IndentSelectionAction.java
index 92f025685891..76eff2bd7a54 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/IndentSelectionAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/IndentSelectionAction.java
@@ -57,7 +57,7 @@ public class IndentSelectionAction extends EditorAction {
@Override
public void executeWriteAction(Editor editor, @Nullable Caret caret, DataContext dataContext) {
Project project = CommonDataKeys.PROJECT.getData(dataContext);
- if (isEnabled(editor, dataContext)) {
+ if (isEnabled(editor, caret, dataContext)) {
indentSelection(editor, project);
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/SplitLineAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/SplitLineAction.java
index 7716a9001b7e..1583bd423ff7 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/SplitLineAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/SplitLineAction.java
@@ -18,10 +18,7 @@ package com.intellij.openapi.editor.actions;
import com.intellij.ide.DataManager;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.IdeActions;
-import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.editor.RangeMarker;
-import com.intellij.openapi.editor.ScrollType;
+import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.actionSystem.EditorAction;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
import com.intellij.openapi.editor.actionSystem.EditorActionManager;
@@ -30,6 +27,7 @@ import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.ide.CopyPasteManager;
import com.intellij.openapi.util.Key;
import com.intellij.util.text.CharArrayUtil;
+import org.jetbrains.annotations.NotNull;
/**
* @author max
@@ -48,13 +46,13 @@ public class SplitLineAction extends EditorAction {
}
@Override
- public boolean isEnabled(Editor editor, DataContext dataContext) {
- return getEnterHandler().isEnabled(editor, dataContext) &&
+ public boolean isEnabledForCaret(@NotNull Editor editor, @NotNull Caret caret, DataContext dataContext) {
+ return getEnterHandler().isEnabled(editor, caret, dataContext) &&
!((EditorEx)editor).isEmbeddedIntoDialogWrapper();
}
@Override
- public void executeWriteAction(Editor editor, DataContext dataContext) {
+ public void executeWriteAction(Editor editor, Caret caret, DataContext dataContext) {
CopyPasteManager.getInstance().stopKillRings();
final Document document = editor.getDocument();
final RangeMarker rangeMarker =
@@ -77,7 +75,7 @@ public class SplitLineAction extends EditorAction {
} else {
DataManager.getInstance().saveInDataContext(dataContext, SPLIT_LINE_KEY, true);
try {
- getEnterHandler().execute(editor, dataContext);
+ getEnterHandler().execute(editor, caret, dataContext);
}
finally {
DataManager.getInstance().saveInDataContext(dataContext, SPLIT_LINE_KEY, null);
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/StartNewLineAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/StartNewLineAction.java
index 0302e484d00d..b2f43bf4458f 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/StartNewLineAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/StartNewLineAction.java
@@ -17,6 +17,7 @@ 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.LogicalPosition;
import com.intellij.openapi.editor.actionSystem.EditorAction;
@@ -24,6 +25,7 @@ import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
import com.intellij.openapi.editor.actionSystem.EditorActionManager;
import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler;
import com.intellij.openapi.ide.CopyPasteManager;
+import org.jetbrains.annotations.NotNull;
/**
* @author max
@@ -39,12 +41,12 @@ public class StartNewLineAction extends EditorAction {
}
@Override
- public boolean isEnabled(Editor editor, DataContext dataContext) {
- return getEnterHandler().isEnabled(editor, dataContext);
+ public boolean isEnabledForCaret(@NotNull Editor editor, @NotNull Caret caret, DataContext dataContext) {
+ return getEnterHandler().isEnabled(editor, caret, dataContext);
}
@Override
- public void executeWriteAction(Editor editor, DataContext dataContext) {
+ public void executeWriteAction(Editor editor, Caret caret, DataContext dataContext) {
CopyPasteManager.getInstance().stopKillRings();
if (editor.getDocument().getLineCount() != 0) {
editor.getSelectionModel().removeSelection();
@@ -53,7 +55,7 @@ public class StartNewLineAction extends EditorAction {
editor.getCaretModel().moveToOffset(lineEndOffset);
}
- getEnterHandler().execute(editor, dataContext);
+ getEnterHandler().execute(editor, caret, dataContext);
}
private static EditorActionHandler getEnterHandler() {
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/StartNewLineBeforeAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/StartNewLineBeforeAction.java
index fc2ae4031ca3..4d8c6ff2f465 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/StartNewLineBeforeAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/StartNewLineBeforeAction.java
@@ -42,8 +42,8 @@ public class StartNewLineBeforeAction extends EditorAction {
}
@Override
- public boolean isEnabled(Editor editor, DataContext dataContext) {
- return getHandler(IdeActions.ACTION_EDITOR_ENTER).isEnabled(editor, dataContext);
+ public boolean isEnabledForCaret(@NotNull Editor editor, @NotNull Caret caret, DataContext dataContext) {
+ return getHandler(IdeActions.ACTION_EDITOR_ENTER).isEnabled(editor, caret, dataContext);
}
@Override
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/UnselectWordAtCaretAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/UnselectWordAtCaretAction.java
index a1ae088a89e2..2d7e3945ee6e 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/UnselectWordAtCaretAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/UnselectWordAtCaretAction.java
@@ -24,11 +24,13 @@
*/
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 com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.project.DumbAware;
+import org.jetbrains.annotations.Nullable;
public class UnselectWordAtCaretAction extends EditorAction implements DumbAware {
public UnselectWordAtCaretAction() {
@@ -42,7 +44,7 @@ public class UnselectWordAtCaretAction extends EditorAction implements DumbAware
}
@Override
- public void execute(Editor editor, DataContext dataContext) {
+ public void doExecute(Editor editor, @Nullable Caret caret, DataContext dataContext) {
}
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/ex/EditorMarkupModel.java b/platform/platform-impl/src/com/intellij/openapi/editor/ex/EditorMarkupModel.java
index 5da1077baf5c..71dee99c3514 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/ex/EditorMarkupModel.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/ex/EditorMarkupModel.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.
@@ -28,7 +28,7 @@ public interface EditorMarkupModel extends MarkupModel {
void setErrorStripeVisible(boolean val);
- void setErrorStripeRenderer(ErrorStripeRenderer renderer);
+ void setErrorStripeRenderer(@NotNull ErrorStripeRenderer renderer);
ErrorStripeRenderer getErrorStripeRenderer();
void addErrorMarkerListener(@NotNull ErrorStripeListener listener, @NotNull Disposable parent);
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorHeaderComponent.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorHeaderComponent.java
index fc1f9048d31f..31b3a56d2317 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorHeaderComponent.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorHeaderComponent.java
@@ -46,13 +46,8 @@ public class EditorHeaderComponent extends JPanel {
paintGradient(g, this);
}
- @NotNull
- protected JBColor getBaseBackgroundColor() {
- return new JBColor(getBackground(), JBColor.background());
- }
-
private void paintGradient(Graphics g, JComponent c) {
- Color GRADIENT_C1 = getBaseBackgroundColor();
+ Color GRADIENT_C1 = isBackgroundSet() ? getBackground() : new JBColor(getBackground(), JBColor.background());
Color GRADIENT_C2 = new JBColor(new Color(Math.max(0, GRADIENT_C1.getRed() - 0x18), Math.max(0, GRADIENT_C1.getGreen() - 0x18),
Math.max(0, GRADIENT_C1.getBlue() - 0x18)), Gray._75);
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 c0ffbd10aca4..6160ea58dcdf 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
@@ -2765,8 +2765,25 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
if (hEnd >= lEnd) {
FoldRegion collapsedFolderAt = myFoldingModel.getCollapsedRegionAtOffset(start);
if (collapsedFolderAt == null) {
- drawStringWithSoftWraps(g, chars, start, lEnd - lIterator.getSeparatorLength(), position, clip, effectColor,
- effectType, fontType, currentColor, logicalPosition);
+ int i = drawStringWithSoftWraps(g, chars, start, lEnd - lIterator.getSeparatorLength(), position, clip, effectColor,
+ effectType, fontType, currentColor, logicalPosition);
+ final VirtualFile file = getVirtualFile();
+ if (myProject != null && file != null && !isOneLineMode()) {
+ for (EditorLinePainter painter : EditorLinePainter.EP_NAME.getExtensions()) {
+ Collection<LineExtensionInfo> extensions = painter.getLineExtensions(myProject, file, lIterator.getLineNumber());
+ if (extensions != null && !extensions.isEmpty()) {
+ for (LineExtensionInfo info : extensions) {
+ drawStringWithSoftWraps(g, info.getText(), 0, info.getText().length(), position, clip,
+ info.getEffectColor() == null ? effectColor : info.getEffectColor(),
+ info.getEffectType() == null ? effectType : info.getEffectType(),
+ info.getFontType(),
+ info.getColor() == null ? currentColor : info.getColor(),
+ logicalPosition);
+ }
+ }
+ }
+ }
+
position.x = 0;
if (position.y > clip.y + clip.height) {
break;
@@ -6749,10 +6766,17 @@ 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 ||
- myProject != null && !ToolWindowManagerEx.getInstanceEx(myProject).getIdsOn(ToolWindowAnchor.TOP).isEmpty();
+ toolWindowIsNotEmpty();
return splitters == null ? super.getBorderInsets(c) : new Insets(thereIsSomethingAbove ? 1 : 0, 0, 0, 0);
}
+ public boolean toolWindowIsNotEmpty() {
+ if (myProject == null) return false;
+ ToolWindowManagerEx m = ToolWindowManagerEx.getInstanceEx(myProject);
+ if (m == null) return false;
+ return !m.getIdsOn(ToolWindowAnchor.TOP).isEmpty();
+ }
+
@Override
public boolean isBorderOpaque() {
return true;
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 6ec29e58dc0b..20c08ec4ec99 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
@@ -368,7 +368,7 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark
}
@Override
- public void setErrorStripeRenderer(ErrorStripeRenderer renderer) {
+ public void setErrorStripeRenderer(@NotNull ErrorStripeRenderer renderer) {
assertIsDispatchThread();
if (myErrorStripeRenderer instanceof Disposable) {
Disposer.dispose((Disposable)myErrorStripeRenderer);
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileTextFieldImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileTextFieldImpl.java
index 63843a932076..64f56eb750eb 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileTextFieldImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileTextFieldImpl.java
@@ -285,7 +285,7 @@ public abstract class FileTextFieldImpl implements FileLookup, Disposable, FileT
myList = new JBList();
myList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
- myList.setCellRenderer(new GroupedItemsListRenderer(new ListItemDescriptor() {
+ myList.setCellRenderer(new GroupedItemsListRenderer(new ListItemDescriptorAdapter() {
public String getTextFor(final Object value) {
final LookupFile file = (LookupFile)value;
@@ -298,10 +298,6 @@ public abstract class FileTextFieldImpl implements FileLookup, Disposable, FileT
}
- public String getTooltipFor(final Object value) {
- return null;
- }
-
public Icon getIconFor(final Object value) {
final LookupFile file = (LookupFile)value;
return file.getIcon();
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/ex/FileEditorManagerEx.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/ex/FileEditorManagerEx.java
index 9520834b4518..30eb78cf706f 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/ex/FileEditorManagerEx.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/ex/FileEditorManagerEx.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,6 +16,7 @@
package com.intellij.openapi.fileEditor.ex;
import com.intellij.openapi.Disposable;
+import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileEditor.EditorDataProvider;
import com.intellij.openapi.fileEditor.FileEditor;
@@ -164,9 +165,9 @@ public abstract class FileEditorManagerEx extends FileEditorManager implements B
public abstract boolean isInsideChange();
@Nullable
- public final Object getData(@NotNull String dataId, @NotNull Editor editor, @NotNull VirtualFile file) {
+ public final Object getData(@NotNull String dataId, @NotNull Editor editor, @NotNull Caret caret) {
for (final EditorDataProvider dataProvider : myDataProviders) {
- final Object o = dataProvider.getData(dataId, editor, file);
+ final Object o = dataProvider.getData(dataId, editor, caret);
if (o != null) return o;
}
return 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 091ff1171157..cce6de27545d 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
@@ -621,6 +621,7 @@ public class FileDocumentManagerImpl extends FileDocumentManager implements Virt
DocumentEx documentEx = (DocumentEx)document;
documentEx.setReadOnly(false);
LoadTextUtil.setCharsetWasDetectedFromBytes(file, null);
+ file.setBOM(null); // reset BOM in case we had one and the external change stripped it away
documentEx.replaceText(LoadTextUtil.loadText(file), file.getModificationStamp());
documentEx.setReadOnly(!wasWritable);
}
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 c7fa51f770d1..bab6d2b2fa4f 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
@@ -1636,7 +1636,7 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec
*/
private final class MyVirtualFileListener extends VirtualFileAdapter {
@Override
- public void beforeFileDeletion(VirtualFileEvent e) {
+ public void beforeFileDeletion(@NotNull VirtualFileEvent e) {
assertDispatchThread();
boolean moveFocus = moveFocusOnDelete();
@@ -1651,7 +1651,7 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec
}
@Override
- public void propertyChanged(VirtualFilePropertyEvent e) {
+ public void propertyChanged(@NotNull VirtualFilePropertyEvent e) {
if (VirtualFile.PROP_NAME.equals(e.getPropertyName())) {
assertDispatchThread();
final VirtualFile file = e.getFile();
@@ -1681,7 +1681,7 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec
}
@Override
- public void fileMoved(VirtualFileMoveEvent e) {
+ public void fileMoved(@NotNull VirtualFileMoveEvent e) {
final VirtualFile file = e.getFile();
final VirtualFile[] openFiles = getOpenFiles();
for (final VirtualFile openFile : openFiles) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/HistoryEntry.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/HistoryEntry.java
index 5f3dd9adad22..51d044866717 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/HistoryEntry.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/HistoryEntry.java
@@ -24,18 +24,19 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.util.containers.HashMap;
import org.jdom.Element;
+import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.Map;
final class HistoryEntry{
- static final String TAG = "entry";
+ @NonNls static final String TAG = "entry";
private static final String FILE_ATTR = "file";
- private static final String PROVIDER_ELEMENT = "provider";
- private static final String EDITOR_TYPE_ID_ATTR = "editor-type-id";
- private static final String SELECTED_ATTR_VALUE = "selected";
- private static final String STATE_ELEMENT = "state";
+ @NonNls private static final String PROVIDER_ELEMENT = "provider";
+ @NonNls private static final String EDITOR_TYPE_ID_ATTR = "editor-type-id";
+ @NonNls private static final String SELECTED_ATTR_VALUE = "selected";
+ @NonNls private static final String STATE_ELEMENT = "state";
public final VirtualFile myFile;
/**
@@ -53,7 +54,7 @@ final class HistoryEntry{
}
}
- public HistoryEntry(Project project, Element e) throws InvalidDataException {
+ public HistoryEntry(@NotNull Project project, @NotNull Element e) throws InvalidDataException {
myFile = getVirtualFile(e);
myProvider2State = new HashMap<FileEditorProvider, FileEditorState>();
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorComponent.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorComponent.java
index 288227eb51bd..de11bd5b9a12 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorComponent.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorComponent.java
@@ -36,7 +36,6 @@ import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.impl.EditorHistoryManager;
-import com.intellij.openapi.fileEditor.impl.FileEditorManagerImpl;
import com.intellij.openapi.fileTypes.FileTypeEvent;
import com.intellij.openapi.fileTypes.FileTypeListener;
import com.intellij.openapi.fileTypes.FileTypeManager;
@@ -278,7 +277,7 @@ class TextEditorComponent extends JBLoadingPanel implements DataProvider {
if (e == null) return null;
if (!myProject.isDisposed()) {
- final Object o = ((FileEditorManagerImpl)FileEditorManager.getInstance(myProject)).getData(dataId, e, myFile);
+ final Object o = FileEditorManager.getInstance(myProject).getData(dataId, e, e.getCaretModel().getCurrentCaret());
if (o != null) return o;
}
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 13a8aaecb724..8a9031986ef8 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
@@ -24,6 +24,7 @@ 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;
+import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.util.containers.ConcurrentHashMap;
import gnu.trove.TIntIntHashMap;
@@ -63,6 +64,9 @@ public class ModifierKeyDoubleClickHandler {
public void registerAction(@NotNull String actionId,
int modifierKeyCode,
int actionKeyCode) {
+ if (SystemInfo.isMac && modifierKeyCode == KeyEvent.VK_CONTROL) {
+ modifierKeyCode = KeyEvent.VK_META;
+ }
final MyDispatcher dispatcher = new MyDispatcher(actionId, modifierKeyCode, actionKeyCode);
IdeEventQueue.EventDispatcher oldDispatcher = myDispatchers.put(actionId, dispatcher);
IdeEventQueue.getInstance().addDispatcher(dispatcher, null);
diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ActionsTree.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ActionsTree.java
index 1b0c17f3ab4e..44ec15003de9 100644
--- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ActionsTree.java
+++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ActionsTree.java
@@ -21,6 +21,7 @@ import com.intellij.ide.ui.UISettings;
import com.intellij.ide.ui.search.SearchUtil;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.actionSystem.ex.QuickList;
+import com.intellij.openapi.actionSystem.impl.ActionMenu;
import com.intellij.openapi.keymap.KeyMapBundle;
import com.intellij.openapi.keymap.Keymap;
import com.intellij.openapi.keymap.KeymapUtil;
@@ -40,12 +41,15 @@ import com.intellij.util.ui.UIUtil;
import com.intellij.util.ui.tree.TreeUtil;
import com.intellij.util.ui.tree.WideSelectionTreeUI;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.*;
import java.awt.*;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseMotionAdapter;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Set;
@@ -91,7 +95,7 @@ public class ActionsTree {
}
}
}
-
+
}
};
myTree.setRootVisible(false);
@@ -99,6 +103,36 @@ public class ActionsTree {
myTree.putClientProperty(WideSelectionTreeUI.STRIPED_CLIENT_PROPERTY, Boolean.TRUE);
myTree.setCellRenderer(new KeymapsRenderer());
+ myTree.addMouseMotionListener(new MouseMotionAdapter() {
+ @Override
+ public void mouseMoved(MouseEvent e) {
+ String description = getDescription(e);
+ if (description != null) {
+ ActionMenu.showDescriptionInStatusBar(true, myTree, description);
+ }
+ else {
+ ActionMenu.showDescriptionInStatusBar(false, myTree, null);
+ }
+ }
+
+ @Nullable
+ private String getDescription(@NotNull MouseEvent e) {
+ TreePath path = myTree.getPathForLocation(e.getX(), e.getY());
+ if (path == null) return null;
+
+ DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent();
+ if (node == null) return null;
+
+ Object userObject = node.getUserObject();
+ if (!(userObject instanceof String)) return null;
+
+ String actionId = (String)userObject;
+ AnAction action = ActionManager.getInstance().getActionOrStub(actionId);
+ if (action == null) return null;
+
+ return action.getTemplatePresentation().getDescription();
+ }
+ });
myTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
@@ -447,6 +481,7 @@ public class ActionsTree {
Icon icon = null;
String text;
boolean bound = false;
+ setToolTipText(null);
if (value instanceof DefaultMutableTreeNode) {
Object userObject = ((DefaultMutableTreeNode)value).getUserObject();
@@ -474,6 +509,7 @@ public class ActionsTree {
if (actionIcon != null) {
icon = actionIcon;
}
+ setToolTipText(action.getTemplatePresentation().getDescription());
}
else {
text = actionId;
@@ -521,7 +557,7 @@ public class ActionsTree {
}
}
}
-
+
private void paintRowData(Tree tree, Object data, Rectangle bounds, Graphics2D g) {
Shortcut[] shortcuts = null;
Set<String> abbreviations = null;
@@ -552,7 +588,7 @@ public class ActionsTree {
Color c2 = new Color(208, 200, 66);
g.translate(0, bounds.y - 1);
-
+
for (Shortcut shortcut : shortcuts) {
int width = metrics.stringWidth(KeymapUtil.getShortcutText(shortcut));
UIUtil.drawSearchMatch(g, x, x + width, bounds.height, c1, c2);
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableExtensionPointUtil.java b/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableExtensionPointUtil.java
index c06dbee44c1a..429a55b2b809 100644
--- a/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableExtensionPointUtil.java
+++ b/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableExtensionPointUtil.java
@@ -71,7 +71,7 @@ public class ConfigurableExtensionPointUtil {
idToConfigurable.put(parentId, parent.addChild(wrapper));
}
else {
- LOG.error("Can't find parent for " + parentId + " (" + wrapper + ")");
+ LOG.debug("Can't find parent for " + parentId + " (" + wrapper + ")");
}
}
}
@@ -79,8 +79,9 @@ public class ConfigurableExtensionPointUtil {
for (final Iterator<String> iterator = idToConfigurable.keySet().iterator(); iterator.hasNext(); ) {
final String key = iterator.next();
final ConfigurableWrapper wrapper = idToConfigurable.get(key);
- if (wrapper.getParentId() != null) {
- iterator.remove();
+ final String parentId = wrapper.getParentId();
+ if (parentId != null && idToConfigurable.containsKey(parentId)) {
+ iterator.remove(); // remove only processed parents
}
}
ContainerUtil.addAll(result, idToConfigurable.values());
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/ex/MixedConfigurableGroup.java b/platform/platform-impl/src/com/intellij/openapi/options/ex/MixedConfigurableGroup.java
index f465e2d0fecb..f1411cf3551d 100644
--- a/platform/platform-impl/src/com/intellij/openapi/options/ex/MixedConfigurableGroup.java
+++ b/platform/platform-impl/src/com/intellij/openapi/options/ex/MixedConfigurableGroup.java
@@ -18,9 +18,11 @@ package com.intellij.openapi.options.ex;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.options.ConfigurableGroup;
import com.intellij.openapi.options.OptionsBundle;
+import com.intellij.openapi.options.SearchableConfigurable;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.Map.Entry;
public final class MixedConfigurableGroup implements ConfigurableGroup {
@@ -66,6 +68,16 @@ public final class MixedConfigurableGroup implements ConfigurableGroup {
}
list.add(configurable);
}
+ ArrayList<Configurable> buildList = map.get("build");
+ if (buildList != null) {
+ NodeConfigurable buildTools = new NodeConfigurable("build.tools");
+ buildTools.add(find("MavenSettings", buildList.iterator()));
+ buildTools.add(find("reference.settingsdialog.project.gradle", buildList.iterator()));
+ buildTools.add(find("reference.settingsdialog.project.gant", buildList.iterator()));
+ if (buildTools.getConfigurables() != null) {
+ buildList.add(0, buildTools);
+ }
+ }
ArrayList<ConfigurableGroup> groups = new ArrayList<ConfigurableGroup>(map.size());
groups.add(new MixedConfigurableGroup("appearance", map));
groups.add(new MixedConfigurableGroup("editor", map));
@@ -80,4 +92,18 @@ public final class MixedConfigurableGroup implements ConfigurableGroup {
groups.add(other);
return groups.toArray(new ConfigurableGroup[groups.size()]);
}
+
+ private static Configurable find(String id, Iterator<Configurable> iterator) {
+ while (iterator.hasNext()) {
+ Configurable configurable = iterator.next();
+ if (configurable instanceof SearchableConfigurable) {
+ SearchableConfigurable sc = (SearchableConfigurable)configurable;
+ if (id.equals(sc.getId())) {
+ iterator.remove();
+ return configurable;
+ }
+ }
+ }
+ return null;
+ }
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/ex/NodeConfigurable.java b/platform/platform-impl/src/com/intellij/openapi/options/ex/NodeConfigurable.java
new file mode 100644
index 000000000000..6571c7a63746
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/openapi/options/ex/NodeConfigurable.java
@@ -0,0 +1,71 @@
+/*
+ * 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.ex;
+
+import com.intellij.openapi.options.Configurable;
+import com.intellij.openapi.options.OptionsBundle;
+import com.intellij.openapi.options.SearchableConfigurable;
+import org.jetbrains.annotations.Nls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+
+public final class NodeConfigurable extends SearchableConfigurable.Parent.Abstract {
+ private final ArrayList<Configurable> myConfigurables = new ArrayList<Configurable>();
+ private final String myId;
+
+ public NodeConfigurable(@NotNull String id) {
+ myId = id;
+ }
+
+ public void add(Configurable configurable) {
+ if (configurable != null) {
+ super.disposeUIResources();
+ myConfigurables.add(configurable);
+ }
+ }
+
+ @Override
+ public void disposeUIResources() {
+ super.disposeUIResources();
+ myConfigurables.clear();
+ }
+
+ @NotNull
+ @Override
+ public String getId() {
+ return myId;
+ }
+
+ @Nullable
+ @Override
+ public String getHelpTopic() {
+ return myId;
+ }
+
+ @Nls
+ @Override
+ public String getDisplayName() {
+ return OptionsBundle.message("node.configurable." + myId + ".display.name");
+ }
+
+ @Override
+ protected Configurable[] buildConfigurables() {
+ int size = myConfigurables.size();
+ return size == 0 ? null : myConfigurables.toArray(new Configurable[size]);
+ }
+}
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 07e5a93670e6..271539f038a0 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
@@ -49,6 +49,7 @@ import com.intellij.ui.navigation.History;
import com.intellij.ui.navigation.Place;
import com.intellij.ui.speedSearch.ElementFilter;
import com.intellij.ui.treeStructure.SimpleNode;
+import com.intellij.ui.treeStructure.filtered.FilteringTreeBuilder;
import com.intellij.util.ui.UIUtil;
import com.intellij.util.ui.update.Activatable;
import com.intellij.util.ui.update.MergingUpdateQueue;
@@ -87,6 +88,7 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat
private final History myHistory = new History(this);
private final OptionsTree myTree;
+ private final SettingsTreeView myTreeView;
private final MySearchField mySearch;
private final Splitter myMainSplitter;
//[back/forward] JComponent myToolbarComponent;
@@ -126,7 +128,12 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat
mySearch = new MySearchField() {
@Override
protected void onTextKeyEvent(final KeyEvent e) {
- myTree.processTextEvent(e);
+ if (myTreeView != null) {
+ myTreeView.myTree.processKeyEvent(e);
+ }
+ else {
+ myTree.processTextEvent(e);
+ }
}
};
@@ -144,12 +151,12 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat
}
});
- myTree = new OptionsTree(myProject, groups, getContext()) {
+ final KeyListener listener = new KeyListener() {
@Override
- protected void onTreeKeyEvent(final KeyEvent e) {
+ public void keyTyped(KeyEvent event) {
myFilterDocumentWasChanged = false;
try {
- mySearch.keyEventToTextField(e);
+ mySearch.keyEventToTextField(event);
}
finally {
if (myFilterDocumentWasChanged && !isFilterFieldVisible()) {
@@ -157,10 +164,33 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat
}
}
}
+
+ @Override
+ public void keyPressed(KeyEvent event) {
+ keyTyped(event);
+ }
+
+ @Override
+ public void keyReleased(KeyEvent event) {
+ keyTyped(event);
+ }
};
+ if (Registry.is("ide.file.settings.tree.new")) {
+ myTreeView = new SettingsTreeView(listener, getContext(), groups);
+ myTree = null;
+ }
+ else {
+ myTreeView = null;
+ myTree = new OptionsTree(myProject, groups, getContext()) {
+ @Override
+ protected void onTreeKeyEvent(final KeyEvent e) {
+ listener.keyTyped(e);
+ }
+ };
+ }
- getContext().addColleague(myTree);
- Disposer.register(this, myTree);
+ getContext().addColleague(myTreeView != null ? myTreeView : myTree);
+ Disposer.register(this, myTreeView != null ? myTreeView : myTree);
mySearch.addDocumentListener(new DocumentAdapter() {
@Override
protected void textChanged(DocumentEvent e) {
@@ -198,7 +228,8 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat
@Override
public Dimension getMinimumSize() {
Dimension dimension = super.getMinimumSize();
- dimension.width = Math.max(myTree.getMinimumSize().width, mySearchWrapper.getPreferredSize().width);
+ JComponent component = myTreeView != null ? myTreeView : myTree;
+ dimension.width = Math.max(component.getMinimumSize().width, mySearchWrapper.getPreferredSize().width);
return dimension;
}
};
@@ -211,7 +242,7 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat
*/
myLeftSide.add(mySearchWrapper, BorderLayout.NORTH);
- myLeftSide.add(myTree, BorderLayout.CENTER);
+ myLeftSide.add(myTreeView != null ? myTreeView : myTree, BorderLayout.CENTER);
setLayout(new BorderLayout());
@@ -233,9 +264,19 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat
mySpotlightUpdate = new MergingUpdateQueue("OptionsSpotlight", 200, false, this, this, this);
if (preselectedConfigurable != null) {
- myTree.select(preselectedConfigurable);
+ if (myTreeView != null) {
+ myTreeView.select(preselectedConfigurable);
+ }
+ else {
+ myTree.select(preselectedConfigurable);
+ }
} else {
- myTree.selectFirst();
+ if (myTreeView != null) {
+ myTreeView.selectFirst();
+ }
+ else {
+ myTree.selectFirst();
+ }
}
Toolkit.getDefaultToolkit().addAWTEventListener(this,
@@ -295,12 +336,16 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat
@Deprecated
@Nullable
public <T extends Configurable> T findConfigurable(Class<T> configurableClass) {
- return myTree.findConfigurable(configurableClass);
+ return myTreeView != null
+ ? myTreeView.findConfigurable(configurableClass)
+ : myTree.findConfigurable(configurableClass);
}
@Nullable
public SearchableConfigurable findConfigurableById(@NotNull String configurableId) {
- return myTree.findConfigurableById(configurableId);
+ return myTreeView != null
+ ? myTreeView.findConfigurableById(configurableId)
+ : myTree.findConfigurableById(configurableId);
}
public ActionCallback clearSearchAndSelect(Configurable configurable) {
@@ -318,7 +363,9 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat
public ActionCallback select(Configurable configurable, final String text) {
myFilter.refilterFor(text, false, true);
- return myTree.select(configurable);
+ return myTreeView != null
+ ? myTreeView.select(configurable)
+ : myTree.select(configurable);
}
private float readProportion(final float defaultValue, final String propertyName) {
@@ -367,7 +414,10 @@ 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")) {
+ if (myTreeView != null) {
+ myOwnDetails.forProject(myTreeView.findConfigurableProject(configurable));
+ }
+ else if (Registry.is("ide.file.settings.order.new")) {
myOwnDetails.forProject(myTree.getConfigurableProject(configurable));
}
@@ -385,7 +435,8 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat
checkModified(oldConfigurable);
checkModified(configurable);
- if (myTree.myBuilder.getSelectedElements().size() == 0) {
+ FilteringTreeBuilder builder = myTreeView != null ? myTreeView.myBuilder : myTree.myBuilder;
+ if (builder.getSelectedElements().size() == 0) {
select(configurable).notify(result);
} else {
result.setDone();
@@ -507,6 +558,9 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat
}
private String[] getBannerText(Configurable configurable) {
+ if (myTreeView != null) {
+ return myTreeView.getPathNames(configurable);
+ }
final List<Configurable> list = myTree.getPathToRoot(configurable);
final String[] result = new String[list.size()];
int add = 0;
@@ -795,7 +849,12 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat
getContext().fireErrorsChanged(errors, null);
if (!errors.isEmpty()) {
- myTree.select(errors.keySet().iterator().next());
+ if (myTreeView != null) {
+ myTreeView.select(errors.keySet().iterator().next());
+ }
+ else {
+ myTree.select(errors.keySet().iterator().next());
+ }
}
}
@@ -835,7 +894,7 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat
return myFiltered.contains(node.getConfigurable()) || isChildOfNameHit(node);
}
- return true;
+ return SettingsTreeView.isFiltered(myFiltered, myHits, value);
}
private boolean isChildOfNameHit(OptionsTree.EditorNode node) {
@@ -929,7 +988,8 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat
myLastSelected = current;
}
- final ActionCallback callback = fireUpdate(adjustSelection ? myTree.findNodeFor(toSelect) : null, adjustSelection, now);
+ SimpleNode node = !adjustSelection ? null : myTreeView != null ? myTreeView.findNode(toSelect) : myTree.findNodeFor(toSelect);
+ final ActionCallback callback = fireUpdate(node, adjustSelection, now);
myFilterDocumentWasChanged = true;
@@ -965,7 +1025,12 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat
myFilter.refilterFor(filter, false, true).doWhenDone(new Runnable() {
@Override
public void run() {
- myTree.select(config).notifyWhenDone(result);
+ if (myTreeView != null) {
+ myTreeView.select(config).notifyWhenDone(result);
+ }
+ else {
+ myTree.select(config).notifyWhenDone(result);
+ }
}
});
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 e0ab24815ece..175b994122ef 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
@@ -23,6 +23,7 @@ import com.intellij.openapi.options.ConfigurableGroup;
import com.intellij.openapi.options.OptionsBundle;
import com.intellij.openapi.options.SearchableConfigurable;
import com.intellij.openapi.options.ex.ConfigurableWrapper;
+import com.intellij.openapi.options.ex.NodeConfigurable;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.ActionCallback;
import com.intellij.openapi.util.Disposer;
@@ -116,10 +117,7 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl
}
});
- final JScrollPane scrolls = ScrollPaneFactory.createScrollPane(myTree);
- scrolls.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
-
- add(scrolls, BorderLayout.CENTER);
+ add(new StickySeparator(myTree), BorderLayout.CENTER);
mySelection = new MergingUpdateQueue("OptionsTree", 150, false, this, this, this).setRestartTimerOnAdd(true);
myTree.getSelectionModel().addTreeSelectionListener(new TreeSelectionListener() {
@@ -290,7 +288,7 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl
}
class Renderer extends GroupedElementsRenderer.Tree {
-
+ private GroupSeparator mySeparator;
private JLabel myProjectIcon;
private JLabel myHandle;
@@ -298,7 +296,8 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl
protected void layout() {
myRendererComponent.setOpaqueActive(false);
- myRendererComponent.add(mySeparatorComponent, BorderLayout.NORTH);
+ mySeparator = new GroupSeparator();
+ myRendererComponent.add(Registry.is("ide.file.settings.order.new") ? mySeparator : mySeparatorComponent, BorderLayout.NORTH);
final NonOpaquePanel content = new NonOpaquePanel(new BorderLayout());
myHandle = new JLabel("", SwingConstants.CENTER);
@@ -325,7 +324,7 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl
JComponent result;
Color fg = UIUtil.getTreeTextForeground();
-
+ mySeparator.configure(null, false);
final Base base = extractNode(value);
if (base instanceof EditorNode) {
@@ -335,6 +334,7 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl
final DefaultMutableTreeNode prevValue = ((DefaultMutableTreeNode)value).getPreviousSibling();
if (prevValue == null || prevValue instanceof LoadingNode) {
group = editor.getGroup();
+ mySeparator.configure(group, false);
}
else {
final Base prevBase = extractNode(prevValue);
@@ -342,6 +342,7 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl
final EditorNode prevEditor = (EditorNode)prevBase;
if (prevEditor.getGroup() != editor.getGroup()) {
group = editor.getGroup();
+ mySeparator.configure(group, true);
}
}
}
@@ -404,8 +405,25 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl
myTextLabel.setBorder(new EmptyBorder(1,2,1,0));
}
- Project project = getConfigurableProject(base);
- if (project != null && Registry.is("ide.file.settings.order.new")) {
+ Project project = null;
+ if (base != null && Registry.is("ide.file.settings.order.new")) {
+ SimpleNode parent = base.getParent();
+ if (parent == myRoot) {
+ project = getConfigurableProject(base); // show icon for top-level nodes
+ if (base.getConfigurable() instanceof NodeConfigurable) { // special case for custom subgroups (build.tools)
+ Configurable[] configurables = ((NodeConfigurable)base.getConfigurable()).getConfigurables();
+ if (configurables != null) { // assume that all configurables have the same project
+ project = getConfigurableProject(configurables[0]);
+ }
+ }
+ }
+ else if (parent instanceof Base && ((Base)parent).getConfigurable() instanceof NodeConfigurable) {
+ if (((Base)base.getParent()).getConfigurable() instanceof NodeConfigurable) {
+ project = getConfigurableProject(base); // special case for custom subgroups
+ }
+ }
+ }
+ if (project != null) {
myProjectIcon.setBackground(selected ? getSelectionBackground() : getBackground());
myProjectIcon.setIcon(selected ? AllIcons.General.ProjectConfigurableSelected : AllIcons.General.ProjectConfigurable);
myProjectIcon.setVisible(true);
@@ -903,4 +921,97 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl
}
return getConfigurableProject(node.getParent());
}
+
+ private static final class GroupSeparator extends JLabel {
+ public static final int SPACE = 10;
+
+ public GroupSeparator() {
+ setFont(UIUtil.getLabelFont());
+ setFont(getFont().deriveFont(Font.BOLD));
+ }
+
+ public void configure(ConfigurableGroup group, boolean isSpaceNeeded) {
+ if (group == null) {
+ setVisible(false);
+ }
+ else {
+ setVisible(true);
+ int bottom = UIUtil.isUnderNativeMacLookAndFeel() ? 1 : 3;
+ int top = isSpaceNeeded
+ ? bottom + SPACE
+ : bottom;
+ setBorder(BorderFactory.createEmptyBorder(top, 3, bottom, 3));
+ setText(group.getDisplayName());
+ }
+ }
+ }
+
+ private static final class StickySeparator extends JComponent {
+ private final SimpleTree myTree;
+ private final JScrollPane myScroller;
+ private final GroupSeparator mySeparator;
+
+ public StickySeparator(SimpleTree tree) {
+ myTree = tree;
+ myScroller = ScrollPaneFactory.createScrollPane(myTree);
+ myScroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
+ mySeparator = new GroupSeparator();
+ add(myScroller);
+ }
+
+ @Override
+ public void doLayout() {
+ myScroller.setBounds(0, 0, getWidth(), getHeight());
+ }
+
+ @Override
+ public void paint(Graphics g) {
+ super.paint(g);
+
+ if (Registry.is("ide.file.settings.order.new")) {
+ ConfigurableGroup group = getGroup(GroupSeparator.SPACE + mySeparator.getFont().getSize());
+ if (group != null && group == getGroup(-GroupSeparator.SPACE)) {
+ mySeparator.configure(group, false);
+
+ Rectangle bounds = myScroller.getViewport().getBounds();
+ int height = mySeparator.getPreferredSize().height;
+ if (bounds.height > height) {
+ bounds.height = height;
+ }
+ g.setColor(myTree.getBackground());
+ if (g instanceof Graphics2D) {
+ int h = bounds.height / 3;
+ int y = bounds.y + bounds.height - h;
+ g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height - h);
+ ((Graphics2D)g).setPaint(UIUtil.getGradientPaint(
+ 0, y, g.getColor(),
+ 0, y + h, ColorUtil.toAlpha(g.getColor(), 0)));
+ g.fillRect(bounds.x, y, bounds.width, h);
+ }
+ else {
+ g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height);
+ }
+ mySeparator.setSize(bounds.width - 1, bounds.height);
+ mySeparator.paint(g.create(bounds.x + 1, bounds.y, bounds.width - 1, bounds.height));
+ }
+ }
+ }
+
+ private ConfigurableGroup getGroup(int offset) {
+ TreePath path = myTree.getClosestPathForLocation(-myTree.getX(), -myTree.getY() + offset);
+ SimpleNode node = myTree.getNodeFor(path);
+ if (node instanceof FilteringTreeStructure.FilteringNode) {
+ Object delegate = ((FilteringTreeStructure.FilteringNode)node).getDelegate();
+ while (delegate instanceof EditorNode) {
+ EditorNode editor = (EditorNode)delegate;
+ ConfigurableGroup group = editor.getGroup();
+ if (group != null) {
+ return group;
+ }
+ delegate = editor.getParent();
+ }
+ }
+ return null;
+ }
+ }
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java
new file mode 100644
index 000000000000..9269da7ab967
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/SettingsTreeView.java
@@ -0,0 +1,864 @@
+/*
+ * 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.newEditor;
+
+import com.intellij.icons.AllIcons;
+import com.intellij.ide.ui.search.ConfigurableHit;
+import com.intellij.ide.util.treeView.NodeDescriptor;
+import com.intellij.openapi.Disposable;
+import com.intellij.openapi.options.*;
+import com.intellij.openapi.options.ex.ConfigurableWrapper;
+import com.intellij.openapi.options.ex.NodeConfigurable;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.ActionCallback;
+import com.intellij.openapi.util.Disposer;
+import com.intellij.ui.*;
+import com.intellij.ui.treeStructure.*;
+import com.intellij.ui.treeStructure.filtered.FilteringTreeBuilder;
+import com.intellij.ui.treeStructure.filtered.FilteringTreeStructure;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.ui.GraphicsUtil;
+import com.intellij.util.ui.UIUtil;
+import com.intellij.util.ui.tree.TreeUtil;
+import com.intellij.util.ui.update.MergingUpdateQueue;
+import com.intellij.util.ui.update.Update;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import java.util.List;
+import javax.swing.*;
+import javax.swing.event.TreeExpansionEvent;
+import javax.swing.event.TreeExpansionListener;
+import javax.swing.event.TreeSelectionEvent;
+import javax.swing.event.TreeSelectionListener;
+import javax.swing.plaf.TreeUI;
+import javax.swing.plaf.basic.BasicTreeUI;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.TreePath;
+import javax.swing.tree.TreeSelectionModel;
+
+/**
+ * @author Sergey.Malenkov
+ */
+final class SettingsTreeView extends JComponent implements Disposable, OptionsEditorColleague {
+ final SimpleTree myTree;
+ final FilteringTreeBuilder myBuilder;
+
+ private final OptionsEditorContext myContext;
+ private final MyRoot myRoot;
+ private final JScrollPane myScroller;
+ private JLabel mySeparator;
+ private final MyRenderer myRenderer = new MyRenderer();
+ private final IdentityHashMap<Configurable, MyNode> myConfigurableToNodeMap = new IdentityHashMap<Configurable, MyNode>();
+ private final MergingUpdateQueue myQueue = new MergingUpdateQueue("OptionsTree", 150, false, this, this, this).setRestartTimerOnAdd(true);
+
+ private Configurable myQueuedConfigurable;
+
+ SettingsTreeView(final KeyListener listener, OptionsEditorContext context, ConfigurableGroup... groups) {
+ myContext = context;
+ myRoot = new MyRoot(groups);
+
+ myTree = new MyTree();
+ myTree.getInputMap().clear();
+ TreeUtil.installActions(myTree);
+
+ myTree.setOpaque(true);
+ myTree.setBorder(BorderFactory.createEmptyBorder(0, 1, 0, 0));
+
+ myTree.setRowHeight(-1);
+ myTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
+
+ myTree.setCellRenderer(myRenderer);
+ myTree.setRootVisible(false);
+ myTree.setShowsRootHandles(false);
+
+ myScroller = ScrollPaneFactory.createScrollPane(myTree);
+ myScroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
+ add(myScroller);
+
+ myTree.addComponentListener(new ComponentAdapter() {
+ @Override
+ public void componentResized(ComponentEvent e) {
+ myBuilder.revalidateTree();
+ }
+
+ @Override
+ public void componentMoved(ComponentEvent e) {
+ myBuilder.revalidateTree();
+ }
+
+ @Override
+ public void componentShown(ComponentEvent e) {
+ myBuilder.revalidateTree();
+ }
+ });
+
+ myTree.getSelectionModel().addTreeSelectionListener(new TreeSelectionListener() {
+ public void valueChanged(TreeSelectionEvent event) {
+ MyNode node = extractNode(event.getNewLeadSelectionPath());
+ select(node == null ? null : node.myConfigurable);
+ }
+ });
+
+ myTree.addKeyListener(new KeyListener() {
+ public void keyTyped(KeyEvent event) {
+ if (listener != null && isValid(event)) {
+ listener.keyTyped(event);
+ }
+ }
+
+ public void keyPressed(KeyEvent event) {
+ if (listener != null && isValid(event)) {
+ listener.keyPressed(event);
+ }
+ }
+
+ public void keyReleased(KeyEvent event) {
+ if (listener != null && isValid(event)) {
+ listener.keyReleased(event);
+ }
+ }
+
+ private boolean isValid(KeyEvent event) {
+ return null == myTree.getInputMap().get(KeyStroke.getKeyStrokeForEvent(event));
+ }
+ });
+ myBuilder = new MyBuilder(new SimpleTreeStructure.Impl(myRoot));
+ myBuilder.setFilteringMerge(300, null);
+ Disposer.register(this, myBuilder);
+ }
+
+ @NotNull
+ String[] getPathNames(Configurable configurable) {
+ ArrayDeque<String> path = new ArrayDeque<String>();
+ MyNode node = myConfigurableToNodeMap.get(configurable);
+ while (node != null) {
+ path.push(node.myDisplayName);
+ SimpleNode parent = node.getParent();
+ node = parent instanceof MyNode
+ ? (MyNode)parent
+ : null;
+ }
+ return ArrayUtil.toStringArray(path);
+ }
+
+ @Nullable
+ SimpleNode findNode(Configurable toSelect) {
+ return myConfigurableToNodeMap.get(toSelect);
+ }
+
+ @Nullable
+ SearchableConfigurable findConfigurableById(@NotNull String id) {
+ for (Configurable configurable : myConfigurableToNodeMap.keySet()) {
+ if (configurable instanceof SearchableConfigurable) {
+ SearchableConfigurable searchable = (SearchableConfigurable)configurable;
+ if (id.equals(searchable.getId())) {
+ return searchable;
+ }
+ }
+ }
+ return null;
+ }
+
+ @Nullable
+ <T extends UnnamedConfigurable> T findConfigurable(@NotNull Class<T> type) {
+ for (UnnamedConfigurable configurable : myConfigurableToNodeMap.keySet()) {
+ if (configurable instanceof ConfigurableWrapper) {
+ ConfigurableWrapper wrapper = (ConfigurableWrapper)configurable;
+ configurable = wrapper.getConfigurable();
+ }
+ if (type.isInstance(configurable)) {
+ return type.cast(configurable);
+ }
+ }
+ return null;
+ }
+
+ @Nullable
+ Project findConfigurableProject(@Nullable Configurable configurable) {
+ if (configurable instanceof ConfigurableWrapper) {
+ ConfigurableWrapper wrapper = (ConfigurableWrapper)configurable;
+ return wrapper.getExtensionPoint().getProject();
+ }
+ return findConfigurableProject(myConfigurableToNodeMap.get(configurable));
+ }
+
+ @Nullable
+ private static Project findConfigurableProject(@Nullable MyNode node) {
+ if (node != null) {
+ Configurable configurable = node.myConfigurable;
+ if (configurable instanceof ConfigurableWrapper) {
+ ConfigurableWrapper wrapper = (ConfigurableWrapper)configurable;
+ return wrapper.getExtensionPoint().getProject();
+ }
+ SimpleNode parent = node.getParent();
+ if (parent instanceof MyNode) {
+ return findConfigurableProject((MyNode)parent);
+ }
+ }
+ return null;
+ }
+
+ @Nullable
+ private ConfigurableGroup findConfigurableGroupAt(int x, int y) {
+ TreePath path = myTree.getClosestPathForLocation(x - myTree.getX(), y - myTree.getY());
+ while (path != null) {
+ MyNode node = extractNode(path);
+ if (node == null) {
+ return null;
+ }
+ if (node.myComposite instanceof ConfigurableGroup) {
+ return (ConfigurableGroup)node.myComposite;
+ }
+ path = path.getParentPath();
+ }
+ return null;
+ }
+
+ @Nullable
+ private static MyNode extractNode(@Nullable Object object) {
+ if (object instanceof TreePath) {
+ TreePath path = (TreePath)object;
+ object = path.getLastPathComponent();
+ }
+ if (object instanceof DefaultMutableTreeNode) {
+ DefaultMutableTreeNode node = (DefaultMutableTreeNode)object;
+ object = node.getUserObject();
+ }
+ if (object instanceof FilteringTreeStructure.FilteringNode) {
+ FilteringTreeStructure.FilteringNode node = (FilteringTreeStructure.FilteringNode)object;
+ object = node.getDelegate();
+ }
+ return object instanceof MyNode
+ ? (MyNode)object
+ : null;
+ }
+
+ static boolean isFiltered(Set<Configurable> configurables, ConfigurableHit hits, SimpleNode value) {
+ if (value instanceof MyNode && !configurables.contains(((MyNode)value).myConfigurable)) {
+ if (hits != null) {
+ configurables = hits.getNameFullHits();
+ while (value != null) {
+ if (value instanceof MyNode) {
+ if (configurables.contains(((MyNode)value).myConfigurable)) {
+ return true;
+ }
+ }
+ value = value.getParent();
+ }
+ }
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public void doLayout() {
+ myScroller.setBounds(0, 0, getWidth(), getHeight());
+ }
+
+ @Override
+ public void paint(Graphics g) {
+ super.paint(g);
+
+ if (mySeparator == null) {
+ mySeparator = new JLabel();
+ mySeparator.setFont(UIUtil.getLabelFont());
+ mySeparator.setFont(getFont().deriveFont(Font.BOLD));
+ }
+ ConfigurableGroup group = findConfigurableGroupAt(0, 5 + mySeparator.getFont().getSize());
+ if (group != null && group == findConfigurableGroupAt(0, -5)) {
+ int offset = UIUtil.isUnderNativeMacLookAndFeel() ? 1 : 3;
+ mySeparator.setBorder(BorderFactory.createEmptyBorder(offset, 18, offset, 3));
+ mySeparator.setText(group.getDisplayName());
+
+ Rectangle bounds = myScroller.getViewport().getBounds();
+ int height = mySeparator.getPreferredSize().height;
+ if (bounds.height > height) {
+ bounds.height = height;
+ }
+ g.setColor(myTree.getBackground());
+ if (g instanceof Graphics2D) {
+ int h = bounds.height / 4;
+ int y = bounds.y + bounds.height - h;
+ g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height - h);
+ ((Graphics2D)g).setPaint(UIUtil.getGradientPaint(
+ 0, y, g.getColor(),
+ 0, y + h, ColorUtil.toAlpha(g.getColor(), 0)));
+ g.fillRect(bounds.x, y, bounds.width, h + h);
+ }
+ else {
+ g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height);
+ }
+ mySeparator.setSize(bounds.width - 1, bounds.height);
+ mySeparator.paint(g.create(bounds.x + 1, bounds.y, bounds.width - 1, bounds.height));
+ }
+ }
+
+ void selectFirst() {
+ for (ConfigurableGroup eachGroup : myRoot.myGroups) {
+ Configurable[] kids = eachGroup.getConfigurables();
+ if (kids.length > 0) {
+ select(kids[0]);
+ return;
+ }
+ }
+ }
+
+ ActionCallback select(@Nullable final Configurable configurable) {
+ if (myBuilder.isSelectionBeingAdjusted()) {
+ return new ActionCallback.Rejected();
+ }
+ final ActionCallback callback = new ActionCallback();
+ myQueuedConfigurable = configurable;
+ myQueue.queue(new Update(this) {
+ public void run() {
+ if (configurable == myQueuedConfigurable) {
+ if (configurable == null) {
+ fireSelected(null, callback);
+ }
+ else {
+ myBuilder.getReady(this).doWhenDone(new Runnable() {
+ @Override
+ public void run() {
+ if (configurable != myQueuedConfigurable) return;
+
+ MyNode editorNode = myConfigurableToNodeMap.get(configurable);
+ FilteringTreeStructure.FilteringNode editorUiNode = myBuilder.getVisibleNodeFor(editorNode);
+ if (editorUiNode == null) return;
+
+ if (!myBuilder.getSelectedElements().contains(editorUiNode)) {
+ myBuilder.select(editorUiNode, new Runnable() {
+ public void run() {
+ fireSelected(configurable, callback);
+ }
+ });
+ }
+ else {
+ myBuilder.scrollSelectionToVisible(new Runnable() {
+ public void run() {
+ fireSelected(configurable, callback);
+ }
+ }, false);
+ }
+ }
+ });
+ }
+ }
+ }
+
+ @Override
+ public void setRejected() {
+ super.setRejected();
+ callback.setRejected();
+ }
+ });
+ return callback;
+ }
+
+ private void fireSelected(Configurable configurable, ActionCallback callback) {
+ myContext.fireSelected(configurable, this).doWhenProcessed(callback.createSetDoneRunnable());
+ }
+
+ @Override
+ public void dispose() {
+ myQueuedConfigurable = null;
+ }
+
+ @Override
+ public ActionCallback onSelected(@Nullable Configurable configurable, Configurable oldConfigurable) {
+ return select(configurable);
+ }
+
+ @Override
+ public ActionCallback onModifiedAdded(Configurable configurable) {
+ myTree.repaint();
+ return new ActionCallback.Done();
+ }
+
+ @Override
+ public ActionCallback onModifiedRemoved(Configurable configurable) {
+ myTree.repaint();
+ return new ActionCallback.Done();
+ }
+
+ @Override
+ public ActionCallback onErrorsChanged() {
+ return new ActionCallback.Done();
+ }
+
+ private final class MyRoot extends CachingSimpleNode {
+ private final ConfigurableGroup[] myGroups;
+
+ private MyRoot(ConfigurableGroup[] groups) {
+ super(null);
+ myGroups = groups;
+ }
+
+ @Override
+ protected SimpleNode[] buildChildren() {
+ if (myGroups == null || myGroups.length == 0) {
+ return NO_CHILDREN;
+ }
+ SimpleNode[] result = new SimpleNode[myGroups.length];
+ for (int i = 0; i < myGroups.length; i++) {
+ result[i] = new MyNode(this, myGroups[i]);
+ }
+ return result;
+ }
+ }
+
+ private final class MyNode extends CachingSimpleNode {
+ private final Configurable.Composite myComposite;
+ private final Configurable myConfigurable;
+ private final String myDisplayName;
+
+ private MyNode(CachingSimpleNode parent, Configurable configurable) {
+ super(parent);
+ myComposite = configurable instanceof Configurable.Composite ? (Configurable.Composite)configurable : null;
+ myConfigurable = configurable;
+ String name = configurable.getDisplayName();
+ myDisplayName = name != null ? name.replace("\n", " ") : "{ " + configurable.getClass().getSimpleName() + " }";
+
+ myConfigurableToNodeMap.put(configurable, this);
+ }
+
+ private MyNode(CachingSimpleNode parent, ConfigurableGroup group) {
+ super(parent);
+ myComposite = group;
+ myConfigurable = null;
+ String name = group.getDisplayName();
+ myDisplayName = name != null ? name.replace("\n", " ") : "{ " + group.getClass().getSimpleName() + " }";
+ }
+
+ @Override
+ protected SimpleNode[] buildChildren() {
+ if (myComposite == null) {
+ return NO_CHILDREN;
+ }
+ Configurable[] configurables = myComposite.getConfigurables();
+ if (configurables == null || configurables.length == 0) {
+ return NO_CHILDREN;
+ }
+ SimpleNode[] result = new SimpleNode[configurables.length];
+ for (int i = 0; i < configurables.length; i++) {
+ result[i] = new MyNode(this, configurables[i]);
+ if (myConfigurable != null) {
+ myContext.registerKid(myConfigurable, configurables[i]);
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public boolean isAlwaysLeaf() {
+ return myComposite == null;
+ }
+
+ @Override
+ public int getWeight() {
+ return WeightBasedComparator.UNDEFINED_WEIGHT;
+ }
+ }
+
+ private final class MyRenderer extends GroupedElementsRenderer.Tree {
+ private JLabel myNodeIcon;
+ private JLabel myProjectIcon;
+
+ protected JComponent createItemComponent() {
+ myTextLabel = new ErrorLabel();
+ return myTextLabel;
+ }
+
+ @Override
+ protected void layout() {
+ myNodeIcon = new JLabel(" ", SwingConstants.RIGHT);
+ myProjectIcon = new JLabel(" ", SwingConstants.LEFT);
+ myProjectIcon.setOpaque(true);
+ myRendererComponent.add(BorderLayout.NORTH, mySeparatorComponent);
+ myRendererComponent.add(BorderLayout.CENTER, myComponent);
+ myRendererComponent.add(BorderLayout.WEST, myNodeIcon);
+ myRendererComponent.add(BorderLayout.EAST, myProjectIcon);
+ }
+
+ public Component getTreeCellRendererComponent(JTree tree,
+ Object value,
+ boolean selected,
+ boolean expanded,
+ boolean leaf,
+ int row,
+ boolean focused) {
+ myTextLabel.setOpaque(selected);
+ myTextLabel.setFont(UIUtil.getLabelFont());
+
+ String text;
+ boolean hasSeparatorAbove = false;
+ int preferredForcedWidth = -1;
+
+ MyNode node = extractNode(value);
+ if (node == null) {
+ text = value.toString();
+ }
+ else {
+ text = node.myDisplayName;
+ // show groups in bold
+ if (myRoot == node.getParent()) {
+ hasSeparatorAbove = node != myRoot.getChildAt(0);
+ myTextLabel.setFont(myTextLabel.getFont().deriveFont(Font.BOLD));
+ }
+ TreePath path = tree.getPathForRow(row);
+ if (path == null) {
+ if (value instanceof DefaultMutableTreeNode) {
+ path = new TreePath(((DefaultMutableTreeNode)value).getPath());
+ }
+ }
+ int forcedWidth = 2000;
+ if (path != null && tree.isVisible()) {
+ Rectangle visibleRect = tree.getVisibleRect();
+
+ int nestingLevel = tree.isRootVisible() ? path.getPathCount() - 1 : path.getPathCount() - 2;
+
+ int left = UIUtil.getTreeLeftChildIndent();
+ int right = UIUtil.getTreeRightChildIndent();
+
+ Insets treeInsets = tree.getInsets();
+
+ int indent = (left + right) * nestingLevel + (treeInsets != null ? treeInsets.left + treeInsets.right : 0);
+
+ forcedWidth = visibleRect.width > 0 ? visibleRect.width - indent : forcedWidth;
+ }
+ preferredForcedWidth = forcedWidth - 4;
+ }
+ Component result = configureComponent(text, null, null, null, selected, hasSeparatorAbove, null, preferredForcedWidth);
+ // update font color for modified configurables
+ if (!selected && node != null) {
+ Configurable configurable = node.myConfigurable;
+ if (configurable != null) {
+ if (myContext.getErrors().containsKey(configurable)) {
+ myTextLabel.setForeground(JBColor.RED);
+ }
+ else if (myContext.getModified().contains(configurable)) {
+ myTextLabel.setForeground(JBColor.BLUE);
+ }
+ }
+ }
+ // configure project icon
+ Project project = null;
+ if (node != null) {
+ SimpleNode parent = node.getParent();
+ if (parent instanceof MyNode) {
+ if (myRoot == parent.getParent()) {
+ project = findConfigurableProject(node); // show icon for top-level nodes
+ if (node.myConfigurable instanceof NodeConfigurable) { // special case for custom subgroups (build.tools)
+ Configurable[] configurables = ((NodeConfigurable)node.myConfigurable).getConfigurables();
+ if (configurables != null) { // assume that all configurables have the same project
+ project = findConfigurableProject(configurables[0]);
+ }
+ }
+ }
+ else if (((MyNode)parent).myConfigurable instanceof NodeConfigurable) {
+ if (((MyNode)node.getParent()).myConfigurable instanceof NodeConfigurable) {
+ project = findConfigurableProject(node); // special case for custom subgroups
+ }
+ }
+ }
+ }
+ if (project != null) {
+ myProjectIcon.setIcon(selected
+ ? AllIcons.General.ProjectConfigurableSelected
+ : AllIcons.General.ProjectConfigurable);
+ myProjectIcon.setToolTipText(OptionsBundle.message(project.isDefault()
+ ? "configurable.default.project.tooltip"
+ : "configurable.current.project.tooltip"));
+ myProjectIcon.setBackground(myTextLabel.getBackground());
+ myProjectIcon.setVisible(true);
+ }
+ else {
+ myProjectIcon.setVisible(false);
+ }
+ // configure node icon
+ if (value instanceof DefaultMutableTreeNode) {
+ DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode)value;
+ TreePath treePath = new TreePath(treeNode.getPath());
+ myNodeIcon.setIcon(myTree.getHandleIcon(treeNode, treePath));
+ }
+ else {
+ myNodeIcon.setIcon(null);
+ }
+ return result;
+ }
+
+
+ public boolean isUnderHandle(Point point) {
+ Point handlePoint = SwingUtilities.convertPoint(myRendererComponent, point, myNodeIcon);
+ Rectangle bounds = myNodeIcon.getBounds();
+ return bounds.x < handlePoint.x && bounds.getMaxX() >= handlePoint.x;
+ }
+ }
+
+ private final class MyTree extends SimpleTree {
+ @Override
+ public String getToolTipText(MouseEvent event) {
+ if (event != null) {
+ Component component = getDeepestRendererComponentAt(event.getX(), event.getY());
+ 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;
+ }
+
+ @Override
+ protected boolean highlightSingleNode() {
+ return false;
+ }
+
+ @Override
+ public void setUI(TreeUI ui) {
+ TreeUI actualUI = ui;
+ if (!(ui instanceof MyTreeUi)) {
+ actualUI = new MyTreeUi();
+ }
+ super.setUI(actualUI);
+ }
+
+ @Override
+ protected boolean isCustomUI() {
+ return true;
+ }
+
+ @Override
+ protected void configureUiHelper(TreeUIHelper helper) {
+ }
+
+ @Override
+ public boolean getScrollableTracksViewportWidth() {
+ return true;
+ }
+
+
+ @Override
+ public void processKeyEvent(KeyEvent e) {
+ TreePath path = myTree.getSelectionPath();
+ if (path != null) {
+ if (e.getKeyCode() == KeyEvent.VK_LEFT) {
+ if (isExpanded(path)) {
+ collapsePath(path);
+ return;
+ }
+ }
+ else if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
+ if (isCollapsed(path)) {
+ expandPath(path);
+ return;
+ }
+ }
+ }
+ super.processKeyEvent(e);
+ }
+
+ @Override
+ protected void processMouseEvent(MouseEvent e) {
+ MyTreeUi ui = (MyTreeUi)myTree.getUI();
+ boolean toggleNow = MouseEvent.MOUSE_RELEASED == e.getID()
+ && UIUtil.isActionClick(e, MouseEvent.MOUSE_RELEASED)
+ && !ui.isToggleEvent(e);
+
+ if (toggleNow || MouseEvent.MOUSE_PRESSED == e.getID()) {
+ TreePath path = getPathForLocation(e.getX(), e.getY());
+ if (path != null) {
+ Rectangle bounds = getPathBounds(path);
+ if (bounds != null && path.getLastPathComponent() instanceof DefaultMutableTreeNode) {
+ DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent();
+ boolean selected = isPathSelected(path);
+ boolean expanded = isExpanded(path);
+ Component comp =
+ myRenderer.getTreeCellRendererComponent(this, node, selected, expanded, node.isLeaf(), getRowForPath(path), isFocusOwner());
+
+ comp.setBounds(bounds);
+ comp.validate();
+
+ Point point = new Point(e.getX() - bounds.x, e.getY() - bounds.y);
+ if (myRenderer.isUnderHandle(point)) {
+ if (toggleNow) {
+ ui.toggleExpandState(path);
+ }
+ e.consume();
+ return;
+ }
+ }
+ }
+ }
+
+ super.processMouseEvent(e);
+ }
+
+ private final class MyTreeUi extends BasicTreeUI {
+
+ @Override
+ public void toggleExpandState(TreePath path) {
+ super.toggleExpandState(path);
+ }
+
+ @Override
+ public boolean isToggleEvent(MouseEvent event) {
+ return super.isToggleEvent(event);
+ }
+
+ @Override
+ protected boolean shouldPaintExpandControl(TreePath path,
+ int row,
+ boolean isExpanded,
+ boolean hasBeenExpanded,
+ boolean isLeaf) {
+ return false;
+ }
+
+ @Override
+ protected void paintHorizontalPartOfLeg(Graphics g,
+ Rectangle clipBounds,
+ Insets insets,
+ Rectangle bounds,
+ TreePath path,
+ int row,
+ boolean isExpanded,
+ boolean hasBeenExpanded,
+ boolean isLeaf) {
+
+ }
+
+ @Override
+ protected void paintVerticalPartOfLeg(Graphics g, Rectangle clipBounds, Insets insets, TreePath path) {
+ }
+
+ @Override
+ public void paint(Graphics g, JComponent c) {
+ GraphicsUtil.setupAntialiasing(g);
+ super.paint(g, c);
+ }
+ }
+ }
+
+ private final class MyBuilder extends FilteringTreeBuilder {
+
+ List<Object> myToExpandOnResetFilter;
+ boolean myRefilteringNow;
+ boolean myWasHoldingFilter;
+
+ public MyBuilder(SimpleTreeStructure structure) {
+ super(myTree, myContext.getFilter(), structure, new WeightBasedComparator(false));
+ myTree.addTreeExpansionListener(new TreeExpansionListener() {
+ public void treeExpanded(TreeExpansionEvent event) {
+ invalidateExpansions();
+ }
+
+ public void treeCollapsed(TreeExpansionEvent event) {
+ invalidateExpansions();
+ }
+ });
+ }
+
+ private void invalidateExpansions() {
+ if (!myRefilteringNow) {
+ myToExpandOnResetFilter = null;
+ }
+ }
+
+ @Override
+ protected boolean isSelectable(Object object) {
+ return object instanceof MyNode;
+ }
+
+ @Override
+ public boolean isAutoExpandNode(NodeDescriptor nodeDescriptor) {
+ return myContext.isHoldingFilter();
+ }
+
+ @Override
+ public boolean isToEnsureSelectionOnFocusGained() {
+ return false;
+ }
+
+ @Override
+ protected ActionCallback refilterNow(Object preferredSelection, boolean adjustSelection) {
+ final List<Object> toRestore = new ArrayList<Object>();
+ if (myContext.isHoldingFilter() && !myWasHoldingFilter && myToExpandOnResetFilter == null) {
+ myToExpandOnResetFilter = myBuilder.getUi().getExpandedElements();
+ }
+ else if (!myContext.isHoldingFilter() && myWasHoldingFilter && myToExpandOnResetFilter != null) {
+ toRestore.addAll(myToExpandOnResetFilter);
+ myToExpandOnResetFilter = null;
+ }
+
+ myWasHoldingFilter = myContext.isHoldingFilter();
+
+ ActionCallback result = super.refilterNow(preferredSelection, adjustSelection);
+ myRefilteringNow = true;
+ return result.doWhenDone(new Runnable() {
+ public void run() {
+ myRefilteringNow = false;
+ if (!myContext.isHoldingFilter() && getSelectedElements().isEmpty()) {
+ restoreExpandedState(toRestore);
+ }
+ }
+ });
+ }
+
+ private void restoreExpandedState(List<Object> toRestore) {
+ TreePath[] selected = myTree.getSelectionPaths();
+ if (selected == null) {
+ selected = new TreePath[0];
+ }
+
+ List<TreePath> toCollapse = new ArrayList<TreePath>();
+
+ for (int eachRow = 0; eachRow < myTree.getRowCount(); eachRow++) {
+ if (!myTree.isExpanded(eachRow)) continue;
+
+ TreePath eachVisiblePath = myTree.getPathForRow(eachRow);
+ if (eachVisiblePath == null) continue;
+
+ Object eachElement = myBuilder.getElementFor(eachVisiblePath.getLastPathComponent());
+ if (toRestore.contains(eachElement)) continue;
+
+
+ for (TreePath eachSelected : selected) {
+ if (!eachVisiblePath.isDescendant(eachSelected)) {
+ toCollapse.add(eachVisiblePath);
+ }
+ }
+ }
+
+ for (TreePath each : toCollapse) {
+ myTree.collapsePath(each);
+ }
+ }
+ }
+}
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 27bb8eb5f245..6a37bb2fb69e 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
@@ -17,7 +17,6 @@ package com.intellij.openapi.progress.impl;
import com.intellij.concurrency.JobScheduler;
import com.intellij.openapi.Disposable;
-import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.application.ex.ApplicationEx;
@@ -46,7 +45,7 @@ import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
-public class ProgressManagerImpl extends ProgressManager implements Disposable{
+public class ProgressManagerImpl extends ProgressManager implements Disposable {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.progress.impl.ProgressManagerImpl");
private final AtomicInteger myCurrentUnsafeProgressCount = new AtomicInteger(0);
private final AtomicInteger myCurrentModalProgressCount = new AtomicInteger(0);
@@ -55,7 +54,7 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable{
private static final boolean DISABLED = "disabled".equals(System.getProperty("idea.ProcessCanceledException"));
private final ScheduledFuture<?> myCheckCancelledFuture;
- public ProgressManagerImpl(Application application) {
+ public ProgressManagerImpl() {
if (DISABLED) {
myCheckCancelledFuture = null;
}
@@ -64,7 +63,6 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable{
@Override
public void run() {
ourNeedToCheckCancel = true;
- ProgressIndicatorProvider.ourNeedToCheckCancel = true;
}
}, 0, 10, TimeUnit.MILLISECONDS);
}
@@ -86,7 +84,6 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable{
if (ourLockedCheckCounter > 10) {
ourLockedCheckCounter = 0;
ourNeedToCheckCancel = true;
- ProgressIndicatorProvider.ourNeedToCheckCancel = true;
}
}
else {
@@ -99,7 +96,6 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable{
public static void canceled() {
ourNeedToCheckCancel = true;
- ProgressIndicatorProvider.ourNeedToCheckCancel = true;
}
private static class NonCancelableIndicator extends EmptyProgressIndicator implements NonCancelableSection {
@@ -371,6 +367,14 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable{
public static Future<?> runProcessWithProgressAsynchronously(@NotNull final Task.Backgroundable task,
@NotNull final ProgressIndicator progressIndicator,
@Nullable final Runnable continuation) {
+ return runProcessWithProgressAsynchronously(task, progressIndicator, continuation, ModalityState.NON_MODAL);
+ }
+
+ @NotNull
+ public static Future<?> runProcessWithProgressAsynchronously(@NotNull final Task.Backgroundable task,
+ @NotNull final ProgressIndicator progressIndicator,
+ @Nullable final Runnable continuation,
+ @NotNull final ModalityState modalityState) {
if (progressIndicator instanceof Disposable) {
Disposer.register(ApplicationManager.getApplication(), (Disposable)progressIndicator);
}
@@ -397,7 +401,7 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable{
public void run() {
task.onCancel();
}
- }, ModalityState.NON_MODAL);
+ }, modalityState);
}
else {
final Task.NotificationInfo notificationInfo = task.notifyFinished();
@@ -412,7 +416,7 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable{
public void run() {
task.onSuccess();
}
- }, ModalityState.NON_MODAL);
+ }, modalityState);
}
}
};
@@ -493,10 +497,6 @@ public class ProgressManagerImpl extends ProgressManager implements Disposable{
@Override
public void dispose() {
- stopCheckCanceled();
- }
-
- private void stopCheckCanceled() {
if (myCheckCancelledFuture != null) myCheckCancelledFuture.cancel(false);
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressIndicatorUtils.java b/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressIndicatorUtils.java
index b98f19b25d17..0c18cb7706d9 100644
--- a/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressIndicatorUtils.java
+++ b/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressIndicatorUtils.java
@@ -61,7 +61,7 @@ public class ProgressIndicatorUtils {
runWithWriteActionPriority(new ProgressIndicatorBase(), task);
}
- public static void runWithWriteActionPriority(final ProgressIndicator progressIndicator, final ReadTask task) {
+ private static void surroundWithListener(@NotNull final ProgressIndicator progressIndicator, @NotNull Runnable runnable) {
final ApplicationAdapter listener = new ApplicationAdapter() {
@Override
public void beforeWriteActionStart(Object action) {
@@ -69,45 +69,70 @@ public class ProgressIndicatorUtils {
}
};
final Application application = ApplicationManager.getApplication();
+ application.addApplicationListener(listener);
try {
- application.addApplicationListener(listener);
- ProgressManager.getInstance().runProcess(new Runnable(){
- @Override
- public void run() {
- // This read action can possible last for a long time, we want it to stop immediately on the first write access.
- // For this purpose we launch it under empty progress and invoke progressIndicator#cancel on write access to avoid possible write lock delays.
- try {
- application.runReadAction(new Runnable() {
- @Override
- public void run() {
- task.computeInReadAction(progressIndicator);
- }
- });
- }
- catch (ProcessCanceledException ignore) {
- }
- finally {
- if (progressIndicator.isCanceled()) {
- task.onCanceled(progressIndicator);
- }
- }
- }
- }, progressIndicator);
+ runnable.run();
}
finally {
application.removeApplicationListener(listener);
}
}
+
+ public static void runWithWriteActionPriority(@NotNull final ProgressIndicator progressIndicator, @NotNull final ReadTask task) {
+ surroundWithListener(progressIndicator, new Runnable() {
+ @Override
+ public void run() {
+ runUnderProgress(progressIndicator, task);
+ }
+ });
+ }
+
+ private static void runUnderProgress(@NotNull final ProgressIndicator progressIndicator, @NotNull final ReadTask task) {
+ ProgressManager.getInstance().runProcess(new Runnable() {
+ @Override
+ public void run() {
+ // This read action can possible last for a long time, we want it to stop immediately on the first write access.
+ // For this purpose we launch it under empty progress and invoke progressIndicator#cancel on write access to avoid possible write lock delays.
+ try {
+ ApplicationManager.getApplication().runReadAction(new Runnable() {
+ @Override
+ public void run() {
+ task.computeInReadAction(progressIndicator);
+ }
+ });
+ }
+ catch (ProcessCanceledException ignore) {
+ }
+ finally {
+ if (progressIndicator.isCanceled()) {
+ task.onCanceled(progressIndicator);
+ }
+ }
+ }
+ }, progressIndicator);
+ }
+
public static void scheduleWithWriteActionPriority(@NotNull final ReadTask task) {
scheduleWithWriteActionPriority(new ProgressIndicatorBase(), task);
}
- public static void scheduleWithWriteActionPriority(final ProgressIndicator indicator, final ReadTask task) {
- ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
+ public static void scheduleWithWriteActionPriority(@NotNull final ProgressIndicator indicator, @NotNull final ReadTask task) {
+ // we have to attach listeners in EDT to avoid "fire write action started while attach listeners from another thread" race condition
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
- runWithWriteActionPriority(indicator, task);
+ surroundWithListener(indicator, new Runnable() {
+ @Override
+ public void run() {
+ ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
+ @Override
+ public void run() {
+ runUnderProgress(indicator, task);
+ }
+ });
+ }
+ });
}
});
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java b/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java
index a20df87718cc..308edb2d81a6 100644
--- a/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java
@@ -392,7 +392,7 @@ public class DumbServiceImpl extends DumbService implements Disposable {
}
private class AppIconProgress extends ProgressIndicatorBase {
- double lastFraction;
+ private double lastFraction;
@Override
public void setFraction(final double fraction) {
@@ -408,16 +408,18 @@ public class DumbServiceImpl extends DumbService implements Disposable {
@Override
public void finish(@NotNull TaskInfo task) {
- UIUtil.invokeLaterIfNeeded(new Runnable() {
- @Override
- public void run() {
- AppIcon appIcon = AppIcon.getInstance();
- if (appIcon.hideProgress(myProject, "indexUpdate")) {
- appIcon.requestAttention(myProject, false);
- appIcon.setOkBadge(myProject, true);
+ if (lastFraction != 0) { // we should call setProgress at least once before
+ UIUtil.invokeLaterIfNeeded(new Runnable() {
+ @Override
+ public void run() {
+ AppIcon appIcon = AppIcon.getInstance();
+ if (appIcon.hideProgress(myProject, "indexUpdate")) {
+ appIcon.requestAttention(myProject, false);
+ appIcon.setOkBadge(myProject, true);
+ }
}
- }
- });
+ });
+ }
}
}
}
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 d1abc0816845..d1573e2adc7f 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
@@ -745,16 +745,6 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer implements FocusTra
@Override
public void windowOpened(WindowEvent e) {
- if (!isModal()) {
- DialogWrapper wrapper = getDialogWrapper();
- if (wrapper != null) {
- JComponent component = wrapper.getPreferredFocusedComponent();
- if (component != null) {
- // request focus for non-modal dialog (i.e. TipDialog)
- IdeFocusManager.findInstance().requestFocus(component, true);
- }
- }
- }
if (!SystemInfo.isMacOSLion) return;
Window window = e.getWindow();
if (window instanceof Dialog) {
@@ -774,14 +764,9 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer implements FocusTra
queue.getKeyEventDispatcher().resetState();
}
- // if (myProject != null) {
- // Project project = myProject.get();
- //if (project != null && !project.isDisposed() && project.isInitialized()) {
- // // IdeFocusManager.findInstanceByComponent(this).requestFocus(new MyFocusCommand(dialogWrapper), true);
- //}
- // }
}
+ // Workaround for switching workspaces on dialog show
if (SystemInfo.isMac && myProject != null && Registry.is("ide.mac.fix.dialog.showing") && !dialogWrapper.isModalProgress()) {
final IdeFrame frame = WindowManager.getInstance().getIdeFrame(myProject.get());
AppIcon.getInstance().requestFocus(frame);
diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/PluginDownloader.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/PluginDownloader.java
index 9739d75be7e7..c93e69438766 100644
--- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/PluginDownloader.java
+++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/PluginDownloader.java
@@ -61,6 +61,7 @@ public class PluginDownloader {
private String myFileName;
private String myPluginName;
+ private BuildNumber myBuildNumber;
private File myFile;
private File myOldFile;
@@ -74,12 +75,18 @@ public class PluginDownloader {
myPluginVersion = pluginVersion;
}
- public PluginDownloader(String pluginId, String pluginUrl, String pluginVersion, String fileName, String pluginName) {
+ public PluginDownloader(String pluginId,
+ String pluginUrl,
+ String pluginVersion,
+ String fileName,
+ String pluginName,
+ BuildNumber buildNumber) {
myPluginId = pluginId;
myPluginUrl = pluginUrl;
myPluginVersion = pluginVersion;
myFileName = fileName;
myPluginName = pluginName;
+ myBuildNumber = buildNumber;
}
@SuppressWarnings("UnusedDeclaration")
@@ -89,7 +96,7 @@ public class PluginDownloader {
}
public boolean prepareToInstall(ProgressIndicator pi) throws IOException {
- return prepareToInstall(pi, null);
+ return prepareToInstall(pi, myBuildNumber);
}
public boolean prepareToInstall(@Nullable ProgressIndicator pi, @Nullable BuildNumber forBuildNumber) throws IOException {
@@ -289,9 +296,15 @@ public class PluginDownloader {
}
private URLConnection openConnection(final String url) throws IOException {
- final URLConnection connection = ApplicationManager.getApplication() != null
- ? HttpConfigurable.getInstance().openConnection(url)
- : new URL(url).openConnection();
+ final URLConnection connection;
+ if (ApplicationManager.getApplication() != null) {
+ connection = HttpConfigurable.getInstance().openConnection(url);
+ }
+ else {
+ connection = new URL(url).openConnection();
+ connection.setConnectTimeout(HttpConfigurable.CONNECTION_TIMEOUT);
+ connection.setReadTimeout(HttpConfigurable.CONNECTION_TIMEOUT);
+ }
if (connection instanceof HttpURLConnection) {
final int responseCode = ((HttpURLConnection)connection).getResponseCode();
if (responseCode != HttpURLConnection.HTTP_OK) {
@@ -385,9 +398,14 @@ public class PluginDownloader {
}
public static PluginDownloader createDownloader(IdeaPluginDescriptor descriptor) throws UnsupportedEncodingException {
+ return createDownloader(descriptor, null);
+ }
+
+ public static PluginDownloader createDownloader(IdeaPluginDescriptor descriptor,
+ BuildNumber buildNumber) throws UnsupportedEncodingException {
PluginDownloader downloader = new PluginDownloader(descriptor.getPluginId().getIdString(),
- UpdateChecker.getDownloadUrl(descriptor),
- descriptor.getVersion(), null, descriptor.getName());
+ UpdateChecker.getDownloadUrl(descriptor, buildNumber),
+ descriptor.getVersion(), null, descriptor.getName(), buildNumber);
downloader.setDescriptor(descriptor);
return downloader;
}
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 354f89c22820..83858cc4fb40 100644
--- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java
+++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java
@@ -239,13 +239,13 @@ public final class UpdateChecker {
updateSettings.myOutdatedPlugins.clear();
if (!toUpdate.isEmpty()) {
try {
- final List<IdeaPluginDescriptor> process = RepositoryHelper.loadPluginsFromRepository(indicator);
+ final List<IdeaPluginDescriptor> process = RepositoryHelper.loadPluginsFromRepository(indicator, buildNumber);
for (IdeaPluginDescriptor loadedPlugin : process) {
final PluginId pluginId = loadedPlugin.getPluginId();
final String idString = pluginId.getIdString();
if (!toUpdate.containsKey(idString)) continue;
if (!downloaded.containsKey(pluginId)) {
- prepareToInstall(PluginDownloader.createDownloader(loadedPlugin), buildNumber, downloaded, incompatiblePlugins, true, indicator);
+ prepareToInstall(PluginDownloader.createDownloader(loadedPlugin, buildNumber), buildNumber, downloaded, incompatiblePlugins, true, indicator);
}
}
}
@@ -376,7 +376,7 @@ public final class UpdateChecker {
final List<IdeaPluginDescriptor> descriptors = RepositoryHelper.loadPluginsFromDescription(inputStream, indicator);
for (IdeaPluginDescriptor descriptor : descriptors) {
((PluginNode)descriptor).setRepositoryName(host);
- prepareToInstall(PluginDownloader.createDownloader(descriptor), buildNumber, downloaded, incompatiblePlugins, collectToUpdate,
+ prepareToInstall(PluginDownloader.createDownloader(descriptor, buildNumber), buildNumber, downloaded, incompatiblePlugins, collectToUpdate,
indicator);
}
@@ -424,7 +424,7 @@ public final class UpdateChecker {
if (progressIndicator != null) {
progressIndicator.setText2(finalPluginUrl);
}
- final PluginDownloader downloader = new PluginDownloader(pluginId, finalPluginUrl, pluginVersion, null, null);
+ final PluginDownloader downloader = new PluginDownloader(pluginId, finalPluginUrl, pluginVersion, null, null, buildNumber);
prepareToInstall(downloader, buildNumber, downloaded, incompatiblePlugins, collectToUpdate, indicator);
}
catch (IOException e) {
@@ -624,11 +624,15 @@ public final class UpdateChecker {
urlToCheck = url;
}
- HttpURLConnection connection = ApplicationManager.getApplication() != null ?
- HttpConfigurable.getInstance().openHttpConnection(urlToCheck) :
- (HttpURLConnection)new URL(urlToCheck).openConnection();
- connection.setReadTimeout(HttpConfigurable.CONNECTION_TIMEOUT);
- connection.setConnectTimeout(HttpConfigurable.CONNECTION_TIMEOUT);
+ HttpURLConnection connection;
+ if (ApplicationManager.getApplication() != null) {
+ connection = HttpConfigurable.getInstance().openHttpConnection(urlToCheck);
+ }
+ else {
+ connection = (HttpURLConnection)new URL(urlToCheck).openConnection();
+ connection.setReadTimeout(HttpConfigurable.CONNECTION_TIMEOUT);
+ connection.setConnectTimeout(HttpConfigurable.CONNECTION_TIMEOUT);
+ }
connection.connect();
inputStreams[0] = connection.getInputStream();
@@ -862,7 +866,7 @@ public final class UpdateChecker {
}
}
- static String getDownloadUrl(IdeaPluginDescriptor descriptor) throws UnsupportedEncodingException {
+ static String getDownloadUrl(IdeaPluginDescriptor descriptor, @Nullable BuildNumber buildNumber) throws UnsupportedEncodingException {
String url = null;
if (descriptor instanceof PluginNode) {
url = ((PluginNode)descriptor).getDownloadUrl();
@@ -881,11 +885,13 @@ public final class UpdateChecker {
String uuid = ApplicationManager.getApplication() == null ?
UUID.randomUUID().toString() :
getInstallationUID(PropertiesComponent.getInstance());
- String buildNumber = ApplicationManager.getApplication() != null
- ? ApplicationInfo.getInstance().getApiVersion()
- : ApplicationInfoImpl.getShadowInstance().getBuild().asString();
+ String buildNumberAsString = buildNumber != null
+ ? buildNumber.asString()
+ : ApplicationManager.getApplication() != null
+ ? ApplicationInfo.getInstance().getApiVersion()
+ : ApplicationInfoImpl.getShadowInstance().getBuild().asString();
url = RepositoryHelper.getDownloadUrl() + URLEncoder.encode(descriptor.getPluginId().getIdString(), "UTF8") +
- "&build=" + buildNumber + "&uuid=" + URLEncoder.encode(uuid, "UTF8");
+ "&build=" + buildNumberAsString + "&uuid=" + URLEncoder.encode(uuid, "UTF8");
}
return url;
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdatesXmlLoader.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdatesXmlLoader.java
index d1010f52e1b1..9c6c6a2020e5 100644
--- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdatesXmlLoader.java
+++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdatesXmlLoader.java
@@ -32,6 +32,7 @@ import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
+import java.net.URLConnection;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
@@ -67,7 +68,10 @@ public class UpdatesXmlLoader {
URL requestUrl = prepareRequestUrl(updateUrl);
- final InputStream inputStream = requestUrl.openStream();
+ URLConnection connection = requestUrl.openConnection();
+ connection.setConnectTimeout(HttpConfigurable.CONNECTION_TIMEOUT);
+ connection.setReadTimeout(HttpConfigurable.CONNECTION_TIMEOUT);
+ final InputStream inputStream = connection.getInputStream();
Reader reader = new InputStreamReader(inputStream);
try {
return new UpdatesInfo(JDOMUtil.loadDocument(inputStream).getRootElement());
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/ex/ToolWindowManagerEx.java b/platform/platform-impl/src/com/intellij/openapi/wm/ex/ToolWindowManagerEx.java
index fbe213f20bb0..2bff2a10d5cd 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/ex/ToolWindowManagerEx.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/ex/ToolWindowManagerEx.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.
@@ -28,7 +28,7 @@ import javax.swing.*;
import java.util.List;
public abstract class ToolWindowManagerEx extends ToolWindowManager {
- public abstract void initToolWindow(ToolWindowEP bean);
+ public abstract void initToolWindow(@NotNull ToolWindowEP bean);
public static ToolWindowManagerEx getInstanceEx(final Project project){
return (ToolWindowManagerEx)getInstance(project);
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/FocusManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/FocusManagerImpl.java
index c302cce7572e..867c404073d3 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/FocusManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/FocusManagerImpl.java
@@ -203,9 +203,6 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable {
public ActionCallback requestFocus(@NotNull final FocusCommand command, final boolean forced) {
assertDispatchThread();
- if (!forced && !command.canFocusChangeFrom(getFocusOwner())) {
- return ActionCallback.REJECTED;
- }
if (isInternalMode) {
recordCommand(command, new Throwable(), forced);
}
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 71f964504102..1613953287b6 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
@@ -24,8 +24,6 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.ui.Divider;
import com.intellij.openapi.ui.Painter;
import com.intellij.openapi.ui.impl.GlassPaneDialogWrapperPeer;
-import com.intellij.openapi.ui.popup.Balloon;
-import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Weighted;
import com.intellij.openapi.wm.IdeGlassPane;
@@ -287,8 +285,6 @@ public class IdeGlassPaneImpl extends JPanel implements IdeGlassPaneEx, IdeEvent
return false;
}
- private MouseEvent myLastRedispatchedEvent = null;
-
private boolean preprocess(final MouseEvent e, final boolean motion, JRootPane eventRootPane) {
try {
final MouseEvent event = convertEvent(e, eventRootPane);
@@ -297,25 +293,6 @@ public class IdeGlassPaneImpl extends JPanel implements IdeGlassPaneEx, IdeEvent
return false;
}
- Component c = SwingUtilities.getDeepestComponentAt(e.getComponent(), e.getX(), e.getY());
- Balloon balloon = JBPopupFactory.getInstance().getParentBalloonFor(c);
- if (balloon != null && myLastRedispatchedEvent != e) {
- if (e.getID() == MouseEvent.MOUSE_PRESSED
- && IdeTooltipManager.getInstance().hasCurrent()
- && IdeTooltipManager.getInstance().hideCurrent(event, null, null, false)) {
- //noinspection SSBasedInspection
- SwingUtilities.invokeLater(new Runnable() {
- @Override
- public void run() {
- myLastRedispatchedEvent = e;
- IdeEventQueue.getInstance().dispatchEvent(e);
- }
- });
- }
- return false;
- }
- myLastRedispatchedEvent = null;
-
for (EventListener each : mySortedMouseListeners) {
if (motion && each instanceof MouseMotionListener) {
fireMouseMotion((MouseMotionListener)each, event);
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 8b78b1632f79..7b9a7494c640 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
@@ -87,6 +87,7 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx {
return tw;
}
+ @NotNull
@Override
public ToolWindow registerToolWindow(@NotNull String id,
@NotNull JComponent component,
@@ -96,11 +97,13 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx {
return doRegisterToolWindow(id, parentDisposable);
}
+ @NotNull
@Override
public ToolWindow registerToolWindow(@NotNull String id, @NotNull JComponent component, @NotNull ToolWindowAnchor anchor) {
return doRegisterToolWindow(id, null);
}
+ @NotNull
@Override
public ToolWindow registerToolWindow(@NotNull String id,
@NotNull JComponent component,
@@ -111,19 +114,22 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx {
return doRegisterToolWindow(id, parentDisposable);
}
+ @NotNull
@Override
public ToolWindow registerToolWindow(@NotNull String id,
@NotNull JComponent component,
@NotNull ToolWindowAnchor anchor,
- Disposable parentDisposable) {
+ @NotNull Disposable parentDisposable) {
return doRegisterToolWindow(id, parentDisposable);
}
+ @NotNull
@Override
public ToolWindow registerToolWindow(@NotNull final String id, final boolean canCloseContent, @NotNull final ToolWindowAnchor anchor) {
return doRegisterToolWindow(id, null);
}
+ @NotNull
@Override
public ToolWindow registerToolWindow(@NotNull final String id,
final boolean canCloseContent,
@@ -132,6 +138,7 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx {
return doRegisterToolWindow(id, null);
}
+ @NotNull
@Override
public ToolWindow registerToolWindow(@NotNull final String id, final boolean canCloseContent, @NotNull final ToolWindowAnchor anchor,
final Disposable parentDisposable, final boolean dumbAware) {
@@ -152,6 +159,7 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx {
return false;
}
+ @NotNull
@Override
public String[] getToolWindowIds() {
return ArrayUtil.EMPTY_STRING_ARRAY;
@@ -168,9 +176,10 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx {
}
@Override
- public void invokeLater(Runnable runnable) {
+ public void invokeLater(@NotNull Runnable runnable) {
}
+ @NotNull
@Override
public IdeFocusManager getFocusManager() {
return IdeFocusManagerHeadless.INSTANCE;
@@ -190,7 +199,7 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx {
}
@Override
- public void initToolWindow(ToolWindowEP bean) {
+ public void initToolWindow(@NotNull ToolWindowEP bean) {
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowImpl.java
index efcdd148d57b..1fa2bd95defe 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowImpl.java
@@ -72,6 +72,7 @@ public final class ToolWindowImpl implements ToolWindowEx {
private boolean myPlaceholderMode;
private ToolWindowFactory myContentFactory;
+ @NotNull
private ActionCallback myActivation = new ActionCallback.Done();
private final BusyObject.Impl myShowing = new BusyObject.Impl() {
@Override
@@ -115,18 +116,22 @@ public final class ToolWindowImpl implements ToolWindowEx {
myChangeSupport.addPropertyChangeListener(l);
}
+ @Override
public final void removePropertyChangeListener(final PropertyChangeListener l) {
myChangeSupport.removePropertyChangeListener(l);
}
+ @Override
public final void activate(final Runnable runnable) {
activate(runnable, true);
}
+ @Override
public void activate(@Nullable final Runnable runnable, final boolean autoFocusContents) {
activate(runnable, autoFocusContents, true);
}
+ @Override
public void activate(@Nullable final Runnable runnable, boolean autoFocusContents, boolean forced) {
ApplicationManager.getApplication().assertIsDispatchThread();
@@ -136,6 +141,7 @@ public final class ToolWindowImpl implements ToolWindowEx {
myToolWindowManager.activateToolWindow(myId, forced, autoFocusContents);
getActivation().doWhenDone(new Runnable() {
+ @Override
public void run() {
myToolWindowManager.invokeLater(new Runnable() {
@Override
@@ -150,6 +156,7 @@ public final class ToolWindowImpl implements ToolWindowEx {
});
}
+ @Override
public final boolean isActive() {
ApplicationManager.getApplication().assertIsDispatchThread();
if (myToolWindowManager.isEditorComponentActive()) return false;
@@ -182,11 +189,13 @@ public final class ToolWindowImpl implements ToolWindowEx {
return result;
}
+ @Override
public final void show(final Runnable runnable) {
ApplicationManager.getApplication().assertIsDispatchThread();
myToolWindowManager.showToolWindow(myId);
if (runnable != null) {
getActivation().doWhenDone(new Runnable() {
+ @Override
public void run() {
myToolWindowManager.invokeLater(runnable);
}
@@ -194,6 +203,7 @@ public final class ToolWindowImpl implements ToolWindowEx {
}
}
+ @Override
public final void hide(@Nullable final Runnable runnable) {
ApplicationManager.getApplication().assertIsDispatchThread();
myToolWindowManager.hideToolWindow(myId, false);
@@ -202,14 +212,17 @@ public final class ToolWindowImpl implements ToolWindowEx {
}
}
+ @Override
public final boolean isVisible() {
return myToolWindowManager.isToolWindowVisible(myId);
}
+ @Override
public final ToolWindowAnchor getAnchor() {
return myToolWindowManager.getToolWindowAnchor(myId);
}
+ @Override
public final void setAnchor(final ToolWindowAnchor anchor, @Nullable final Runnable runnable) {
ApplicationManager.getApplication().assertIsDispatchThread();
myToolWindowManager.setToolWindowAnchor(myId, anchor);
@@ -218,11 +231,13 @@ public final class ToolWindowImpl implements ToolWindowEx {
}
}
+ @Override
public boolean isSplitMode() {
ApplicationManager.getApplication().assertIsDispatchThread();
return myToolWindowManager.isSplitMode(myId);
}
+ @Override
public void setContentUiType(ToolWindowContentUiType type, @Nullable Runnable runnable) {
ApplicationManager.getApplication().assertIsDispatchThread();
myToolWindowManager.setContentUiType(myId, type);
@@ -231,15 +246,18 @@ public final class ToolWindowImpl implements ToolWindowEx {
}
}
+ @Override
public void setDefaultContentUiType(@NotNull ToolWindowContentUiType type) {
myToolWindowManager.setDefaultContentUiType(this, type);
}
+ @Override
public ToolWindowContentUiType getContentUiType() {
ApplicationManager.getApplication().assertIsDispatchThread();
return myToolWindowManager.getContentUiType(myId);
}
+ @Override
public void setSplitMode(final boolean isSideTool, @Nullable final Runnable runnable) {
ApplicationManager.getApplication().assertIsDispatchThread();
myToolWindowManager.setSideTool(myId, isSideTool);
@@ -248,20 +266,24 @@ public final class ToolWindowImpl implements ToolWindowEx {
}
}
+ @Override
public final void setAutoHide(final boolean state) {
ApplicationManager.getApplication().assertIsDispatchThread();
myToolWindowManager.setToolWindowAutoHide(myId, state);
}
+ @Override
public final boolean isAutoHide() {
ApplicationManager.getApplication().assertIsDispatchThread();
return myToolWindowManager.isToolWindowAutoHide(myId);
}
+ @Override
public final ToolWindowType getType() {
return myToolWindowManager.getToolWindowType(myId);
}
+ @Override
public final void setType(final ToolWindowType type, @Nullable final Runnable runnable) {
ApplicationManager.getApplication().assertIsDispatchThread();
myToolWindowManager.setToolWindowType(myId, type);
@@ -270,19 +292,23 @@ public final class ToolWindowImpl implements ToolWindowEx {
}
}
+ @Override
public final ToolWindowType getInternalType() {
ApplicationManager.getApplication().assertIsDispatchThread();
return myToolWindowManager.getToolWindowInternalType(myId);
}
+ @Override
public void stretchWidth(int value) {
myToolWindowManager.stretchWidth(this, value);
}
+ @Override
public void stretchHeight(int value) {
myToolWindowManager.stretchHeight(this, value);
}
+ @Override
public InternalDecorator getDecorator() {
return myDecorator;
}
@@ -297,6 +323,7 @@ public final class ToolWindowImpl implements ToolWindowEx {
getDecorator().setTitleActions(actions);
}
+ @Override
public final void setAvailable(final boolean available, final Runnable runnable) {
ApplicationManager.getApplication().assertIsDispatchThread();
final Boolean oldAvailable = myAvailable ? Boolean.TRUE : Boolean.FALSE;
@@ -307,6 +334,7 @@ public final class ToolWindowImpl implements ToolWindowEx {
}
}
+ @Override
public void installWatcher(ContentManager contentManager) {
new ContentManagerWatcher(this, contentManager);
}
@@ -316,14 +344,17 @@ public final class ToolWindowImpl implements ToolWindowEx {
* <code>ContentManager</code> class. Otherwise it delegates the functionality to the
* passed content manager.
*/
+ @Override
public final boolean isAvailable() {
return myAvailable && myComponent != null;
}
+ @Override
public final JComponent getComponent() {
return myComponent;
}
+ @Override
public ContentManager getContentManager() {
return myContentManager;
}
@@ -332,6 +363,7 @@ public final class ToolWindowImpl implements ToolWindowEx {
return myContentUI;
}
+ @Override
public final Icon getIcon() {
ApplicationManager.getApplication().assertIsDispatchThread();
return myIcon;
@@ -342,17 +374,20 @@ public final class ToolWindowImpl implements ToolWindowEx {
return myId;
}
+ @Override
public final String getTitle() {
ApplicationManager.getApplication().assertIsDispatchThread();
return getSelectedContent().getDisplayName();
}
+ @Override
@NotNull
public final String getStripeTitle() {
ApplicationManager.getApplication().assertIsDispatchThread();
return ObjectUtils.notNull(myStripeTitle, myId);
}
+ @Override
public final void setIcon(final Icon icon) {
ApplicationManager.getApplication().assertIsDispatchThread();
final Icon oldIcon = getIcon();
@@ -364,6 +399,7 @@ public final class ToolWindowImpl implements ToolWindowEx {
myChangeSupport.firePropertyChange(PROP_ICON, oldIcon, icon);
}
+ @Override
public final void setTitle(String title) {
ApplicationManager.getApplication().assertIsDispatchThread();
String oldTitle = getTitle();
@@ -371,6 +407,7 @@ public final class ToolWindowImpl implements ToolWindowEx {
myChangeSupport.firePropertyChange(PROP_TITLE, oldTitle, title);
}
+ @Override
public final void setStripeTitle(@NotNull String stripeTitle) {
ApplicationManager.getApplication().assertIsDispatchThread();
String oldTitle = myStripeTitle;
@@ -415,18 +452,22 @@ public final class ToolWindowImpl implements ToolWindowEx {
return myDecorator != null ? myDecorator.createPopupGroup() : null;
}
+ @Override
public void setDefaultState(@Nullable final ToolWindowAnchor anchor, @Nullable final ToolWindowType type, @Nullable final Rectangle floatingBounds) {
myToolWindowManager.setDefaultState(this, anchor, type, floatingBounds);
}
+ @Override
public void setToHideOnEmptyContent(final boolean hideOnEmpty) {
myHideOnEmptyContent = hideOnEmpty;
}
+ @Override
public boolean isToHideOnEmptyContent() {
return myHideOnEmptyContent;
}
+ @Override
public boolean isDisposed() {
return myContentManager.isDisposed();
}
@@ -439,12 +480,15 @@ public final class ToolWindowImpl implements ToolWindowEx {
myPlaceholderMode = placeholderMode;
}
+ @Override
+ @NotNull
public ActionCallback getActivation() {
return myActivation;
}
- public ActionCallback setActivation(ActionCallback activation) {
- if (myActivation != null && !myActivation.isProcessed() && !myActivation.equals(activation)) {
+ @NotNull
+ public ActionCallback setActivation(@NotNull ActionCallback activation) {
+ if (!myActivation.isProcessed() && !myActivation.equals(activation)) {
myActivation.setRejected();
}
@@ -467,6 +511,7 @@ public final class ToolWindowImpl implements ToolWindowEx {
}
}
+ @Override
public void showContentPopup(InputEvent inputEvent) {
myContentUI.toggleContentPopup();
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java
index 555e0666f72e..95b3d54f8030 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java
@@ -363,6 +363,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
return IdeFocusManager.getInstance(project);
}
+ @NotNull
public Project getProject() {
return myProject;
}
@@ -482,21 +483,14 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
}
@Override
- public void initToolWindow(ToolWindowEP bean) {
- ToolWindowAnchor toolWindowAnchor;
- try {
- toolWindowAnchor = ToolWindowAnchor.fromText(bean.anchor);
- }
- catch (Exception e) {
- LOG.error(e);
- return;
- }
+ public void initToolWindow(@NotNull ToolWindowEP bean) {
JLabel label = new JLabel("Initializing...", SwingConstants.CENTER);
label.setOpaque(true);
final Color treeBg = UIManager.getColor("Tree.background");
label.setBackground(ColorUtil.toAlpha(treeBg, 180));
final Color treeFg = UIUtil.getTreeForeground();
label.setForeground(ColorUtil.toAlpha(treeFg, 180));
+ ToolWindowAnchor toolWindowAnchor = ToolWindowAnchor.fromText(bean.anchor);
final ToolWindowFactory factory = bean.getToolWindowFactory();
final ToolWindowImpl toolWindow =
(ToolWindowImpl)registerToolWindow(bean.id, label, toolWindowAnchor, myProject, DumbService.isDumbAware(factory),
@@ -747,7 +741,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
myActiveStack.push(id);
}
- if (autoFocusContents) {
+ if (autoFocusContents && ApplicationManager.getApplication().isActive()) {
appendRequestFocusInToolWindowCmd(id, commandsList, forcedFocusRequest);
}
}
@@ -826,6 +820,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
appendApplyWindowInfoCmd(info, commandsList);
}
+ @NotNull
@Override
public String[] getToolWindowIds() {
final WindowInfoImpl[] infos = myLayout.getInfos();
@@ -1087,6 +1082,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
appendApplyWindowInfoCmd(toBeShownInfo, commandsList);
}
+ @NotNull
@Override
public ToolWindow registerToolWindow(@NotNull final String id,
@NotNull final JComponent component,
@@ -1094,6 +1090,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
return registerToolWindow(id, component, anchor, false);
}
+ @NotNull
@Override
public ToolWindow registerToolWindow(@NotNull final String id,
@NotNull JComponent component,
@@ -1102,6 +1099,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
return registerToolWindow(id, component, anchor, parentDisposable, false, false);
}
+ @NotNull
@Override
public ToolWindow registerToolWindow(@NotNull String id,
@NotNull JComponent component,
@@ -1111,6 +1109,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
return registerToolWindow(id, component, anchor, parentDisposable, canWorkInDumbMode, false);
}
+ @NotNull
@Override
public ToolWindow registerToolWindow(@NotNull final String id,
@NotNull JComponent component,
@@ -1120,6 +1119,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
return registerDisposable(id, parentDisposable, registerToolWindow(id, component, anchor, false, canCloseContents, canWorkInDumbMode));
}
+ @NotNull
private ToolWindow registerToolWindow(@NotNull final String id,
@NotNull final JComponent component,
@NotNull final ToolWindowAnchor anchor,
@@ -1127,11 +1127,13 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
return registerToolWindow(id, component, anchor, false, false, canWorkInDumbMode);
}
+ @NotNull
@Override
public ToolWindow registerToolWindow(@NotNull final String id, final boolean canCloseContent, @NotNull final ToolWindowAnchor anchor) {
return registerToolWindow(id, null, anchor, false, canCloseContent, false);
}
+ @NotNull
@Override
public ToolWindow registerToolWindow(@NotNull final String id,
final boolean canCloseContent,
@@ -1141,15 +1143,18 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
}
+ @NotNull
@Override
public ToolWindow registerToolWindow(@NotNull final String id,
final boolean canCloseContent,
@NotNull final ToolWindowAnchor anchor,
@NotNull final Disposable parentDisposable,
final boolean canWorkInDumbMode) {
- return registerDisposable(id, parentDisposable, registerToolWindow(id, null, anchor, false, canCloseContent, canWorkInDumbMode));
+ ToolWindow window = registerToolWindow(id, null, anchor, false, canCloseContent, canWorkInDumbMode);
+ return registerDisposable(id, parentDisposable, window);
}
+ @NotNull
private ToolWindow registerToolWindow(@NotNull final String id,
@Nullable final JComponent component,
@NotNull final ToolWindowAnchor anchor,
@@ -1216,7 +1221,8 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
return toolWindow;
}
- private ToolWindow registerDisposable(final String id, @NotNull final Disposable parentDisposable, final ToolWindow window) {
+ @NotNull
+ private ToolWindow registerDisposable(@NotNull final String id, @NotNull final Disposable parentDisposable, @NotNull ToolWindow window) {
Disposer.register(parentDisposable, new Disposable() {
@Override
public void dispose() {
@@ -1353,12 +1359,13 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
}
@Override
- public void invokeLater(final Runnable runnable) {
+ public void invokeLater(@NotNull final Runnable runnable) {
List<FinalizableCommand> commandList = new ArrayList<FinalizableCommand>();
commandList.add(new InvokeLaterCmd(runnable, myWindowManager.getCommandProcessor()));
execute(commandList);
}
+ @NotNull
@Override
public IdeFocusManager getFocusManager() {
return IdeFocusManager.getInstance(myProject);
diff --git a/platform/platform-impl/src/com/intellij/remote/RemoteSdkAdditionalData.java b/platform/platform-impl/src/com/intellij/remote/RemoteSdkAdditionalData.java
index b51c85bc2c18..2da812614b88 100644
--- a/platform/platform-impl/src/com/intellij/remote/RemoteSdkAdditionalData.java
+++ b/platform/platform-impl/src/com/intellij/remote/RemoteSdkAdditionalData.java
@@ -25,8 +25,9 @@ public interface RemoteSdkAdditionalData<T extends RemoteSdkCredentials>
extends SdkAdditionalData, RemoteSdkCredentialsProducer<T>, RemoteSdkProperties {
void completeInitialization();
+ @Deprecated
boolean isInitialized();
-
+ @Deprecated
void setInitialized(boolean initialized);
void setVagrantConnectionType(@NotNull VagrantBasedCredentialsHolder vagrantBasedCredentials);
diff --git a/platform/platform-impl/src/com/intellij/remote/RemoteSdkCredentialsHolder.java b/platform/platform-impl/src/com/intellij/remote/RemoteSdkCredentialsHolder.java
index d92839e212b8..ae84919ac9ce 100644
--- a/platform/platform-impl/src/com/intellij/remote/RemoteSdkCredentialsHolder.java
+++ b/platform/platform-impl/src/com/intellij/remote/RemoteSdkCredentialsHolder.java
@@ -144,6 +144,16 @@ public class RemoteSdkCredentialsHolder extends RemoteCredentialsHolder implemen
myRemoteSdkProperties.setInitialized(initialized);
}
+ @Override
+ public boolean isValid() {
+ return myRemoteSdkProperties.isValid();
+ }
+
+ @Override
+ public void setValid(boolean valid) {
+ myRemoteSdkProperties.setValid(valid);
+ }
+
public static boolean isRemoteSdk(@Nullable String path) {
if (path != null) {
return path.startsWith(SSH_PREFIX) || path.startsWith(RemoteConnectionCredentialsWrapper.VAGRANT_PREFIX) ||
diff --git a/platform/platform-impl/src/com/intellij/remote/RemoteSdkProperties.java b/platform/platform-impl/src/com/intellij/remote/RemoteSdkProperties.java
index a690afd96afc..d9cca99cce14 100644
--- a/platform/platform-impl/src/com/intellij/remote/RemoteSdkProperties.java
+++ b/platform/platform-impl/src/com/intellij/remote/RemoteSdkProperties.java
@@ -84,9 +84,19 @@ public interface RemoteSdkProperties {
String getSdkId();
+ /**
+ * isValid() is used now
+ * To be removed in IDEA 15
+ *
+ * @deprecated
+ */
@Deprecated
boolean isInitialized();
@Deprecated
void setInitialized(boolean initialized);
+
+ boolean isValid();
+
+ void setValid(boolean valid);
}
diff --git a/platform/platform-impl/src/com/intellij/remote/RemoteSdkPropertiesHolder.java b/platform/platform-impl/src/com/intellij/remote/RemoteSdkPropertiesHolder.java
index a0407d27f7e9..68e22f79c7fc 100644
--- a/platform/platform-impl/src/com/intellij/remote/RemoteSdkPropertiesHolder.java
+++ b/platform/platform-impl/src/com/intellij/remote/RemoteSdkPropertiesHolder.java
@@ -36,6 +36,7 @@ public class RemoteSdkPropertiesHolder implements RemoteSdkProperties {
private static final String REMOTE_ROOTS = "REMOTE_ROOTS";
private static final String REMOTE_PATH = "REMOTE_PATH";
private static final String INITIALIZED = "INITIALIZED";
+ private static final String VALID = "VALID";
private static final String PATH_MAPPINGS = "PATH_MAPPINGS";
private String mySdkId;
@@ -51,6 +52,8 @@ public class RemoteSdkPropertiesHolder implements RemoteSdkProperties {
private boolean myInitialized = false;
+ private boolean myValid = true;
+
@NotNull
private PathMappingSettings myPathMappings = new PathMappingSettings();
@@ -144,6 +147,16 @@ public class RemoteSdkPropertiesHolder implements RemoteSdkProperties {
myInitialized = initialized;
}
+ @Override
+ public boolean isValid() {
+ return myValid;
+ }
+
+ @Override
+ public void setValid(boolean valid) {
+ myValid = valid;
+ }
+
public void copyTo(RemoteSdkProperties copy) {
copy.setInterpreterPath(getInterpreterPath());
copy.setHelpersPath(getHelpersPath());
@@ -152,6 +165,8 @@ public class RemoteSdkPropertiesHolder implements RemoteSdkProperties {
copy.setRemoteRoots(getRemoteRoots());
copy.setInitialized(isInitialized());
+
+ copy.setValid(isValid());
}
public void save(Element rootElement) {
@@ -159,6 +174,7 @@ public class RemoteSdkPropertiesHolder implements RemoteSdkProperties {
rootElement.setAttribute(HELPERS_PATH, StringUtil.notNullize(getHelpersPath()));
rootElement.setAttribute(INITIALIZED, Boolean.toString(isInitialized()));
+ rootElement.setAttribute(VALID, Boolean.toString(isValid()));
PathMappingSettings.writeExternal(rootElement, myPathMappings);
@@ -177,6 +193,8 @@ public class RemoteSdkPropertiesHolder implements RemoteSdkProperties {
setInitialized(StringUtil.parseBoolean(element.getAttributeValue(INITIALIZED), true));
+ setValid(StringUtil.parseBoolean(element.getAttributeValue(VALID), true));
+
setPathMappings(PathMappingSettings.readExternal(element));
}
}
diff --git a/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java b/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java
index d8b204cfd76c..1fc23e5f4055 100644
--- a/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java
+++ b/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java
@@ -54,7 +54,7 @@ public abstract class AbstractExpandableItemsHandler<KeyType, ComponentType exte
myTipComponent = new TipComponent();
- myTipComponent.addMouseListener(new MouseAdapter() {
+ MouseAdapter tipMouseAdapter = new MouseAdapter() {
@Override
public void mouseExited(MouseEvent e) {
// don't hide the hint if mouse exited to myComponent
@@ -62,7 +62,60 @@ public abstract class AbstractExpandableItemsHandler<KeyType, ComponentType exte
hideHint();
}
}
- });
+
+ @Override
+ public void mouseWheelMoved(MouseWheelEvent e) {
+ Point p = e.getLocationOnScreen();
+ SwingUtilities.convertPointFromScreen(p, myComponent);
+ myComponent.dispatchEvent(new MouseWheelEvent(myComponent,
+ e.getID(),
+ e.getWhen(),
+ e.getModifiers(),
+ p.x, p.y,
+ e.getClickCount(),
+ e.isPopupTrigger(),
+ e.getScrollType(),
+ e.getScrollAmount(),
+ e.getWheelRotation()));
+ }
+
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ Point p = e.getLocationOnScreen();
+ SwingUtilities.convertPointFromScreen(p, myComponent);
+ myComponent.dispatchEvent(new MouseEvent(myComponent,
+ e.getID(),
+ e.getWhen(),
+ e.getModifiers(),
+ p.x, p.y,
+ e.getClickCount(),
+ e.isPopupTrigger(),
+ e.getButton()));
+ }
+
+ @Override
+ public void mousePressed(MouseEvent e) {
+ mouseClicked(e);
+ }
+
+ @Override
+ public void mouseReleased(MouseEvent e) {
+ mouseClicked(e);
+ }
+
+ @Override
+ public void mouseMoved(MouseEvent e) {
+ mouseClicked(e);
+ }
+
+ @Override
+ public void mouseDragged(MouseEvent e) {
+ mouseClicked(e);
+ }
+ };
+ myTipComponent.addMouseListener(tipMouseAdapter);
+ myTipComponent.addMouseWheelListener(tipMouseAdapter);
+ myTipComponent.addMouseMotionListener(tipMouseAdapter);
myComponent.addMouseListener(
new MouseListener() {
diff --git a/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java b/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java
index 513d5cedb2ab..d41d0bb5ef18 100644
--- a/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java
+++ b/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java
@@ -331,7 +331,7 @@ public class BalloonImpl implements Balloon, IdeTooltip.Ui {
Integer result = JLayeredPane.DEFAULT_LAYER;
switch (myLayer) {
case normal:
- result = JLayeredPane.DEFAULT_LAYER;
+ result = JLayeredPane.POPUP_LAYER;
break;
case top:
result = JLayeredPane.DRAG_LAYER;
diff --git a/platform/platform-impl/src/com/intellij/ui/JBTabsPaneImpl.java b/platform/platform-impl/src/com/intellij/ui/JBTabsPaneImpl.java
index d5fc8dcca1ba..fe041c5ea02b 100644
--- a/platform/platform-impl/src/com/intellij/ui/JBTabsPaneImpl.java
+++ b/platform/platform-impl/src/com/intellij/ui/JBTabsPaneImpl.java
@@ -21,6 +21,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.ui.tabs.*;
import com.intellij.ui.tabs.impl.JBEditorTabs;
+import com.intellij.ui.tabs.impl.JBTabsImpl;
import com.intellij.ui.tabs.impl.TabLabel;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
@@ -34,8 +35,7 @@ import java.awt.event.MouseListener;
import java.util.concurrent.CopyOnWriteArraySet;
public class JBTabsPaneImpl implements TabbedPane, SwingConstants {
-
- private final JBTabs myTabs;
+ private final JBTabsImpl myTabs;
private final CopyOnWriteArraySet<ChangeListener> myListeners = new CopyOnWriteArraySet<ChangeListener>();
public JBTabsPaneImpl(@Nullable Project project, int tabPlacement, @NotNull Disposable parent) {
@@ -64,6 +64,9 @@ public class JBTabsPaneImpl implements TabbedPane, SwingConstants {
maxOffset++;
g2d.setPaint(UIUtil.getPanelBackground());
+ if (getFirstTabOffset() > 0) {
+ g2d.fillRect(clip.x, clip.y, clip.x + getFirstTabOffset() - 1, clip.y + maxLength - TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT);
+ }
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);
@@ -77,6 +80,7 @@ public class JBTabsPaneImpl implements TabbedPane, SwingConstants {
super.paintSelectionAndBorder(g2d);
}
};
+ myTabs.setFirstTabOffset(10);
myTabs.addListener(new TabsListener.Adapter() {
@Override
diff --git a/platform/platform-impl/src/com/intellij/ui/LibNotifyWrapper.java b/platform/platform-impl/src/com/intellij/ui/LibNotifyWrapper.java
index aac2e77982ba..e8c6f49f8088 100644
--- a/platform/platform-impl/src/com/intellij/ui/LibNotifyWrapper.java
+++ b/platform/platform-impl/src/com/intellij/ui/LibNotifyWrapper.java
@@ -49,6 +49,7 @@ class LibNotifyWrapper implements SystemNotificationsImpl.Notifier {
}
private final LibNotify myLibNotify;
+ private final String myIcon;
private LibNotifyWrapper() {
myLibNotify = (LibNotify)Native.loadLibrary("libnotify.so.4", LibNotify.class);
@@ -58,6 +59,9 @@ class LibNotifyWrapper implements SystemNotificationsImpl.Notifier {
throw new IllegalStateException("notify_init failed");
}
+ String icon = AppUIUtil.findIcon(PathManager.getBinPath());
+ myIcon = icon != null ? icon : "dialog-information";
+
MessageBusConnection connection = ApplicationManager.getApplication().getMessageBus().connect();
connection.subscribe(AppLifecycleListener.TOPIC, new AppLifecycleListener.Adapter() {
@Override
@@ -69,9 +73,7 @@ class LibNotifyWrapper implements SystemNotificationsImpl.Notifier {
@Override
public void notify(@NotNull Set<String> allNames, @NotNull String name, @NotNull String title, @NotNull String description) {
- String icon = AppUIUtil.findIcon(PathManager.getBinPath());
- if (icon == null) icon = "dialog-information";
- Pointer notification = myLibNotify.notify_notification_new(title, description, icon);
+ Pointer notification = myLibNotify.notify_notification_new(title, description, myIcon);
myLibNotify.notify_notification_show(notification, null);
}
}
diff --git a/platform/platform-impl/src/com/intellij/ui/SpeedSearchBase.java b/platform/platform-impl/src/com/intellij/ui/SpeedSearchBase.java
index c738995059dc..cbcde2d36418 100644
--- a/platform/platform-impl/src/com/intellij/ui/SpeedSearchBase.java
+++ b/platform/platform-impl/src/com/intellij/ui/SpeedSearchBase.java
@@ -288,6 +288,10 @@ public abstract class SpeedSearchBase<Comp extends JComponent> extends SpeedSear
return null;
}
+ public void showPopup() {
+ manageSearchPopup(new SearchPopup(""));
+ }
+
public void hidePopup() {
manageSearchPopup(null);
}
diff --git a/platform/platform-impl/src/com/intellij/ui/TableSpeedSearch.java b/platform/platform-impl/src/com/intellij/ui/TableSpeedSearch.java
index b596204e6ad2..eeeb90dc7ae7 100644
--- a/platform/platform-impl/src/com/intellij/ui/TableSpeedSearch.java
+++ b/platform/platform-impl/src/com/intellij/ui/TableSpeedSearch.java
@@ -20,7 +20,6 @@ import com.intellij.util.PairFunction;
import com.intellij.util.containers.Convertor;
import javax.swing.*;
-import javax.swing.table.TableModel;
import java.util.ListIterator;
public class TableSpeedSearch extends SpeedSearchBase<JTable> {
@@ -55,9 +54,8 @@ public class TableSpeedSearch extends SpeedSearchBase<JTable> {
@Override
protected boolean isSpeedSearchEnabled() {
- JTable table = getComponent();
- boolean tableIsNotEmpty = table.getRowCount() != 0 && table.getColumnCount() != 0;
- return tableIsNotEmpty && !table.isEditing() && super.isSpeedSearchEnabled();
+ boolean tableIsNotEmpty = myComponent.getRowCount() != 0 && myComponent.getColumnCount() != 0;
+ return tableIsNotEmpty && !myComponent.isEditing() && super.isSpeedSearchEnabled();
}
@Override
@@ -67,16 +65,14 @@ public class TableSpeedSearch extends SpeedSearchBase<JTable> {
@Override
protected int getElementCount() {
- final TableModel tableModel = myComponent.getModel();
- return tableModel.getRowCount() * tableModel.getColumnCount();
+ return myComponent.getRowCount() * myComponent.getColumnCount();
}
@Override
protected void selectElement(Object element, String selectedText) {
final int index = ((Integer)element).intValue();
- final TableModel model = myComponent.getModel();
- final int row = index / model.getColumnCount();
- final int col = index % model.getColumnCount();
+ final int row = index / myComponent.getColumnCount();
+ final int col = index % myComponent.getColumnCount();
myComponent.getSelectionModel().setSelectionInterval(row, row);
myComponent.getColumnModel().getSelectionModel().setSelectionInterval(col, col);
TableUtil.scrollSelectionToVisible(myComponent);
@@ -87,7 +83,7 @@ public class TableSpeedSearch extends SpeedSearchBase<JTable> {
final int row = myComponent.getSelectedRow();
final int col = myComponent.getSelectedColumn();
// selected row is not enough as we want to select specific cell in a large multi-column table
- return row > -1 && col > -1 ? row * myComponent.getModel().getColumnCount() + col : -1;
+ return row > -1 && col > -1 ? row * myComponent.getColumnCount() + col : -1;
}
@Override
@@ -98,10 +94,9 @@ public class TableSpeedSearch extends SpeedSearchBase<JTable> {
@Override
protected String getElementText(Object element) {
final int index = ((Integer)element).intValue();
- final TableModel model = myComponent.getModel();
- int row = myComponent.convertRowIndexToModel(index / model.getColumnCount());
- int col = myComponent.convertColumnIndexToModel(index % model.getColumnCount());
- Object value = model.getValueAt(row, col);
+ int row = index / myComponent.getColumnCount();
+ int col = index % myComponent.getColumnCount();
+ Object value = myComponent.getValueAt(row, col);
return myToStringConvertor.fun(value, new Cell(row, col));
}
diff --git a/platform/platform-impl/src/com/intellij/ui/content/impl/ContentImpl.java b/platform/platform-impl/src/com/intellij/ui/content/impl/ContentImpl.java
index 82dd6ff085fd..595a93db592f 100644
--- a/platform/platform-impl/src/com/intellij/ui/content/impl/ContentImpl.java
+++ b/platform/platform-impl/src/com/intellij/ui/content/impl/ContentImpl.java
@@ -1,6 +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.
@@ -45,7 +44,7 @@ public class ContentImpl extends UserDataHolderBase implements Content {
private JComponent myComponent;
private Icon myIcon;
private final PropertyChangeSupport myChangeSupport = new PropertyChangeSupport(this);
- private ContentManager myManager = null;
+ private ContentManager myManager;
private boolean myIsLocked = false;
private boolean myPinnable = true;
private Icon myLayeredIcon = new LayeredIcon(2);
@@ -294,6 +293,7 @@ public class ContentImpl extends UserDataHolderBase implements Content {
return myPlace;
}
+ @Override
@NonNls
public String toString() {
StringBuilder sb = new StringBuilder("Content name=").append(myDisplayName);
diff --git a/platform/platform-impl/src/com/intellij/ui/content/impl/ContentManagerImpl.java b/platform/platform-impl/src/com/intellij/ui/content/impl/ContentManagerImpl.java
index b6e739692ede..d0b110f083bf 100644
--- a/platform/platform-impl/src/com/intellij/ui/content/impl/ContentManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/ui/content/impl/ContentManagerImpl.java
@@ -15,6 +15,7 @@
*/
package com.intellij.ui.content.impl;
+import com.intellij.ide.DataManager;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.DataProvider;
@@ -32,13 +33,15 @@ import com.intellij.ui.components.panels.Wrapper;
import com.intellij.ui.content.*;
import com.intellij.ui.switcher.SwitchProvider;
import com.intellij.ui.switcher.SwitchTarget;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.SmartList;
+
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
-import javax.swing.event.EventListenerList;
import java.awt.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
@@ -55,21 +58,21 @@ public class ContentManagerImpl implements ContentManager, PropertyChangeListene
private static final Logger LOG = Logger.getInstance("#com.intellij.ui.content.impl.ContentManagerImpl");
private ContentUI myUI;
- private final ArrayList<Content> myContents;
- private EventListenerList myListeners;
- private List<Content> mySelection = new ArrayList<Content>();
+ private final List<Content> myContents = new ArrayList<Content>();
+ private final List<ContentManagerListener> myListeners = ContainerUtil.createLockFreeCopyOnWriteList();
+ private final List<Content> mySelection = new ArrayList<Content>();
private final boolean myCanCloseContents;
- private MyContentComponent myContentComponent;
- private MyFocusProxy myFocusProxy;
- private JPanel myComponent;
-
+ private Wrapper.FocusHolder myFocusProxy;
+ private MyNonOpaquePanel myComponent;
private final Set<Content> myContentWithChangedComponent = new HashSet<Content>();
private boolean myDisposed;
private final Project myProject;
+ private final List<DataProvider> dataProviders = new SmartList<DataProvider>();
+
/**
* WARNING: as this class adds listener to the ProjectManager which is removed on projectClosed event, all instances of this class
* must be created on already OPENED projects, otherwise there will be memory leak!
@@ -77,8 +80,6 @@ public class ContentManagerImpl implements ContentManager, PropertyChangeListene
public ContentManagerImpl(@NotNull ContentUI contentUI, boolean canCloseContents, @NotNull Project project) {
myProject = project;
myCanCloseContents = canCloseContents;
- myContents = new ArrayList<Content>();
- myListeners = new EventListenerList();
myUI = contentUI;
myUI.setManager(this);
@@ -95,15 +96,18 @@ public class ContentManagerImpl implements ContentManager, PropertyChangeListene
@Override
public JComponent getComponent() {
if (myComponent == null) {
- myComponent = new NonOpaquePanel(new BorderLayout());
+ myComponent = new MyNonOpaquePanel();
+
+ myFocusProxy = new Wrapper.FocusHolder();
+ myFocusProxy.setOpaque(false);
+ myFocusProxy.setPreferredSize(new Dimension(0, 0));
- myFocusProxy = new MyFocusProxy();
- myContentComponent = new MyContentComponent();
- myContentComponent.setContent(myUI.getComponent());
- myContentComponent.setFocusCycleRoot(true);
+ MyContentComponent contentComponent = new MyContentComponent();
+ contentComponent.setContent(myUI.getComponent());
+ contentComponent.setFocusCycleRoot(true);
myComponent.add(myFocusProxy, BorderLayout.NORTH);
- myComponent.add(myContentComponent, BorderLayout.CENTER);
+ myComponent.add(contentComponent, BorderLayout.CENTER);
}
return myComponent;
}
@@ -117,58 +121,51 @@ public class ContentManagerImpl implements ContentManager, PropertyChangeListene
return busyObject != null ? busyObject.getReady(requestor) : new ActionCallback.Done();
}
- private class MyContentComponent extends NonOpaquePanel implements DataProvider, SwitchProvider {
-
- private final List<DataProvider> myProviders = new ArrayList<DataProvider>();
-
- public void addProvider(final DataProvider provider) {
- myProviders.add(provider);
+ private class MyNonOpaquePanel extends NonOpaquePanel implements DataProvider {
+ public MyNonOpaquePanel() {
+ super(new BorderLayout());
}
@Override
@Nullable
- public Object getData(@NonNls final String dataId) {
- if (PlatformDataKeys.CONTENT_MANAGER.is(dataId)) return ContentManagerImpl.this;
- if (PlatformDataKeys.NONEMPTY_CONTENT_MANAGER.is(dataId) && getContentCount() > 1) {
+ public Object getData(@NonNls String dataId) {
+ if (PlatformDataKeys.CONTENT_MANAGER.is(dataId) || PlatformDataKeys.NONEMPTY_CONTENT_MANAGER.is(dataId) && getContentCount() > 1) {
return ContentManagerImpl.this;
}
- for (DataProvider each : myProviders) {
- final Object data = each.getData(dataId);
- if (data != null) return data;
+ for (DataProvider dataProvider : dataProviders) {
+ Object data = dataProvider.getData(dataId);
+ if (data != null) {
+ return data;
+ }
}
if (myUI instanceof DataProvider) {
return ((DataProvider)myUI).getData(dataId);
}
- return null;
+ DataProvider provider = DataManager.getDataProvider(this);
+ return provider == null ? null : provider.getData(dataId);
}
+ }
+ private class MyContentComponent extends NonOpaquePanel implements SwitchProvider {
@Override
public List<SwitchTarget> getTargets(boolean onlyVisible, boolean originalProvider) {
if (myUI instanceof SwitchProvider) {
return ((SwitchProvider)myUI).getTargets(onlyVisible, false);
}
- return new ArrayList<SwitchTarget>();
+ return new SmartList<SwitchTarget>();
}
@Override
public SwitchTarget getCurrentTarget() {
- if (myUI instanceof SwitchProvider) {
- return ((SwitchProvider)myUI).getCurrentTarget();
- }
-
- return null;
+ return myUI instanceof SwitchProvider ? ((SwitchProvider)myUI).getCurrentTarget() : null;
}
@Override
public JComponent getComponent() {
- if (myUI instanceof SwitchProvider) {
- return myUI.getComponent();
- }
-
- return this;
+ return myUI instanceof SwitchProvider ? myUI.getComponent() : this;
}
@Override
@@ -177,35 +174,23 @@ public class ContentManagerImpl implements ContentManager, PropertyChangeListene
}
}
- private class MyFocusProxy extends Wrapper.FocusHolder implements DataProvider {
- private MyFocusProxy() {
- setOpaque(false);
- setPreferredSize(new Dimension(0, 0));
- }
-
- @Override
- @Nullable
- public Object getData(@NonNls final String dataId) {
- return myContentComponent.getData(dataId);
- }
- }
-
@Override
public void addContent(@NotNull Content content, final int order) {
- addContent(content, null, order);
+ doAddContent(content, order);
}
@Override
public void addContent(@NotNull Content content) {
- addContent(content, null, -1);
+ doAddContent(content, -1);
}
@Override
public void addContent(@NotNull final Content content, final Object constraints) {
- addContent(content, constraints, -1);
+ doAddContent(content, -1);
}
- private void addContent(@NotNull final Content content, final Object constraints, final int index) {
+ private void doAddContent(@NotNull final Content content, final int index) {
+ ApplicationManager.getApplication().assertIsDispatchThread();
if (myContents.contains(content)) return;
((ContentImpl)content).setManager(this);
@@ -227,24 +212,26 @@ public class ContentManagerImpl implements ContentManager, PropertyChangeListene
@Override
public boolean removeContent(@NotNull Content content, final boolean dispose) {
- return removeContent(content, true, dispose);
+ return removeContent(content, true, dispose).isDone();
}
@NotNull
@Override
public ActionCallback removeContent(@NotNull Content content, boolean dispose, final boolean trackFocus, final boolean forcedFocus) {
final ActionCallback result = new ActionCallback();
- _removeContent(content, true, dispose).doWhenDone(new Runnable() {
+ removeContent(content, true, dispose).doWhenDone(new Runnable() {
@Override
public void run() {
if (trackFocus) {
Content current = getSelectedContent();
if (current != null) {
setSelectedContent(current, true, true, !forcedFocus);
- } else {
+ }
+ else {
result.setDone();
}
- } else {
+ }
+ else {
result.setDone();
}
}
@@ -253,11 +240,9 @@ public class ContentManagerImpl implements ContentManager, PropertyChangeListene
return result;
}
- private boolean removeContent(final Content content, boolean trackSelection, boolean dispose) {
- return _removeContent(content, trackSelection, dispose).isDone();
- }
-
- private ActionCallback _removeContent(Content content, boolean trackSelection, boolean dispose) {
+ @NotNull
+ private ActionCallback removeContent(@NotNull Content content, boolean trackSelection, boolean dispose) {
+ ApplicationManager.getApplication().assertIsDispatchThread();
int indexToBeRemoved = getIndexOfContent(content);
if (indexToBeRemoved == -1) return new ActionCallback.Rejected();
@@ -604,43 +589,39 @@ public class ContentManagerImpl implements ContentManager, PropertyChangeListene
@Override
public void addContentManagerListener(@NotNull ContentManagerListener l) {
- myListeners.add(ContentManagerListener.class, l);
+ myListeners.add(0,l);
}
@Override
public void removeContentManagerListener(@NotNull ContentManagerListener l) {
- myListeners.remove(ContentManagerListener.class, l);
+ myListeners.remove(l);
}
private void fireContentAdded(Content content, int newIndex, ContentManagerEvent.ContentOperation operation) {
ContentManagerEvent event = new ContentManagerEvent(this, content, newIndex, operation);
- ContentManagerListener[] listeners = myListeners.getListeners(ContentManagerListener.class);
- for (ContentManagerListener listener : listeners) {
+ for (ContentManagerListener listener : myListeners) {
listener.contentAdded(event);
}
}
private void fireContentRemoved(Content content, int oldIndex, ContentManagerEvent.ContentOperation operation) {
ContentManagerEvent event = new ContentManagerEvent(this, content, oldIndex, operation);
- ContentManagerListener[] listeners = myListeners.getListeners(ContentManagerListener.class);
- for (ContentManagerListener listener : listeners) {
+ for (ContentManagerListener listener : myListeners) {
listener.contentRemoved(event);
}
}
private void fireSelectionChanged(Content content, ContentManagerEvent.ContentOperation operation) {
ContentManagerEvent event = new ContentManagerEvent(this, content, myContents.indexOf(content), operation);
- ContentManagerListener[] listeners = myListeners.getListeners(ContentManagerListener.class);
- for (ContentManagerListener listener : listeners) {
+ for (ContentManagerListener listener : myListeners) {
listener.selectionChanged(event);
}
}
private boolean fireContentRemoveQuery(Content content, int oldIndex, ContentManagerEvent.ContentOperation operation) {
ContentManagerEvent event = new ContentManagerEvent(this, content, oldIndex, operation);
- ContentManagerListener[] listeners = myListeners.getListeners(ContentManagerListener.class);
- for (ContentManagerListener listener : listeners) {
+ for (ContentManagerListener listener : myListeners) {
listener.contentRemoveQuery(event);
if (event.isConsumed()) {
return false;
@@ -692,13 +673,13 @@ public class ContentManagerImpl implements ContentManager, PropertyChangeListene
@Override
public void addDataProvider(@NotNull final DataProvider provider) {
- myContentComponent.addProvider(provider);
+ dataProviders.add(provider);
}
@Override
- public void propertyChange(final PropertyChangeEvent evt) {
- if (Content.PROP_COMPONENT.equals(evt.getPropertyName())) {
- myContentWithChangedComponent.add((Content)evt.getSource());
+ public void propertyChange(@NotNull PropertyChangeEvent event) {
+ if (Content.PROP_COMPONENT.equals(event.getPropertyName())) {
+ myContentWithChangedComponent.add((Content)event.getSource());
}
}
@@ -718,10 +699,10 @@ public class ContentManagerImpl implements ContentManager, PropertyChangeListene
myDisposed = true;
myContents.clear();
- mySelection = null;
+ mySelection.clear();
myContentWithChangedComponent.clear();
myUI = null;
- myListeners = null;
+ myListeners.clear();
}
@Override
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 e50403abef45..a967245c9224 100644
--- a/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java
+++ b/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java
@@ -487,22 +487,24 @@ public class AbstractPopup implements JBPopup {
if (dominantArea != null) {
final Component focusedComponent = getWndManager().getFocusedComponent(myProject);
- Window window = SwingUtilities.windowForComponent(focusedComponent);
- JLayeredPane layeredPane;
- if (window instanceof JFrame) {
- layeredPane = ((JFrame)window).getLayeredPane();
- }
- else if (window instanceof JDialog) {
- layeredPane = ((JDialog)window).getLayeredPane();
- }
- else if (window instanceof JWindow) {
- layeredPane = ((JWindow)window).getLayeredPane();
- }
- else {
- throw new IllegalStateException("cannot find parent window: project=" + myProject + "; window=" + window);
- }
+ if (focusedComponent != null) {
+ Window window = SwingUtilities.windowForComponent(focusedComponent);
+ JLayeredPane layeredPane;
+ if (window instanceof JFrame) {
+ layeredPane = ((JFrame)window).getLayeredPane();
+ }
+ else if (window instanceof JDialog) {
+ layeredPane = ((JDialog)window).getLayeredPane();
+ }
+ else if (window instanceof JWindow) {
+ layeredPane = ((JWindow)window).getLayeredPane();
+ }
+ else {
+ throw new IllegalStateException("cannot find parent window: project=" + myProject + "; window=" + window);
+ }
- return relativePointWithDominantRectangle(layeredPane, dominantArea);
+ return relativePointWithDominantRectangle(layeredPane, dominantArea);
+ }
}
return JBPopupFactory.getInstance().guessBestPopupLocation(dataContext);
@@ -777,7 +779,9 @@ public class AbstractPopup implements JBPopup {
Rectangle original = new Rectangle(targetBounds);
if (myLocateWithinScreen) {
- ScreenUtil.moveRectangleToFitTheScreen(targetBounds);
+ if (myMovable) {
+ ScreenUtil.moveRectangleToFitTheScreen(targetBounds);
+ }
}
if (myMouseOutCanceller != null) {
diff --git a/platform/platform-impl/src/com/intellij/ui/popup/list/PopupListElementRenderer.java b/platform/platform-impl/src/com/intellij/ui/popup/list/PopupListElementRenderer.java
index 5d657487f6a5..1428ffc9b29d 100644
--- a/platform/platform-impl/src/com/intellij/ui/popup/list/PopupListElementRenderer.java
+++ b/platform/platform-impl/src/com/intellij/ui/popup/list/PopupListElementRenderer.java
@@ -16,7 +16,7 @@
package com.intellij.ui.popup.list;
import com.intellij.icons.AllIcons;
-import com.intellij.openapi.ui.popup.ListItemDescriptor;
+import com.intellij.openapi.ui.popup.ListItemDescriptorAdapter;
import com.intellij.openapi.ui.popup.ListPopupStep;
import com.intellij.ui.ColorUtil;
import com.intellij.util.ui.UIUtil;
@@ -27,18 +27,13 @@ public class PopupListElementRenderer extends GroupedItemsListRenderer {
private final ListPopupImpl myPopup;
public PopupListElementRenderer(final ListPopupImpl aPopup) {
- super(new ListItemDescriptor() {
+ super(new ListItemDescriptorAdapter() {
@Override
public String getTextFor(Object value) {
return aPopup.getListStep().getTextFor(value);
}
@Override
- public String getTooltipFor(Object value) {
- return null;
- }
-
- @Override
public Icon getIconFor(Object value) {
return aPopup.getListStep().getIconFor(value);
}
diff --git a/platform/platform-impl/src/icons/PlatformImplIcons.java b/platform/platform-impl/src/icons/PlatformImplIcons.java
new file mode 100644
index 000000000000..87dd75428d01
--- /dev/null
+++ b/platform/platform-impl/src/icons/PlatformImplIcons.java
@@ -0,0 +1,28 @@
+package icons;
+
+import com.intellij.openapi.util.IconLoader;
+
+import javax.swing.*;
+
+/**
+ * NOTE THIS FILE IS AUTO-GENERATED
+ * DO NOT EDIT IT BY HAND, run build/scripts/icons.gant instead
+ */
+public class PlatformImplIcons {
+ private static Icon load(String path) {
+ return IconLoader.getIcon(path, PlatformImplIcons.class);
+ }
+
+ public static final Icon Android = load("/icons/plugins/Android.png"); // 48x48
+ public static final Icon ApplicationServers = load("/icons/plugins/ApplicationServers.png"); // 48x48
+ public static final Icon BuildTools = load("/icons/plugins/BuildTools.png"); // 48x48
+ public static final Icon Clouds = load("/icons/plugins/Clouds.png"); // 48x48
+ public static final Icon DatabaseTools = load("/icons/plugins/DatabaseTools.png"); // 48x48
+ public static final Icon JavaFrameworks = load("/icons/plugins/JavaFrameworks.png"); // 48x48
+ public static final Icon OtherTools = load("/icons/plugins/OtherTools.png"); // 48x48
+ public static final Icon PluginDevelopment = load("/icons/plugins/PluginDevelopment.png"); // 48x48
+ public static final Icon Swing = load("/icons/plugins/Swing.png"); // 48x48
+ public static final Icon TestTools = load("/icons/plugins/TestTools.png"); // 48x48
+ public static final Icon VersionControls = load("/icons/plugins/VersionControls.png"); // 48x48
+ public static final Icon WebDevelopment = load("/icons/plugins/WebDevelopment.png"); // 48x48
+}
diff --git a/community-resources/src/plugins/Android.png b/platform/platform-impl/src/icons/plugins/Android.png
index 9d55c0e3409c..9d55c0e3409c 100644
--- a/community-resources/src/plugins/Android.png
+++ b/platform/platform-impl/src/icons/plugins/Android.png
Binary files differ
diff --git a/community-resources/src/plugins/Android@2x.png b/platform/platform-impl/src/icons/plugins/Android@2x.png
index e3d989db2b55..e3d989db2b55 100644
--- a/community-resources/src/plugins/Android@2x.png
+++ b/platform/platform-impl/src/icons/plugins/Android@2x.png
Binary files differ
diff --git a/community-resources/src/plugins/ApplicationServers.png b/platform/platform-impl/src/icons/plugins/ApplicationServers.png
index a6195b804f61..a6195b804f61 100644
--- a/community-resources/src/plugins/ApplicationServers.png
+++ b/platform/platform-impl/src/icons/plugins/ApplicationServers.png
Binary files differ
diff --git a/community-resources/src/plugins/ApplicationServers@2x.png b/platform/platform-impl/src/icons/plugins/ApplicationServers@2x.png
index d6901f88646d..d6901f88646d 100644
--- a/community-resources/src/plugins/ApplicationServers@2x.png
+++ b/platform/platform-impl/src/icons/plugins/ApplicationServers@2x.png
Binary files differ
diff --git a/community-resources/src/plugins/BuildTools.png b/platform/platform-impl/src/icons/plugins/BuildTools.png
index c16226fb628f..c16226fb628f 100644
--- a/community-resources/src/plugins/BuildTools.png
+++ b/platform/platform-impl/src/icons/plugins/BuildTools.png
Binary files differ
diff --git a/community-resources/src/plugins/BuildTools@2x.png b/platform/platform-impl/src/icons/plugins/BuildTools@2x.png
index ecd58cfeab83..ecd58cfeab83 100644
--- a/community-resources/src/plugins/BuildTools@2x.png
+++ b/platform/platform-impl/src/icons/plugins/BuildTools@2x.png
Binary files differ
diff --git a/community-resources/src/plugins/Clouds.png b/platform/platform-impl/src/icons/plugins/Clouds.png
index 9da8c7f39dea..9da8c7f39dea 100644
--- a/community-resources/src/plugins/Clouds.png
+++ b/platform/platform-impl/src/icons/plugins/Clouds.png
Binary files differ
diff --git a/community-resources/src/plugins/Clouds@2x.png b/platform/platform-impl/src/icons/plugins/Clouds@2x.png
index 5338f618e25d..5338f618e25d 100644
--- a/community-resources/src/plugins/Clouds@2x.png
+++ b/platform/platform-impl/src/icons/plugins/Clouds@2x.png
Binary files differ
diff --git a/community-resources/src/plugins/DatabaseTools.png b/platform/platform-impl/src/icons/plugins/DatabaseTools.png
index 459b90ed30bd..459b90ed30bd 100644
--- a/community-resources/src/plugins/DatabaseTools.png
+++ b/platform/platform-impl/src/icons/plugins/DatabaseTools.png
Binary files differ
diff --git a/community-resources/src/plugins/DatabaseTools@2x.png b/platform/platform-impl/src/icons/plugins/DatabaseTools@2x.png
index 8b7fbbf33005..8b7fbbf33005 100644
--- a/community-resources/src/plugins/DatabaseTools@2x.png
+++ b/platform/platform-impl/src/icons/plugins/DatabaseTools@2x.png
Binary files differ
diff --git a/community-resources/src/plugins/JavaFrameworks.png b/platform/platform-impl/src/icons/plugins/JavaFrameworks.png
index 1ba077ca27ca..1ba077ca27ca 100644
--- a/community-resources/src/plugins/JavaFrameworks.png
+++ b/platform/platform-impl/src/icons/plugins/JavaFrameworks.png
Binary files differ
diff --git a/community-resources/src/plugins/JavaFrameworks@2x.png b/platform/platform-impl/src/icons/plugins/JavaFrameworks@2x.png
index 1b9e872bd758..1b9e872bd758 100644
--- a/community-resources/src/plugins/JavaFrameworks@2x.png
+++ b/platform/platform-impl/src/icons/plugins/JavaFrameworks@2x.png
Binary files differ
diff --git a/platform/platform-impl/src/icons/plugins/OtherTools.png b/platform/platform-impl/src/icons/plugins/OtherTools.png
new file mode 100644
index 000000000000..eabbc4bc32d5
--- /dev/null
+++ b/platform/platform-impl/src/icons/plugins/OtherTools.png
Binary files differ
diff --git a/community-resources/src/plugins/OtherTools@2x.png b/platform/platform-impl/src/icons/plugins/OtherTools@2x.png
index fa3b2021761a..fa3b2021761a 100644
--- a/community-resources/src/plugins/OtherTools@2x.png
+++ b/platform/platform-impl/src/icons/plugins/OtherTools@2x.png
Binary files differ
diff --git a/community-resources/src/plugins/PluginDevelopment.png b/platform/platform-impl/src/icons/plugins/PluginDevelopment.png
index 68a4a9ccf205..68a4a9ccf205 100644
--- a/community-resources/src/plugins/PluginDevelopment.png
+++ b/platform/platform-impl/src/icons/plugins/PluginDevelopment.png
Binary files differ
diff --git a/community-resources/src/plugins/PluginDevelopment@2x.png b/platform/platform-impl/src/icons/plugins/PluginDevelopment@2x.png
index f02ae30b598d..f02ae30b598d 100644
--- a/community-resources/src/plugins/PluginDevelopment@2x.png
+++ b/platform/platform-impl/src/icons/plugins/PluginDevelopment@2x.png
Binary files differ
diff --git a/community-resources/src/plugins/Swing.png b/platform/platform-impl/src/icons/plugins/Swing.png
index f0b032a73105..f0b032a73105 100644
--- a/community-resources/src/plugins/Swing.png
+++ b/platform/platform-impl/src/icons/plugins/Swing.png
Binary files differ
diff --git a/community-resources/src/plugins/Swing@2x.png b/platform/platform-impl/src/icons/plugins/Swing@2x.png
index a0712688ac8c..a0712688ac8c 100644
--- a/community-resources/src/plugins/Swing@2x.png
+++ b/platform/platform-impl/src/icons/plugins/Swing@2x.png
Binary files differ
diff --git a/community-resources/src/plugins/TestTools.png b/platform/platform-impl/src/icons/plugins/TestTools.png
index 9d79fa47ea6b..9d79fa47ea6b 100644
--- a/community-resources/src/plugins/TestTools.png
+++ b/platform/platform-impl/src/icons/plugins/TestTools.png
Binary files differ
diff --git a/community-resources/src/plugins/TestTools@2x.png b/platform/platform-impl/src/icons/plugins/TestTools@2x.png
index 95af9f268ef4..95af9f268ef4 100644
--- a/community-resources/src/plugins/TestTools@2x.png
+++ b/platform/platform-impl/src/icons/plugins/TestTools@2x.png
Binary files differ
diff --git a/community-resources/src/plugins/VersionControls.png b/platform/platform-impl/src/icons/plugins/VersionControls.png
index be676163e539..be676163e539 100644
--- a/community-resources/src/plugins/VersionControls.png
+++ b/platform/platform-impl/src/icons/plugins/VersionControls.png
Binary files differ
diff --git a/community-resources/src/plugins/VersionControls@2x.png b/platform/platform-impl/src/icons/plugins/VersionControls@2x.png
index 427637d7848b..427637d7848b 100644
--- a/community-resources/src/plugins/VersionControls@2x.png
+++ b/platform/platform-impl/src/icons/plugins/VersionControls@2x.png
Binary files differ
diff --git a/community-resources/src/plugins/WebDevelopment.png b/platform/platform-impl/src/icons/plugins/WebDevelopment.png
index d9e7430921de..d9e7430921de 100644
--- a/community-resources/src/plugins/WebDevelopment.png
+++ b/platform/platform-impl/src/icons/plugins/WebDevelopment.png
Binary files differ
diff --git a/community-resources/src/plugins/WebDevelopment@2x.png b/platform/platform-impl/src/icons/plugins/WebDevelopment@2x.png
index 52f6be48c8a5..52f6be48c8a5 100644
--- a/community-resources/src/plugins/WebDevelopment@2x.png
+++ b/platform/platform-impl/src/icons/plugins/WebDevelopment@2x.png
Binary files differ
diff --git a/platform/platform-resources-en/src/messages/ActionsBundle.properties b/platform/platform-resources-en/src/messages/ActionsBundle.properties
index 47c4cef92207..50500e895c48 100644
--- a/platform/platform-resources-en/src/messages/ActionsBundle.properties
+++ b/platform/platform-resources-en/src/messages/ActionsBundle.properties
@@ -939,6 +939,7 @@ action.Debugger.Inspect.text=Inspect
action.Debugger.CopyValue.text=Copy Value
action.Debugger.ViewText.text=View Text
action.Debugger.ViewText.description=View text value of selected node in a separate pane
+action.Debugger.ShowReferring.text=Show Referring Objects
action.Debugger.CompareValueWithClipboard.text=Compare Value with Clipboard
action.Debugger.CompareValueWithClipboard.description=Compare value of selected node with clipboard text
action.Debugger.CustomizeContextView.text=Customize Data Views...
diff --git a/platform/platform-resources-en/src/messages/ApplicationBundle.properties b/platform/platform-resources-en/src/messages/ApplicationBundle.properties
index 5d539357ca3d..75d0f242e38c 100644
--- a/platform/platform-resources-en/src/messages/ApplicationBundle.properties
+++ b/platform/platform-resources-en/src/messages/ApplicationBundle.properties
@@ -360,7 +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:
+editbox.tab.title.limit=Tab title limit (characters):
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/ExecutionBundle.properties b/platform/platform-resources-en/src/messages/ExecutionBundle.properties
index 155e2b6c6d74..183dda3d52b8 100644
--- a/platform/platform-resources-en/src/messages/ExecutionBundle.properties
+++ b/platform/platform-resources-en/src/messages/ExecutionBundle.properties
@@ -171,6 +171,7 @@ terminating.process.progress.kill=Kill process
waiting.for.vm.detach.progress.text=Waiting for process detach
restart.error.message.title=Restart Error
rerun.configuration.action.name=Rerun ''{0}''
+stop.configuration.action.name=Stop ''{0}''
rerun.singleton.confirmation.message=''{0}'' is single-instance run configuration.\nAre you sure you want to stop {1, choice, 1#the running one|2#{1, number} running instances}?
rerun.confirmation.button.text=Stop and Rerun
rerun.confirmation.checkbox=Confirm rerun with process termination
diff --git a/platform/platform-resources-en/src/messages/FindBundle.properties b/platform/platform-resources-en/src/messages/FindBundle.properties
index 8a857db74fd0..067ef38e17f6 100644
--- a/platform/platform-resources-en/src/messages/FindBundle.properties
+++ b/platform/platform-resources-en/src/messages/FindBundle.properties
@@ -134,4 +134,5 @@ find.scope.custom.radio=Cu&stom:
find.usages.ambiguous.title=Find Usages Of {0}
0.occurrences.replaced={0,choice,0#No|1#{0}} {0,choice,0#occurrences|1#occurrence|2#occurrences} replaced
found.occurrences=Found Occurrences
-occurrence=occurrence \ No newline at end of file
+occurrence=occurrence
+results.options.group=Result options \ No newline at end of file
diff --git a/platform/platform-resources-en/src/messages/InspectionsBundle.properties b/platform/platform-resources-en/src/messages/InspectionsBundle.properties
index 40940d687471..a339716f031e 100644
--- a/platform/platform-resources-en/src/messages/InspectionsBundle.properties
+++ b/platform/platform-resources-en/src/messages/InspectionsBundle.properties
@@ -667,7 +667,7 @@ unused.library.roots.problem.descriptor=Unused roots {0} from library ''{1}''
unused.library.backward.analysis.job.description=Perform backward analysis
inspection.duplicates.option.report.propertykey.expressions=&Ignore @PropertyKey expressions
inspection.same.parameter.fix.name=Inline value ''{1}'' for parameter ''{0}''
-fix.all.inspection.problems.in.file=Fix all ''{0}'' problems
+fix.all.inspection.problems.in.file=Fix all ''{0}'' problems in file
cleanup.in.file=Cleanup code
cleanup.in.scope=Cleanup code on...
severities.default.settings.message=Edit Settings|Colors \\& Fonts
diff --git a/platform/platform-resources-en/src/messages/OptionsBundle.properties b/platform/platform-resources-en/src/messages/OptionsBundle.properties
index aa2d1047c66e..2a78c19bdd82 100644
--- a/platform/platform-resources-en/src/messages/OptionsBundle.properties
+++ b/platform/platform-resources-en/src/messages/OptionsBundle.properties
@@ -198,6 +198,8 @@ options.xml.display.name=XML
settings.panel.title=Settings
+node.configurable.build.tools.display.name=Build Tools
+
configurable.group.appearance.settings.display.name=Appearance and Behavior
configurable.group.editor.settings.display.name=Editor
configurable.group.project.settings.display.name=Current Project
diff --git a/platform/platform-resources-en/src/messages/RefactoringBundle.properties b/platform/platform-resources-en/src/messages/RefactoringBundle.properties
index 080dce748805..48d0e63d60c0 100644
--- a/platform/platform-resources-en/src/messages/RefactoringBundle.properties
+++ b/platform/platform-resources-en/src/messages/RefactoringBundle.properties
@@ -438,6 +438,7 @@ inline.command=Inline {0}
inline.local.variable.prompt=Inline local variable ''{0}''?
inline.local.variable.definition.prompt=Inline local variable ''{0}'' definition?
occurences.string=({0,choice,1#1 occurrence|2#{0,number} occurrences})
+occurrences.string=({0,choice,1#1 occurrence|2#{0,number} occurrences})
inline.method.title=Inline Method
inline.method.method.label=Method {0}
inline.method.border.title=Inline
diff --git a/platform/platform-resources/src/META-INF/LangExtensions.xml b/platform/platform-resources/src/META-INF/LangExtensions.xml
index aaae5ddfab28..c338dac9848b 100644
--- a/platform/platform-resources/src/META-INF/LangExtensions.xml
+++ b/platform/platform-resources/src/META-INF/LangExtensions.xml
@@ -166,8 +166,7 @@
<applicationService serviceInterface="com.intellij.util.download.DownloadableFileService"
serviceImplementation="com.intellij.util.download.impl.DownloadableFileServiceImpl"/>
- <applicationService serviceInterface="com.intellij.psi.impl.DocumentCommitThread"
- serviceImplementation="com.intellij.psi.impl.DocumentCommitThread"/>
+ <applicationService serviceImplementation="com.intellij.psi.impl.DocumentCommitThread"/>
<applicationService serviceInterface="com.intellij.psi.stubs.StubTreeLoader"
serviceImplementation="com.intellij.psi.stubs.StubTreeLoaderImpl"/>
@@ -614,7 +613,7 @@
<editorCustomization implementation="com.intellij.ui.RightMarginEditorCustomization"/>
<!-- Colors & Fonts-->
- <editorOptionsProvider instance="com.intellij.application.options.colors.ColorAndFontOptions"
+ <applicationConfigurable groupId="editor" dynamic="true" instance="com.intellij.application.options.colors.ColorAndFontOptions"
id="reference.settingsdialog.IDE.editor.colors"/>
<editorOptionsProvider instance="com.intellij.application.options.editor.EditorTabsConfigurable" id="editor.preferences.tabs"
displayName="Editor Tabs"/>
@@ -652,6 +651,7 @@
<editorActionHandler action="EditorEnter" implementationClass="com.intellij.codeInsight.editorActions.EnterHandler" id="editorEnter"/>
<editorActionHandler action="EditorLineEnd" implementationClass="com.intellij.codeInsight.editorActions.EndHandler"/>
<editorActionHandler action="EditorSelectWord" implementationClass="com.intellij.codeInsight.editorActions.SelectWordHandler"/>
+ <editorActionHandler action="EditorSelectWord" implementationClass="com.intellij.openapi.editor.actions.SelectWordAtCaretAction$Handler" order="first"/>
<editorActionHandler action="EditorUnSelectWord" implementationClass="com.intellij.codeInsight.editorActions.UnSelectWordHandler"/>
<editorActionHandler action="EditorPaste" implementationClass="com.intellij.codeInsight.editorActions.PasteHandler"/>
<editorActionHandler action="EditorCopy" implementationClass="com.intellij.codeInsight.editorActions.CopyHandler"/>
@@ -825,7 +825,7 @@
<defaultHighlightingSettingProvider implementation="com.intellij.codeInsight.daemon.impl.analysis.GeneratedSourcesHighlightingSettingProvider"/>
<editorNotificationProvider implementation="com.intellij.ide.GeneratedFileEditingNotificationProvider"/>
- <editorTabTitleProvider implementation="com.intellij.openapi.fileEditor.impl.UniqueNameEditorTabTitleProvider"/>
+ <editorTabTitleProvider implementation="com.intellij.openapi.fileEditor.impl.UniqueNameEditorTabTitleProvider" order="last"/>
<projectService serviceInterface="com.intellij.psi.util.PsiModificationTracker"
serviceImplementation="com.intellij.psi.impl.PsiModificationTrackerImpl"/>
@@ -889,6 +889,8 @@
<editorOptionsProvider id="editing.postfixCompletion" instance="com.intellij.codeInsight.template.postfix.settings.PostfixTemplatesConfigurable"/>
<completion.contributor language="any" implementationClass="com.intellij.codeInsight.template.postfix.completion.PostfixTemplateCompletionContributor"/>
+ <projectService serviceInterface="com.intellij.execution.ExecutionManager" serviceImplementation="com.intellij.execution.impl.ExecutionManagerImpl"/>
+ <projectService serviceInterface="com.intellij.execution.ExecutionTargetManager" serviceImplementation="com.intellij.execution.ExecutionTargetManagerImpl"/>
</extensions>
</idea-plugin>
diff --git a/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml b/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml
index e8a45edbf138..a4dfd49a71a8 100644
--- a/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml
+++ b/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml
@@ -230,6 +230,8 @@
<with attribute="implementationClass" implements="com.intellij.codeInsight.template.postfix.templates.PostfixTemplateProvider"/>
</extensionPoint>
+ <extensionPoint name="editor.linePainter" interface="com.intellij.openapi.editor.EditorLinePainter"/>
+
<extensionPoint name="actionFromOptionDescriptorProvider" interface="com.intellij.ide.ui.search.ActionFromOptionDescriptorProvider"/>
</extensionPoints>
</idea-plugin>
diff --git a/platform/platform-resources/src/META-INF/PlatformExtensions.xml b/platform/platform-resources/src/META-INF/PlatformExtensions.xml
index 7aa76abcd4f8..467ef8233919 100644
--- a/platform/platform-resources/src/META-INF/PlatformExtensions.xml
+++ b/platform/platform-resources/src/META-INF/PlatformExtensions.xml
@@ -239,6 +239,10 @@
<applicationService serviceInterface="com.intellij.ui.ColorChooserService"
serviceImplementation="com.intellij.ui.ColorChooserServiceImpl"/>
+ <applicationService serviceInterface="com.intellij.openapi.actionSystem.AbbreviationManager"
+ serviceImplementation="com.intellij.openapi.actionSystem.impl.AbbreviationManagerImpl"/>
+ <exportable serviceInterface="com.intellij.openapi.actionSystem.AbbreviationManager"/>
+
<scopeParserExtension implementation="com.intellij.psi.search.scope.packageSet.FilePackageSetParserExtension"/>
<applicationService serviceInterface="com.intellij.openapi.ui.popup.StackingPopupDispatcher" serviceImplementation="com.intellij.ui.popup.StackingPopupDispatcherImpl"/>
diff --git a/platform/platform-resources/src/META-INF/PlatformLangPlugin.xml b/platform/platform-resources/src/META-INF/PlatformLangPlugin.xml
index b7a11c39ecae..ea14882e5ae6 100644
--- a/platform/platform-resources/src/META-INF/PlatformLangPlugin.xml
+++ b/platform/platform-resources/src/META-INF/PlatformLangPlugin.xml
@@ -101,5 +101,8 @@
<xi:include href="/META-INF/vcs-log-graph.xml" xpointer="xpointer(/idea-plugin/*)">
<xi:fallback/>
</xi:include>
+ <xi:include href="/META-INF/dvcs.xml" xpointer="xpointer(/idea-plugin/*)">
+ <xi:fallback/>
+ </xi:include>
</idea-plugin>
diff --git a/platform/platform-resources/src/META-INF/PlatformPlugin.xml b/platform/platform-resources/src/META-INF/PlatformPlugin.xml
index db1cae3e76aa..773b00c2b9f2 100644
--- a/platform/platform-resources/src/META-INF/PlatformPlugin.xml
+++ b/platform/platform-resources/src/META-INF/PlatformPlugin.xml
@@ -10,6 +10,9 @@
<xi:include href="/META-INF/vcs-log-graph.xml" xpointer="xpointer(/idea-plugin/*)">
<xi:fallback/>
</xi:include>
+ <xi:include href="/META-INF/dvcs.xml" xpointer="xpointer(/idea-plugin/*)">
+ <xi:fallback/>
+ </xi:include>
<extensionPoints>
<xi:include href="/META-INF/PlatformExtensionPoints.xml" xpointer="xpointer(/idea-plugin/extensionPoints/*)"/>
diff --git a/platform/platform-resources/src/META-INF/xdebugger.xml b/platform/platform-resources/src/META-INF/xdebugger.xml
index 4b03978f9473..4dde33287f0c 100644
--- a/platform/platform-resources/src/META-INF/xdebugger.xml
+++ b/platform/platform-resources/src/META-INF/xdebugger.xml
@@ -36,6 +36,7 @@
<xdebugger.debuggerSupport implementation="com.intellij.xdebugger.impl.XDebuggerSupport" order="first"/>
<xdebugger.configurableProvider implementation="com.intellij.xdebugger.impl.settings.XDebuggerConfigurableProvider" order="first"/>
+ <editor.linePainter implementation="com.intellij.xdebugger.impl.evaluate.XDebuggerEditorLinePainter"/>
<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 57b863fb916b..7b0830e86b02 100644
--- a/platform/platform-resources/src/brokenPlugins.txt
+++ b/platform/platform-resources/src/brokenPlugins.txt
@@ -1,18 +1,19 @@
// 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.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
+NodeJS 138.1189 138.1145 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.1161 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 7.0.0.20140707
+org.jetbrains.plugins.ruby 6.0.0.20140207 6.5.2.20140512 7.0.0.20140704 7.0.0.20140707 7.0.0.20140724
Pythonid 3.1 4.0.25
Karma 138.21 134.1163 134.1039 134.686 134.31
-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.intellij.scala 0.42.23 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
"JSTestDriver Plugin" 138.21 136.1141 134.1163 134.686 134.31 134.307 134.1039
AngularJS 134.1094 0.1.8 0.1.9
org.jetbrains.plugins.vagrant 0.1 0.2
-org.intellij.clojure 0.2.1.178 \ No newline at end of file
+org.intellij.clojure 0.2.1.178
+net.nicoulaj.idea.markdown 0.9.6 0.9.5 0.9.4 0.9.3 0.9.2 0.9.1 0.8.3 0.8.2 0.8.1 0.8 0.7 0.6.1 0.6 0.5.1 0.5 0.4 0.3 0.2 0.1
diff --git a/platform/platform-resources/src/componentSets/Execution.xml b/platform/platform-resources/src/componentSets/Execution.xml
index 829135bbb0b2..6f548daa692b 100644
--- a/platform/platform-resources/src/componentSets/Execution.xml
+++ b/platform/platform-resources/src/componentSets/Execution.xml
@@ -18,17 +18,7 @@
<loadForDefaultProject/>
</component>
<component>
- <interface-class>com.intellij.execution.ExecutionTargetManager</interface-class>
- <implementation-class>com.intellij.execution.ExecutionTargetManagerImpl</implementation-class>
- <option name="workspace" value="true"/>
- <loadForDefaultProject/>
- </component>
- <component>
<implementation-class>com.intellij.execution.impl.ProjectRunConfigurationManager</implementation-class>
</component>
- <component>
- <interface-class>com.intellij.execution.ExecutionManager</interface-class>
- <implementation-class>com.intellij.execution.impl.ExecutionManagerImpl</implementation-class>
- </component>
</project-components>
-</components> \ No newline at end of file
+</components>
diff --git a/platform/platform-resources/src/componentSets/UICore.xml b/platform/platform-resources/src/componentSets/UICore.xml
index 8d7d5d63e055..6d2b09835c8c 100644
--- a/platform/platform-resources/src/componentSets/UICore.xml
+++ b/platform/platform-resources/src/componentSets/UICore.xml
@@ -14,10 +14,6 @@
<headless-implementation-class>com.intellij.idea.CommandLineApplication$MyDataManagerImpl</headless-implementation-class>
</component>
<component>
- <interface-class>com.intellij.openapi.actionSystem.AbbreviationManager</interface-class>
- <implementation-class>com.intellij.openapi.actionSystem.impl.AbbreviationManagerImpl</implementation-class>
- </component>
- <component>
<interface-class>com.intellij.openapi.actionSystem.ActionManager</interface-class>
<implementation-class>com.intellij.openapi.actionSystem.impl.ActionManagerImpl</implementation-class>
</component>
diff --git a/platform/platform-resources/src/idea/LangActions.xml b/platform/platform-resources/src/idea/LangActions.xml
index 65fa309fe3b9..3b0289f12433 100644
--- a/platform/platform-resources/src/idea/LangActions.xml
+++ b/platform/platform-resources/src/idea/LangActions.xml
@@ -364,6 +364,7 @@
<separator/>
<reference id="NavBarToolBarOthers"/>
<separator/>
+ <reference ref="SearchEverywhere"/>
</group>
<group id="Bookmarks">
@@ -697,6 +698,7 @@
</group>
<group id="XDebugger.ToolWindow.LeftToolbar">
+ <reference ref="Rerun"/>
<reference ref="Resume"/>
<reference ref="Pause"/>
<reference ref="Stop"/>
diff --git a/platform/platform-resources/src/idea/PlatformActions.xml b/platform/platform-resources/src/idea/PlatformActions.xml
index 869a8a754886..7773a2b00e49 100644
--- a/platform/platform-resources/src/idea/PlatformActions.xml
+++ b/platform/platform-resources/src/idea/PlatformActions.xml
@@ -457,6 +457,7 @@
</group>
<separator/>
<reference ref="HelpTopics"/>
+ <reference ref="SearchEverywhere"/>
</group>
<group id="NavBarVcsGroup"/>
@@ -580,8 +581,8 @@
<action id="MaintenanceAction" class="com.intellij.ide.actions.MaintenanceAction"/>
<group id="MaintenanceGroup">
- <action id="UiDebugger" class="com.intellij.ui.debugger.ShowUiDebuggerAction"/>
<action id="ShowRegistry" class="com.intellij.openapi.util.registry.ShowRegistryAction"/>
+ <action id="UiDebugger" class="com.intellij.ui.debugger.ShowUiDebuggerAction"/>
</group>
<action id="Console.Execute" class="com.intellij.openapi.actionSystem.EmptyAction"/>
diff --git a/platform/platform-tests/testSrc/com/intellij/execution/process/AnsiEscapeDecoderTest.java b/platform/platform-tests/testSrc/com/intellij/execution/process/AnsiEscapeDecoderTest.java
new file mode 100644
index 000000000000..32ec00d1a733
--- /dev/null
+++ b/platform/platform-tests/testSrc/com/intellij/execution/process/AnsiEscapeDecoderTest.java
@@ -0,0 +1,55 @@
+package com.intellij.execution.process;
+
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.Pair;
+import com.intellij.testFramework.PlatformTestCase;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.junit.Assert;
+
+import java.util.List;
+
+public class AnsiEscapeDecoderTest extends PlatformTestCase {
+
+ public void testTextWithoutColors() throws Exception {
+ AnsiEscapeDecoder decoder = new AnsiEscapeDecoder();
+ decoder.escapeText("", ProcessOutputTypes.STDOUT, createExpectedAcceptor(ContainerUtil.newArrayList(
+ Pair.create("", ProcessOutputTypes.STDOUT)
+ )));
+ decoder.escapeText("simple text", ProcessOutputTypes.STDOUT, createExpectedAcceptor(ContainerUtil.newArrayList(
+ Pair.create("simple text", ProcessOutputTypes.STDOUT)
+ )));
+ }
+
+ public void testSingleColoredChunk() throws Exception {
+ AnsiEscapeDecoder decoder = new AnsiEscapeDecoder();
+ decoder.escapeText("Chrome 35.0.1916 (Linux): Executed 0 of 1\u001B[32m SUCCESS\u001B[39m (0 secs / 0 secs)\n", ProcessOutputTypes.STDOUT, createExpectedAcceptor(ContainerUtil.newArrayList(
+ Pair.create("Chrome 35.0.1916 (Linux): Executed 0 of 1", ProcessOutputTypes.STDOUT),
+ Pair.create(" SUCCESS", ColoredOutputTypeRegistry.getInstance().getOutputKey("\u001B[32m")),
+ Pair.create(" (0 secs / 0 secs)\n", ColoredOutputTypeRegistry.getInstance().getOutputKey("\u001B[39m"))
+ )));
+ }
+
+ public void testCompoundEscSeq() throws Exception {
+ AnsiEscapeDecoder decoder = new AnsiEscapeDecoder();
+ decoder.escapeText("E\u001B[41m\u001B[37mE\u001B[0mE", ProcessOutputTypes.STDOUT, createExpectedAcceptor(ContainerUtil.newArrayList(
+ Pair.create("E", ProcessOutputTypes.STDOUT),
+ Pair.create("E", ColoredOutputTypeRegistry.getInstance().getOutputKey("\u001B[41;37m")),
+ Pair.create("E", ProcessOutputTypes.STDOUT)
+ )));
+ }
+
+ private static AnsiEscapeDecoder.ColoredChunksAcceptor createExpectedAcceptor(@NotNull final List<Pair<String, Key>> expected) {
+ return new AnsiEscapeDecoder.ColoredChunksAcceptor() {
+ @Override
+ public void coloredChunksAvailable(List<Pair<String, Key>> chunks) {
+ Assert.assertEquals(expected, chunks);
+ }
+
+ @Override
+ public void coloredTextAvailable(String text, Key attributes) {
+ throw new RuntimeException(); // shouldn't be called
+ }
+ };
+ }
+}
diff --git a/platform/platform-tests/testSrc/com/intellij/history/integration/ui/LocalHistoryActionsTest.java b/platform/platform-tests/testSrc/com/intellij/history/integration/ui/LocalHistoryActionsTest.java
index 6ba1e4aa12de..bbcbe9b4c2f2 100644
--- a/platform/platform-tests/testSrc/com/intellij/history/integration/ui/LocalHistoryActionsTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/history/integration/ui/LocalHistoryActionsTest.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,11 +20,7 @@ import com.intellij.history.integration.TestVirtualFile;
import com.intellij.history.integration.ui.actions.LocalHistoryAction;
import com.intellij.history.integration.ui.actions.ShowHistoryAction;
import com.intellij.history.integration.ui.actions.ShowSelectionHistoryAction;
-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.actionSystem.PlatformDataKeys;
+import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.EditorFactory;
@@ -135,6 +131,6 @@ public class LocalHistoryActionsTest extends LocalHistoryUITestCase {
return null;
}
};
- return new AnActionEvent(null, dc, "", a.getTemplatePresentation(), null, -1);
+ return new AnActionEvent(null, dc, "", a.getTemplatePresentation(), ActionManager.getInstance(), -1);
}
}
diff --git a/platform/platform-tests/testSrc/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterKeyPasswordSafeTest.java b/platform/platform-tests/testSrc/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterKeyPasswordSafeTest.java
index 0e2355f5c3c1..a84497a8f083 100644
--- a/platform/platform-tests/testSrc/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterKeyPasswordSafeTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/ide/passwordSafe/impl/providers/masterKey/MasterKeyPasswordSafeTest.java
@@ -28,13 +28,13 @@ public class MasterKeyPasswordSafeTest {
@Test
public void testMasterKey() throws PasswordSafeException {
PasswordDatabase db = new PasswordDatabase();
- MasterKeyPasswordSafe s1 = testProvider(db);
+ MasterKeyPasswordSafe s1 = new MasterKeyPasswordSafe(db);
s1.resetMasterPassword("pass1", false);
s1.storePassword(null, MasterKeyPasswordSafeTest.class, "TEST", "test");
assertEquals("test", s1.getPassword(null, MasterKeyPasswordSafeTest.class, "TEST"));
assertTrue(s1.changeMasterPassword("pass1", "pass2", false));
assertEquals("test", s1.getPassword(null, MasterKeyPasswordSafeTest.class, "TEST"));
- MasterKeyPasswordSafe s2 = testProvider(db);
+ MasterKeyPasswordSafe s2 = new MasterKeyPasswordSafe(db);
assertFalse(s2.setMasterPassword("pass1"));
assertTrue(s2.setMasterPassword("pass2"));
assertEquals("test", s2.getPassword(null, MasterKeyPasswordSafeTest.class, "TEST"));
@@ -45,19 +45,4 @@ public class MasterKeyPasswordSafeTest {
s2.resetMasterPassword("fail", false);
assertNull(s2.getPassword(null, MasterKeyPasswordSafeTest.class, "TEST"));
}
-
- /**
- * Get test instance of the provider
- * @param db the database to use
- * @return a instance of the provider
- */
- private static MasterKeyPasswordSafe testProvider(final PasswordDatabase db) {
- return new MasterKeyPasswordSafe(db) {
- @Override
- protected boolean isTestMode() {
- return true;
- }
- };
- }
-
}
diff --git a/platform/platform-tests/testSrc/com/intellij/ide/util/treeView/TreeUiTest.java b/platform/platform-tests/testSrc/com/intellij/ide/util/treeView/TreeUiTest.java
index 92b2ebad945c..99c6f5b5d25a 100644
--- a/platform/platform-tests/testSrc/com/intellij/ide/util/treeView/TreeUiTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/ide/util/treeView/TreeUiTest.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,7 +15,6 @@
*/
package com.intellij.ide.util.treeView;
-import com.intellij.openapi.diagnostic.Log;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.Progressive;
@@ -2753,22 +2752,6 @@ public class TreeUiTest extends AbstractTreeBuilderTest {
return suite;
}
- @Override
- protected void tearDown() throws Exception {
- AbstractTreeUi ui = getBuilder().getUi();
- if (ui != null) {
- ui.getReady(this).doWhenProcessed(new Runnable() {
- @Override
- public void run() {
- Log.flush();
- }
- });
- } else {
- Log.flush();
- }
- super.tearDown();
- }
-
private abstract static class MyRunnable implements Runnable {
@Override
public final void run() {
diff --git a/platform/platform-tests/testSrc/com/intellij/psi/PsiDocumentManagerImplTest.java b/platform/platform-tests/testSrc/com/intellij/psi/impl/PsiDocumentManagerImplTest.java
index 2ab0446e86a4..b1ab5117dba9 100644
--- a/platform/platform-tests/testSrc/com/intellij/psi/PsiDocumentManagerImplTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/psi/impl/PsiDocumentManagerImplTest.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.intellij.psi;
+package com.intellij.psi.impl;
import com.intellij.ide.impl.ProjectUtil;
import com.intellij.mock.MockDocument;
@@ -27,8 +27,9 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ex.ProjectManagerEx;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.impl.DebugUtil;
-import com.intellij.psi.impl.PsiDocumentManagerImpl;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiManager;
import com.intellij.psi.impl.source.PsiFileImpl;
import com.intellij.testFramework.LeakHunter;
import com.intellij.testFramework.LightVirtualFile;
@@ -46,6 +47,13 @@ public class PsiDocumentManagerImplTest extends PlatformLangTestCase {
return (PsiDocumentManagerImpl)PsiDocumentManager.getInstance(getProject());
}
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ DocumentCommitThread.getInstance();
+ UIUtil.dispatchAllInvocationEvents();
+ }
+
public void testGetCachedPsiFile_NoFile() throws Exception {
final PsiFile file = getPsiDocumentManager().getCachedPsiFile(new MockDocument());
assertNull(file);
@@ -367,4 +375,23 @@ public class PsiDocumentManagerImplTest extends PlatformLangTestCase {
ProjectUtil.closeAndDispose(alienProject);
}
}
+
+ public void testCommitThreadGetSuspendedDuringWriteActions() {
+ final DocumentCommitThread commitThread = DocumentCommitThread.getInstance();
+ assertTrue(commitThread.isEnabled());
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
+ @Override
+ public void run() {
+ assertFalse(commitThread.isEnabled());
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
+ @Override
+ public void run() {
+ assertFalse(commitThread.isEnabled());
+ }
+ });
+ assertFalse(commitThread.isEnabled());
+ }
+ });
+ assertTrue(commitThread.isEnabled());
+ }
}
diff --git a/platform/platform-tests/testSrc/com/intellij/ui/tabs/impl/JBTabsDemo.java b/platform/platform-tests/testSrc/com/intellij/ui/tabs/impl/JBTabsDemo.java
index 4544a7e547f1..1f3f1a8a248d 100644
--- a/platform/platform-tests/testSrc/com/intellij/ui/tabs/impl/JBTabsDemo.java
+++ b/platform/platform-tests/testSrc/com/intellij/ui/tabs/impl/JBTabsDemo.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,6 +16,7 @@
package com.intellij.ui.tabs.impl;
import com.intellij.icons.AllIcons;
+import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.IconLoader;
@@ -46,7 +47,7 @@ public class JBTabsDemo {
final JFrame frame = new JFrame();
frame.getContentPane().setLayout(new BorderLayout(0, 0));
final int[] count = new int[1];
- final JBTabsImpl tabs = new JBTabsImpl(null, null, null, Disposer.newDisposable());
+ final JBTabsImpl tabs = new JBTabsImpl(null, ActionManager.getInstance(), null, Disposer.newDisposable());
tabs.setTestMode(true);
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 17a7abc2a694..fdae3317e74e 100644
--- a/platform/projectModel-api/src/com/intellij/openapi/roots/ProjectFileIndex.java
+++ b/platform/projectModel-api/src/com/intellij/openapi/roots/ProjectFileIndex.java
@@ -49,6 +49,16 @@ public interface ProjectFileIndex extends FileIndex {
Module getModuleForFile(@NotNull VirtualFile file);
/**
+ * Returns module to which the specified file belongs.
+ *
+ * @param file the file for which the module is requested.
+ * @param honorExclusion if {@code false} the containing module will be returned even if the file is located under a folder marked as excluded
+ * @return the module instance or null if the file does not belong to content of any module.
+ */
+ @Nullable
+ Module getModuleForFile(@NotNull VirtualFile file, boolean honorExclusion);
+
+ /**
* Returns the order entries which contain the specified file (either in CLASSES or SOURCES).
*
* @param file the file for which the order entries are requested.
@@ -88,6 +98,16 @@ public interface ProjectFileIndex extends FileIndex {
VirtualFile getContentRootForFile(@NotNull VirtualFile file);
/**
+ * Returns the module content root to which the specified file or directory belongs.
+ *
+ * @param file the file or directory for which the information is requested.
+ * @param honorExclusion if {@code false} the containing content root will be returned even if the file is located under a folder marked as excluded
+ * @return the file for the content root, or null if the file does not belong to this project.
+ */
+ @Nullable
+ VirtualFile getContentRootForFile(@NotNull VirtualFile file, final boolean honorExclusion);
+
+ /**
* Returns the name of the package corresponding to the specified directory.
*
* @param dir the directory for which the package name is requested.
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 e87d3c749b10..70eb213d86c8 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,7 +17,6 @@
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;
@@ -26,8 +25,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
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";
@@ -65,10 +62,4 @@ public abstract class DirectoryIndex {
@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/ModuleFileIndexImpl.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ModuleFileIndexImpl.java
index 8140a3c15211..eb8a9ddf5587 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
@@ -18,17 +18,18 @@ package com.intellij.openapi.roots.impl;
import com.intellij.openapi.fileTypes.FileTypeRegistry;
import com.intellij.openapi.module.Module;
-import com.intellij.openapi.roots.ContentIterator;
-import com.intellij.openapi.roots.ModuleFileIndex;
-import com.intellij.openapi.roots.ModuleRootManager;
-import com.intellij.openapi.roots.OrderEntry;
+import com.intellij.openapi.roots.*;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileFilter;
+import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.model.java.JavaModuleSourceRootTypes;
import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
import java.util.Set;
@@ -79,12 +80,12 @@ public class ModuleFileIndexImpl extends FileIndexBase implements ModuleFileInde
@Override
@NotNull
public List<OrderEntry> getOrderEntriesForFile(@NotNull VirtualFile fileOrDir) {
- return myDirectoryIndex.findAllOrderEntriesWithOwnerModule(getInfoForFileOrDirectory(fileOrDir), myModule);
+ return findAllOrderEntriesWithOwnerModule(myModule, myDirectoryIndex.getOrderEntries(getInfoForFileOrDirectory(fileOrDir)));
}
@Override
public OrderEntry getOrderEntryForFile(@NotNull VirtualFile fileOrDir) {
- return myDirectoryIndex.findOrderEntryWithOwnerModule(getInfoForFileOrDirectory(fileOrDir), myModule);
+ return findOrderEntryWithOwnerModule(myModule, myDirectoryIndex.getOrderEntries(getInfoForFileOrDirectory(fileOrDir)));
}
@Override
@@ -100,6 +101,97 @@ public class ModuleFileIndexImpl extends FileIndexBase implements ModuleFileInde
return info.isInModuleSource() && myModule.equals(info.getModule()) && rootTypes.contains(myDirectoryIndex.getSourceRootType(info));
}
+ @Nullable
+ static OrderEntry findOrderEntryWithOwnerModule(@NotNull Module ownerModule, @NotNull OrderEntry[] orderEntries) {
+ if (orderEntries.length < 10) {
+ for (OrderEntry entry : orderEntries) {
+ if (entry.getOwnerModule() == ownerModule) return entry;
+ }
+ return null;
+ }
+ int index = Arrays.binarySearch(orderEntries, new FakeOrderEntry(ownerModule), RootIndex.BY_OWNER_MODULE);
+ return index < 0 ? null : orderEntries[index];
+ }
+
+ @NotNull
+ private static List<OrderEntry> findAllOrderEntriesWithOwnerModule(@NotNull Module ownerModule, @NotNull OrderEntry[] entries) {
+ 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, new FakeOrderEntry(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);
+ }
+
+ private static class FakeOrderEntry implements OrderEntry {
+ private final Module myOwnerModule;
+
+ public FakeOrderEntry(Module ownerModule) {
+ myOwnerModule = ownerModule;
+ }
+
+ @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 myOwnerModule;
+ }
+
+ @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();
+ }
+ }
+
private class ContentFilter implements VirtualFileFilter {
@Override
public boolean accept(@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 e2417193149e..aec6e11a6d15 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
@@ -30,6 +30,7 @@ import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileFilter;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.model.java.JavaModuleSourceRootTypes;
import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
@@ -91,10 +92,18 @@ public class ProjectFileIndexImpl extends FileIndexBase implements ProjectFileIn
@Override
public Module getModuleForFile(@NotNull VirtualFile file) {
+ return getModuleForFile(file, true);
+ }
+
+ @Nullable
+ @Override
+ public Module getModuleForFile(@NotNull VirtualFile file, boolean honorExclusion) {
if (file instanceof VirtualFileWindow) file = ((VirtualFileWindow)file).getDelegate();
DirectoryInfo info = getInfoForFileOrDirectory(file);
- if (!info.isInProject()) return null;
- return info.getModule();
+ if (info.isInProject() || !honorExclusion && info.isExcluded()) {
+ return info.getModule();
+ }
+ return null;
}
@Override
@@ -119,9 +128,16 @@ public class ProjectFileIndexImpl extends FileIndexBase implements ProjectFileIn
@Override
public VirtualFile getContentRootForFile(@NotNull VirtualFile file) {
+ return getContentRootForFile(file, true);
+ }
+
+ @Override
+ public VirtualFile getContentRootForFile(@NotNull VirtualFile file, final boolean honorExclusion) {
final DirectoryInfo info = getInfoForFileOrDirectory(file);
- if (!info.isInProject()) return null;
- return info.getContentRoot();
+ if (info.isInProject() || !honorExclusion && info.isExcluded()) {
+ return info.getContentRoot();
+ }
+ return null;
}
@Override
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 eb04fb6c103e..bc85dabc9aec 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
@@ -497,10 +497,11 @@ public class RootIndex {
}
@Nullable
- private Module findParentModuleForExcluded(@NotNull List<VirtualFile> hierarchy) {
+ private VirtualFile findNearestContentRootForExcluded(@NotNull List<VirtualFile> hierarchy) {
for (VirtualFile root : hierarchy) {
- Module module = contentRootOf.get(root);
- if (module != null) return module;
+ if (contentRootOf.containsKey(root)) {
+ return root;
+ }
}
return null;
}
@@ -604,10 +605,14 @@ public class RootIndex {
VirtualFile moduleContentRoot = info.findModuleRootInfo(hierarchy);
VirtualFile libraryClassRoot = info.findLibraryRootInfo(hierarchy, false);
VirtualFile librarySourceRoot = info.findLibraryRootInfo(hierarchy, true);
- Module parentModuleForExcluded = null;
- if (moduleContentRoot == null && libraryClassRoot == null && librarySourceRoot == null) {
- parentModuleForExcluded = info.findParentModuleForExcluded(hierarchy);
- if (parentModuleForExcluded == null) {
+ boolean inProject = moduleContentRoot != null || libraryClassRoot != null || librarySourceRoot != null;
+ VirtualFile nearestContentRoot;
+ if (inProject) {
+ nearestContentRoot = moduleContentRoot;
+ }
+ else {
+ nearestContentRoot = info.findNearestContentRootForExcluded(hierarchy);
+ if (nearestContentRoot == null) {
return new Pair<DirectoryInfo, String>(NonProjectDirectoryInfo.EXCLUDED, null);
}
}
@@ -619,10 +624,9 @@ public class RootIndex {
boolean inLibrarySource = librarySourceRoot != null;
int typeId = moduleSourceRoot != null ? info.rootTypeId.get(moduleSourceRoot) : 0;
- Module module = parentModuleForExcluded != null ? parentModuleForExcluded : info.contentRootOf.get(moduleContentRoot);
+ Module module = info.contentRootOf.get(nearestContentRoot);
DirectoryInfo directoryInfo =
- new DirectoryInfoImpl(root, module, moduleContentRoot, sourceRoot, libraryClassRoot, inModuleSources, inLibrarySource,
- parentModuleForExcluded != null, typeId);
+ new DirectoryInfoImpl(root, module, nearestContentRoot, sourceRoot, libraryClassRoot, inModuleSources, inLibrarySource, !inProject, typeId);
String packagePrefix = info.calcPackagePrefix(root, hierarchy, moduleContentRoot, libraryClassRoot, librarySourceRoot);
diff --git a/platform/remote-servers/agent-rt/src/com/intellij/remoteServer/agent/util/CloudAgentLoggingHandler.java b/platform/remote-servers/agent-rt/src/com/intellij/remoteServer/agent/util/CloudAgentLoggingHandler.java
index 3dae58e59bb9..7055bace613b 100644
--- a/platform/remote-servers/agent-rt/src/com/intellij/remoteServer/agent/util/CloudAgentLoggingHandler.java
+++ b/platform/remote-servers/agent-rt/src/com/intellij/remoteServer/agent/util/CloudAgentLoggingHandler.java
@@ -15,10 +15,14 @@
*/
package com.intellij.remoteServer.agent.util;
+import com.intellij.remoteServer.agent.util.log.LogListener;
+
/**
* @author michael.golubev
*/
public interface CloudAgentLoggingHandler {
void println(String message);
+
+ LogListener getOrCreateLogListener(String pipeName);
}
diff --git a/platform/remote-servers/agent-rt/src/com/intellij/remoteServer/agent/util/CloudAgentWithDeployment.java b/platform/remote-servers/agent-rt/src/com/intellij/remoteServer/agent/util/CloudAgentWithDeployment.java
index 27533ffd1bb8..cf76eaa5216a 100644
--- a/platform/remote-servers/agent-rt/src/com/intellij/remoteServer/agent/util/CloudAgentWithDeployment.java
+++ b/platform/remote-servers/agent-rt/src/com/intellij/remoteServer/agent/util/CloudAgentWithDeployment.java
@@ -21,10 +21,9 @@ import com.intellij.remoteServer.agent.annotation.ChildCall;
* @author michael.golubev
*/
public interface CloudAgentWithDeployment<Config extends CloudAgentConfig,
- DeploymentConfig extends CloudAgentDeploymentConfig,
- LoggingHandler extends CloudAgentLoggingHandler>
+ DeploymentConfig extends CloudAgentDeploymentConfig>
extends CloudAgentBase<Config> {
@ChildCall
- CloudAgentDeployment createDeployment(DeploymentConfig config, LoggingHandler loggingHandler);
+ CloudAgentDeployment createDeployment(DeploymentConfig config, CloudAgentLoggingHandler loggingHandler);
}
diff --git a/platform/remote-servers/agent-rt/src/com/intellij/remoteServer/agent/util/CloudGitAgent.java b/platform/remote-servers/agent-rt/src/com/intellij/remoteServer/agent/util/CloudGitAgent.java
index cc9867477c7e..bc30b0bce2c8 100644
--- a/platform/remote-servers/agent-rt/src/com/intellij/remoteServer/agent/util/CloudGitAgent.java
+++ b/platform/remote-servers/agent-rt/src/com/intellij/remoteServer/agent/util/CloudGitAgent.java
@@ -29,5 +29,5 @@ public interface CloudGitAgent<C extends CloudAgentConfigBase, D extends CloudGi
void disconnect();
@ChildCall
- D createDeployment(String deploymentName, CloudLoggingHandler loggingHandler);
+ D createDeployment(String deploymentName, CloudAgentLoggingHandler loggingHandler);
}
diff --git a/platform/remote-servers/agent-rt/src/com/intellij/remoteServer/agent/util/log/LogListener.java b/platform/remote-servers/agent-rt/src/com/intellij/remoteServer/agent/util/log/LogListener.java
index 564402b19797..06e2896e7867 100644
--- a/platform/remote-servers/agent-rt/src/com/intellij/remoteServer/agent/util/log/LogListener.java
+++ b/platform/remote-servers/agent-rt/src/com/intellij/remoteServer/agent/util/log/LogListener.java
@@ -20,11 +20,11 @@ package com.intellij.remoteServer.agent.util.log;
*/
public interface LogListener {
- void lineLogged(String line, String deploymentName, String kind);
+ void lineLogged(String line);
LogListener NULL = new LogListener() {
- public void lineLogged(String line, String deploymentName, String kind) {
+ public void lineLogged(String line) {
}
};
diff --git a/platform/remote-servers/agent-rt/src/com/intellij/remoteServer/agent/util/log/LogPipe.java b/platform/remote-servers/agent-rt/src/com/intellij/remoteServer/agent/util/log/LogPipe.java
index 0b7bb1cf77a3..f56fe0940e65 100644
--- a/platform/remote-servers/agent-rt/src/com/intellij/remoteServer/agent/util/log/LogPipe.java
+++ b/platform/remote-servers/agent-rt/src/com/intellij/remoteServer/agent/util/log/LogPipe.java
@@ -30,16 +30,14 @@ public abstract class LogPipe {
private final ILogger myLog;
private final String myDeploymentName;
- private final String myKind;
private boolean myClosed;
private int myTotalLines;
private int myLines2Skip;
- public LogPipe(String deploymentName, String logKind, ILogger log) {
+ public LogPipe(String deploymentName, ILogger log) {
myDeploymentName = deploymentName;
- myKind = logKind;
myLog = log;
myClosed = false;
}
@@ -73,7 +71,7 @@ public abstract class LogPipe {
}
if (myLines2Skip == 0) {
- getLogListener().lineLogged(line, myDeploymentName, myKind);
+ getLogListener().lineLogged(line);
myTotalLines++;
}
else {
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudGitApplicationRuntime.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudGitApplicationRuntime.java
index 990167d951e4..5f40b5ac4257 100644
--- a/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudGitApplicationRuntime.java
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudGitApplicationRuntime.java
@@ -20,8 +20,8 @@ import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Ref;
+import com.intellij.remoteServer.agent.util.CloudAgentLoggingHandler;
import com.intellij.remoteServer.agent.util.CloudGitAgentDeployment;
-import com.intellij.remoteServer.agent.util.CloudLoggingHandler;
import com.intellij.remoteServer.runtime.deployment.DeploymentLogManager;
import com.intellij.util.ThrowableRunnable;
import org.jetbrains.annotations.NotNull;
@@ -31,7 +31,7 @@ public class CloudGitApplicationRuntime extends CloudApplicationRuntime {
private final CloudMultiSourceServerRuntimeInstance myServerRuntime;
private final DeploymentLogManager myLogManager;
- private final CloudLoggingHandler myLoggingHandler;
+ private final CloudAgentLoggingHandler myLoggingHandler;
private final CloudGitAgentDeployment myDeployment;
@@ -53,7 +53,7 @@ public class CloudGitApplicationRuntime extends CloudApplicationRuntime {
return myLogManager;
}
- protected CloudLoggingHandler getLoggingHandler() {
+ protected CloudAgentLoggingHandler getLoggingHandler() {
return myLoggingHandler;
}
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudLoggingHandlerImpl.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudLoggingHandlerImpl.java
index c816daceb859..346bd0af3046 100644
--- a/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudLoggingHandlerImpl.java
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudLoggingHandlerImpl.java
@@ -15,7 +15,7 @@
*/
package com.intellij.remoteServer.util;
-import com.intellij.remoteServer.agent.util.CloudLoggingHandler;
+import com.intellij.remoteServer.agent.util.CloudAgentLoggingHandler;
import com.intellij.remoteServer.agent.util.log.LogListener;
import com.intellij.remoteServer.runtime.deployment.DeploymentLogManager;
import com.intellij.remoteServer.runtime.log.LoggingHandler;
@@ -25,7 +25,7 @@ import java.util.HashMap;
/**
* @author michael.golubev
*/
-public class CloudLoggingHandlerImpl implements CloudLoggingHandler {
+public class CloudLoggingHandlerImpl implements CloudAgentLoggingHandler {
private final HashMap<String, LogListener> myPipeName2LogListener;
@@ -52,7 +52,7 @@ public class CloudLoggingHandlerImpl implements CloudLoggingHandler {
logListener = new LogListener() {
@Override
- public void lineLogged(String line, String deploymentName, String kind) {
+ public void lineLogged(String line) {
loggingHandler.print(line + "\n");
}
};
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudSilentLoggingHandlerImpl.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudSilentLoggingHandlerImpl.java
index 69bcbdadfb7c..49321fdfc398 100644
--- a/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudSilentLoggingHandlerImpl.java
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudSilentLoggingHandlerImpl.java
@@ -1,13 +1,13 @@
package com.intellij.remoteServer.util;
import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.remoteServer.agent.util.CloudLoggingHandler;
+import com.intellij.remoteServer.agent.util.CloudAgentLoggingHandler;
import com.intellij.remoteServer.agent.util.log.LogListener;
/**
* @author michael.golubev
*/
-public class CloudSilentLoggingHandlerImpl implements CloudLoggingHandler {
+public class CloudSilentLoggingHandlerImpl implements CloudAgentLoggingHandler {
private static final Logger LOG = Logger.getInstance("#" + CloudSilentLoggingHandlerImpl.class.getName());
diff --git a/platform/script-debugger/backend/src/org/jetbrains/rpc/MessageManager.java b/platform/script-debugger/backend/src/org/jetbrains/rpc/MessageManager.java
index 54fd4c023bd1..f7a29497e1c2 100644
--- a/platform/script-debugger/backend/src/org/jetbrains/rpc/MessageManager.java
+++ b/platform/script-debugger/backend/src/org/jetbrains/rpc/MessageManager.java
@@ -124,7 +124,10 @@ public final class MessageManager<OUTGOING, INCOMING, INCOMING_WITH_SEQ, SUCCESS
Arrays.sort(keys);
for (int key : keys) {
try {
- map.get(key).onError("Connection closed", null);
+ AsyncResultCallback<SUCCESS, ERROR_DETAILS> callback = map.get(key);
+ if (callback != null) {
+ callback.onError("Connection closed", null);
+ }
}
catch (Throwable e) {
LOG.error("Failed to reject callback on connection closed", e);
diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java
index 632be05a09b5..d0850c9eef85 100644
--- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java
+++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java
@@ -23,6 +23,7 @@ import com.intellij.execution.testframework.sm.runner.states.*;
import com.intellij.execution.testframework.sm.runner.ui.TestsPresentationUtil;
import com.intellij.execution.ui.ConsoleViewContentType;
import com.intellij.ide.util.EditSourceUtil;
+import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
@@ -30,6 +31,7 @@ import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.pom.Navigatable;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.testIntegration.TestLocationProvider;
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.ContainerUtilRt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -202,9 +204,10 @@ public class SMTestProxy extends AbstractTestProxy {
myState.getMagnitude() == TestStateInfo.Magnitude.PASSED_INDEX;
}
- public void addChild(final SMTestProxy child) {
+ public void addChild(@NotNull SMTestProxy child) {
+ ApplicationManager.getApplication().assertIsDispatchThread();
if (myChildren == null) {
- myChildren = new ArrayList<SMTestProxy>();
+ myChildren = ContainerUtil.newArrayListWithCapacity(4);
}
myChildren.add(child);
@@ -641,8 +644,7 @@ public class SMTestProxy extends AbstractTestProxy {
// test - no matter what we will return
myIsEmpty = true;
myIsEmptyIsCached = true;
-
- return myIsEmpty;
+ return true;
}
myIsEmpty = true;
diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/StructuralSearchProfile.java b/platform/structuralsearch/source/com/intellij/structuralsearch/StructuralSearchProfile.java
index e40683dce04e..bd3d773f26f5 100644
--- a/platform/structuralsearch/source/com/intellij/structuralsearch/StructuralSearchProfile.java
+++ b/platform/structuralsearch/source/com/intellij/structuralsearch/StructuralSearchProfile.java
@@ -184,9 +184,13 @@ public abstract class StructuralSearchProfile {
return element.getClass();
}
+ @NotNull
public String getTypedVarString(PsiElement element) {
if (element instanceof PsiNamedElement) {
- return ((PsiNamedElement)element).getName();
+ final String name = ((PsiNamedElement)element).getName();
+ if (name != null) {
+ return name;
+ }
}
return element.getText();
}
diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/StructuralSearchProfileBase.java b/platform/structuralsearch/source/com/intellij/structuralsearch/StructuralSearchProfileBase.java
index 9e9496115809..47222f932714 100644
--- a/platform/structuralsearch/source/com/intellij/structuralsearch/StructuralSearchProfileBase.java
+++ b/platform/structuralsearch/source/com/intellij/structuralsearch/StructuralSearchProfileBase.java
@@ -176,6 +176,7 @@ public abstract class StructuralSearchProfileBase extends StructuralSearchProfil
return false;
}
+ @NotNull
@Override
public String getTypedVarString(PsiElement element) {
final PsiElement initialElement = element;
@@ -480,10 +481,7 @@ public abstract class StructuralSearchProfileBase extends StructuralSearchProfil
private void visitLiteral(PsiElement literal) {
String value = literal.getText();
- if (value.length() > 2 &&
- (value.charAt(0) == '"' && value.charAt(value.length() - 1) == '"') ||
- (value.charAt(0) == '\'' && value.charAt(value.length() - 1) == '\'')) {
-
+ if (StringUtil.isQuotedString(value)) {
if (mySubstitutionPatterns == null) {
final String[] prefixes = myGlobalVisitor.getContext().getPattern().getTypedVarPrefixes();
mySubstitutionPatterns = createPatterns(prefixes);
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 70c1cdccd03e..55aa79bfcf0b 100644
--- a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/CompiledPattern.java
+++ b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/CompiledPattern.java
@@ -12,6 +12,7 @@ import com.intellij.structuralsearch.impl.matcher.handlers.MatchingHandler;
import com.intellij.structuralsearch.impl.matcher.handlers.SimpleHandler;
import com.intellij.structuralsearch.impl.matcher.handlers.SubstitutionHandler;
import com.intellij.structuralsearch.impl.matcher.strategies.MatchingStrategy;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
@@ -82,7 +83,7 @@ public abstract class CompiledPattern {
public boolean isRealTypedVar(PsiElement element) {
if (element!=null && element.getTextLength()>0) {
String str = getTypedVarString(element);
- if (str == null || str.length()==0) {
+ if (str.length() == 0) {
return false;
}
return isTypedVar( str );
@@ -91,6 +92,7 @@ public abstract class CompiledPattern {
}
}
+ @NotNull
public String getTypedVarString(PsiElement element) {
final StructuralSearchProfile profile = StructuralSearchUtil.getProfileByPsiElement(element);
if (profile == null) {
diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/CompileContext.java b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/CompileContext.java
index 09758a5e2191..f28e83b7ad1c 100644
--- a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/CompileContext.java
+++ b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/CompileContext.java
@@ -41,10 +41,6 @@ public class CompileContext {
return searchHelper;
}
- void setSearchHelper(OptimizingSearchHelper searchHelper) {
- this.searchHelper = searchHelper;
- }
-
public CompiledPattern getPattern() {
return pattern;
}
diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/FindInFilesOptimizingSearchHelper.java b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/FindInFilesOptimizingSearchHelper.java
index ff7f06a36d5b..c2fa05fef149 100644
--- a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/FindInFilesOptimizingSearchHelper.java
+++ b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/FindInFilesOptimizingSearchHelper.java
@@ -3,7 +3,6 @@ package com.intellij.structuralsearch.impl.matcher.compiler;
import com.intellij.lang.Language;
import com.intellij.lang.LanguageNamesValidation;
import com.intellij.lang.refactoring.NamesValidator;
-import com.intellij.lexer.Lexer;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.LanguageFileType;
import com.intellij.openapi.project.Project;
@@ -22,7 +21,6 @@ class FindInFilesOptimizingSearchHelper extends OptimizingSearchHelperBase {
private PsiSearchHelper helper;
private THashMap<PsiFile,PsiFile> filesToScan;
private THashMap<PsiFile,PsiFile> filesToScan2;
- private Lexer javaLexer;
private final boolean findMatchingFiles;
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 6dba855121cb..07808d33c003 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
@@ -10,10 +10,7 @@ import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.LanguageFileType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiErrorElement;
-import com.intellij.psi.PsiFile;
-import com.intellij.psi.PsiRecursiveElementWalkingVisitor;
+import com.intellij.psi.*;
import com.intellij.psi.impl.source.PsiFileImpl;
import com.intellij.psi.impl.source.tree.LeafElement;
import com.intellij.psi.search.GlobalSearchScope;
@@ -26,6 +23,7 @@ import com.intellij.structuralsearch.impl.matcher.MatcherImplUtil;
import com.intellij.structuralsearch.impl.matcher.PatternTreeContext;
import com.intellij.structuralsearch.impl.matcher.filters.LexicalNodesFilter;
import com.intellij.structuralsearch.impl.matcher.handlers.MatchPredicate;
+import com.intellij.structuralsearch.impl.matcher.handlers.MatchingHandler;
import com.intellij.structuralsearch.impl.matcher.handlers.SubstitutionHandler;
import com.intellij.structuralsearch.impl.matcher.predicates.*;
import com.intellij.structuralsearch.plugin.ui.Configuration;
@@ -73,7 +71,9 @@ public class PatternCompiler {
List<PsiElement> elements = compileByAllPrefixes(project, options, result, context, prefixes);
- context.getPattern().setNodes(elements);
+ final CompiledPattern pattern = context.getPattern();
+ checkForUnknownVariables(pattern, elements);
+ pattern.setNodes(elements);
if (context.getSearchHelper().doOptimizing() && context.getSearchHelper().isScannedSomething()) {
final Set<PsiFile> set = context.getSearchHelper().getFilesSetToScan();
@@ -105,6 +105,28 @@ public class PatternCompiler {
return result;
}
+ private static void checkForUnknownVariables(final CompiledPattern pattern, List<PsiElement> elements) {
+ for (PsiElement element : elements) {
+ element.accept(new PsiRecursiveElementWalkingVisitor() {
+ @Override
+ public void visitElement(PsiElement element) {
+ if (element instanceof PsiComment) {
+ return;
+ }
+ super.visitElement(element);
+
+ if (!(element instanceof LeafElement) || !pattern.isTypedVar(element)) {
+ return;
+ }
+ final MatchingHandler handler = pattern.getHandler(pattern.getTypedVarString(element));
+ if (handler == null) {
+ throw new MalformedPatternException();
+ }
+ }
+ });
+ }
+ }
+
public static String getLastFindPlan() {
return ((TestModeOptimizingSearchHelper)lastTestingContext.getSearchHelper()).getSearchPlan();
}
@@ -322,11 +344,8 @@ public class PatternCompiler {
@Override
public String getPrefix(int varIndex) {
- try {
- return myPrefixes[varIndex];
- } catch (ArrayIndexOutOfBoundsException e) {
- return null;
- }
+ if (varIndex >= myPrefixes.length) return null;
+ return myPrefixes[varIndex];
}
}
@@ -462,10 +481,9 @@ public class PatternCompiler {
PsiElement[] matchStatements;
try {
- final String pattern = buf.toString();
- matchStatements = MatcherImplUtil.createTreeFromText(pattern, PatternTreeContext.Block, options.getFileType(),
+ matchStatements = MatcherImplUtil.createTreeFromText(buf.toString(), PatternTreeContext.Block, options.getFileType(),
options.getDialect(), options.getPatternContext(), project, false);
- if (matchStatements.length==0) throw new MalformedPatternException(pattern);
+ if (matchStatements.length==0) throw new MalformedPatternException();
} catch (IncorrectOperationException e) {
throw new MalformedPatternException(e.getMessage());
}
@@ -487,12 +505,11 @@ public class PatternCompiler {
}
private static void addScriptConstraint(String name, MatchVariableConstraint constraint, SubstitutionHandler handler) {
- MatchPredicate predicate;
if (constraint.getScriptCodeConstraint()!= null && constraint.getScriptCodeConstraint().length() > 2) {
final String script = StringUtil.stripQuotesAroundValue(constraint.getScriptCodeConstraint());
final String s = ScriptSupport.checkValidScript(script);
if (s != null) throw new MalformedPatternException("Script constraint for " + constraint.getName() + " has problem "+s);
- predicate = new ScriptPredicate(name, script);
+ MatchPredicate predicate = new ScriptPredicate(name, script);
addPredicate(handler,predicate);
}
}
diff --git a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java
index da479a70f93c..735147b85bfb 100644
--- a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java
+++ b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java
@@ -2943,4 +2943,35 @@ public class StructuralSearchTest extends StructuralSearchTestCase {
String pattern3 = "'_a::'_b";
assertEquals("should find all method references", 3, findMatchesCount(source, pattern3));
}
+
+ public void testNoUnexpectedException() {
+ String source = "{}";
+
+ String pattern1 = "/*$A$a*/";
+ MalformedPatternException ex = null;
+ try {
+ findMatchesCount(source, pattern1);
+ } catch (MalformedPatternException e) {
+ ex = e;
+ }
+ assertNotNull(ex);
+
+ String pattern2 = "class $A$Visitor {}";
+ try {
+ findMatchesCount(source, pattern2);
+ } catch (MalformedPatternException e) {
+ ex = e;
+ }
+ assertNotNull(ex);
+
+ String pattern3 = "class $Class$ { \n" +
+ " class $n$$FieldType$ $FieldName$ = $Init$;\n" +
+ "}";
+ try {
+ findMatchesCount(source, pattern3);
+ } catch (MalformedPatternException e) {
+ ex = e;
+ }
+ assertNotNull(ex);
+ }
}
diff --git a/platform/testFramework/src/com/intellij/mock/Mock.java b/platform/testFramework/src/com/intellij/mock/Mock.java
index 575bc0991c3e..73d6538c52b9 100644
--- a/platform/testFramework/src/com/intellij/mock/Mock.java
+++ b/platform/testFramework/src/com/intellij/mock/Mock.java
@@ -321,10 +321,6 @@ public class Mock {
public void closeAllFiles() {
}
- public Editor openTextEditorEnsureNoFocus(@NotNull OpenFileDescriptor descriptor) {
- return null;
- }
-
@Override
@NotNull
public Pair<FileEditor[], FileEditorProvider[]> openFileWithProviders(@NotNull VirtualFile file,
@@ -558,52 +554,55 @@ public class Mock {
return false;
}
+ @NotNull
@Override
public ToolWindow registerToolWindow(@NotNull String id, @NotNull JComponent component, @NotNull ToolWindowAnchor anchor) {
- return null;
+ throw new RuntimeException();
}
+ @NotNull
@Override
public ToolWindow registerToolWindow(@NotNull String id,
@NotNull JComponent component,
@NotNull ToolWindowAnchor anchor,
Disposable parentDisposable,
boolean canWorkInDumbMode, boolean canCloseContents) {
- return null;
+ throw new RuntimeException();
}
+ @NotNull
@Override
public ToolWindow registerToolWindow(@NotNull String id,
@NotNull JComponent component,
@NotNull ToolWindowAnchor anchor,
Disposable parentDisposable,
boolean canWorkInDumbMode) {
- return null;
+ throw new RuntimeException();
}
+ @NotNull
@Override
- public ToolWindow registerToolWindow(@NotNull String id, @NotNull JComponent component, @NotNull ToolWindowAnchor anchor, Disposable parentDisposable) {
- return null;
+ public ToolWindow registerToolWindow(@NotNull String id, @NotNull JComponent component, @NotNull ToolWindowAnchor anchor, @NotNull Disposable parentDisposable) {
+ throw new RuntimeException();
}
+ @NotNull
@Override
public ToolWindow registerToolWindow(@NotNull final String id, final boolean canCloseContent, @NotNull final ToolWindowAnchor anchor) {
- return null;
+ throw new RuntimeException();
}
+ @NotNull
@Override
public ToolWindow registerToolWindow(@NotNull final String id, final boolean canCloseContent, @NotNull final ToolWindowAnchor anchor,
final Disposable parentDisposable, final boolean dumbAware) {
- return null;
+ throw new RuntimeException();
}
+ @NotNull
@Override
public ToolWindow registerToolWindow(@NotNull final String id, final boolean canCloseContent, @NotNull final ToolWindowAnchor anchor, final boolean secondary) {
- return null;
- }
-
- public JComponent getFocusTargetFor(final JComponent comp) {
- return null;
+ throw new RuntimeException();
}
@Override
@@ -614,19 +613,12 @@ public class Mock {
public void activateEditorComponent() {
}
- public ActionCallback requestFocus(final Component c, final boolean forced) {
- return new ActionCallback.Done();
- }
-
- public ActionCallback requestFocus(final ActiveRunnable command, final boolean forced) {
- return new ActionCallback.Done();
- }
-
@Override
public boolean isEditorComponentActive() {
return false;
}
+ @NotNull
@Override
public String[] getToolWindowIds() {
return ArrayUtil.EMPTY_STRING_ARRAY;
@@ -643,9 +635,10 @@ public class Mock {
}
@Override
- public void invokeLater(Runnable runnable) {
+ public void invokeLater(@NotNull Runnable runnable) {
}
+ @NotNull
@Override
public IdeFocusManager getFocusManager() {
return IdeFocusManagerHeadless.INSTANCE;
diff --git a/platform/testFramework/src/com/intellij/projectView/TestProjectTreeStructure.java b/platform/testFramework/src/com/intellij/projectView/TestProjectTreeStructure.java
index 95a7b8b6b9e9..400744bcc9e0 100644
--- a/platform/testFramework/src/com/intellij/projectView/TestProjectTreeStructure.java
+++ b/platform/testFramework/src/com/intellij/projectView/TestProjectTreeStructure.java
@@ -46,7 +46,7 @@ public class TestProjectTreeStructure extends AbstractProjectTreeStructure imple
}
public AbstractProjectViewPSIPane createPane() {
- final AbstractProjectViewPSIPane pane = new TestProjectViewPSIPane(myProject, this);
+ final AbstractProjectViewPSIPane pane = new TestProjectViewPSIPane(myProject, this, 9);
pane.createComponent();
Disposer.register(this, pane);
return pane;
diff --git a/platform/testFramework/src/com/intellij/projectView/TestProjectViewPSIPane.java b/platform/testFramework/src/com/intellij/projectView/TestProjectViewPSIPane.java
index 9add34347b86..9f85f3b977f9 100644
--- a/platform/testFramework/src/com/intellij/projectView/TestProjectViewPSIPane.java
+++ b/platform/testFramework/src/com/intellij/projectView/TestProjectViewPSIPane.java
@@ -1,8 +1,22 @@
+/*
+ * 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.projectView;
import com.intellij.ide.SelectInTarget;
import com.intellij.ide.projectView.BaseProjectTreeBuilder;
-import com.intellij.ide.projectView.ProjectView;
import com.intellij.ide.projectView.impl.AbstractProjectViewPSIPane;
import com.intellij.ide.projectView.impl.ProjectAbstractTreeStructureBase;
import com.intellij.ide.projectView.impl.ProjectTreeBuilder;
@@ -10,10 +24,7 @@ import com.intellij.ide.projectView.impl.ProjectViewTree;
import com.intellij.ide.util.treeView.AbstractTreeBuilder;
import com.intellij.ide.util.treeView.AbstractTreeUpdater;
import com.intellij.ide.util.treeView.AlphaComparator;
-import com.intellij.openapi.project.DumbAwareRunnable;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.startup.StartupManager;
-import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -24,11 +35,13 @@ import javax.swing.tree.DefaultTreeModel;
* @author yole
*/
class TestProjectViewPSIPane extends AbstractProjectViewPSIPane {
- private TestProjectTreeStructure myTestTreeStructure;
+ private final TestProjectTreeStructure myTestTreeStructure;
+ private final int myWeight;
- public TestProjectViewPSIPane(Project project, TestProjectTreeStructure treeStructure) {
+ public TestProjectViewPSIPane(Project project, TestProjectTreeStructure treeStructure, int weight) {
super(project);
myTestTreeStructure = treeStructure;
+ myWeight = weight;
}
@Override
@@ -36,11 +49,6 @@ class TestProjectViewPSIPane extends AbstractProjectViewPSIPane {
return null;
}
- @NonNls
- public String getComponentName() {
- return "comp name";
- }
-
@Override
protected AbstractTreeUpdater createTreeUpdater(AbstractTreeBuilder treeBuilder) {
return new AbstractTreeUpdater(treeBuilder);
@@ -55,11 +63,6 @@ class TestProjectViewPSIPane extends AbstractProjectViewPSIPane {
protected AbstractTreeUpdater createUpdater() {
return createTreeUpdater(this);
}
-
- protected void addTaskToWorker(final Runnable runnable, boolean first, final Runnable postRunnable) {
- runnable.run();
- postRunnable.run();
- }
};
}
@@ -96,26 +99,6 @@ class TestProjectViewPSIPane extends AbstractProjectViewPSIPane {
@Override
public int getWeight() {
- return 0;
- }
-
- public void projectOpened() {
- final Runnable runnable = new DumbAwareRunnable() {
- @Override
- public void run() {
- final ProjectView projectView = ProjectView.getInstance(myProject);
- projectView.addProjectPane(TestProjectViewPSIPane.this);
- }
- };
- StartupManager.getInstance(myProject).registerPostStartupActivity(runnable);
- }
-
- public void projectClosed() {
- }
-
- public void initComponent() { }
-
- public void disposeComponent() {
-
+ return myWeight;
}
}
diff --git a/platform/testFramework/src/com/intellij/testFramework/EditorTestUtil.java b/platform/testFramework/src/com/intellij/testFramework/EditorTestUtil.java
index 870d6d53b998..a86c1c1440dc 100644
--- a/platform/testFramework/src/com/intellij/testFramework/EditorTestUtil.java
+++ b/platform/testFramework/src/com/intellij/testFramework/EditorTestUtil.java
@@ -23,7 +23,6 @@ import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.*;
-import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
import com.intellij.openapi.editor.actionSystem.EditorActionManager;
import com.intellij.openapi.editor.actionSystem.TypedAction;
import com.intellij.openapi.editor.ex.EditorEx;
@@ -46,7 +45,6 @@ import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
-import org.junit.Assert;
import java.awt.*;
import java.util.ArrayList;
@@ -73,40 +71,45 @@ public class EditorTestUtil {
public static void performTypingAction(Editor editor, char c) {
EditorActionManager actionManager = EditorActionManager.getInstance();
if (c == BACKSPACE_FAKE_CHAR) {
- EditorActionHandler actionHandler = actionManager.getActionHandler(IdeActions.ACTION_EDITOR_BACKSPACE);
- actionHandler.execute(editor, DataManager.getInstance().getDataContext());
+ executeAction(editor, IdeActions.ACTION_EDITOR_BACKSPACE);
} else if (c == SMART_ENTER_FAKE_CHAR) {
- EditorActionHandler actionHandler = actionManager.getActionHandler(IdeActions.ACTION_EDITOR_COMPLETE_STATEMENT);
- actionHandler.execute(editor, DataManager.getInstance().getDataContext());
+ executeAction(editor, IdeActions.ACTION_EDITOR_COMPLETE_STATEMENT);
} else if (c == SMART_LINE_SPLIT_CHAR) {
- EditorActionHandler actionHandler = actionManager.getActionHandler(IdeActions.ACTION_EDITOR_SPLIT);
- actionHandler.execute(editor, DataManager.getInstance().getDataContext());
+ executeAction(editor, IdeActions.ACTION_EDITOR_SPLIT);
}
else if (c == '\n') {
- EditorActionHandler actionHandler = actionManager.getActionHandler(IdeActions.ACTION_EDITOR_ENTER);
- actionHandler.execute(editor, DataManager.getInstance().getDataContext());
+ executeAction(editor, IdeActions.ACTION_EDITOR_ENTER);
}
else {
TypedAction action = actionManager.getTypedAction();
- action.actionPerformed(editor, c, DataManager.getInstance().getDataContext());
+ action.actionPerformed(editor, c, DataManager.getInstance().getDataContext(editor.getContentComponent()));
}
}
- public static void performReferenceCopy(DataContext dataContext) {
+ public static void executeAction(Editor editor, String actionId) {
+ executeAction(editor, actionId, false);
+ }
+
+ public static void executeAction(Editor editor, String actionId, boolean assertActionIsEnabled) {
ActionManager actionManager = ActionManager.getInstance();
- AnAction action = actionManager.getAction(IdeActions.ACTION_COPY_REFERENCE);
- AnActionEvent
- event = new AnActionEvent(null, dataContext, "", action.getTemplatePresentation(),
- ActionManager.getInstance(), 0);
- action.update(event);
- Assert.assertTrue(event.getPresentation().isEnabled());
+ AnAction action = actionManager.getAction(actionId);
+ assertNotNull(action);
+ DataContext dataContext = DataManager.getInstance().getDataContext(editor.getContentComponent());
+ AnActionEvent event = new AnActionEvent(null, dataContext, "", action.getTemplatePresentation(), actionManager, 0);
+ action.beforeActionPerformedUpdate(event);
+ if (!event.getPresentation().isEnabled()) {
+ assertFalse("Action " + actionId + " is disabled", assertActionIsEnabled);
+ return;
+ }
action.actionPerformed(event);
}
+ public static void performReferenceCopy(Editor editor) {
+ executeAction(editor, IdeActions.ACTION_COPY_REFERENCE, true);
+ }
+
public static void performPaste(Editor editor) {
- EditorActionManager actionManager = EditorActionManager.getInstance();
- EditorActionHandler actionHandler = actionManager.getActionHandler(IdeActions.ACTION_EDITOR_PASTE);
- actionHandler.execute(editor, null, DataManager.getInstance().getDataContext());
+ executeAction(editor, IdeActions.ACTION_EDITOR_PASTE, true);
}
public static List<IElementType> getAllTokens(EditorHighlighter highlighter) {
diff --git a/platform/testFramework/src/com/intellij/testFramework/LightPlatformCodeInsightTestCase.java b/platform/testFramework/src/com/intellij/testFramework/LightPlatformCodeInsightTestCase.java
index 3c1f96113532..9dedcc6d47a8 100644
--- a/platform/testFramework/src/com/intellij/testFramework/LightPlatformCodeInsightTestCase.java
+++ b/platform/testFramework/src/com/intellij/testFramework/LightPlatformCodeInsightTestCase.java
@@ -19,10 +19,7 @@ import com.intellij.codeInsight.generation.actions.CommentByLineCommentAction;
import com.intellij.ide.DataManager;
import com.intellij.injected.editor.DocumentWindow;
import com.intellij.injected.editor.EditorWindow;
-import com.intellij.openapi.actionSystem.AnActionEvent;
-import com.intellij.openapi.actionSystem.CommonDataKeys;
-import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.actionSystem.IdeActions;
+import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.application.ex.PathManagerEx;
@@ -145,7 +142,7 @@ public abstract class LightPlatformCodeInsightTestCase extends LightPlatformTest
* @throws java.io.IOException
*/
@NotNull
- protected static Document configureFromFileText(@NonNls @NotNull final String fileName, @NonNls @NotNull final String fileText) throws IOException {
+ protected static Document configureFromFileText(@NonNls @NotNull final String fileName, @NonNls @NotNull final String fileText) {
return new WriteCommandAction<Document>(null) {
@Override
protected void run(@NotNull Result<Document> result) throws Throwable {
@@ -353,24 +350,6 @@ public abstract class LightPlatformCodeInsightTestCase extends LightPlatformTest
return userMessage + " [" + engineMessage + "]";
}
- @Override
- public Object getData(String dataId) {
- if (CommonDataKeys.EDITOR.is(dataId)) {
- return myEditor;
- }
- if (dataId.equals(AnActionEvent.injectedId(CommonDataKeys.EDITOR.getName()))) {
- return InjectedLanguageUtil.getEditorForInjectedLanguageNoCommit(getEditor(), getFile());
- }
- if (CommonDataKeys.PSI_FILE.is(dataId)) {
- return myFile;
- }
- if (dataId.equals(AnActionEvent.injectedId(CommonDataKeys.PSI_FILE.getName()))) {
- Editor editor = InjectedLanguageUtil.getEditorForInjectedLanguageNoCommit(getEditor(), getFile());
- return editor instanceof EditorWindow ? ((EditorWindow)editor).getInjectedFile() : getFile();
- }
- return super.getData(dataId);
- }
-
/**
* @return Editor used in test.
*/
@@ -508,9 +487,7 @@ public abstract class LightPlatformCodeInsightTestCase extends LightPlatformTest
CommandProcessor.getInstance().executeCommand(getProject(), new Runnable() {
@Override
public void run() {
- EditorActionManager actionManager = EditorActionManager.getInstance();
- EditorActionHandler actionHandler = actionManager.getActionHandler(actionId);
- actionHandler.execute(getEditor(), null, DataManager.getInstance().getDataContext());
+ EditorTestUtil.executeAction(getEditor(), actionId);
}
}, "", null);
}
diff --git a/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java b/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java
index 33051b471049..268eb6d0831e 100644
--- a/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java
+++ b/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java
@@ -722,10 +722,7 @@ public abstract class LightPlatformTestCase extends UsefulTestCase implements Da
@Override
public Object getData(String dataId) {
- if (CommonDataKeys.PROJECT.is(dataId)) {
- return ourProject;
- }
- return null;
+ return ourProject == null || ourProject.isDisposed() ? null : new TestDataProvider(ourProject).getData(dataId);
}
protected Sdk getProjectJDK() {
diff --git a/platform/testFramework/src/com/intellij/testFramework/ParsingTestCase.java b/platform/testFramework/src/com/intellij/testFramework/ParsingTestCase.java
index f000733e8881..46b3adca7557 100644
--- a/platform/testFramework/src/com/intellij/testFramework/ParsingTestCase.java
+++ b/platform/testFramework/src/com/intellij/testFramework/ParsingTestCase.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.
@@ -89,7 +89,7 @@ public abstract class ParsingTestCase extends PlatformLiteFixture {
getApplication().getPicoContainer().registerComponent(new AbstractComponentAdapter(ProgressManager.class.getName(), Object.class) {
@Override
public Object getComponentInstance(PicoContainer container) throws PicoInitializationException, PicoIntrospectionException {
- return new ProgressManagerImpl(getApplication());
+ return new ProgressManagerImpl();
}
@Override
diff --git a/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java b/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java
index 347661846e2a..d9b32080f458 100644
--- a/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java
+++ b/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java
@@ -198,6 +198,7 @@ public abstract class PlatformTestCase extends UsefulTestCase implements DataPro
}
DocumentCommitThread.getInstance().clearQueue();
+ UIUtil.dispatchAllInvocationEvents();
}
public Project getProject() {
diff --git a/platform/testFramework/src/com/intellij/testFramework/ProjectViewTestUtil.java b/platform/testFramework/src/com/intellij/testFramework/ProjectViewTestUtil.java
index 66b59d06d200..548c312614d4 100644
--- a/platform/testFramework/src/com/intellij/testFramework/ProjectViewTestUtil.java
+++ b/platform/testFramework/src/com/intellij/testFramework/ProjectViewTestUtil.java
@@ -15,17 +15,27 @@
*/
package com.intellij.testFramework;
+import com.intellij.ide.projectView.ProjectView;
import com.intellij.ide.projectView.ProjectViewNode;
import com.intellij.ide.projectView.impl.AbstractProjectViewPSIPane;
+import com.intellij.ide.projectView.impl.ProjectViewImpl;
import com.intellij.ide.projectView.impl.nodes.BasePsiNode;
import com.intellij.ide.util.treeView.AbstractTreeNode;
import com.intellij.ide.util.treeView.AbstractTreeStructure;
+import com.intellij.openapi.extensions.Extensions;
+import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Queryable;
import com.intellij.openapi.util.MultiValuesMap;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.wm.ToolWindow;
+import com.intellij.openapi.wm.ToolWindowAnchor;
+import com.intellij.openapi.wm.ToolWindowEP;
+import com.intellij.openapi.wm.ToolWindowId;
+import com.intellij.openapi.wm.ex.ToolWindowManagerEx;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.util.Function;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.junit.Assert;
@@ -151,4 +161,22 @@ public class ProjectViewTestUtil {
DefaultMutableTreeNode nodeForElement = getNodeForElement(element, pane);
return nodeForElement != null && isExpanded((DefaultMutableTreeNode)nodeForElement.getParent(), pane);
}
+
+ public static void setupImpl(@NotNull Project project, boolean loadPaneExtensions) {
+ ToolWindowManagerEx toolWindowManager = ToolWindowManagerEx.getInstanceEx(project);
+ ToolWindow toolWindow = toolWindowManager.getToolWindow(ToolWindowId.PROJECT_VIEW);
+
+ if (toolWindow == null) {
+ ToolWindowEP[] beans = Extensions.getExtensions(ToolWindowEP.EP_NAME);
+ for (final ToolWindowEP bean : beans) {
+ if (bean.id.equals(ToolWindowId.PROJECT_VIEW)) {
+ toolWindow = toolWindowManager.registerToolWindow(bean.id, new JLabel(), ToolWindowAnchor.fromText(bean.anchor), project,
+ false, bean.canCloseContents);
+ break;
+ }
+ }
+ }
+
+ ((ProjectViewImpl)ProjectView.getInstance(project)).setupImpl(toolWindow, loadPaneExtensions);
+ }
}
diff --git a/platform/testFramework/src/com/intellij/testFramework/TestDataProvider.java b/platform/testFramework/src/com/intellij/testFramework/TestDataProvider.java
index cc8376832e36..1ed87bbcb0fa 100644
--- a/platform/testFramework/src/com/intellij/testFramework/TestDataProvider.java
+++ b/platform/testFramework/src/com/intellij/testFramework/TestDataProvider.java
@@ -20,7 +20,6 @@ import com.intellij.openapi.actionSystem.DataProvider;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.impl.EditorComponentImpl;
-import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx;
import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider;
@@ -50,18 +49,21 @@ public class TestDataProvider implements DataProvider {
if (CommonDataKeys.PROJECT.is(dataId)) {
return myProject;
}
- else if (CommonDataKeys.EDITOR.is(dataId) || OpenFileDescriptor.NAVIGATE_IN_EDITOR.is(dataId)) {
- return FileEditorManager.getInstance(myProject).getSelectedTextEditor();
+ FileEditorManagerEx manager = FileEditorManagerEx.getInstanceEx(myProject);
+ if (manager == null) {
+ return null;
+ }
+ if (CommonDataKeys.EDITOR.is(dataId) || OpenFileDescriptor.NAVIGATE_IN_EDITOR.is(dataId)) {
+ return manager.getSelectedTextEditor();
}
else if (PlatformDataKeys.FILE_EDITOR.is(dataId)) {
- Editor editor = FileEditorManager.getInstance(myProject).getSelectedTextEditor();
+ Editor editor = manager.getSelectedTextEditor();
return editor == null ? null : TextEditorProvider.getInstance().getTextEditor(editor);
}
else {
Editor editor = (Editor)getData(CommonDataKeys.EDITOR.getName());
if (editor != null) {
- FileEditorManagerEx manager = FileEditorManagerEx.getInstanceEx(myProject);
- Object managerData = manager.getData(dataId, editor, manager.getSelectedFiles()[0]);
+ Object managerData = manager.getData(dataId, editor, editor.getCaretModel().getCurrentCaret());
if (managerData != null) {
return managerData;
}
diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/CodeInsightTestFixture.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/CodeInsightTestFixture.java
index a309f9acda8f..581ca54b6baa 100644
--- a/platform/testFramework/src/com/intellij/testFramework/fixtures/CodeInsightTestFixture.java
+++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/CodeInsightTestFixture.java
@@ -350,7 +350,8 @@ public interface CodeInsightTestFixture extends IdeaProjectTestFixture {
* hint text. Throws an assertion if no such intentions are found or if multiple intentions match the hint text.
*
* @param hint the text that the intention text should begin with.
- * @return the list of matching intentions
+ * @return the matching intention
+ * @throws java.lang.AssertionError if no intentions are found or if multiple intentions match the hint text.
*/
IntentionAction findSingleIntention(@NotNull String hint);
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 27a45cbfe99e..72bbff443dfa 100644
--- a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/HeavyIdeaTestFixtureImpl.java
+++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/HeavyIdeaTestFixtureImpl.java
@@ -205,7 +205,7 @@ class HeavyIdeaTestFixtureImpl extends BaseFixture implements HeavyIdeaTestFixtu
Editor editor = (Editor)getData(CommonDataKeys.EDITOR.getName());
if (editor != null) {
FileEditorManagerEx manager = FileEditorManagerEx.getInstanceEx(myProject);
- return manager.getData(dataId, editor, manager.getSelectedFiles()[0]);
+ return manager.getData(dataId, editor, editor.getCaretModel().getCurrentCaret());
}
else if (LangDataKeys.IDE_VIEW.is(dataId)) {
VirtualFile[] contentRoots = ProjectRootManager.getInstance(myProject).getContentRoots();
@@ -217,6 +217,7 @@ class HeavyIdeaTestFixtureImpl extends BaseFixture implements HeavyIdeaTestFixtu
}
+ @NotNull
@Override
public PsiDirectory[] getDirectories() {
return new PsiDirectory[] {psiDirectory};
diff --git a/platform/testRunner/src/com/intellij/execution/testframework/actions/AbstractRerunFailedTestsAction.java b/platform/testRunner/src/com/intellij/execution/testframework/actions/AbstractRerunFailedTestsAction.java
index 9be02ae51271..30f8599e2aaf 100644
--- a/platform/testRunner/src/com/intellij/execution/testframework/actions/AbstractRerunFailedTestsAction.java
+++ b/platform/testRunner/src/com/intellij/execution/testframework/actions/AbstractRerunFailedTestsAction.java
@@ -69,7 +69,7 @@ public class AbstractRerunFailedTestsAction extends AnAction implements AnAction
protected ExecutionEnvironment myEnvironment;
private final JComponent myParent;
-
+ @SuppressWarnings("UnusedDeclaration")
public AbstractRerunFailedTestsAction() {
//We call this constructor with a little help from reflection.
myParent = null;
@@ -83,6 +83,7 @@ public class AbstractRerunFailedTestsAction extends AnAction implements AnAction
registerCustomShortcutSet(getShortcutSet(), myParent);
}
+ @Override
public void dispose() {
registry.remove(this);
}
@@ -127,6 +128,7 @@ public class AbstractRerunFailedTestsAction extends AnAction implements AnAction
return candidates.get(0);
}
+ @Override
public final void update(AnActionEvent e) {
AbstractRerunFailedTestsAction action = findActualAction();
e.getPresentation().setEnabled(action.isActive(e));
@@ -167,6 +169,7 @@ public class AbstractRerunFailedTestsAction extends AnAction implements AnAction
return Filter.FAILED_OR_INTERRUPTED;
}
+ @Override
public void actionPerformed(AnActionEvent e) {
findActualAction().showPopup(e);
}
@@ -225,6 +228,7 @@ public class AbstractRerunFailedTestsAction extends AnAction implements AnAction
.setResizable(false)
.setRequestFocus(true)
.setItemChoosenCallback(new Runnable() {
+ @Override
public void run() {
final Object value = list.getSelectedValue();
if (value instanceof Executor) {
@@ -237,12 +241,11 @@ public class AbstractRerunFailedTestsAction extends AnAction implements AnAction
private void performAction(ProgramRunner runner, MyRunProfile profile, Executor executor) {
try {
- final ExecutionEnvironment environment =
- new ExecutionEnvironmentBuilder(myEnvironment).setRunnerId(runner.getRunnerId())
- .setExecutor(executor)
- .setRunProfile(profile)
- .build();
- runner.execute(environment);
+ new ExecutionEnvironmentBuilder(myEnvironment)
+ .runner(runner)
+ .executor(executor)
+ .runProfile(profile)
+ .buildAndExecute();
}
catch (ExecutionException e1) {
LOG.error(e1);
@@ -291,58 +294,71 @@ public class AbstractRerunFailedTestsAction extends AnAction implements AnAction
}
+ @Override
public void checkConfiguration() throws RuntimeConfigurationException {
}
///////////////////////////////////Delegates
+ @Override
public void readExternal(final Element element) throws InvalidDataException {
myConfiguration.readExternal(element);
}
+ @Override
public void writeExternal(final Element element) throws WriteExternalException {
myConfiguration.writeExternal(element);
}
+ @Override
@NotNull
public SettingsEditor<? extends RunConfiguration> getConfigurationEditor() {
return myConfiguration.getConfigurationEditor();
}
+ @Override
@NotNull
public ConfigurationType getType() {
return myConfiguration.getType();
}
+ @Override
public ConfigurationPerRunnerSettings createRunnerSettings(final ConfigurationInfoProvider provider) {
return myConfiguration.createRunnerSettings(provider);
}
+ @Override
public SettingsEditor<ConfigurationPerRunnerSettings> getRunnerSettingsEditor(final ProgramRunner runner) {
return myConfiguration.getRunnerSettingsEditor(runner);
}
+ @Override
public RunConfiguration clone() {
return myConfiguration.clone();
}
+ @Override
public int getUniqueID() {
return myConfiguration.getUniqueID();
}
+ @Override
public LogFileOptions getOptionsForPredefinedLogFile(PredefinedLogFile predefinedLogFile) {
return myConfiguration.getOptionsForPredefinedLogFile(predefinedLogFile);
}
+ @Override
public ArrayList<PredefinedLogFile> getPredefinedLogFiles() {
return myConfiguration.getPredefinedLogFiles();
}
+ @Override
public ArrayList<LogFileOptions> getAllLogFiles() {
return myConfiguration.getAllLogFiles();
}
+ @Override
public ArrayList<LogFileOptions> getLogFiles() {
return myConfiguration.getLogFiles();
}
}
-} \ No newline at end of file
+}
diff --git a/platform/testRunner/src/com/intellij/execution/testframework/autotest/AutoTestManager.java b/platform/testRunner/src/com/intellij/execution/testframework/autotest/AutoTestManager.java
index fb433b23ec56..3f15ee3f6de3 100644
--- a/platform/testRunner/src/com/intellij/execution/testframework/autotest/AutoTestManager.java
+++ b/platform/testRunner/src/com/intellij/execution/testframework/autotest/AutoTestManager.java
@@ -2,9 +2,12 @@ package com.intellij.execution.testframework.autotest;
import com.intellij.execution.DelayedDocumentWatcher;
import com.intellij.execution.process.ProcessHandler;
+import com.intellij.execution.runners.ExecutionUtil;
import com.intellij.execution.ui.RunContentDescriptor;
-import com.intellij.execution.ui.RunContentManagerImpl;
+import com.intellij.ide.DataManager;
import com.intellij.ide.util.PropertiesComponent;
+import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.project.Project;
@@ -15,6 +18,7 @@ import com.intellij.ui.content.Content;
import com.intellij.util.Consumer;
import com.intellij.util.containers.WeakHashMap;
+import javax.swing.*;
import java.util.Collections;
import java.util.Set;
@@ -79,21 +83,21 @@ public class AutoTestManager {
}
private static void runAutoTest(Content content) {
- RunContentDescriptor descriptor = RunContentManagerImpl.getRunContentDescriptorByContent(content);
- if (descriptor == null) {
- return;
- }
- Runnable restarter = descriptor.getRestarter();
- if (restarter == null) {
- return;
- }
- final ProcessHandler processHandler = descriptor.getProcessHandler();
- if (processHandler != null && !processHandler.isProcessTerminated()) {
- return;
+ JComponent component = content.getComponent();
+ if (component != null) {
+ DataContext dataContext = DataManager.getInstance().getDataContext(component);
+ RunContentDescriptor descriptor = LangDataKeys.RUN_CONTENT_DESCRIPTOR.getData(dataContext);
+ if (descriptor != null) {
+ ProcessHandler processHandler = descriptor.getProcessHandler();
+ if (processHandler != null && !processHandler.isProcessTerminated()) {
+ return;
+ }
+
+ descriptor.setActivateToolWindowWhenAdded(false);
+ descriptor.setReuseToolWindowActivation(true);
+ ExecutionUtil.restart(content);
+ }
}
- descriptor.setActivateToolWindowWhenAdded(false);
- descriptor.setReuseToolWindowActivation(true);
- restarter.run();
}
int getDelay() {
diff --git a/platform/testRunner/src/com/intellij/execution/testframework/autotest/ToggleAutoTestAction.java b/platform/testRunner/src/com/intellij/execution/testframework/autotest/ToggleAutoTestAction.java
index 893ddb320aab..256ff0277c83 100644
--- a/platform/testRunner/src/com/intellij/execution/testframework/autotest/ToggleAutoTestAction.java
+++ b/platform/testRunner/src/com/intellij/execution/testframework/autotest/ToggleAutoTestAction.java
@@ -2,10 +2,10 @@ package com.intellij.execution.testframework.autotest;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.ui.RunContentDescriptor;
-import com.intellij.execution.ui.RunContentManager;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
+import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.actionSystem.ToggleAction;
import com.intellij.openapi.project.Project;
@@ -21,15 +21,15 @@ public class ToggleAutoTestAction extends ToggleAction {
@Override
public boolean isSelected(AnActionEvent e) {
- Project project = e.getData(CommonDataKeys.PROJECT);
- RunContentDescriptor descriptor = e.getData(RunContentManager.RUN_CONTENT_DESCRIPTOR);
+ Project project = e.getProject();
+ RunContentDescriptor descriptor = e.getData(LangDataKeys.RUN_CONTENT_DESCRIPTOR);
return !(project == null || descriptor == null) && AutoTestManager.getInstance(project).isAutoTestEnabled(descriptor);
}
@Override
public void setSelected(AnActionEvent e, boolean state) {
Project project = e.getData(CommonDataKeys.PROJECT);
- RunContentDescriptor descriptor = e.getData(RunContentManager.RUN_CONTENT_DESCRIPTOR);
+ RunContentDescriptor descriptor = e.getData(LangDataKeys.RUN_CONTENT_DESCRIPTOR);
if (project != null && descriptor != null) {
AutoTestManager.getInstance(project).setAutoTestEnabled(descriptor, state);
}
diff --git a/platform/usageView/src/com/intellij/usages/UsageViewPresentation.java b/platform/usageView/src/com/intellij/usages/UsageViewPresentation.java
index c715c6a169c6..c597eea48db0 100644
--- a/platform/usageView/src/com/intellij/usages/UsageViewPresentation.java
+++ b/platform/usageView/src/com/intellij/usages/UsageViewPresentation.java
@@ -38,6 +38,7 @@ public class UsageViewPresentation {
private boolean myShowCancelButton = false;
private boolean myOpenInNewTab = true;
private boolean myCodeUsages = true;
+ private boolean myUsageTypeFilteringAvailable;
private String myUsagesWord = UsageViewBundle.message("usage.name");
private String myTabName;
@@ -198,5 +199,13 @@ public class UsageViewPresentation {
public void setMergeDupLinesAvailable(boolean mergeDupLinesAvailable) {
myMergeDupLinesAvailable = mergeDupLinesAvailable;
}
+
+ public boolean isUsageTypeFilteringAvailable() {
+ return myCodeUsages || myUsageTypeFilteringAvailable;
+ }
+
+ public void setUsageTypeFilteringAvailable(boolean usageTypeFilteringAvailable) {
+ myUsageTypeFilteringAvailable = usageTypeFilteringAvailable;
+ }
}
diff --git a/platform/usageView/src/com/intellij/usages/impl/UsageGroupingRuleProviderImpl.java b/platform/usageView/src/com/intellij/usages/impl/UsageGroupingRuleProviderImpl.java
index 175257143ffb..11713b812523 100644
--- a/platform/usageView/src/com/intellij/usages/impl/UsageGroupingRuleProviderImpl.java
+++ b/platform/usageView/src/com/intellij/usages/impl/UsageGroupingRuleProviderImpl.java
@@ -104,7 +104,7 @@ public class UsageGroupingRuleProviderImpl implements UsageGroupingRuleProvider
ArrayList<AnAction> result = ContainerUtil.newArrayList();
- if (view.getPresentation().isCodeUsages()) {
+ if (view.getPresentation().isUsageTypeFilteringAvailable()) {
GroupByUsageTypeAction groupByUsageTypeAction = new GroupByUsageTypeAction(impl);
groupByUsageTypeAction.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_T, InputEvent.CTRL_DOWN_MASK)), component, impl);
diff --git a/platform/util/resources/misc/registry.properties b/platform/util/resources/misc/registry.properties
index bbda04a2461a..e9802f2321ae 100644
--- a/platform/util/resources/misc/registry.properties
+++ b/platform/util/resources/misc/registry.properties
@@ -43,6 +43,8 @@ actionSystem.enableAbbreviations=true
ide.firstStartup=true
ide.debugMode=false
+ide.debugger.inline=false
+ide.debugger.inline.description=Enables variables view in editor
ide.debugMode.description=Record additional information to make bug reports more informative.
ide.debug.minProgressTime=0
ide.forcedShowTooltip=alt
@@ -313,6 +315,7 @@ testng_sm_runner=false
show.flex.debug.design.view=false
git.new.log=true
diff.patience.alg=false
+diff.status.tracker.skip.spaces=true
svn.use.terminal=false
svn.use.incoming.optimization=false
@@ -391,6 +394,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.file.settings.tree.new=false
ide.new.project.settings=true
ide.new.project.settings.description=Temporary key for new project settings dialog UI
diff --git a/platform/util/src/com/intellij/icons/AllIcons.java b/platform/util/src/com/intellij/icons/AllIcons.java
index be3f4f212072..318895db57f1 100644
--- a/platform/util/src/com/intellij/icons/AllIcons.java
+++ b/platform/util/src/com/intellij/icons/AllIcons.java
@@ -76,6 +76,7 @@ public class AllIcons {
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 GroupByClass = IconLoader.getIcon("/actions/GroupByClass.png"); // 16x16
public static final Icon GroupByModule = IconLoader.getIcon("/actions/GroupByModule.png"); // 16x16
public static final Icon GroupByModuleGroup = IconLoader.getIcon("/actions/GroupByModuleGroup.png"); // 16x16
public static final Icon GroupByPackage = IconLoader.getIcon("/actions/GroupByPackage.png"); // 16x16
diff --git a/platform/util/src/com/intellij/openapi/diagnostic/Log.java b/platform/util/src/com/intellij/openapi/diagnostic/Log.java
index dfc00ae9b4c6..842a8356f591 100644
--- a/platform/util/src/com/intellij/openapi/diagnostic/Log.java
+++ b/platform/util/src/com/intellij/openapi/diagnostic/Log.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.
@@ -15,13 +15,11 @@
*/
package com.intellij.openapi.diagnostic;
-
import java.util.ArrayList;
import java.util.List;
-/**
- * This is a very primitive fast logging class, primary for race-conditions debugging.
- */
+/** @deprecated use {@link com.intellij.openapi.diagnostic.Logger} (to be removed in IDEA 15) */
+@SuppressWarnings("unused")
public class Log {
private static final List<String> myStrings = new ArrayList<String>();
private static final List<Throwable> myThrowables = new ArrayList<Throwable>();
diff --git a/platform/util/src/com/intellij/openapi/progress/ProcessCanceledException.java b/platform/util/src/com/intellij/openapi/progress/ProcessCanceledException.java
index e3029934b2e5..e6133b255411 100644
--- a/platform/util/src/com/intellij/openapi/progress/ProcessCanceledException.java
+++ b/platform/util/src/com/intellij/openapi/progress/ProcessCanceledException.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,9 @@ package com.intellij.openapi.progress;
import com.intellij.util.SystemProperties;
public class ProcessCanceledException extends RuntimeException {
- private static boolean ourHasStackTraces = SystemProperties.getBooleanProperty("idea.is.internal", false);
+ private static final boolean ourHasStackTraces = SystemProperties.getBooleanProperty("idea.is.internal", false);
public ProcessCanceledException() {
- int i = 0;
}
public ProcessCanceledException(Throwable cause) {
diff --git a/platform/util/src/com/intellij/openapi/util/TextRange.java b/platform/util/src/com/intellij/openapi/util/TextRange.java
index 797bc23ee747..4c09b969a570 100644
--- a/platform/util/src/com/intellij/openapi/util/TextRange.java
+++ b/platform/util/src/com/intellij/openapi/util/TextRange.java
@@ -99,6 +99,16 @@ public class TextRange implements Segment, Serializable {
}
@NotNull
+ public CharSequence subSequence(@NotNull CharSequence str) {
+ try {
+ return str.subSequence(myStartOffset, myEndOffset);
+ }
+ catch (IndexOutOfBoundsException e) {
+ throw new IndexOutOfBoundsException("Can't extract " + this + " range from " + str);
+ }
+ }
+
+ @NotNull
public TextRange cutOut(@NotNull TextRange subRange) {
assert subRange.getStartOffset() <= getLength() : subRange + "; this="+this;
assert subRange.getEndOffset() <= getLength() : subRange + "; this="+this;
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 cfcbe7967d35..adec13d20412 100644
--- a/platform/util/src/com/intellij/openapi/util/io/FileUtil.java
+++ b/platform/util/src/com/intellij/openapi/util/io/FileUtil.java
@@ -1264,10 +1264,10 @@ public class FileUtil extends FileUtilRt {
if (path == null) return null;
if (SystemInfo.isUnix || !unixOnly) {
- final File projectDir = new File(path);
- final File userHomeDir = new File(SystemProperties.getUserHome());
+ File projectDir = new File(path);
+ File userHomeDir = new File(SystemProperties.getUserHome());
if (isAncestor(userHomeDir, projectDir, true)) {
- return "~/" + getRelativePath(userHomeDir, projectDir);
+ return '~' + File.separator + getRelativePath(userHomeDir, projectDir);
}
}
diff --git a/platform/util/src/com/intellij/openapi/util/registry/Registry.java b/platform/util/src/com/intellij/openapi/util/registry/Registry.java
index e418e553fb6b..d41ea08161b3 100644
--- a/platform/util/src/com/intellij/openapi/util/registry/Registry.java
+++ b/platform/util/src/com/intellij/openapi/util/registry/Registry.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.openapi.util.registry;
import com.intellij.util.containers.HashMap;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.awt.*;
@@ -33,30 +34,29 @@ public class Registry {
@NonNls
private static final String REGISTRY_BUNDLE = "misc.registry";
- private final LinkedHashMap<String, String> myUserProperties = new LinkedHashMap<String, String>();
+ private final Map<String, String> myUserProperties = new LinkedHashMap<String, String>();
private final Map<String, String> myLoadedUserProperties = new HashMap<String, String>();
private final Map<String, RegistryValue> myValues = new ConcurrentHashMap<String, RegistryValue>();
private static final Registry ourInstance = new Registry();
- public static RegistryValue get(@PropertyKey(resourceBundle = REGISTRY_BUNDLE) String key) {
+ @NotNull
+ public static RegistryValue get(@PropertyKey(resourceBundle = REGISTRY_BUNDLE) @NotNull String key) {
final Registry registry = getInstance();
- if (registry.myValues.containsKey(key)) {
- return registry.myValues.get(key);
- }
- else {
- final RegistryValue value = new RegistryValue(registry, key);
+ RegistryValue value = registry.myValues.get(key);
+ if (value == null) {
+ value = new RegistryValue(registry, key);
registry.myValues.put(key, value);
- return value;
}
+ return value;
}
- public static boolean is(@PropertyKey(resourceBundle = REGISTRY_BUNDLE) String key) {
+ public static boolean is(@PropertyKey(resourceBundle = REGISTRY_BUNDLE) @NotNull String key) throws MissingResourceException {
return get(key).asBoolean();
}
- public static boolean is(@PropertyKey(resourceBundle = REGISTRY_BUNDLE) String key, boolean defaultValue) {
+ public static boolean is(@PropertyKey(resourceBundle = REGISTRY_BUNDLE) @NotNull String key, boolean defaultValue) {
try {
return get(key).asBoolean();
}
@@ -65,11 +65,11 @@ public class Registry {
}
}
- public static int intValue(@PropertyKey(resourceBundle = REGISTRY_BUNDLE) String key) {
+ public static int intValue(@PropertyKey(resourceBundle = REGISTRY_BUNDLE) @NotNull String key) throws MissingResourceException {
return get(key).asInteger();
}
- public static int intValue(@PropertyKey(resourceBundle = REGISTRY_BUNDLE) String key, int defaultValue) {
+ public static int intValue(@PropertyKey(resourceBundle = REGISTRY_BUNDLE) @NotNull String key, int defaultValue) {
try {
return get(key).asInteger();
}
@@ -78,18 +78,20 @@ public class Registry {
}
}
- public static double doubleValue(@PropertyKey(resourceBundle = REGISTRY_BUNDLE) String key) {
+ public static double doubleValue(@PropertyKey(resourceBundle = REGISTRY_BUNDLE) @NotNull String key) throws MissingResourceException {
return get(key).asDouble();
}
- public static String stringValue(@PropertyKey(resourceBundle = REGISTRY_BUNDLE) String key) {
+ @NotNull
+ public static String stringValue(@PropertyKey(resourceBundle = REGISTRY_BUNDLE) @NotNull String key) throws MissingResourceException {
return get(key).asString();
}
- public static Color getColor(@PropertyKey(resourceBundle = REGISTRY_BUNDLE) String key, Color defaultValue) {
+ public static Color getColor(@PropertyKey(resourceBundle = REGISTRY_BUNDLE) @NotNull String key, Color defaultValue) throws MissingResourceException {
return get(key).asColor(defaultValue);
}
+ @NotNull
static ResourceBundle getBundle() {
ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
@@ -104,6 +106,7 @@ public class Registry {
return ourInstance;
}
+ @NotNull
public Element getState() {
final Element state = new Element("registry");
for (String eachKey : myUserProperties.keySet()) {
@@ -115,7 +118,7 @@ public class Registry {
return state;
}
- public void loadState(Element state) {
+ public void loadState(@NotNull Element state) {
final List entries = state.getChildren("entry");
for (Object each : entries) {
final Element eachEntry = (Element) each;
@@ -132,15 +135,17 @@ public class Registry {
}
}
+ @NotNull
Map<String, String> getUserProperties() {
return myUserProperties;
}
+ @NotNull
public static List<RegistryValue> getAll() {
final ResourceBundle bundle = getBundle();
final Enumeration<String> keys = bundle.getKeys();
- final ArrayList<RegistryValue> result = new ArrayList<RegistryValue>();
+ List<RegistryValue> result = new ArrayList<RegistryValue>();
while (keys.hasMoreElements()) {
final String each = keys.nextElement();
@@ -152,7 +157,7 @@ public class Registry {
}
public void restoreDefaults() {
- final HashMap<String, String> old = new HashMap<String, String>();
+ Map<String, String> old = new HashMap<String, String>();
old.putAll(myUserProperties);
for (String each : old.keySet()) {
get(each).resetToDefault();
@@ -167,7 +172,7 @@ public class Registry {
return isRestartNeeded(myUserProperties) || isRestartNeeded(myLoadedUserProperties);
}
- private static boolean isRestartNeeded(Map<String, String> map) {
+ private static boolean isRestartNeeded(@NotNull Map<String, String> map) {
for (String s : map.keySet()) {
final RegistryValue eachValue = get(s);
if (eachValue.isRestartRequired() && eachValue.isChangedSinceAppStart()) return true;
diff --git a/platform/util/src/com/intellij/openapi/util/registry/RegistryValue.java b/platform/util/src/com/intellij/openapi/util/registry/RegistryValue.java
index 6c89311457f4..ae3873b8744f 100644
--- a/platform/util/src/com/intellij/openapi/util/registry/RegistryValue.java
+++ b/platform/util/src/com/intellij/openapi/util/registry/RegistryValue.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.
@@ -42,16 +42,18 @@ public class RegistryValue {
private Double myDoubleCachedValue;
private Boolean myBooleanCachedValue;
- RegistryValue(Registry registry, String key) {
+ RegistryValue(@NotNull Registry registry, @NotNull String key) {
myRegistry = registry;
myKey = key;
}
+ @NotNull
public String getKey() {
return myKey;
}
+ @NotNull
public String asString() {
final String value = get(myKey, null, true);
assert value != null : myKey;
@@ -97,6 +99,7 @@ public class RegistryValue {
return defaultValue;
}
+ @NotNull
public String getDescription() {
return get(myKey + ".description", "", false);
}
@@ -109,42 +112,36 @@ public class RegistryValue {
return !asString().equals(getBundleValue(myKey, false));
}
- private String get(String key, String defaultValue, boolean isValue) {
+ private String get(@NotNull String key, String defaultValue, boolean isValue) throws MissingResourceException {
if (isValue) {
if (myStringCachedValue == null) {
myStringCachedValue = _get(key, defaultValue, isValue);
- }
- if (isBoolean()) {
- myStringCachedValue = Boolean.valueOf(myStringCachedValue).toString();
+ if (isBoolean()) {
+ myStringCachedValue = Boolean.valueOf(myStringCachedValue).toString();
+ }
}
return myStringCachedValue;
}
- else {
- return _get(key, defaultValue, isValue);
- }
+ return _get(key, defaultValue, isValue);
}
- private String _get(String key, String defaultValue, boolean mustExistInBundle) {
+ private String _get(@NotNull String key, String defaultValue, boolean mustExistInBundle) throws MissingResourceException {
final String userValue = myRegistry.getUserProperties().get(key);
- if (userValue == null) {
- String systemProperty = System.getProperty(key);
- if (systemProperty != null) {
- return systemProperty;
- }
- final String bundleValue = getBundleValue(key, mustExistInBundle);
- if (bundleValue != null) {
- return bundleValue;
- }
- else {
- return defaultValue;
- }
- }
- else {
+ if (userValue != null) {
return userValue;
}
+ String systemProperty = System.getProperty(key);
+ if (systemProperty != null) {
+ return systemProperty;
+ }
+ final String bundleValue = getBundleValue(key, mustExistInBundle);
+ if (bundleValue != null) {
+ return bundleValue;
+ }
+ return defaultValue;
}
- private String getBundleValue(String key, boolean mustExist) {
+ private static String getBundleValue(@NotNull String key, boolean mustExist) throws MissingResourceException {
try {
return Registry.getBundle().getString(key);
}
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 bc37f673bb03..e364a8568fda 100644
--- a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java
+++ b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java
@@ -1331,6 +1331,7 @@ public class StringUtil extends StringUtilRt {
}
public static boolean isQuotedString(@NotNull String text) {
+ if (text.length() < 2) return false;
return startsWithChar(text, '\"') && endsWithChar(text, '\"')
|| startsWithChar(text, '\'') && endsWithChar(text, '\'');
}
@@ -2678,7 +2679,7 @@ public class StringUtil extends StringUtilRt {
continue;
}
- if (i > 0 && (ch == '/' || ch == '\\' || ch == '.' || Character.isUpperCase(ch))) {
+ if (i > 0 && (ch == '/' || ch == '\\' || ch == '.' || ch == '-' || Character.isUpperCase(ch))) {
words.add(builder.toString());
builder.delete(0, builder.length());
}
diff --git a/platform/util/src/com/intellij/util/ReflectionUtil.java b/platform/util/src/com/intellij/util/ReflectionUtil.java
index df33a80d4cba..d5f6a58dc951 100644
--- a/platform/util/src/com/intellij/util/ReflectionUtil.java
+++ b/platform/util/src/com/intellij/util/ReflectionUtil.java
@@ -95,6 +95,7 @@ public class ReflectionUtil {
+ " loaded by " + ((Class)anInterface).getClassLoader();
}
+ @NotNull
public static Class<?> getRawType(@NotNull Type type) {
if (type instanceof Class) {
return (Class)type;
@@ -288,15 +289,18 @@ public class ReflectionUtil {
});
}
+ @NotNull
public static List<Method> getClassPublicMethods(@NotNull Class aClass) {
return getClassPublicMethods(aClass, false);
}
-
+
+ @NotNull
public static List<Method> getClassPublicMethods(@NotNull Class aClass, boolean includeSynthetic) {
Method[] methods = aClass.getMethods();
return includeSynthetic ? Arrays.asList(methods) : filterRealMethods(methods);
}
+ @NotNull
public static List<Method> getClassDeclaredMethods(@NotNull Class aClass) {
return getClassDeclaredMethods(aClass, false);
}
@@ -306,13 +310,15 @@ public class ReflectionUtil {
Method[] methods = aClass.getDeclaredMethods();
return includeSynthetic ? Arrays.asList(methods) : filterRealMethods(methods);
}
+
@NotNull
public static List<Field> getClassDeclaredFields(@NotNull Class aClass) {
Field[] fields = aClass.getDeclaredFields();
return Arrays.asList(fields);
}
- private static List<Method> filterRealMethods(Method[] methods) {
+ @NotNull
+ private static List<Method> filterRealMethods(@NotNull Method[] methods) {
List<Method> result = ContainerUtil.newArrayList();
for (Method method : methods) {
if (!method.isSynthetic()) {
@@ -323,8 +329,8 @@ public class ReflectionUtil {
}
@Nullable
- public static Class getMethodDeclaringClass(@NotNull Class<?> instanceClass, @NonNls @NotNull String name, @NotNull Class... parameters) {
- Method method = getMethod(instanceClass, name, parameters);
+ public static Class getMethodDeclaringClass(@NotNull Class<?> instanceClass, @NonNls @NotNull String methodName, @NotNull Class... parameters) {
+ Method method = getMethod(instanceClass, methodName, parameters);
return method == null ? null : method.getDeclaringClass();
}
diff --git a/platform/util/src/com/intellij/util/containers/ClassMap.java b/platform/util/src/com/intellij/util/containers/ClassMap.java
index 078dfd693e63..d2d3bbb3e6dc 100644
--- a/platform/util/src/com/intellij/util/containers/ClassMap.java
+++ b/platform/util/src/com/intellij/util/containers/ClassMap.java
@@ -16,6 +16,7 @@
package com.intellij.util.containers;
import gnu.trove.THashMap;
+import org.jetbrains.annotations.NotNull;
import java.util.Collection;
import java.util.Map;
@@ -29,18 +30,18 @@ public class ClassMap<T> {
public ClassMap() {
this(new THashMap<Class, T>());
}
- protected ClassMap(Map<Class, T> map) {
+ protected ClassMap(@NotNull Map<Class, T> map) {
myMap = map;
}
- public void put(Class aClass, T value) {
+ public void put(@NotNull Class aClass, T value) {
myMap.put(aClass, value);
}
- public void remove(Class aClass) {
+ public void remove(@NotNull Class aClass) {
myMap.remove(aClass);
}
- public T get(Class aClass) {
+ public T get(@NotNull Class aClass) {
T t = myMap.get(aClass);
if (t != null) {
return t;
@@ -63,6 +64,7 @@ public class ClassMap<T> {
return null;
}
+ @NotNull
public final Collection<T> values() {
return myMap.values();
}
diff --git a/platform/util/src/com/intellij/util/containers/ContainerUtil.java b/platform/util/src/com/intellij/util/containers/ContainerUtil.java
index 171cfababfa9..dca7a0e6b30d 100644
--- a/platform/util/src/com/intellij/util/containers/ContainerUtil.java
+++ b/platform/util/src/com/intellij/util/containers/ContainerUtil.java
@@ -1113,6 +1113,10 @@ public class ContainerUtil extends ContainerUtilRt {
*/
@NotNull
public static <T> List<T> concat(@NotNull final List<? extends T> list1, @NotNull final List<? extends T> list2) {
+ if (list1.isEmpty() && list2.isEmpty()) {
+ return Collections.emptyList();
+ }
+
final int size1 = list1.size();
final int size = size1 + list2.size();
diff --git a/platform/util/src/com/intellij/util/containers/TransferToEDTQueue.java b/platform/util/src/com/intellij/util/containers/TransferToEDTQueue.java
index 787ebc320490..5db4de22b401 100644
--- a/platform/util/src/com/intellij/util/containers/TransferToEDTQueue.java
+++ b/platform/util/src/com/intellij/util/containers/TransferToEDTQueue.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.
@@ -147,6 +147,12 @@ public class TransferToEDTQueue<T> {
}
}
+ public int size() {
+ synchronized (myQueue) {
+ return myQueue.size();
+ }
+ }
+
// process all queue in current thread
public void drain() {
int processed = 0;
diff --git a/platform/util/src/com/intellij/util/containers/WeakStringInterner.java b/platform/util/src/com/intellij/util/containers/WeakStringInterner.java
index ec223a8c6880..eb1c7b329f76 100644
--- a/platform/util/src/com/intellij/util/containers/WeakStringInterner.java
+++ b/platform/util/src/com/intellij/util/containers/WeakStringInterner.java
@@ -16,26 +16,27 @@
package com.intellij.util.containers;
import com.intellij.reference.SoftReference;
+import com.intellij.util.ConcurrencyUtil;
import org.jetbrains.annotations.NotNull;
import java.lang.ref.WeakReference;
-import java.util.*;
import java.util.HashSet;
+import java.util.Set;
/**
* @author peter
*/
public class WeakStringInterner extends StringInterner {
- private final WeakHashMap<String, WeakReference<String>> myMap = new WeakHashMap<String, WeakReference<String>>();
+ private final ConcurrentWeakHashMap<String, WeakReference<String>> myMap = new ConcurrentWeakHashMap<String, WeakReference<String>>();
@NotNull
@Override
public String intern(@NotNull String name) {
- String interned = SoftReference.dereference(myMap.get(name));
- if (interned != null) {
- return interned;
- }
- myMap.put(name, new WeakReference<String>(name));
+ WeakReference<String> key = new WeakReference<String>(name);
+ String interned = SoftReference.dereference(ConcurrencyUtil.cacheOrGet(myMap, name, key));
+ if (interned != null) return interned;
+
+ myMap.put(name, key);
return name;
}
diff --git a/platform/util/src/com/intellij/util/io/IntToIntBtree.java b/platform/util/src/com/intellij/util/io/IntToIntBtree.java
index b17fc6cc5c6c..475f3cb67a94 100644
--- a/platform/util/src/com/intellij/util/io/IntToIntBtree.java
+++ b/platform/util/src/com/intellij/util/io/IntToIntBtree.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.
@@ -30,7 +30,7 @@ import java.util.Arrays;
* Date: 7/12/11
* Time: 1:34 PM
*/
-class IntToIntBtree {
+public class IntToIntBtree {
public static int version() {
return 4 + (IOUtil.ourByteBuffersUseNativeByteOrder ? 0xFF : 0);
}
@@ -55,10 +55,10 @@ class IntToIntBtree {
private boolean hasZeroKey;
private int zeroKeyValue;
- private boolean isLarge = true;
+ private final boolean isLarge = true;
private final ResizeableMappedFile storage;
private final boolean offloadToSiblingsBeforeSplit = false;
- private boolean indexNodeIsHashTable = true;
+ private final boolean indexNodeIsHashTable = true;
final int metaDataLeafPageLength;
final int hashPageCapacity;
@@ -66,8 +66,8 @@ class IntToIntBtree {
private TIntIntHashMap myCachedMappings;
private final int myCachedMappingsSize;
- public IntToIntBtree(int _pageSize, File file, PagedFileStorage.StorageLockContext storageLockContext, boolean initial) throws IOException {
- pageSize = _pageSize;
+ public IntToIntBtree(int pageSize, @NotNull File file, @NotNull PagedFileStorage.StorageLockContext storageLockContext, boolean initial) throws IOException {
+ this.pageSize = pageSize;
if (initial) {
FileUtil.delete(file);
@@ -82,13 +82,12 @@ class IntToIntBtree {
root.setIndexLeaf(true);
}
- int i = (pageSize - BtreePage.RESERVED_META_PAGE_LEN) / BtreeIndexNodeView.INTERIOR_SIZE - 1;
+ int i = (this.pageSize - BtreePage.RESERVED_META_PAGE_LEN) / BtreeIndexNodeView.INTERIOR_SIZE - 1;
assert i < Short.MAX_VALUE && i % 2 == 0;
maxInteriorNodes = (short)i;
maxLeafNodes = (short)i;
- int metaPageLen = BtreePage.RESERVED_META_PAGE_LEN;
-
+ int metaPageLen;
if (indexNodeIsHashTable) {
++i;
while(!isPrime(i)) i -= 2;
@@ -97,8 +96,10 @@ class IntToIntBtree {
metaPageLen = BtreePage.RESERVED_META_PAGE_LEN;
i = (int)(hashPageCapacity * 0.9);
if ((i & 1) == 1) ++i;
- } else {
+ }
+ else {
hashPageCapacity = -1;
+ metaPageLen = BtreePage.RESERVED_META_PAGE_LEN;
}
metaDataLeafPageLength = metaPageLen;
@@ -108,20 +109,18 @@ class IntToIntBtree {
if (hasCachedMappings) {
myCachedMappings = new TIntIntHashMap(myCachedMappingsSize = 4 * maxLeafNodes);
- } else {
+ }
+ else {
myCachedMappings = null;
myCachedMappingsSize = -1;
}
}
- public void persistVars(BtreeDataStorage storage, boolean toDisk) {
- if (toDisk) {
- storage.persistInt(0, height | (hasZeroKey ? HAS_ZERO_KEY_MASK :0), true);
- } else {
- int i = storage.persistInt(0, 0, false);
- hasZeroKey = (i & HAS_ZERO_KEY_MASK) != 0;
- height = i & ~HAS_ZERO_KEY_MASK;
- }
+ // return total number of bytes needed for storing information
+ public int persistVars(@NotNull BtreeDataStorage storage, boolean toDisk) {
+ int i = storage.persistInt(0, height | (hasZeroKey ? HAS_ZERO_KEY_MASK :0), toDisk);
+ hasZeroKey = (i & HAS_ZERO_KEY_MASK) != 0;
+ height = i & ~HAS_ZERO_KEY_MASK;
pagesCount = storage.persistInt(4, pagesCount, toDisk);
movedMembersCount = storage.persistInt(8, movedMembersCount, toDisk);
@@ -132,9 +131,10 @@ class IntToIntBtree {
hashedPagesCount = storage.persistInt(28, hashedPagesCount, toDisk);
root.setAddress(storage.persistInt(32, root.address, toDisk));
zeroKeyValue = storage.persistInt(36, zeroKeyValue, toDisk);
+ return 40;
}
- interface BtreeDataStorage {
+ public interface BtreeDataStorage {
int persistInt(int offset, int value, boolean toDisk);
}
@@ -155,10 +155,11 @@ class IntToIntBtree {
}
private BtreeIndexNodeView myAccessNodeView;
- private int myLastGetKey, myOptimizedInserts;
+ private int myLastGetKey;
+ private int myOptimizedInserts;
private boolean myCanUseLastKey;
- public boolean get(int key, int[] result) {
+ public boolean get(int key, @NotNull int[] result) {
if (key == 0) {
if (hasZeroKey) {
result[0] = zeroKeyValue;
@@ -199,7 +200,8 @@ class IntToIntBtree {
if (hasCachedMappings) {
myCachedMappings.put(key, value);
if (myCachedMappings.size() == myCachedMappingsSize) flushCachedMappings();
- } else {
+ }
+ else {
boolean canUseLastKey = myCanUseLastKey;
if (canUseLastKey) {
myCanUseLastKey = false;
@@ -256,12 +258,12 @@ class IntToIntBtree {
}
}
- void doClose() throws IOException {
+ public void doClose() throws IOException {
myCachedMappings = null;
storage.close();
}
- void doFlush() {
+ public void doFlush() {
flushCachedMappings();
storage.force();
}
@@ -445,11 +447,11 @@ class IntToIntBtree {
putInt(offset, value);
}
- private final int indexToOffset(int i) {
+ private int indexToOffset(int i) {
return i * INTERIOR_SIZE + (isHashedLeaf() ? btree.metaDataLeafPageLength:RESERVED_META_PAGE_LEN);
}
- private final int keyAt(int i) {
+ private int keyAt(int i) {
if (doSanityCheck) {
if (isHashedLeaf()) myAssert(i < btree.hashPageCapacity);
else myAssert(i < getChildrenCount());
@@ -495,7 +497,7 @@ class IntToIntBtree {
setFlag(INDEX_LEAF_MASK, value);
}
- private final boolean isHashedLeaf() {
+ private boolean isHashedLeaf() {
return isHashedLeaf;
}
@@ -608,7 +610,8 @@ class IntToIntBtree {
if (hashedLeaf) {
hashLeafData = new HashLeafData(this, recordCount);
if (doOffloadToSiblingsWhenHashed(parent, hashLeafData)) return parentAddress;
- } else {
+ }
+ else {
if (doOffloadToSiblingsSorted(parent)) return parentAddress;
}
}
@@ -1074,16 +1077,14 @@ class IntToIntBtree {
private static final boolean useDoubleHash = true;
private int hashIndex(int value) {
- int hash, index;
-
final int length = btree.hashPageCapacity;
- hash = value & 0x7fffffff;
- index = hash % length;
+ int hash = value & 0x7fffffff;
+ int index = hash % length;
int keyAtIndex = keyAt(index);
- int total = 0;
btree.hashSearchRequests++;
+ int total = 0;
if (useDoubleHash) {
if (keyAtIndex != value && keyAtIndex != HASH_FREE) {
// see Knuth, p. 529
@@ -1148,11 +1149,21 @@ class IntToIntBtree {
if (childrenAddresses.length > 0) {
BtreeIndexNodeView child = new BtreeIndexNodeView(this);
- for(int i = 0; i < childrenAddresses.length; ++i) {
- child.setAddress(childrenAddresses[i]);
- if (!processLeafPages(child, processor)) return false;
+ for (int childrenAddress : childrenAddresses) {
+ child.setAddress(childrenAddress);
+ if (!processLeafPages(child, processor)) return false;
}
}
return true;
}
+
+ public void withStorageLock(@NotNull Runnable runnable) {
+ storage.getPagedFileStorage().lock();
+ try {
+ runnable.run();
+ }
+ finally {
+ storage.getPagedFileStorage().unlock();
+ }
+ }
}
diff --git a/platform/util/src/com/intellij/util/io/PagedFileStorage.java b/platform/util/src/com/intellij/util/io/PagedFileStorage.java
index 69315f1b3764..1fca8e063394 100644
--- a/platform/util/src/com/intellij/util/io/PagedFileStorage.java
+++ b/platform/util/src/com/intellij/util/io/PagedFileStorage.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.
@@ -88,11 +88,11 @@ public class PagedFileStorage implements Forceable {
private static final ByteOrder ourNativeByteOrder = ByteOrder.nativeOrder();
public void lock() {
- myStorageLockContext.myLock.lock();
+ myStorageLockContext.lock();
}
public void unlock() {
- myStorageLockContext.myLock.unlock();
+ myStorageLockContext.unlock();
}
public StorageLockContext getStorageLockContext() {
@@ -510,11 +510,11 @@ public class PagedFileStorage implements Forceable {
}
public void lock() {
- myDefaultStorageLockContext.myLock.lock();
+ myDefaultStorageLockContext.lock();
}
public void unlock() {
- myDefaultStorageLockContext.myLock.unlock();
+ myDefaultStorageLockContext.unlock();
}
private int registerPagedFileStorage(@NotNull PagedFileStorage storage) {
@@ -658,7 +658,9 @@ public class PagedFileStorage implements Forceable {
LOG.info("Max memory:"+maxMemory.get(null) + ", reserved memory:" + reservedMemory.get(null));
}
}
- catch (Throwable t) {}
+ catch (Throwable t) {
+
+ }
throw new MappingFailedException(
"Cannot recover from OOME in memory mapping: -Xmx=" + Runtime.getRuntime().maxMemory() / MB + "MB " +
"new size limit: " + mySizeLimit / MB + "MB " +
@@ -669,7 +671,7 @@ public class PagedFileStorage implements Forceable {
}
}
- private void checkThreadAccess(StorageLockContext storageLockContext) {
+ private static void checkThreadAccess(StorageLockContext storageLockContext) {
if (storageLockContext.myCheckThreadAccess && !storageLockContext.myLock.isHeldByCurrentThread()) {
throw new IllegalStateException("Must hold StorageLock lock to access PagedFileStorage");
}
@@ -776,5 +778,12 @@ public class PagedFileStorage implements Forceable {
public StorageLockContext(boolean checkAccess) {
this(ourLock, checkAccess);
}
+
+ public void lock() {
+ myLock.lock();
+ }
+ public void unlock() {
+ myLock.unlock();
+ }
}
}
diff --git a/platform/util/src/com/intellij/util/io/RandomAccessDataFile.java b/platform/util/src/com/intellij/util/io/RandomAccessDataFile.java
index 9a297bcef6d1..d4383a55d03e 100644
--- a/platform/util/src/com/intellij/util/io/RandomAccessDataFile.java
+++ b/platform/util/src/com/intellij/util/io/RandomAccessDataFile.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,11 +47,11 @@ public class RandomAccessDataFile implements Forceable, Closeable {
private static final boolean DEBUG = false;
- public RandomAccessDataFile(final File file) throws IOException {
+ public RandomAccessDataFile(@NotNull File file) throws IOException {
this(file, PagePool.SHARED);
}
- public RandomAccessDataFile(final File file, final PagePool pool) throws IOException {
+ public RandomAccessDataFile(@NotNull File file, @NotNull PagePool pool) throws IOException {
myPool = pool;
myFile = file;
if (!file.exists()) {
@@ -201,6 +201,9 @@ public class RandomAccessDataFile implements Forceable, Closeable {
dispose();
}
+ /**
+ * Flushes dirty pages to underlying buffers
+ */
@Override
public void force() {
assertNotDisposed();
@@ -210,6 +213,23 @@ public class RandomAccessDataFile implements Forceable, Closeable {
}
}
+ /**
+ * Flushes dirty pages to buffers and saves them to disk
+ */
+ public void sync() {
+ force();
+ try {
+ RandomAccessFile file = getRandomAccessFile();
+ file.getChannel().force(true);
+ }
+ catch (IOException ignored) {
+
+ }
+ finally {
+ releaseFile();
+ }
+ }
+
public void flushSomePages(int maxPagesToFlush) {
assertNotDisposed();
if (isDirty()) {
@@ -229,7 +249,7 @@ public class RandomAccessDataFile implements Forceable, Closeable {
private void assertNotDisposed() {
if (myIsDisposed) {
- LOG.assertTrue(false, "storage file is disposed: " + myFile);
+ LOG.error("storage file is disposed: " + myFile);
}
}
@@ -316,6 +336,7 @@ public class RandomAccessDataFile implements Forceable, Closeable {
file.seek(fileOffset);
}
+ @Override
public int hashCode() {
return myCount;
}
diff --git a/platform/util/src/com/intellij/util/io/storage/HeavyProcessLatch.java b/platform/util/src/com/intellij/util/io/storage/HeavyProcessLatch.java
index e0d349c0c7ad..663cd215cfbe 100644
--- a/platform/util/src/com/intellij/util/io/storage/HeavyProcessLatch.java
+++ b/platform/util/src/com/intellij/util/io/storage/HeavyProcessLatch.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,19 +19,47 @@
*/
package com.intellij.util.io.storage;
+import com.intellij.openapi.Disposable;
+import com.intellij.openapi.util.Disposer;
+import com.intellij.util.EventDispatcher;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.EventListener;
+import java.util.concurrent.atomic.AtomicInteger;
+
public class HeavyProcessLatch {
public static final HeavyProcessLatch INSTANCE = new HeavyProcessLatch();
- private int myHeavyProcessCounter = 0;
-
- public synchronized void processStarted() {
- myHeavyProcessCounter++;
+
+ private final AtomicInteger myHeavyProcessCounter = new AtomicInteger();
+ private final EventDispatcher<HeavyProcessListener> myEventDispatcher = EventDispatcher.create(HeavyProcessListener.class);
+
+ private HeavyProcessLatch() {
+ }
+
+ public void processStarted() {
+ myHeavyProcessCounter.incrementAndGet();
+ myEventDispatcher.getMulticaster().processStarted();
}
- public synchronized void processFinished() {
- myHeavyProcessCounter--;
+ public void processFinished() {
+ myHeavyProcessCounter.decrementAndGet();
+ myEventDispatcher.getMulticaster().processFinished();
+ }
+
+ public boolean isRunning() {
+ return myHeavyProcessCounter.get() != 0;
+ }
+
+ public interface HeavyProcessListener extends EventListener {
+ public void processStarted();
+
+ public void processFinished();
}
- public synchronized boolean isRunning() {
- return myHeavyProcessCounter != 0;
+ @NotNull
+ public Disposable addListener(@NotNull HeavyProcessListener listener) {
+ Disposable disposable = Disposer.newDisposable();
+ myEventDispatcher.addListener(listener, disposable);
+ return disposable;
}
} \ 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 d5bc95f99cef..f9517ad09ade 100644
--- a/platform/util/src/com/intellij/util/text/StringSearcher.java
+++ b/platform/util/src/com/intellij/util/text/StringSearcher.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.
@@ -123,7 +123,7 @@ public class StringSearcher {
}
}
- int step = 0 <= lastChar && lastChar < 128 ? mySearchTable[lastChar] : 1;
+ int step = lastChar < 128 ? mySearchTable[lastChar] : 1;
if (step <= 0) {
int index;
@@ -160,7 +160,7 @@ public class StringSearcher {
if (i < 0) return end - start - myPatternLength + 1;
}
- int step = 0 <= lastChar && lastChar < 128 ? mySearchTable[lastChar] : 1;
+ int step = lastChar < 128 ? mySearchTable[lastChar] : 1;
if (step <= 0) {
int index;
diff --git a/platform/util/src/com/intellij/util/xmlb/MapBinding.java b/platform/util/src/com/intellij/util/xmlb/MapBinding.java
index 6a8423d2ed4b..dbc3c0e082c3 100644
--- a/platform/util/src/com/intellij/util/xmlb/MapBinding.java
+++ b/platform/util/src/com/intellij/util/xmlb/MapBinding.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,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package com.intellij.util.xmlb;
import com.intellij.openapi.util.JDOMUtil;
@@ -35,22 +34,22 @@ import java.util.Set;
import static com.intellij.util.xmlb.Constants.*;
class MapBinding implements Binding {
- private final Binding myKeyBinding;
- private final Binding myValueBinding;
- private final MapAnnotation myMapAnnotation;
private static final Comparator<Object> KEY_COMPARATOR = new Comparator<Object>() {
+ @SuppressWarnings("unchecked")
@Override
- public int compare(final Object o1, final Object o2) {
+ public int compare(Object o1, Object o2) {
if (o1 instanceof Comparable && o2 instanceof Comparable) {
Comparable c1 = (Comparable)o1;
Comparable c2 = (Comparable)o2;
return c1.compareTo(c2);
}
-
return 0;
}
};
+ private final Binding myKeyBinding;
+ private final Binding myValueBinding;
+ private final MapAnnotation myMapAnnotation;
public MapBinding(ParameterizedType type, Accessor accessor) {
Type[] arguments = type.getActualTypeArguments();
@@ -69,7 +68,7 @@ class MapBinding implements Binding {
Element m;
if (myMapAnnotation == null || myMapAnnotation.surroundWithTag()) {
- m = new Element(Constants.MAP);
+ m = new Element(MAP);
}
else {
m = (Element)context;
@@ -92,14 +91,14 @@ class MapBinding implements Binding {
if (kNode instanceof Text) {
Text text = (Text)kNode;
- entry.setAttribute(getKeyAttributeValue(), text.getText());
+ entry.setAttribute(getKeyAttributeName(), text.getText());
}
else {
if (myMapAnnotation != null && !myMapAnnotation.surroundKeyWithTag()) {
entry.addContent((Content)kNode);
}
else {
- Element key = new Element(getKeyAttributeValue());
+ Element key = new Element(getKeyAttributeName());
entry.addContent(key);
key.addContent((Content)kNode);
}
@@ -129,12 +128,12 @@ class MapBinding implements Binding {
return myMapAnnotation == null ? ENTRY : myMapAnnotation.entryTagName();
}
- private String getValueAttributeName() {
- return myMapAnnotation == null ? VALUE : myMapAnnotation.valueAttributeName();
+ private String getKeyAttributeName() {
+ return myMapAnnotation == null ? KEY : myMapAnnotation.keyAttributeName();
}
- private String getKeyAttributeValue() {
- return myMapAnnotation == null ? KEY : myMapAnnotation.keyAttributeName();
+ private String getValueAttributeName() {
+ return myMapAnnotation == null ? VALUE : myMapAnnotation.valueAttributeName();
}
@Override
@@ -164,7 +163,7 @@ class MapBinding implements Binding {
assert entry.getName().equals(getEntryAttributeName());
- Attribute keyAttr = entry.getAttribute(getKeyAttributeValue());
+ Attribute keyAttr = entry.getAttribute(getKeyAttributeName());
if (keyAttr != null) {
k = myKeyBinding.deserialize(o, keyAttr);
}
@@ -181,7 +180,7 @@ class MapBinding implements Binding {
assert k != null : "no key found";
}
else {
- final Object keyNode = entry.getChildren(getKeyAttributeValue()).get(0);
+ final Object keyNode = entry.getChildren(getKeyAttributeName()).get(0);
k = myKeyBinding.deserialize(o, JDOMUtil.getContent((Element)keyNode));
}
}
@@ -223,7 +222,7 @@ class MapBinding implements Binding {
return myMapAnnotation.entryTagName().equals(((Element)node).getName());
}
- return ((Element)node).getName().equals(Constants.MAP);
+ return ((Element)node).getName().equals(MAP);
}
@Override
diff --git a/platform/util/testSrc/com/intellij/openapi/util/io/FileUtilLightTest.java b/platform/util/testSrc/com/intellij/openapi/util/io/FileUtilLightTest.java
index bf0e0d5b9036..dd1f46dace4c 100644
--- a/platform/util/testSrc/com/intellij/openapi/util/io/FileUtilLightTest.java
+++ b/platform/util/testSrc/com/intellij/openapi/util/io/FileUtilLightTest.java
@@ -18,11 +18,13 @@ package com.intellij.openapi.util.io;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.util.ArrayUtil;
import com.intellij.util.PairProcessor;
+import com.intellij.util.SystemProperties;
import com.intellij.util.ThreeState;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.Convertor;
import org.junit.Test;
+import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.util.Arrays;
@@ -189,4 +191,11 @@ public class FileUtilLightTest {
assertEquals("/a/b/.././c/", FileUtil.normalize("\\\\\\a\\\\//b//..///./c//"));
}
}
+
+ @Test
+ public void testRelativeToUserHome() {
+ assertEquals(SystemProperties.getUserHome(), FileUtil.getLocationRelativeToUserHome(SystemProperties.getUserHome(), false));
+ String expected = SystemInfo.isWindows ? "~\\relative" : "~/relative";
+ assertEquals(expected, FileUtil.getLocationRelativeToUserHome(SystemProperties.getUserHome() + "/relative", false));
+ }
}
diff --git a/platform/util/testSrc/com/intellij/util/text/StringUtilTest.java b/platform/util/testSrc/com/intellij/util/text/StringUtilTest.java
index 383c07f2a87e..d2f593d13ff1 100644
--- a/platform/util/testSrc/com/intellij/util/text/StringUtilTest.java
+++ b/platform/util/testSrc/com/intellij/util/text/StringUtilTest.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.
@@ -178,6 +178,16 @@ public class StringUtilTest extends TestCase {
assertEquals("foo|", StringUtil.unquoteString("foo|", '|'));
}
+ public void testIsQuotedString() {
+ assertFalse(StringUtil.isQuotedString(""));
+ assertFalse(StringUtil.isQuotedString("'"));
+ assertFalse(StringUtil.isQuotedString("\""));
+ assertTrue(StringUtil.isQuotedString("\"\""));
+ assertTrue(StringUtil.isQuotedString("''"));
+ assertTrue(StringUtil.isQuotedString("'ab'"));
+ assertTrue(StringUtil.isQuotedString("\"foo\""));
+ }
+
public void testJoin() {
assertEquals("foo,,bar", StringUtil.join(Arrays.asList("foo", "", "bar"), ","));
assertEquals("foo,,bar", StringUtil.join(new String[]{"foo", "", "bar"}, ","));
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 c6b0daa0852d..938021c03e55 100644
--- a/platform/vcs-api/src/com/intellij/openapi/vcs/ProjectLevelVcsManager.java
+++ b/platform/vcs-api/src/com/intellij/openapi/vcs/ProjectLevelVcsManager.java
@@ -229,7 +229,8 @@ public abstract class ProjectLevelVcsManager {
public abstract boolean isBackgroundVcsOperationRunning();
public abstract List<VirtualFile> getRootsUnderVcsWithoutFiltering(final AbstractVcs vcs);
- public abstract VirtualFile[] getRootsUnderVcs(AbstractVcs vcs);
+
+ public abstract VirtualFile[] getRootsUnderVcs(@NotNull AbstractVcs vcs);
/**
* Also includes into list all modules under roots
diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/update/FileGroup.java b/platform/vcs-api/src/com/intellij/openapi/vcs/update/FileGroup.java
index a5fa2c121ed2..d9684018484a 100644
--- a/platform/vcs-api/src/com/intellij/openapi/vcs/update/FileGroup.java
+++ b/platform/vcs-api/src/com/intellij/openapi/vcs/update/FileGroup.java
@@ -254,6 +254,9 @@ public class FileGroup implements JDOMExternalizable {
return null;
}
+ /**
+ * @deprecated: remove after IDEA 14
+ */
public void setRevisions(final String path, final AbstractVcs vcs, final VcsRevisionNumber revision) {
for (UpdatedFile file : myFiles) {
if (file.getPath().startsWith(path)) {
diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/update/UpdatedFiles.java b/platform/vcs-api/src/com/intellij/openapi/vcs/update/UpdatedFiles.java
index d8d6d53371d8..fdd3237af1cd 100644
--- a/platform/vcs-api/src/com/intellij/openapi/vcs/update/UpdatedFiles.java
+++ b/platform/vcs-api/src/com/intellij/openapi/vcs/update/UpdatedFiles.java
@@ -106,6 +106,10 @@ public class UpdatedFiles implements JDOMExternalizable {
return result;
}
+ /**
+ * @deprecated: remove after IDEA 14
+ */
+ @SuppressWarnings("UnusedDeclaration")
public void setRevisions(final String path, final AbstractVcs vcs, final VcsRevisionNumber revision) {
for(FileGroup group: myGroups) {
group.setRevisions(path, vcs, revision);
diff --git a/platform/vcs-api/src/com/intellij/vcsUtil/VcsUtil.java b/platform/vcs-api/src/com/intellij/vcsUtil/VcsUtil.java
index bdd9304e9d88..7266e344c72f 100644
--- a/platform/vcs-api/src/com/intellij/vcsUtil/VcsUtil.java
+++ b/platform/vcs-api/src/com/intellij/vcsUtil/VcsUtil.java
@@ -577,18 +577,6 @@ public class VcsUtil {
return files;
}
- public static boolean caseDiffers(final String s1, final String s2) {
- String s1Trimmed = s1.trim();
- String s2Trimmed = s2.trim();
-
- if (File.separatorChar != '/') {
- s1Trimmed = s1Trimmed.replace(File.separatorChar, '/');
- s2Trimmed = s2Trimmed.replace(File.separatorChar, '/');
- }
-
- return (! s1Trimmed.equals(s2Trimmed)) && s1Trimmed.equalsIgnoreCase(s2Trimmed);
- }
-
private static final String ANNO_ASPECT = "show.vcs.annotation.aspect.";
//public static boolean isAspectAvailableByDefault(LineAnnotationAspect aspect) {
// if (aspect.getId() == null) return aspect.isShowByDefault();
diff --git a/platform/vcs-api/src/com/intellij/lifecycle/PeriodicalTasksCloser.java b/platform/vcs-api/vcs-api-core/src/com/intellij/lifecycle/PeriodicalTasksCloser.java
index bbb4847fbc64..3b6a7ff2a5c6 100644
--- a/platform/vcs-api/src/com/intellij/lifecycle/PeriodicalTasksCloser.java
+++ b/platform/vcs-api/vcs-api-core/src/com/intellij/lifecycle/PeriodicalTasksCloser.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.
diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/FilePath.java b/platform/vcs-api/vcs-api-core/src/com/intellij/openapi/vcs/FilePath.java
index 90fd92f2e78e..1ca489c0d128 100644
--- a/platform/vcs-api/src/com/intellij/openapi/vcs/FilePath.java
+++ b/platform/vcs-api/vcs-api-core/src/com/intellij/openapi/vcs/FilePath.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.
diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/VcsException.java b/platform/vcs-api/vcs-api-core/src/com/intellij/openapi/vcs/VcsException.java
index 5a72bfe1fba6..dacf4e654f5f 100644
--- a/platform/vcs-api/src/com/intellij/openapi/vcs/VcsException.java
+++ b/platform/vcs-api/vcs-api-core/src/com/intellij/openapi/vcs/VcsException.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.
diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/VcsKey.java b/platform/vcs-api/vcs-api-core/src/com/intellij/openapi/vcs/VcsKey.java
index f3a507cf8e56..4e2871b3f539 100644
--- a/platform/vcs-api/src/com/intellij/openapi/vcs/VcsKey.java
+++ b/platform/vcs-api/vcs-api-core/src/com/intellij/openapi/vcs/VcsKey.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.
diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/changes/Change.java b/platform/vcs-api/vcs-api-core/src/com/intellij/openapi/vcs/changes/Change.java
index 8e300bd2a291..b1d8978eea68 100644
--- a/platform/vcs-api/src/com/intellij/openapi/vcs/changes/Change.java
+++ b/platform/vcs-api/vcs-api-core/src/com/intellij/openapi/vcs/changes/Change.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.
@@ -25,7 +25,7 @@ import com.intellij.openapi.vcs.FileStatus;
import com.intellij.openapi.vcs.VcsBundle;
import com.intellij.openapi.vcs.impl.VcsPathPresenter;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.vcsUtil.VcsUtil;
+import com.intellij.vcsUtil.VcsFilePathUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
@@ -120,7 +120,8 @@ public class Change {
}
if ((! Comparing.equal(myBeforeRevision.getFile(), myAfterRevision.getFile())) ||
- ((! SystemInfo.isFileSystemCaseSensitive) && VcsUtil.caseDiffers(myBeforeRevision.getFile().getPath(), myAfterRevision.getFile().getPath()))) {
+ ((! SystemInfo.isFileSystemCaseSensitive) && VcsFilePathUtil
+ .caseDiffers(myBeforeRevision.getFile().getPath(), myAfterRevision.getFile().getPath()))) {
myType = Type.MOVED;
return myType;
}
diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/changes/ContentRevision.java b/platform/vcs-api/vcs-api-core/src/com/intellij/openapi/vcs/changes/ContentRevision.java
index af21b167041f..de5944ac9b3c 100644
--- a/platform/vcs-api/src/com/intellij/openapi/vcs/changes/ContentRevision.java
+++ b/platform/vcs-api/vcs-api-core/src/com/intellij/openapi/vcs/changes/ContentRevision.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.
diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/changes/MergeTexts.java b/platform/vcs-api/vcs-api-core/src/com/intellij/openapi/vcs/changes/MergeTexts.java
index 18423d8ad490..16ed06a00b41 100644
--- a/platform/vcs-api/src/com/intellij/openapi/vcs/changes/MergeTexts.java
+++ b/platform/vcs-api/vcs-api-core/src/com/intellij/openapi/vcs/changes/MergeTexts.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.
diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/history/LongRevisionNumber.java b/platform/vcs-api/vcs-api-core/src/com/intellij/openapi/vcs/history/LongRevisionNumber.java
index ffcedbb456c2..52bae307b01e 100644
--- a/platform/vcs-api/src/com/intellij/openapi/vcs/history/LongRevisionNumber.java
+++ b/platform/vcs-api/vcs-api-core/src/com/intellij/openapi/vcs/history/LongRevisionNumber.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.
diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/history/VcsRevisionNumber.java b/platform/vcs-api/vcs-api-core/src/com/intellij/openapi/vcs/history/VcsRevisionNumber.java
index 4647ecac78af..9d5851da6889 100644
--- a/platform/vcs-api/src/com/intellij/openapi/vcs/history/VcsRevisionNumber.java
+++ b/platform/vcs-api/vcs-api-core/src/com/intellij/openapi/vcs/history/VcsRevisionNumber.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.
diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/impl/VcsPathPresenter.java b/platform/vcs-api/vcs-api-core/src/com/intellij/openapi/vcs/impl/VcsPathPresenter.java
index b8c239f84a71..9985cf77518f 100644
--- a/platform/vcs-api/src/com/intellij/openapi/vcs/impl/VcsPathPresenter.java
+++ b/platform/vcs-api/vcs-api-core/src/com/intellij/openapi/vcs/impl/VcsPathPresenter.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.
diff --git a/platform/vcs-api/src/com/intellij/vcsUtil/Rethrow.java b/platform/vcs-api/vcs-api-core/src/com/intellij/vcsUtil/Rethrow.java
index dc2e3b9409bd..6c42caaa3126 100644
--- a/platform/vcs-api/src/com/intellij/vcsUtil/Rethrow.java
+++ b/platform/vcs-api/vcs-api-core/src/com/intellij/vcsUtil/Rethrow.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.
diff --git a/platform/vcs-api/vcs-api-core/src/com/intellij/vcsUtil/VcsFilePathUtil.java b/platform/vcs-api/vcs-api-core/src/com/intellij/vcsUtil/VcsFilePathUtil.java
new file mode 100644
index 000000000000..b6992f53ab0c
--- /dev/null
+++ b/platform/vcs-api/vcs-api-core/src/com/intellij/vcsUtil/VcsFilePathUtil.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.vcsUtil;
+
+import java.io.File;
+
+public class VcsFilePathUtil {
+ public static boolean caseDiffers(final String s1, final String s2) {
+ String s1Trimmed = s1.trim();
+ String s2Trimmed = s2.trim();
+
+ if (File.separatorChar != '/') {
+ s1Trimmed = s1Trimmed.replace(File.separatorChar, '/');
+ s2Trimmed = s2Trimmed.replace(File.separatorChar, '/');
+ }
+
+ return (! s1Trimmed.equals(s2Trimmed)) && s1Trimmed.equalsIgnoreCase(s2Trimmed);
+ }
+}
diff --git a/platform/vcs-api/vcs-api-core/vcs-api-core.iml b/platform/vcs-api/vcs-api-core/vcs-api-core.iml
new file mode 100644
index 000000000000..434160533f3b
--- /dev/null
+++ b/platform/vcs-api/vcs-api-core/vcs-api-core.iml
@@ -0,0 +1,15 @@
+<?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="annotations" />
+ <orderEntry type="module" module-name="core-api" />
+ <orderEntry type="module" module-name="editor-ui-api" />
+ </component>
+</module>
+
diff --git a/platform/vcs-api/vcs-api.iml b/platform/vcs-api/vcs-api.iml
index 685d664dd28f..d6c7d2eb1b67 100644
--- a/platform/vcs-api/vcs-api.iml
+++ b/platform/vcs-api/vcs-api.iml
@@ -9,6 +9,7 @@
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="platform-api" exported="" />
<orderEntry type="library" name="microba" level="project" />
+ <orderEntry type="module" module-name="vcs-api-core" exported="" />
</component>
</module>
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/CommonCheckinFilesAction.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/CommonCheckinFilesAction.java
index 89d1f5695e63..1829413f0f7e 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/CommonCheckinFilesAction.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/CommonCheckinFilesAction.java
@@ -23,12 +23,14 @@ import com.intellij.openapi.vcs.changes.LocalChangeList;
import com.intellij.openapi.vcs.checkin.CheckinEnvironment;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.HashSet;
+import org.jetbrains.annotations.NotNull;
import java.util.Collection;
import java.util.Iterator;
import java.util.Set;
public class CommonCheckinFilesAction extends AbstractCommonCheckinAction {
+ @Override
protected String getActionName(final VcsContext dataContext) {
final String checkinActionName = getCheckinActionName(dataContext);
return modifyCheckinActionName(dataContext, checkinActionName);
@@ -125,14 +127,16 @@ public class CommonCheckinFilesAction extends AbstractCommonCheckinAction {
return false;
}
- protected boolean isApplicableRoot(VirtualFile file, FileStatus status, VcsContext dataContext) {
+ protected boolean isApplicableRoot(@NotNull VirtualFile file, @NotNull FileStatus status, @NotNull VcsContext dataContext) {
return status != FileStatus.UNKNOWN && status != FileStatus.IGNORED;
}
+ @Override
protected FilePath[] getRoots(final VcsContext context) {
return context.getSelectedFilePaths();
}
+ @Override
protected boolean filterRootsBeforeAction() {
return true;
}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/AbstractRefreshablePanel.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/AbstractRefreshablePanel.java
index 070a4e95587a..fe20806a8ed4 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/AbstractRefreshablePanel.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/AbstractRefreshablePanel.java
@@ -49,7 +49,7 @@ public abstract class AbstractRefreshablePanel<T> implements RefreshablePanel<Ch
private final DetailsPanel myDetailsPanel;
private final GenericDetailsLoader<Ticket, T> myDetailsLoader;
private final BackgroundTaskQueue myQueue;
- private boolean myDisposed;
+ private volatile boolean myDisposed;
protected AbstractRefreshablePanel(final Project project, final String loadingTitle, final BackgroundTaskQueue queue) {
myQueue = queue;
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangesFragmentedDiffPanel.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangesFragmentedDiffPanel.java
index 025795eb08ed..731634b85080 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangesFragmentedDiffPanel.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangesFragmentedDiffPanel.java
@@ -549,7 +549,7 @@ public class ChangesFragmentedDiffPanel implements Disposable {
}
private static final int[] ourMarks = {1,2,4,8,-1};
- public static final Hashtable<Integer,JLabel> LABELS = new Hashtable<Integer, JLabel>();
+ public static final Hashtable<Integer, JComponent> LABELS = new Hashtable<Integer, JComponent>();
public static final int ALL_VALUE = 5;
static {
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 77dd9b3f42b3..ce6ca72ab996 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
@@ -218,8 +218,8 @@ public class FragmentedDiffRequestFromChange {
final List<BeforeAfter<TextRange>> result = new ArrayList<BeforeAfter<TextRange>>();
if (myRanges == null || myRanges.isEmpty()) return Collections.emptyList();
for (Range range : myRanges) {
- final TextRange before = new TextRange(range.getUOffset1(), range.getUOffset2());
- final TextRange after = new TextRange(range.getOffset1(), range.getOffset2());
+ final TextRange before = new TextRange(range.getVcsLine1(), range.getVcsLine2());
+ final TextRange after = new TextRange(range.getLine1(), range.getLine2());
result.add(new BeforeAfter<TextRange>(before, after));
}
return result;
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CommittedChangesCache.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CommittedChangesCache.java
index 2da25f6e92c1..6619b98ea5e9 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CommittedChangesCache.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CommittedChangesCache.java
@@ -44,6 +44,7 @@ import com.intellij.util.Consumer;
import com.intellij.util.MessageBusUtil;
import com.intellij.util.NotNullFunction;
import com.intellij.util.containers.ConcurrentHashMap;
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import com.intellij.util.messages.MessageBus;
import com.intellij.util.messages.MessageBusConnection;
@@ -772,16 +773,21 @@ public class CommittedChangesCache implements PersistentStateComponent<Committed
}
public void processUpdatedFiles(final UpdatedFiles updatedFiles) {
+ processUpdatedFiles(updatedFiles, null);
+ }
+
+ public void processUpdatedFiles(final UpdatedFiles updatedFiles,
+ @Nullable final Consumer<List<CommittedChangeList>> incomingChangesConsumer) {
final Runnable task = new Runnable() {
@Override
public void run() {
debug("Processing updated files");
final Collection<ChangesCacheFile> caches = myCachesHolder.getAllCaches();
+ myPendingUpdateCount += caches.size();
for(final ChangesCacheFile cache: caches) {
- myPendingUpdateCount++;
try {
if (cache.isEmpty()) {
- pendingUpdateProcessed();
+ pendingUpdateProcessed(incomingChangesConsumer);
continue;
}
debug("Processing updated files in " + cache.getLocation());
@@ -789,12 +795,12 @@ public class CommittedChangesCache implements PersistentStateComponent<Committed
if (needRefresh) {
debug("Found unaccounted files, requesting refresh");
// todo do we need double-queueing here???
- processUpdatedFilesAfterRefresh(cache, updatedFiles);
+ processUpdatedFilesAfterRefresh(cache, updatedFiles, incomingChangesConsumer);
}
else {
debug("Clearing cached incoming changelists");
myCachedIncomingChangeLists = null;
- pendingUpdateProcessed();
+ pendingUpdateProcessed(incomingChangesConsumer);
}
}
catch (IOException e) {
@@ -806,15 +812,20 @@ public class CommittedChangesCache implements PersistentStateComponent<Committed
myTaskQueue.run(task);
}
- private void pendingUpdateProcessed() {
+ private void pendingUpdateProcessed(@Nullable Consumer<List<CommittedChangeList>> incomingChangesConsumer) {
myPendingUpdateCount--;
if (myPendingUpdateCount == 0) {
notifyIncomingChangesUpdated(myNewIncomingChanges);
+ if (incomingChangesConsumer != null) {
+ incomingChangesConsumer.consume(ContainerUtil.newArrayList(myNewIncomingChanges));
+ }
myNewIncomingChanges.clear();
}
}
- private void processUpdatedFilesAfterRefresh(final ChangesCacheFile cache, final UpdatedFiles updatedFiles) {
+ private void processUpdatedFilesAfterRefresh(final ChangesCacheFile cache,
+ final UpdatedFiles updatedFiles,
+ @Nullable final Consumer<List<CommittedChangeList>> incomingChangesConsumer) {
refreshCacheAsync(cache, false, new RefreshResultConsumer() {
@Override
public void receivedChanges(final List<CommittedChangeList> committedChangeLists) {
@@ -833,7 +844,7 @@ public class CommittedChangesCache implements PersistentStateComponent<Committed
debug("Clearing cached incoming changelists");
myCachedIncomingChangeLists = null;
}
- pendingUpdateProcessed();
+ pendingUpdateProcessed(incomingChangesConsumer);
}
catch (IOException e) {
LOG.error(e);
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesBrowserNode.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesBrowserNode.java
index 7d4156873d7c..b7a42218e3e6 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesBrowserNode.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesBrowserNode.java
@@ -150,7 +150,7 @@ public class ChangesBrowserNode<T> extends DefaultMutableTreeNode {
public <T> List<T> getAllObjectsUnder(final Class<T> clazz) {
List<T> changes = new ArrayList<T>();
- final Enumeration enumeration = depthFirstEnumeration();
+ final Enumeration enumeration = preorderEnumeration();
while (enumeration.hasMoreElements()) {
ChangesBrowserNode child = (ChangesBrowserNode)enumeration.nextElement();
final Object value = child.getUserObject();
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesModuleGroupingPolicy.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesModuleGroupingPolicy.java
index 2ed36d79947f..1efc7b44d66b 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesModuleGroupingPolicy.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesModuleGroupingPolicy.java
@@ -21,6 +21,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.Nullable;
@@ -55,8 +56,9 @@ public class ChangesModuleGroupingPolicy implements ChangesGroupingPolicy {
if (vFile == null) {
vFile = LocalFileSystem.getInstance().findFileByIoFile(new File(node.getPath()));
}
- if (vFile != null && Comparing.equal(vFile, index.getContentRootForFile(vFile))) {
- Module module = index.getModuleForFile(vFile);
+ boolean hideExcludedFiles = Registry.is("ide.hide.excluded.files");
+ if (vFile != null && Comparing.equal(vFile, index.getContentRootForFile(vFile, hideExcludedFiles))) {
+ Module module = index.getModuleForFile(vFile, hideExcludedFiles);
return getNodeForModule(module, rootNode);
}
return null;
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsBackgroundOperationsConfigurable.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsBackgroundOperationsConfigurable.java
new file mode 100644
index 000000000000..695f8b9143db
--- /dev/null
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsBackgroundOperationsConfigurable.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 com.intellij.openapi.vcs.configurable;
+
+
+import com.intellij.openapi.options.ConfigurationException;
+import com.intellij.openapi.options.SearchableConfigurable;
+import com.intellij.openapi.project.Project;
+import org.jetbrains.annotations.Nls;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+
+public class VcsBackgroundOperationsConfigurable implements SearchableConfigurable {
+ private VcsBackgroundOperationsConfigurationPanel myPanel;
+ private final Project myProject;
+
+ public VcsBackgroundOperationsConfigurable(Project project) {
+ myProject = project;
+ }
+
+ @Override
+ public void reset() {
+ myPanel.reset();
+ }
+
+ @Override
+ public void apply() throws ConfigurationException {
+ myPanel.apply();
+ }
+
+ @Override
+ public boolean isModified() {
+ return myPanel.isModified();
+ }
+
+ @Nls
+ public String getDisplayName() {
+ return "Background";
+ }
+
+ public String getHelpTopic() {
+ return "project.propVCSSupport.Background";
+ }
+
+ @NotNull
+ public String getId() {
+ return getHelpTopic();
+ }
+
+ public Runnable enableSearch(String option) {
+ return null;
+ }
+
+ public JComponent createComponent() {
+ myPanel = new VcsBackgroundOperationsConfigurationPanel(myProject);
+ return myPanel.getPanel();
+ }
+
+ public void disposeUIResources() {
+ myPanel = null;
+ }
+
+}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsBackgroundOperationsConfigurationPanel.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsBackgroundOperationsConfigurationPanel.java
index 1a9884ee003b..6b23766b9038 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsBackgroundOperationsConfigurationPanel.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsBackgroundOperationsConfigurationPanel.java
@@ -31,7 +31,7 @@ import java.awt.event.ActionListener;
import java.util.LinkedHashMap;
import java.util.Map;
-public class VcsBackgroundOperationsConfigurationPanel implements SearchableConfigurable {
+public class VcsBackgroundOperationsConfigurationPanel {
private JPanel myPanel;
@@ -151,30 +151,6 @@ public class VcsBackgroundOperationsConfigurationPanel implements SearchableConf
return myPanel;
}
- @Nls
- public String getDisplayName() {
- return "Background";
- }
-
- public String getHelpTopic() {
- return "project.propVCSSupport.Background";
- }
-
- @NotNull
- public String getId() {
- return getHelpTopic();
- }
-
- public Runnable enableSearch(String option) {
- return null;
- }
-
- public JComponent createComponent() {
- return getPanel();
- }
-
- public void disposeUIResources() {
- }
private void createUIComponents() {
myCacheSettingsPanel = new CacheSettingsPanel();
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsGeneralConfigurationConfigurable.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsGeneralConfigurationConfigurable.java
new file mode 100644
index 000000000000..03368a82464c
--- /dev/null
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsGeneralConfigurationConfigurable.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 com.intellij.openapi.vcs.configurable;
+
+import com.intellij.openapi.options.ConfigurationException;
+import com.intellij.openapi.options.SearchableConfigurable;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vcs.AbstractVcs;
+import com.intellij.openapi.vcs.ProjectLevelVcsManager;
+import org.jetbrains.annotations.Nls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.util.Arrays;
+import java.util.Collection;
+
+public class VcsGeneralConfigurationConfigurable implements SearchableConfigurable {
+ private VcsGeneralConfigurationPanel myPanel;
+ private Project myProject;
+ private VcsManagerConfigurable myMainConfigurable;
+
+ public VcsGeneralConfigurationConfigurable(Project project, VcsManagerConfigurable configurable) {
+ myProject = project;
+ myMainConfigurable = configurable;
+ }
+
+ @Nullable
+ @Override
+ public JComponent createComponent() {
+ myPanel = new VcsGeneralConfigurationPanel(myProject);
+ if (getMappings() != null) {
+ myPanel.updateAvailableOptions(getMappings().getActiveVcses());
+ addListenerToGeneralPanel();
+ }
+ else {
+ myPanel.updateAvailableOptions(Arrays.asList(ProjectLevelVcsManager.getInstance(myProject).getAllActiveVcss()));
+ }
+ addListenerToGeneralPanel();
+
+ return myPanel.getPanel();
+ }
+
+ private VcsDirectoryConfigurationPanel getMappings() {
+ return myMainConfigurable.getMappings();
+ }
+
+ private void addListenerToGeneralPanel() {
+ VcsDirectoryConfigurationPanel mappings = getMappings();
+ if (mappings != null) {
+ mappings.addVcsListener(new ModuleVcsListener() {
+ @Override
+ public void activeVcsSetChanged(Collection<AbstractVcs> activeVcses) {
+ myPanel.updateAvailableOptions(activeVcses);
+ }
+ });
+ }
+ }
+
+ @Override
+ public void apply() throws ConfigurationException {
+ myPanel.apply();
+ }
+
+ @Override
+ public boolean isModified() {
+ return myPanel.isModified();
+ }
+
+ @Override
+ public void reset() {
+ myPanel.reset();
+ }
+
+ @Override
+ public void disposeUIResources() {
+ myPanel = null;
+ }
+ @Nls
+ public String getDisplayName() {
+ return "Confirmation";
+ }
+
+ @NotNull
+ public String getHelpTopic() {
+ return "project.propVCSSupport.Confirmation";
+ }
+
+ @NotNull
+ public String getId() {
+ return getHelpTopic();
+ }
+
+ public Runnable enableSearch(String option) {
+ return null;
+ }
+
+}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsGeneralConfigurationPanel.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsGeneralConfigurationPanel.java
index 781e4fd949a6..45a7267d7587 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsGeneralConfigurationPanel.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsGeneralConfigurationPanel.java
@@ -36,7 +36,7 @@ import java.awt.*;
import java.util.*;
import java.util.List;
-public class VcsGeneralConfigurationPanel implements SearchableConfigurable {
+public class VcsGeneralConfigurationPanel {
private JCheckBox myForceNonEmptyComment;
private JCheckBox myShowReadOnlyStatusDialog;
@@ -294,29 +294,4 @@ public class VcsGeneralConfigurationPanel implements SearchableConfigurable {
return StringUtil.join(result, ", ");
}
- @Nls
- public String getDisplayName() {
- return "Confirmation";
- }
-
- @NotNull
- public String getHelpTopic() {
- return "project.propVCSSupport.Confirmation";
- }
-
- public JComponent createComponent() {
- return getPanel();
- }
-
- public void disposeUIResources() {
- }
-
- @NotNull
- public String getId() {
- return getHelpTopic();
- }
-
- public Runnable enableSearch(String option) {
- return null;
- }
}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsManagerConfigurable.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsManagerConfigurable.java
index 304275d732d7..a392ff1f5db2 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsManagerConfigurable.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsManagerConfigurable.java
@@ -40,7 +40,7 @@ import java.util.List;
public class VcsManagerConfigurable extends SearchableConfigurable.Parent.Abstract implements Configurable.NoScroll {
private final Project myProject;
private VcsDirectoryConfigurationPanel myMappings;
- private VcsGeneralConfigurationPanel myGeneralPanel;
+ private VcsGeneralConfigurationConfigurable myGeneralPanel;
public VcsManagerConfigurable(Project project) {
myProject = project;
@@ -49,9 +49,6 @@ public class VcsManagerConfigurable extends SearchableConfigurable.Parent.Abstra
@Override
public JComponent createComponent() {
myMappings = new VcsDirectoryConfigurationPanel(myProject);
- if (myGeneralPanel != null) {
- addListenerToGeneralPanel();
- }
return myMappings;
}
@@ -118,26 +115,12 @@ public class VcsManagerConfigurable extends SearchableConfigurable.Parent.Abstra
@Override
protected Configurable[] buildConfigurables() {
- myGeneralPanel = new VcsGeneralConfigurationPanel(myProject){
- @Override
- public void disposeUIResources() {
- super.disposeUIResources();
- myGeneralPanel = null;
- }
- };
-
- if (myMappings != null) {
- myGeneralPanel.updateAvailableOptions(myMappings.getActiveVcses());
- addListenerToGeneralPanel();
- }
- else {
- myGeneralPanel.updateAvailableOptions(Arrays.asList(ProjectLevelVcsManager.getInstance(myProject).getAllActiveVcss()));
- }
+ myGeneralPanel = new VcsGeneralConfigurationConfigurable(myProject, this);
List<Configurable> result = new ArrayList<Configurable>();
result.add(myGeneralPanel);
- result.add(new VcsBackgroundOperationsConfigurationPanel(myProject));
+ result.add(new VcsBackgroundOperationsConfigurable(myProject));
if (!myProject.isDefault()) {
result.add(new IgnoredSettingsPanel(myProject));
@@ -165,13 +148,8 @@ public class VcsManagerConfigurable extends SearchableConfigurable.Parent.Abstra
return result.toArray(new Configurable[result.size()]);
}
- private void addListenerToGeneralPanel() {
- myMappings.addVcsListener(new ModuleVcsListener() {
- @Override
- public void activeVcsSetChanged(Collection<AbstractVcs> activeVcses) {
- myGeneralPanel.updateAvailableOptions(activeVcses);
- }
- });
+ public VcsDirectoryConfigurationPanel getMappings() {
+ return myMappings;
}
private Configurable createVcsConfigurableWrapper(final VcsDescriptor vcs) {
@@ -237,5 +215,4 @@ public class VcsManagerConfigurable extends SearchableConfigurable.Parent.Abstra
}
};
}
-
}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/CopyLineStatusRangeAction.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/CopyLineStatusRangeAction.java
index aaa512c4e674..a9f761a2b5e0 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/CopyLineStatusRangeAction.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/CopyLineStatusRangeAction.java
@@ -35,7 +35,7 @@ public class CopyLineStatusRangeAction extends BaseLineStatusRangeAction {
}
public void actionPerformed(final AnActionEvent e) {
- final String content = myLineStatusTracker.getUpToDateContent(myRange).toString();
+ final String content = myLineStatusTracker.getVcsContent(myRange).toString();
CopyPasteManager.getInstance().setContents(new StringSelection(content));
}
}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTracker.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTracker.java
index 44a56e7df517..9d8d73a92be9 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTracker.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTracker.java
@@ -32,21 +32,21 @@ import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.VcsBundle;
import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager;
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.EditorNotificationPanel;
+import com.intellij.util.ExceptionUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.diff.FilesTooBigForDiffException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.ListIterator;
+import java.util.*;
/**
* @author irengrig
@@ -61,7 +61,7 @@ public class LineStatusTracker {
private BaseLoadState myBaseLoaded;
private final Document myDocument;
- private final Document myUpToDateDocument;
+ private final Document myVcsDocument;
private List<Range> myRanges;
@@ -69,34 +69,35 @@ public class LineStatusTracker {
private MyDocumentListener myDocumentListener;
+ private boolean mySuppressUpdate;
private boolean myBulkUpdate;
private final Application myApplication;
@Nullable private RevisionPack myBaseRevisionNumber;
private String myPreviousBaseRevision;
private boolean myAnathemaThrown;
private FileEditorManager myFileEditorManager;
+ private final VcsDirtyScopeManager myVcsDirtyScopeManager;
private final VirtualFile myVirtualFile;
private boolean myReleased = false;
private LineStatusTracker(@NotNull final Document document,
- @NotNull final Document upToDateDocument,
+ @NotNull final Document vcsDocument,
final Project project,
@Nullable final VirtualFile virtualFile) {
myVirtualFile = virtualFile;
myApplication = ApplicationManager.getApplication();
myDocument = document;
- myUpToDateDocument = upToDateDocument;
- myUpToDateDocument.putUserData(UndoConstants.DONT_RECORD_UNDO, Boolean.TRUE);
+ myVcsDocument = vcsDocument;
+ myVcsDocument.putUserData(UndoConstants.DONT_RECORD_UNDO, Boolean.TRUE);
myProject = project;
myBaseLoaded = BaseLoadState.LOADING;
- synchronized (myLock) {
- myRanges = new ArrayList<Range>();
- }
+ myRanges = new ArrayList<Range>();
myAnathemaThrown = false;
myFileEditorManager = FileEditorManager.getInstance(myProject);
+ myVcsDirtyScopeManager = VcsDirtyScopeManager.getInstance(myProject);
}
- public void initialize(@NotNull final String upToDateContent, @NotNull RevisionPack baseRevisionNumber) {
+ public void initialize(@NotNull final String vcsContent, @NotNull RevisionPack baseRevisionNumber) {
ApplicationManager.getApplication().assertIsDispatchThread();
synchronized (myLock) {
@@ -107,9 +108,9 @@ public class LineStatusTracker {
myBaseRevisionNumber = baseRevisionNumber;
myPreviousBaseRevision = null;
- myUpToDateDocument.setReadOnly(false);
- myUpToDateDocument.replaceString(0, myUpToDateDocument.getTextLength(), upToDateContent);
- myUpToDateDocument.setReadOnly(true);
+ myVcsDocument.setReadOnly(false);
+ myVcsDocument.replaceString(0, myVcsDocument.getTextLength(), vcsContent);
+ myVcsDocument.setReadOnly(true);
reinstallRanges();
if (myDocumentListener == null) {
@@ -144,7 +145,7 @@ public class LineStatusTracker {
removeAnathema();
removeHighlightersFromMarkupModel();
try {
- myRanges = new RangesBuilder(myDocument, myUpToDateDocument).getRanges();
+ myRanges = new RangesBuilder(myDocument, myVcsDocument).getRanges();
}
catch (FilesTooBigForDiffException e) {
myRanges.clear();
@@ -175,10 +176,10 @@ public class LineStatusTracker {
LOG.assertTrue(!myReleased, "Already released");
int first =
- range.getOffset1() >= getLineCount(myDocument) ? myDocument.getTextLength() : myDocument.getLineStartOffset(range.getOffset1());
+ range.getLine1() >= getLineCount(myDocument) ? myDocument.getTextLength() : myDocument.getLineStartOffset(range.getLine1());
int second =
- range.getOffset2() >= getLineCount(myDocument) ? myDocument.getTextLength() : myDocument.getLineStartOffset(range.getOffset2());
+ range.getLine2() >= getLineCount(myDocument) ? myDocument.getTextLength() : myDocument.getLineStartOffset(range.getLine2());
final RangeHighlighter highlighter = DocumentMarkupModel.forDocument(myDocument, myProject, true)
.addRangeHighlighter(first, second, HighlighterLayer.FIRST - 1, null, HighlighterTargetArea.LINES_IN_RANGE);
@@ -192,19 +193,19 @@ public class LineStatusTracker {
highlighter.setEditorFilter(MarkupEditorFilterFactory.createIsNotDiffFilter());
final String tooltip;
- if (range.getOffset1() == range.getOffset2()) {
- if (range.getUOffset1() + 1 == range.getUOffset2()) {
- tooltip = VcsBundle.message("tooltip.text.line.before.deleted", range.getOffset1() + 1);
+ if (range.getLine1() == range.getLine2()) {
+ if (range.getVcsLine1() + 1 == range.getVcsLine2()) {
+ tooltip = VcsBundle.message("tooltip.text.line.before.deleted", range.getLine1() + 1);
}
else {
- tooltip = VcsBundle.message("tooltip.text.lines.before.deleted", range.getOffset1() + 1, range.getUOffset2() - range.getUOffset1());
+ tooltip = VcsBundle.message("tooltip.text.lines.before.deleted", range.getLine1() + 1, range.getVcsLine2() - range.getVcsLine1());
}
}
- else if (range.getOffset1() + 1 == range.getOffset2()) {
- tooltip = VcsBundle.message("tooltip.text.line.changed", range.getOffset1() + 1);
+ else if (range.getLine1() + 1 == range.getLine2()) {
+ tooltip = VcsBundle.message("tooltip.text.line.changed", range.getLine1() + 1);
}
else {
- tooltip = VcsBundle.message("tooltip.text.lines.changed", range.getOffset1() + 1, range.getOffset2());
+ tooltip = VcsBundle.message("tooltip.text.lines.changed", range.getLine1() + 1, range.getLine2());
}
highlighter.setErrorStripeTooltip(tooltip);
@@ -238,9 +239,9 @@ public class LineStatusTracker {
}
}
- public Document getUpToDateDocument() {
+ public Document getVcsDocument() {
myApplication.assertIsDispatchThread();
- return myUpToDateDocument;
+ return myVcsDocument;
}
public void startBulkUpdate() {
@@ -285,11 +286,11 @@ public class LineStatusTracker {
// there can be multiple resets before init -> take from document only firts time -> when right after install(),
// where myPreviousBaseRevision become null
if (BaseLoadState.LOADED.equals(myBaseLoaded) && myPreviousBaseRevision == null) {
- myPreviousBaseRevision = myUpToDateDocument.getText();
+ myPreviousBaseRevision = myVcsDocument.getText();
}
- myUpToDateDocument.setReadOnly(false);
- myUpToDateDocument.setText("");
- myUpToDateDocument.setReadOnly(true);
+ myVcsDocument.setReadOnly(false);
+ myVcsDocument.setText("");
+ myVcsDocument.setReadOnly(true);
removeAnathema();
removeHighlightersFromMarkupModel();
myBaseLoaded = BaseLoadState.LOADING;
@@ -298,15 +299,13 @@ public class LineStatusTracker {
private class MyDocumentListener extends DocumentAdapter {
// We have 3 document versions:
- // * VCS version - upToDate*
- // * before change - my*
- // * after change - current*
+ // * VCS version
+ // * before change
+ // * after change
- private int myFirstChangedLine;
- private int myLastChangedLine;
- private int myChangedLines;
- private int myTotalLines;
- private final VcsDirtyScopeManager myVcsDirtyScopeManager = VcsDirtyScopeManager.getInstance(myProject);
+ private int myLine1;
+ private int myBeforeChangedLines;
+ private int myBeforeTotalLines;
@Override
public void beforeDocumentChange(DocumentEvent e) {
@@ -314,13 +313,21 @@ public class LineStatusTracker {
synchronized (myLock) {
if (myReleased) return;
- if (myBulkUpdate || myAnathemaThrown || BaseLoadState.LOADED != myBaseLoaded) return;
+ if (myBulkUpdate || mySuppressUpdate || myAnathemaThrown || BaseLoadState.LOADED != myBaseLoaded) return;
+ assert myDocument == e.getDocument();
+
try {
- myFirstChangedLine = myDocument.getLineNumber(e.getOffset());
- myLastChangedLine = e.getOldLength() == 0 ? myFirstChangedLine : myDocument.getLineNumber(e.getOffset() + e.getOldLength() - 1);
- if (StringUtil.endsWithChar(e.getOldFragment(), '\n')) myLastChangedLine++;
- myChangedLines = myLastChangedLine - myFirstChangedLine;
- myTotalLines = getLineCount(e.getDocument());
+ myLine1 = myDocument.getLineNumber(e.getOffset());
+ if (e.getOldLength() == 0) {
+ myBeforeChangedLines = 1;
+ }
+ else {
+ int line1 = myLine1;
+ int line2 = myDocument.getLineNumber(e.getOffset() + e.getOldLength());
+ myBeforeChangedLines = line2 - line1 + 1;
+ }
+
+ myBeforeTotalLines = getLineCount(myDocument);
}
catch (ProcessCanceledException ignore) {
}
@@ -333,138 +340,307 @@ public class LineStatusTracker {
synchronized (myLock) {
if (myReleased) return;
- if (myBulkUpdate || myAnathemaThrown || BaseLoadState.LOADED != myBaseLoaded) return;
- try {
- int currentFirstChangedLine = myFirstChangedLine;
- int currentLastChangedLine =
- e.getNewLength() == 0 ? currentFirstChangedLine : myDocument.getLineNumber(e.getOffset() + e.getNewLength() - 1);
- if (StringUtil.endsWithChar(e.getNewFragment(), '\n')) currentLastChangedLine++;
- int currentChangedLines = currentLastChangedLine - currentFirstChangedLine;
- int upToDateTotalLine = getLineCount(myUpToDateDocument);
-
- int linesShift = currentChangedLines - myChangedLines;
-
- List<Range> rangesBeforeChange = new ArrayList<Range>();
- List<Range> rangesAfterChange = new ArrayList<Range>();
- List<Range> changedRanges = new ArrayList<Range>();
- sortRanges(myRanges, myFirstChangedLine, myLastChangedLine, rangesBeforeChange, changedRanges, rangesAfterChange);
-
- Range firstChangedRange = ContainerUtil.getFirstItem(changedRanges);
- Range lastChangedRange = ContainerUtil.getLastItem(changedRanges);
- Range lastRangeBefore = ContainerUtil.getLastItem(rangesBeforeChange);
- Range firstRangeAfter = ContainerUtil.getFirstItem(rangesAfterChange);
-
- if (firstChangedRange != null && firstChangedRange.getOffset1() < myFirstChangedLine) {
- myFirstChangedLine = firstChangedRange.getOffset1();
- }
- if (lastChangedRange != null && lastChangedRange.getOffset2() > myLastChangedLine) {
- myLastChangedLine = lastChangedRange.getOffset2() - 1;
- }
+ if (myBulkUpdate || mySuppressUpdate || myAnathemaThrown || BaseLoadState.LOADED != myBaseLoaded) return;
+ assert myDocument == e.getDocument();
- currentFirstChangedLine = myFirstChangedLine;
- currentLastChangedLine = myLastChangedLine + linesShift;
+ int afterChangedLines;
+ if (e.getNewLength() == 0) {
+ afterChangedLines = 1;
+ }
+ else {
+ int line1 = myLine1;
+ int line2 = myDocument.getLineNumber(e.getOffset() + e.getNewLength());
+ afterChangedLines = line2 - line1 + 1;
+ }
- int upToDateFirstLine = getUpToDateLine1(lastRangeBefore, myFirstChangedLine);
- int upToDateLastLine = getUpToDateLine2(firstRangeAfter, myLastChangedLine, myTotalLines, upToDateTotalLine);
+ int linesShift = afterChangedLines - myBeforeChangedLines;
- List<Range> newChangedRanges =
- getNewChangedRanges(currentFirstChangedLine, currentLastChangedLine, upToDateFirstLine, upToDateLastLine);
+ int line1 = myLine1;
+ int line2 = line1 + myBeforeChangedLines; // TODO: optimize some whole-line-changed cases
- shiftRanges(rangesAfterChange, linesShift);
+ int[] fixed = fixRanges(e, line1, line2);
+ line1 = fixed[0];
+ line2 = fixed[1];
- if (!changedRanges.equals(newChangedRanges)) {
- replaceRanges(changedRanges, newChangedRanges);
+ doUpdateRanges(line1, line2, linesShift, myBeforeTotalLines);
+ }
+ }
+ }
- myRanges = new ArrayList<Range>(rangesBeforeChange.size() + newChangedRanges.size() + rangesAfterChange.size());
+ @NotNull
+ private int[] fixRanges(@NotNull DocumentEvent e, int line1, int line2) {
+ CharSequence document = myDocument.getCharsSequence();
+ int offset = e.getOffset();
- myRanges.addAll(rangesBeforeChange);
- myRanges.addAll(newChangedRanges);
- myRanges.addAll(rangesAfterChange);
+ if (e.getOldLength() == 0 && e.getNewLength() != 0) {
+ if (StringUtil.endsWithChar(e.getNewFragment(), '\n') && isNewline(offset - 1, document)) {
+ return new int[]{line1, line2 - 1};
+ }
+ if (StringUtil.startsWithChar(e.getNewFragment(), '\n') && isNewline(offset + e.getNewLength(), document)) {
+ return new int[]{line1 + 1, line2};
+ }
+ }
+ if (e.getOldLength() != 0 && e.getNewLength() == 0) {
+ if (StringUtil.endsWithChar(e.getOldFragment(), '\n') && isNewline(offset - 1, document)) {
+ return new int[]{line1, line2 - 1};
+ }
+ if (StringUtil.startsWithChar(e.getOldFragment(), '\n') && isNewline(offset + e.getNewLength(), document)) {
+ return new int[]{line1 + 1, line2};
+ }
+ }
- for (Range range : myRanges) {
- if (!range.hasHighlighter()) range.setHighlighter(createHighlighter(range));
- }
+ return new int[]{line1, line2};
+ }
- if (myRanges.isEmpty() && myVirtualFile != null) {
- SwingUtilities.invokeLater(new Runnable() {
- @Override
- public void run() {
- FileDocumentManager.getInstance().saveDocument(e.getDocument());
- boolean[] stillEmpty = new boolean[1];
- synchronized (myLock) {
- stillEmpty[0] = myRanges.isEmpty();
- }
- if (stillEmpty[0]) {
- // file was modified, and now it's not -> dirty local change
- myVcsDirtyScopeManager.fileDirty(myVirtualFile);
- }
- }
- });
- }
- }
- }
- catch (ProcessCanceledException ignore) {
+ private static boolean isNewline(int offset, @NotNull CharSequence sequence) {
+ if (offset < 0) return false;
+ if (offset >= sequence.length()) return false;
+ return sequence.charAt(offset) == '\n';
+ }
+
+ private void doUpdateRanges(int beforeChangedLine1,
+ int beforeChangedLine2,
+ int linesShift,
+ int beforeTotalLines) {
+ List<Range> rangesBeforeChange = new ArrayList<Range>();
+ List<Range> rangesAfterChange = new ArrayList<Range>();
+ List<Range> changedRanges = new ArrayList<Range>();
+
+ sortRanges(beforeChangedLine1, beforeChangedLine2, linesShift, rangesBeforeChange, changedRanges, rangesAfterChange);
+
+ Range firstChangedRange = ContainerUtil.getFirstItem(changedRanges);
+ Range lastChangedRange = ContainerUtil.getLastItem(changedRanges);
+
+ if (firstChangedRange != null && firstChangedRange.getLine1() < beforeChangedLine1) {
+ beforeChangedLine1 = firstChangedRange.getLine1();
+ }
+ if (lastChangedRange != null && lastChangedRange.getLine2() > beforeChangedLine2) {
+ beforeChangedLine2 = lastChangedRange.getLine2();
+ }
+
+ doUpdateRanges(beforeChangedLine1, beforeChangedLine2, linesShift, beforeTotalLines,
+ rangesBeforeChange, changedRanges, rangesAfterChange);
+ }
+
+ private void doUpdateRanges(int beforeChangedLine1,
+ int beforeChangedLine2,
+ int linesShift, // before -> after
+ int beforeTotalLines,
+ @NotNull List<Range> rangesBefore,
+ @NotNull List<Range> changedRanges,
+ @NotNull List<Range> rangesAfter) {
+ try {
+ int vcsTotalLines = getLineCount(myVcsDocument);
+
+ Range lastRangeBefore = ContainerUtil.getLastItem(rangesBefore);
+ Range firstRangeAfter = ContainerUtil.getFirstItem(rangesAfter);
+
+ int afterChangedLine1 = beforeChangedLine1;
+ int afterChangedLine2 = beforeChangedLine2 + linesShift;
+
+ int vcsLine1 = getVcsLine1(lastRangeBefore, beforeChangedLine1);
+ int vcsLine2 = getVcsLine2(firstRangeAfter, beforeChangedLine2, beforeTotalLines, vcsTotalLines);
+
+ List<Range> newChangedRanges = getNewChangedRanges(afterChangedLine1, afterChangedLine2, vcsLine1, vcsLine2);
+
+ shiftRanges(rangesAfter, linesShift);
+
+ if (!changedRanges.equals(newChangedRanges)) {
+ replaceRanges(changedRanges, newChangedRanges);
+
+ myRanges = new ArrayList<Range>(rangesBefore.size() + newChangedRanges.size() + rangesAfter.size());
+
+ myRanges.addAll(rangesBefore);
+ myRanges.addAll(newChangedRanges);
+ myRanges.addAll(rangesAfter);
+
+ for (Range range : myRanges) {
+ if (!range.hasHighlighter()) range.setHighlighter(createHighlighter(range));
}
- catch (FilesTooBigForDiffException e1) {
- installAnathema();
- removeHighlightersFromMarkupModel();
+
+ if (myRanges.isEmpty() && myVirtualFile != null) {
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ FileDocumentManager.getInstance().saveDocument(myDocument);
+ boolean stillEmpty;
+ synchronized (myLock) {
+ stillEmpty = myRanges.isEmpty();
+ }
+ if (stillEmpty) {
+ // file was modified, and now it's not -> dirty local change
+ myVcsDirtyScopeManager.fileDirty(myVirtualFile);
+ }
+ }
+ });
}
}
}
+ catch (ProcessCanceledException ignore) {
+ }
+ catch (FilesTooBigForDiffException e1) {
+ installAnathema();
+ removeHighlightersFromMarkupModel();
+ }
+ }
- private int getUpToDateLine1(@Nullable Range range, int line) {
- return range == null ? line : line + range.getUOffset2() - range.getOffset2();
+ private static int getVcsLine1(@Nullable Range range, int line) {
+ return range == null ? line : line + range.getVcsLine2() - range.getLine2();
+ }
+
+ private static int getVcsLine2(@Nullable Range range, int line, int totalLinesBefore, int totalLinesAfter) {
+ return range == null ? totalLinesAfter - totalLinesBefore + line : line + range.getVcsLine1() - range.getLine1();
+ }
+
+ private List<Range> getNewChangedRanges(int changedLine1, int changedLine2, int vcsLine1, int vcsLine2)
+ throws FilesTooBigForDiffException {
+
+ if (changedLine1 == changedLine2 && vcsLine1 == vcsLine2) {
+ return Collections.emptyList();
+ }
+ if (changedLine1 == changedLine2) {
+ return Collections.singletonList(new Range(changedLine1, changedLine2, vcsLine1, vcsLine2, Range.DELETED));
}
+ if (vcsLine1 == vcsLine2) {
+ return Collections.singletonList(new Range(changedLine1, changedLine2, vcsLine1, vcsLine2, Range.INSERTED));
+ }
+
+ List<String> lines = new DocumentWrapper(myDocument).getLines(changedLine1, changedLine2 - 1);
+ List<String> vcsLines = new DocumentWrapper(myVcsDocument).getLines(vcsLine1, vcsLine2 - 1);
- private int getUpToDateLine2(@Nullable Range range, int line, int totalLinesBefore, int totalLinesAfter) {
- return range == null ? totalLinesAfter - totalLinesBefore + line : line + range.getUOffset1() - range.getOffset1();
+ return new RangesBuilder(lines, vcsLines, changedLine1, vcsLine1).getRanges();
+ }
+
+ private void replaceRanges(@NotNull List<Range> rangesInChange, @NotNull List<Range> newRangesInChange) {
+ for (Range range : rangesInChange) {
+ if (range.getHighlighter() != null) {
+ range.getHighlighter().dispose();
+ }
+ range.setHighlighter(null);
+ range.invalidate();
}
+ for (Range range : newRangesInChange) {
+ range.setHighlighter(createHighlighter(range));
+ }
+ }
- private List<Range> getNewChangedRanges(int firstChangedLine, int lastChangedLine, int upToDateFirstLine, int upToDateLastLine)
- throws FilesTooBigForDiffException {
- List<String> lines = new DocumentWrapper(myDocument).getLines(firstChangedLine, lastChangedLine);
- List<String> uLines = new DocumentWrapper(myUpToDateDocument).getLines(upToDateFirstLine, upToDateLastLine);
- return new RangesBuilder(lines, uLines, firstChangedLine, upToDateFirstLine).getRanges();
+ private static void shiftRanges(@NotNull List<Range> rangesAfterChange, int shift) {
+ for (final Range range : rangesAfterChange) {
+ range.shift(shift);
}
+ }
- private void replaceRanges(@NotNull List<Range> rangesInChange, @NotNull List<Range> newRangesInChange) {
- for (Range range : rangesInChange) {
- if (range.getHighlighter() != null) {
- range.getHighlighter().dispose();
+ private void sortRanges(int beforeChangedLine1,
+ int beforeChangedLine2,
+ int linesShift,
+ @NotNull List<Range> rangesBeforeChange,
+ @NotNull List<Range> changedRanges,
+ @NotNull List<Range> rangesAfterChange) {
+ if (!Registry.is("diff.status.tracker.skip.spaces")) {
+ for (Range range : myRanges) {
+ if (range.getLine2() < beforeChangedLine1) {
+ rangesBeforeChange.add(range);
+ }
+ else if (range.getLine1() > beforeChangedLine2) {
+ rangesAfterChange.add(range);
+ }
+ else {
+ changedRanges.add(range);
}
- range.setHighlighter(null);
- range.invalidate();
- }
- for (Range range : newRangesInChange) {
- range.setHighlighter(createHighlighter(range));
}
}
+ else {
+ int lastBefore = -1;
+ int firstAfter = myRanges.size();
+ for (int i = 0; i < myRanges.size(); i++) {
+ Range range = myRanges.get(i);
- private void shiftRanges(@NotNull List<Range> rangesAfterChange, int shift) {
- for (final Range aRangesAfterChange : rangesAfterChange) {
- aRangesAfterChange.shift(shift);
+ if (range.getLine2() < beforeChangedLine1) {
+ lastBefore = i;
+ }
+ else if (range.getLine1() > beforeChangedLine2) {
+ firstAfter = i;
+ break;
+ }
}
- }
- }
- public static void sortRanges(@NotNull List<Range> ranges,
- int firstChangedLine,
- int lastChangedLine,
- @NotNull List<Range> rangesBeforeChange,
- @NotNull List<Range> changedRanges,
- @NotNull List<Range> rangesAfterChange) {
- for (Range range : ranges) {
- int offset1 = range.getOffset1() - 1;
- int offset2 = range.getOffset2();
- if (offset2 < firstChangedLine) {
- rangesBeforeChange.add(range);
+ // Expand on ranges, that are separated from changes only by empty/whitespaces lines
+ // This is needed to reduce amount of confusing cases, when changed blocks are matched wrong due to matched empty lines between them
+ CharSequence sequence = myDocument.getCharsSequence();
+
+ while (true) {
+ if (lastBefore == -1) break;
+
+ if (lastBefore < myRanges.size() - 1 && firstAfter - lastBefore > 1) {
+ Range firstChangedRange = myRanges.get(lastBefore + 1);
+ if (firstChangedRange.getLine1() < beforeChangedLine1) {
+ beforeChangedLine1 = firstChangedRange.getLine1();
+ }
+ }
+
+ if (beforeChangedLine1 >= getLineCount(myDocument)) break;
+ int offset1 = myDocument.getLineStartOffset(beforeChangedLine1) - 2;
+
+ int deltaLines = 0;
+ while (offset1 > 0) {
+ char c = sequence.charAt(offset1);
+ if (!StringUtil.isWhiteSpace(c)) break;
+ if (c == '\n') deltaLines++;
+ offset1--;
+ }
+
+ if (deltaLines == 0) break;
+ beforeChangedLine1 -= deltaLines;
+
+ if (myRanges.get(lastBefore).getLine2() < beforeChangedLine1) break;
+ while (lastBefore != -1 && myRanges.get(lastBefore).getLine2() >= beforeChangedLine1) {
+ lastBefore--;
+ }
}
- else if (offset1 > lastChangedLine) {
- rangesAfterChange.add(range);
+
+ while (true) {
+ if (firstAfter == myRanges.size()) break;
+
+ if (firstAfter > 0 && firstAfter - lastBefore > 1) {
+ Range lastChangedRange = myRanges.get(firstAfter - 1);
+ if (lastChangedRange.getLine2() > beforeChangedLine2) {
+ beforeChangedLine2 = lastChangedRange.getLine2();
+ }
+ }
+
+ if (beforeChangedLine2 + linesShift < 1) break;
+ int offset2 = myDocument.getLineEndOffset(beforeChangedLine2 + linesShift - 1) + 1;
+
+ int deltaLines = 0;
+ while (offset2 < sequence.length()) {
+ char c = sequence.charAt(offset2);
+ if (!StringUtil.isWhiteSpace(c)) break;
+ if (c == '\n') deltaLines++;
+ offset2++;
+ }
+
+ if (deltaLines == 0) break;
+ beforeChangedLine2 += deltaLines;
+
+ if (myRanges.get(firstAfter).getLine1() > beforeChangedLine2) break;
+ while (firstAfter != myRanges.size() && myRanges.get(firstAfter).getLine1() <= beforeChangedLine2) {
+ firstAfter++;
+ }
}
- else {
- changedRanges.add(range);
+
+
+ for (int i = 0; i < myRanges.size(); i++) {
+ Range range = myRanges.get(i);
+ if (i <= lastBefore) {
+ rangesBeforeChange.add(range);
+ }
+ else if (i >= firstAfter) {
+ rangesAfterChange.add(range);
+ }
+ else {
+ changedRanges.add(range);
+ }
}
}
}
@@ -496,7 +672,7 @@ public class LineStatusTracker {
}
for (final Range range : myRanges) {
- if (line > range.getOffset1() || line > range.getOffset2()) {
+ if (line > range.getLine1() || line > range.getLine2()) {
continue;
}
return range;
@@ -515,7 +691,7 @@ public class LineStatusTracker {
for (ListIterator<Range> iterator = myRanges.listIterator(myRanges.size()); iterator.hasPrevious(); ) {
final Range range = iterator.previous();
- if (range.getOffset1() > line) {
+ if (range.getLine1() > line) {
continue;
}
return range;
@@ -528,10 +704,10 @@ public class LineStatusTracker {
public Range getRangeForLine(final int line) {
synchronized (myLock) {
for (final Range range : myRanges) {
- if (range.getType() == Range.DELETED && line == range.getOffset1()) {
+ if (range.getType() == Range.DELETED && line == range.getLine1()) {
return range;
}
- else if (line >= range.getOffset1() && line < range.getOffset2()) {
+ else if (line >= range.getLine1() && line < range.getLine2()) {
return range;
}
}
@@ -539,172 +715,127 @@ public class LineStatusTracker {
}
}
- public void rollbackChanges(@NotNull Range range) {
- myApplication.assertWriteAccessAllowed();
+ private void doRollbackRange(@NotNull Range range) {
+ if (range.getType() == Range.MODIFIED) {
+ TextRange currentTextRange = getCurrentTextRange(range);
+ int offset1 = currentTextRange.getStartOffset();
+ int offset2 = currentTextRange.getEndOffset();
- synchronized (myLock) {
- if (!range.isValid()) {
- LOG.warn("Rollback of invalid range");
- return;
- }
-
- if (range.getType() == Range.MODIFIED) {
- TextRange currentTextRange = getCurrentTextRange(range);
- int offset1 = currentTextRange.getStartOffset();
- int offset2 = currentTextRange.getEndOffset();
+ CharSequence vcsContent = getVcsContent(range);
+ myDocument.replaceString(offset1, offset2, vcsContent);
+ }
+ else if (range.getType() == Range.INSERTED) {
+ TextRange currentTextRange = getCurrentTextRange(range);
+ int offset1 = currentTextRange.getStartOffset();
+ int offset2 = currentTextRange.getEndOffset();
- CharSequence upToDateContent = getUpToDateContent(range);
- myDocument.replaceString(offset1, offset2, upToDateContent);
+ if (offset1 > 0) {
+ offset1--;
}
- else if (range.getType() == Range.INSERTED) {
- TextRange currentTextRange = getCurrentTextRange(range);
- int offset1 = currentTextRange.getStartOffset();
- int offset2 = currentTextRange.getEndOffset();
-
- if (offset1 > 0) {
- offset1--;
- }
- else if (offset2 < myDocument.getTextLength()) {
- offset2++;
- }
- myDocument.deleteString(offset1, offset2);
+ else if (offset2 < myDocument.getTextLength()) {
+ offset2++;
}
- else if (range.getType() == Range.DELETED) {
- CharSequence content = getUpToDateContent(range);
- if (range.getOffset2() == getLineCount(myDocument)) {
- myDocument.insertString(myDocument.getTextLength(), "\n" + content);
- }
- else {
- myDocument.insertString(myDocument.getLineStartOffset(range.getOffset2()), content + "\n");
- }
+ myDocument.deleteString(offset1, offset2);
+ }
+ else if (range.getType() == Range.DELETED) {
+ CharSequence content = getVcsContent(range);
+ if (range.getLine2() == getLineCount(myDocument)) {
+ myDocument.insertString(myDocument.getTextLength(), "\n" + content);
}
else {
- throw new IllegalArgumentException("Unknown range type: " + range.getType());
+ myDocument.insertString(myDocument.getLineStartOffset(range.getLine2()), content + "\n");
}
}
+ else {
+ throw new IllegalArgumentException("Unknown range type: " + range.getType());
+ }
}
- public void rollbackChanges(@NotNull SegmentTree lines) {
+ public void rollbackChanges(@NotNull Range range) {
myApplication.assertWriteAccessAllowed();
synchronized (myLock) {
- List<Range> affectedRanges = new ArrayList<Range>();
+ if (myBulkUpdate) return;
- boolean wasEnd = false;
- boolean simple = true;
- for (Range range : myRanges) {
- if (!range.isValid()) {
- LOG.warn("Rollback of invalid range");
- return;
- }
-
- boolean check;
- if (range.getOffset1() == range.getOffset2()) {
- check = lines.check(range.getOffset1());
- }
- else {
- check = lines.check(range.getOffset1(), range.getOffset2());
- }
- if (check) {
- if (wasEnd) simple = false;
- affectedRanges.add(range);
- }
- else {
- if (!affectedRanges.isEmpty()) wasEnd = true;
- }
+ if (!range.isValid()) {
+ LOG.warn("Rollback of invalid range");
+ return;
}
- if (simple) {
- rollbackChangesSimple(affectedRanges);
- }
- else {
- rollbackChangesComplex(affectedRanges);
- }
+ doRollbackRange(range);
}
}
- private void rollbackChangesSimple(@NotNull List<Range> ranges) {
- if (ranges.isEmpty()) return;
-
- Range first = ranges.get(0);
- Range last = ranges.get(ranges.size() - 1);
+ public void rollbackChanges(@NotNull BitSet lines) {
+ myApplication.assertWriteAccessAllowed();
- byte type = first == last ? first.getType() : Range.MODIFIED;
- final Range merged = new Range(first.getOffset1(), last.getOffset2(), first.getUOffset1(), last.getUOffset2(), type);
+ synchronized (myLock) {
+ if (myBulkUpdate) return;
- // We don't expect complex Insertion/Deletion operation - they shouldn't exist
- assert type != Range.MODIFIED || (first.getOffset1() != last.getOffset2() && first.getUOffset1() != last.getUOffset2());
+ try {
+ mySuppressUpdate = true;
- rollbackChanges(merged);
- }
+ Range first = null;
+ Range last = null;
- private void rollbackChangesComplex(@NotNull List<Range> ranges) {
- // We can't relay on assumption, that revert of a single change will not affect any other.
- // This, among the others, is because of 'magic' ranges for revert, that will affect nearby lines implicitly.
- // So it's dangerous to apply ranges ony-by-one and we have to create single atomic modification.
- // Usage of Bulk mode will lead to full rebuild of tracker, and therefore will be slow..
+ int shift = 0;
+ for (Range range : myRanges) {
+ if (!range.isValid()) {
+ LOG.warn("Rollback of invalid range");
+ break;
+ }
- if (ranges.isEmpty()) return;
- if (ranges.size() == 1) {
- rollbackChanges(ranges.get(0));
- return;
- }
+ boolean check;
+ if (range.getLine1() == range.getLine2()) {
+ check = lines.get(range.getLine1());
+ }
+ else {
+ int next = lines.nextSetBit(range.getLine1());
+ check = next != -1 && next < range.getLine2();
+ }
- Range first = ranges.get(0);
- Range last = ranges.get(ranges.size() - 1);
+ if (check) {
+ if (first == null) {
+ first = range;
+ }
+ last = range;
- // We don't expect complex Insertion/Deletion operation - they shouldn't exist.
- assert first != last && first.getOffset1() != last.getOffset2() && first.getUOffset1() != last.getUOffset2();
+ Range shiftedRange = new Range(range);
+ shiftedRange.shift(shift);
- final int start = getCurrentTextRange(first).getStartOffset();
- final int end = getCurrentTextRange(last).getEndOffset();
+ doRollbackRange(shiftedRange);
- StringBuilder builder = new StringBuilder();
+ shift += (range.getVcsLine2() - range.getVcsLine1()) - (range.getLine2() - range.getLine1());
+ }
+ }
- int lastOffset = start;
- for (Range range : ranges) {
- TextRange textRange = getCurrentTextRange(range);
+ if (first != null) {
+ int beforeChangedLine1 = first.getLine1();
+ int beforeChangedLine2 = last.getLine2();
- builder.append(myDocument.getText(new TextRange(lastOffset, textRange.getStartOffset())));
- lastOffset = textRange.getEndOffset();
+ int beforeTotalLines = getLineCount(myDocument) - shift;
- if (range.getType() == Range.MODIFIED) {
- builder.append(getUpToDateContent(range));
- }
- else if (range.getType() == Range.INSERTED) {
- if (builder.length() > 0) {
- builder.deleteCharAt(builder.length() - 1);
- }
- else {
- lastOffset++;
+ doUpdateRanges(beforeChangedLine1, beforeChangedLine2, shift, beforeTotalLines);
}
}
- else if (range.getType() == Range.DELETED) {
- CharSequence content = getUpToDateContent(range);
- if (range.getOffset2() == getLineCount(myDocument)) {
- builder.append('\n').append(content);
- }
- else {
- builder.append(content).append('\n');
- }
+ catch (Throwable e) {
+ reinstallRanges();
+ if (e instanceof Error) throw ((Error)e);
+ if (e instanceof RuntimeException) throw ((RuntimeException)e);
+ throw new RuntimeException(e);
}
- else {
- throw new IllegalArgumentException("Unknown range type: " + range.getType());
+ finally {
+ mySuppressUpdate = false;
}
}
- builder.append(myDocument.getText(new TextRange(lastOffset, end)));
-
- final String s = builder.toString();
-
- myDocument.replaceString(start, end, s);
}
- public CharSequence getUpToDateContent(@NotNull Range range) {
+ public CharSequence getVcsContent(@NotNull Range range) {
synchronized (myLock) {
- TextRange textRange = getUpToDateRange(range);
+ TextRange textRange = getVcsRange(range);
final int startOffset = textRange.getStartOffset();
final int endOffset = textRange.getEndOffset();
- return myUpToDateDocument.getCharsSequence().subSequence(startOffset, endOffset);
+ return myVcsDocument.getCharsSequence().subSequence(startOffset, endOffset);
}
}
@@ -715,18 +846,18 @@ public class LineStatusTracker {
LOG.warn("Current TextRange of invalid range");
}
- return getRange(range.getOffset1(), range.getOffset2(), myDocument);
+ return getRange(range.getLine1(), range.getLine2(), myDocument);
}
}
@NotNull
- TextRange getUpToDateRange(@NotNull Range range) {
+ TextRange getVcsRange(@NotNull Range range) {
synchronized (myLock) {
if (!range.isValid()) {
- LOG.warn("UpToDate TextRange of invalid range");
+ LOG.warn("Vcs TextRange of invalid range");
}
- return getRange(range.getUOffset1(), range.getUOffset2(), myUpToDateDocument);
+ return getRange(range.getVcsLine1(), range.getVcsLine2(), myVcsDocument);
}
}
@@ -737,14 +868,14 @@ public class LineStatusTracker {
* So we consider '\n' not as a part of line, but a separator between lines
*/
@NotNull
- private static TextRange getRange(int offset1, int offset2, @NotNull Document document) {
- if (offset1 == offset2) {
- int lineStartOffset = offset1 < getLineCount(document) ? document.getLineStartOffset(offset1) : document.getTextLength();
+ private static TextRange getRange(int line1, int line2, @NotNull Document document) {
+ if (line1 == line2) {
+ int lineStartOffset = line1 < getLineCount(document) ? document.getLineStartOffset(line1) : document.getTextLength();
return new TextRange(lineStartOffset, lineStartOffset);
}
else {
- int startOffset = document.getLineStartOffset(offset1);
- int endOffset = document.getLineEndOffset(offset2 - 1);
+ int startOffset = document.getLineStartOffset(line1);
+ int endOffset = document.getLineEndOffset(line2 - 1);
return new TextRange(startOffset, endOffset);
}
}
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 d332d1faa792..2230f9c4ff59 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
@@ -208,13 +208,13 @@ public class LineStatusTrackerDrawing {
component.add(toolbarPanel, BorderLayout.NORTH);
if (range.getType() != Range.INSERTED) {
- final DocumentEx doc = (DocumentEx) tracker.getUpToDateDocument();
+ final DocumentEx doc = (DocumentEx) tracker.getVcsDocument();
final EditorEx uEditor = (EditorEx)EditorFactory.getInstance().createViewer(doc, tracker.getProject());
final EditorHighlighter highlighter = EditorHighlighterFactory.getInstance().createEditorHighlighter(tracker.getProject(), getFileName(tracker.getDocument()));
uEditor.setHighlighter(highlighter);
final EditorFragmentComponent editorFragmentComponent =
- EditorFragmentComponent.createEditorFragmentComponent(uEditor, range.getUOffset1(), range.getUOffset2(), false, false);
+ EditorFragmentComponent.createEditorFragmentComponent(uEditor, range.getVcsLine1(), range.getVcsLine2(), false, false);
component.add(editorFragmentComponent, BorderLayout.CENTER);
@@ -252,7 +252,7 @@ public class LineStatusTrackerDrawing {
public static void moveToRange(final Range range, final Editor editor, final LineStatusTracker tracker) {
final Document document = tracker.getDocument();
- final int lastOffset = document.getLineStartOffset(Math.min(range.getOffset2(), document.getLineCount() - 1));
+ final int lastOffset = document.getLineStartOffset(Math.min(range.getLine2(), document.getLineCount() - 1));
editor.getCaretModel().moveToOffset(lastOffset);
editor.getScrollingModel().scrollToCaret(ScrollType.CENTER);
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/Range.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/Range.java
index e166acd30fec..e788b1849ce3 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/Range.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/Range.java
@@ -31,29 +31,28 @@ public class Range {
public static final byte INSERTED = 2;
public static final byte DELETED = 3;
- // offset1/offset2 - line numbers
// (2,3) - modified 2nd line
// (2,2) - empty range between 1 and 2 lines
// index of first line is 0
- private int myOffset1;
- private int myOffset2;
- private final int myUpToDateOffset1;
- private final int myUpToDateOffset2;
+ private int myLine1;
+ private int myLine2;
+ private final int myVcsLine1;
+ private final int myVcsLine2;
private final byte myType;
@Nullable private RangeHighlighter myRangeHighlighter;
private boolean myValid = true;
- public static Range createOn(@NotNull Diff.Change change, int shift, int upToDateShift) {
+ public static Range createOn(@NotNull Diff.Change change, int shift, int vcsShift) {
byte type = getChangeTypeFrom(change);
- int offset1 = shift + change.line1;
- int offset2 = offset1 + change.inserted;
+ int line1 = shift + change.line1;
+ int line2 = line1 + change.inserted;
- int uOffset1 = upToDateShift + change.line0;
- int uOffset2 = uOffset1 + change.deleted;
+ int vcsLine1 = vcsShift + change.line0;
+ int vcsLine2 = vcsLine1 + change.deleted;
- return new Range(offset1, offset2, uOffset1, uOffset2, type);
+ return new Range(line1, line2, vcsLine1, vcsLine2, type);
}
private static byte getChangeTypeFrom(@NotNull Diff.Change change) {
@@ -64,31 +63,35 @@ public class Range {
return 0;
}
- public Range(int offset1, int offset2, int uOffset1, int uOffset2, byte type) {
- myOffset1 = offset1;
- myOffset2 = offset2;
- myUpToDateOffset1 = uOffset1;
- myUpToDateOffset2 = uOffset2;
+ public Range(@NotNull Range range) {
+ this(range.getLine1(), range.getLine2(), range.getVcsLine1(), range.getVcsLine2(), range.getType());
+ }
+
+ public Range(int line1, int line2, int vcsLine1, int vcsLine2, byte type) {
+ myLine1 = line1;
+ myLine2 = line2;
+ myVcsLine1 = vcsLine1;
+ myVcsLine2 = vcsLine2;
myType = type;
}
public int hashCode() {
- return myUpToDateOffset1 ^ myUpToDateOffset2 ^ myType ^ myOffset1 ^ myOffset2;
+ return myVcsLine1 ^ myVcsLine2 ^ myType ^ myLine1 ^ myLine2;
}
public boolean equals(Object object) {
if (!(object instanceof Range)) return false;
Range other = (Range)object;
return
- (myUpToDateOffset1 == other.myUpToDateOffset1)
- && (myUpToDateOffset2 == other.myUpToDateOffset2)
- && (myOffset1 == other.myOffset1)
- && (myOffset2 == other.myOffset2)
+ (myVcsLine1 == other.myVcsLine1)
+ && (myVcsLine2 == other.myVcsLine2)
+ && (myLine1 == other.myLine1)
+ && (myLine2 == other.myLine2)
&& (myType == other.myType);
}
public String toString() {
- return String.format("%s, %s, %s, %s, %s", myOffset1, myOffset2, myUpToDateOffset1, myUpToDateOffset2, getTypeName());
+ return String.format("%s, %s, %s, %s, %s", myLine1, myLine2, myVcsLine1, myVcsLine2, getTypeName());
}
@NonNls
@@ -109,43 +112,32 @@ public class Range {
}
public int getUpToDateRangeLength() {
- return myUpToDateOffset2 - myUpToDateOffset1;
+ return myVcsLine2 - myVcsLine1;
}
public void shift(int shift) {
- myOffset1 += shift;
- myOffset2 += shift;
- }
-
- public int getOffset1() {
- return myOffset1;
- }
-
- public int getOffset2() {
- return myOffset2;
+ myLine1 += shift;
+ myLine2 += shift;
}
- public int getUOffset1() {
- return myUpToDateOffset1;
+ public int getLine1() {
+ return myLine1;
}
- public int getUOffset2() {
- return myUpToDateOffset2;
+ public int getLine2() {
+ return myLine2;
}
- public boolean canBeMergedWith(@NotNull Range range) {
- return myOffset2 == range.myOffset1;
+ public int getVcsLine1() {
+ return myVcsLine1;
}
- @NotNull
- public Range mergeWith(@NotNull Range range) {
- return new Range(myOffset1, range.myOffset2, myUpToDateOffset1, range.myUpToDateOffset2, mergedStatusWith(range));
+ public int getVcsLine2() {
+ return myVcsLine2;
}
- private byte mergedStatusWith(@NotNull Range range) {
- byte type = myType;
- if (myType != range.myType) type = MODIFIED;
- return type;
+ public boolean rightBefore(@NotNull Range range) {
+ return myLine2 == range.myLine1;
}
public boolean hasHighlighter() {
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/RangesBuilder.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/RangesBuilder.java
index 74f9e43d08ad..509a9168de42 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/RangesBuilder.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/RangesBuilder.java
@@ -31,17 +31,17 @@ import java.util.List;
public class RangesBuilder {
private List<Range> myRanges;
- public RangesBuilder(@NotNull Document current, @NotNull Document upToDate) throws FilesTooBigForDiffException {
- this(new DocumentWrapper(current).getLines(), new DocumentWrapper(upToDate).getLines(), 0, 0);
+ public RangesBuilder(@NotNull Document current, @NotNull Document vcs) throws FilesTooBigForDiffException {
+ this(new DocumentWrapper(current).getLines(), new DocumentWrapper(vcs).getLines(), 0, 0);
}
- public RangesBuilder(@NotNull List<String> current, @NotNull List<String> upToDate, int shift, int uShift) throws FilesTooBigForDiffException {
+ public RangesBuilder(@NotNull List<String> current, @NotNull List<String> vcs, int shift, int vcsShift) throws FilesTooBigForDiffException {
myRanges = new LinkedList<Range>();
- Diff.Change ch = Diff.buildChanges(ArrayUtil.toStringArray(upToDate), ArrayUtil.toStringArray(current));
+ Diff.Change ch = Diff.buildChanges(ArrayUtil.toStringArray(vcs), ArrayUtil.toStringArray(current));
while (ch != null) {
- Range range = Range.createOn(ch, shift, uShift);
+ Range range = Range.createOn(ch, shift, vcsShift);
myRanges.add(range);
ch = ch.link;
}
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 6e08d90a3b5d..1286b6815fcf 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
@@ -29,68 +29,60 @@ import com.intellij.openapi.vfs.ReadonlyStatusHandler;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.util.BitSet;
import java.util.List;
public class RollbackLineStatusAction extends DumbAwareAction {
- public RollbackLineStatusAction() {
- super(ActionsBundle.actionText("Vcs.RollbackChangedLines"),
- ActionsBundle.actionDescription("Vcs.RollbackChangedLines"),
- AllIcons.Actions.Reset);
- }
-
@Override
public void update(AnActionEvent e) {
Project project = e.getProject();
- if (project == null) {
- e.getPresentation().setEnabled(false);
- return;
- }
- Editor editor = CommonDataKeys.EDITOR.getData(e.getDataContext());
- if (editor == null) {
- e.getPresentation().setEnabled(false);
+ Editor editor = e.getData(CommonDataKeys.EDITOR);
+ if (project == null || editor == null) {
+ e.getPresentation().setEnabledAndVisible(false);
return;
}
LineStatusTracker tracker = LineStatusTrackerManager.getInstance(project).getLineStatusTracker(editor.getDocument());
if (tracker == null) {
- e.getPresentation().setEnabled(false);
+ e.getPresentation().setEnabledAndVisible(false);
return;
}
- e.getPresentation().setEnabled(true);
+ e.getPresentation().setEnabledAndVisible(true);
}
@Override
public void actionPerformed(AnActionEvent e) {
Project project = e.getProject();
- Editor editor = CommonDataKeys.EDITOR.getData(e.getDataContext());
+ Editor editor = e.getRequiredData(CommonDataKeys.EDITOR);
LineStatusTracker tracker = LineStatusTrackerManager.getInstance(project).getLineStatusTracker(editor.getDocument());
- if (tracker == null) return;
+ assert tracker != null;
rollback(tracker, editor, null);
}
protected static void rollback(@NotNull LineStatusTracker tracker, @Nullable Editor editor, @Nullable Range range) {
+ assert editor != null || range != null;
+
if (range != null) {
doRollback(tracker, range);
return;
}
- if (editor == null) return;
Document document = editor.getDocument();
int totalLines = getLineCount(document);
- SegmentTree lines = new SegmentTree(totalLines + 1);
+ BitSet lines = new BitSet(totalLines + 1);
List<Caret> carets = editor.getCaretModel().getAllCarets();
for (Caret caret : carets) {
if (caret.hasSelection()) {
int line1 = editor.offsetToLogicalPosition(caret.getSelectionStart()).line;
int line2 = editor.offsetToLogicalPosition(caret.getSelectionEnd()).line;
- lines.mark(line1, line2 + 1);
- if (caret.getSelectionEnd() == document.getTextLength()) lines.mark(totalLines);
+ lines.set(line1, line2 + 1);
+ if (caret.getSelectionEnd() == document.getTextLength()) lines.set(totalLines);
}
else {
- lines.mark(caret.getLogicalPosition().line);
- if (caret.getOffset() == document.getTextLength()) lines.mark(totalLines);
+ lines.set(caret.getLogicalPosition().line);
+ if (caret.getOffset() == document.getTextLength()) lines.set(totalLines);
}
}
@@ -106,7 +98,7 @@ public class RollbackLineStatusAction extends DumbAwareAction {
});
}
- private static void doRollback(@NotNull final LineStatusTracker tracker, @NotNull final SegmentTree lines) {
+ private static void doRollback(@NotNull final LineStatusTracker tracker, @NotNull final BitSet lines) {
execute(tracker, new Runnable() {
@Override
public void run() {
@@ -116,7 +108,6 @@ public class RollbackLineStatusAction extends DumbAwareAction {
}
private static void execute(@NotNull final LineStatusTracker tracker, @NotNull final Runnable task) {
- // TODO: is there possible data races?
CommandProcessor.getInstance().executeCommand(tracker.getProject(), new Runnable() {
public void run() {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/RollbackLineStatusRangeAction.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/RollbackLineStatusRangeAction.java
index f1795b5efc3c..7f71900654b6 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/RollbackLineStatusRangeAction.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/RollbackLineStatusRangeAction.java
@@ -30,7 +30,7 @@ public class RollbackLineStatusRangeAction extends RollbackLineStatusAction {
@Override
public void update(AnActionEvent e) {
- e.getPresentation().setEnabled(true);
+ e.getPresentation().setEnabledAndVisible(true);
}
public void actionPerformed(final AnActionEvent e) {
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/SegmentTree.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/SegmentTree.java
deleted file mode 100644
index 68307129c13e..000000000000
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/SegmentTree.java
+++ /dev/null
@@ -1,116 +0,0 @@
-package com.intellij.openapi.vcs.ex;
-
-import org.jetbrains.annotations.Nullable;
-
-public class SegmentTree {
- private final int myActualLength;
- private final int myLength;
-
- private final Node myRoot;
-
- public SegmentTree(int length) {
- myActualLength = length;
- myLength = toUpperSquare(length);
- myRoot = new Node();
- }
-
- public void mark(int pos) {
- mark(pos, pos + 1);
- }
-
- public void mark(int start, int end) {
- start = correct(0, myActualLength, start);
- end = correct(0, myActualLength, end);
-
- myRoot.mark(0, myLength, start, end);
- }
-
- public boolean check(int pos) {
- return check(pos, pos + 1);
- }
-
- public boolean check(int start, int end) {
- start = correct(0, myActualLength, start);
- end = correct(0, myActualLength, end);
-
- return myRoot.check(0, myLength, start, end);
- }
-
- private static int toUpperSquare(int value) {
- int high = Integer.highestOneBit(value);
- return high == value ? value : high * 2;
- }
-
- private static class Node {
- @Nullable
- public Node myLeft;
-
- @Nullable
- public Node myRight;
-
- public boolean myMarked;
-
- public boolean mark(int thisStart, int thisEnd, int start, int end) {
- if (myLeft == null && myMarked) return true;
-
- if (start == end) return false;
-
- myMarked = true;
-
- if (thisStart == start && thisEnd == end) {
- myLeft = null;
- myRight = null;
- return true;
- }
-
- if (myLeft == null) {
- myLeft = new Node();
- myRight = new Node();
- }
-
- int mid = thisStart + (thisEnd - thisStart) / 2;
- int start1 = correct(thisStart, mid, start);
- int end1 = correct(thisStart, mid, end);
- int start2 = correct(mid, thisEnd, start);
- int end2 = correct(mid, thisEnd, end);
-
- boolean marked = true;
- marked &= myLeft.mark(thisStart, mid, start1, end1);
- marked &= myRight.mark(mid, thisEnd, start2, end2);
-
- if (marked) {
- myLeft = null;
- myRight = null;
- }
-
- return marked;
- }
-
- public boolean check(int thisStart, int thisEnd, int start, int end) {
- if (start == end) return false;
-
- if (thisStart == start && thisEnd == end) {
- return myMarked;
- }
-
- if (myLeft == null) return myMarked;
-
- int mid = thisStart + (thisEnd - thisStart) / 2;
- int start1 = correct(thisStart, mid, start);
- int end1 = correct(thisStart, mid, end);
- int start2 = correct(mid, thisEnd, start);
- int end2 = correct(mid, thisEnd, end);
-
- if (myLeft.check(thisStart, mid, start1, end1)) return true;
- if (myRight.check(mid, thisEnd, start2, end2)) return true;
-
- return false;
- }
- }
-
- private static int correct(int start, int end, int value) {
- if (value < start) return start;
- if (value > end) return end;
- return value;
- }
-}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/ShowLineStatusRangeDiffAction.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/ShowLineStatusRangeDiffAction.java
index 38f65446a56f..23ea7e341edb 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/ShowLineStatusRangeDiffAction.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/ShowLineStatusRangeDiffAction.java
@@ -49,10 +49,10 @@ public class ShowLineStatusRangeDiffAction extends BaseLineStatusRangeAction {
return new DiffRequest(myLineStatusTracker.getProject()) {
@NotNull
public DiffContent[] getContents() {
- Range range = expand(myRange, myLineStatusTracker.getDocument(), myLineStatusTracker.getUpToDateDocument());
+ Range range = expand(myRange, myLineStatusTracker.getDocument(), myLineStatusTracker.getVcsDocument());
return new DiffContent[]{
- createDiffContent(myLineStatusTracker.getUpToDateDocument(),
- myLineStatusTracker.getUpToDateRange(range),
+ createDiffContent(myLineStatusTracker.getVcsDocument(),
+ myLineStatusTracker.getVcsRange(range),
null),
createDiffContent(myLineStatusTracker.getDocument(),
myLineStatusTracker.getCurrentTextRange(range),
@@ -81,12 +81,12 @@ public class ShowLineStatusRangeDiffAction extends BaseLineStatusRangeAction {
private static Range expand(@NotNull Range range, @NotNull Document document, @NotNull Document uDocument) {
if (range.getType() == Range.MODIFIED) return range;
if (range.getType() == Range.INSERTED || range.getType() == Range.DELETED) {
- boolean canExpandBefore = range.getOffset1() != 0 && range.getUOffset1() != 0;
- boolean canExpandAfter = range.getOffset2() < document.getLineCount() && range.getUOffset2() < uDocument.getLineCount();
- int offset1 = range.getOffset1() - (canExpandBefore ? 1 : 0);
- int uOffset1 = range.getUOffset1() - (canExpandBefore ? 1 : 0);
- int offset2 = range.getOffset2() + (canExpandAfter ? 1 : 0);
- int uOffset2 = range.getUOffset2() + (canExpandAfter ? 1 : 0);
+ boolean canExpandBefore = range.getLine1() != 0 && range.getVcsLine1() != 0;
+ boolean canExpandAfter = range.getLine2() < document.getLineCount() && range.getVcsLine2() < uDocument.getLineCount();
+ int offset1 = range.getLine1() - (canExpandBefore ? 1 : 0);
+ int uOffset1 = range.getVcsLine1() - (canExpandBefore ? 1 : 0);
+ int offset2 = range.getLine2() + (canExpandAfter ? 1 : 0);
+ int uOffset2 = range.getVcsLine2() + (canExpandAfter ? 1 : 0);
return new Range(offset1, offset2, uOffset1, uOffset2, range.getType());
}
throw new IllegalArgumentException("Unknown range type: " + range.getType());
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ModuleDefaultVcsRootPolicy.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ModuleDefaultVcsRootPolicy.java
index 4b057f49b282..615b0fc35e9e 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ModuleDefaultVcsRootPolicy.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ModuleDefaultVcsRootPolicy.java
@@ -28,6 +28,7 @@ import com.intellij.openapi.roots.FileIndexFacade;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.vcs.*;
import com.intellij.openapi.vcs.changes.DirtBuilder;
import com.intellij.openapi.vcs.changes.FilePathUnderVcs;
@@ -116,7 +117,7 @@ public class ModuleDefaultVcsRootPolicy extends DefaultVcsRootPolicy {
.isValidAncestor(myBaseDir, file)) {
return myBaseDir;
}
- final VirtualFile contentRoot = ProjectRootManager.getInstance(myProject).getFileIndex().getContentRootForFile(file);
+ final VirtualFile contentRoot = ProjectRootManager.getInstance(myProject).getFileIndex().getContentRootForFile(file, Registry.is("ide.hide.excluded.files"));
if (contentRoot != null) {
return contentRoot;
}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ModuleVcsPathPresenter.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ModuleVcsPathPresenter.java
index 5c2adcbccd8d..1e1cbdf55f5f 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ModuleVcsPathPresenter.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ModuleVcsPathPresenter.java
@@ -23,6 +23,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.changes.ContentRevision;
import com.intellij.openapi.vcs.changes.patch.RelativePathCalculator;
@@ -48,10 +49,10 @@ public class ModuleVcsPathPresenter extends VcsPathPresenter {
return ApplicationManager.getApplication().runReadAction(new Computable<String>() {
@Override
public String compute() {
- ProjectFileIndex fileIndex = ProjectRootManager.getInstance(myProject)
- .getFileIndex();
- Module module = fileIndex.getModuleForFile(file);
- VirtualFile contentRoot = fileIndex.getContentRootForFile(file);
+ ProjectFileIndex fileIndex = ProjectRootManager.getInstance(myProject).getFileIndex();
+ boolean hideExcludedFiles = Registry.is("ide.hide.excluded.files");
+ Module module = fileIndex.getModuleForFile(file, hideExcludedFiles);
+ VirtualFile contentRoot = fileIndex.getContentRootForFile(file, hideExcludedFiles);
if (module == null || contentRoot == null) return file.getPresentableUrl();
StringBuffer result = new StringBuffer();
result.append("[");
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 e699383321ae..84ca76e1d89f 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
@@ -661,7 +661,7 @@ public class ProjectLevelVcsManagerImpl extends ProjectLevelVcsManagerEx impleme
@Override
@NotNull
- public VirtualFile[] getRootsUnderVcs(AbstractVcs vcs) {
+ public VirtualFile[] getRootsUnderVcs(@NotNull AbstractVcs vcs) {
return myMappingsToRoots.getRootsUnderVcs(vcs);
}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/UpToDateLineNumberProviderImpl.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/UpToDateLineNumberProviderImpl.java
index 795652f0b773..5d049f3e9c14 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/UpToDateLineNumberProviderImpl.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/UpToDateLineNumberProviderImpl.java
@@ -54,15 +54,15 @@ public class UpToDateLineNumberProviderImpl implements UpToDateLineNumberProvide
if (lineInRange(range, start) || lineInRange(range, end)) {
return true;
}
- if (range.getOffset1() > start) {
- return range.getOffset1() < end;
+ if (range.getLine1() > start) {
+ return range.getLine1() < end;
}
}
return false;
}
private static boolean lineInRange(final Range range, final int currentNumber) {
- return range.getOffset1() <= currentNumber && range.getOffset2() >= currentNumber;
+ return range.getLine1() <= currentNumber && range.getLine2() >= currentNumber;
}
@Override
@@ -72,7 +72,7 @@ public class UpToDateLineNumberProviderImpl implements UpToDateLineNumberProvide
return false;
}
for (Range range : tracker.getRanges()) {
- if (range.getOffset1() <= currentNumber && range.getOffset2() >= currentNumber) {
+ if (range.getLine1() <= currentNumber && range.getLine2() >= currentNumber) {
return true;
}
}
@@ -111,8 +111,8 @@ public class UpToDateLineNumberProviderImpl implements UpToDateLineNumberProvide
for (final Object range1 : ranges) {
Range range = (Range)range1;
- int startOffset = range.getOffset1();
- int endOffset = range.getOffset2();
+ int startOffset = range.getLine1();
+ int endOffset = range.getLine2();
if ((startOffset <= currentNumber) && (endOffset > currentNumber)) {
return ABSENT_LINE_NUMBER;
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/projectlevelman/MappingsToRoots.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/projectlevelman/MappingsToRoots.java
index 677c26e6d9f1..1be3cbf0cda3 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/projectlevelman/MappingsToRoots.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/projectlevelman/MappingsToRoots.java
@@ -42,7 +42,7 @@ public class MappingsToRoots {
}
@NotNull
- public VirtualFile[] getRootsUnderVcs(final AbstractVcs vcs) {
+ public VirtualFile[] getRootsUnderVcs(@NotNull AbstractVcs vcs) {
List<VirtualFile> result = myMappings.getMappingsAsFilesUnderVcs(vcs);
final AbstractVcs.RootsConvertor convertor = vcs.getCustomConvertor();
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 5ff541ebc67d..57754f0190cc 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
@@ -273,7 +273,7 @@ public class NewMappings {
return FileUtil.startsWith(systemIndependentPath, mapping.systemIndependentPath());
}
- public List<VirtualFile> getMappingsAsFilesUnderVcs(final AbstractVcs vcs) {
+ public List<VirtualFile> getMappingsAsFilesUnderVcs(@NotNull AbstractVcs vcs) {
final List<VirtualFile> result = new ArrayList<VirtualFile>();
final String vcsName = vcs.getName();
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/update/AbstractCommonUpdateAction.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/update/AbstractCommonUpdateAction.java
index d2c7b556b88e..5fa282c06e14 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/update/AbstractCommonUpdateAction.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/update/AbstractCommonUpdateAction.java
@@ -38,7 +38,6 @@ import com.intellij.openapi.vcs.changes.RemoteRevisionsCache;
import com.intellij.openapi.vcs.changes.VcsAnnotationRefresher;
import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager;
import com.intellij.openapi.vcs.changes.VcsDirtyScopeManagerImpl;
-import com.intellij.openapi.vcs.changes.committed.CommittedChangesAdapter;
import com.intellij.openapi.vcs.changes.committed.CommittedChangesCache;
import com.intellij.openapi.vcs.ex.ProjectLevelVcsManagerEx;
import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier;
@@ -46,6 +45,7 @@ import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
+import com.intellij.util.Consumer;
import com.intellij.util.WaitForProgressToShow;
import com.intellij.util.ui.OptionsDialog;
import com.intellij.vcsUtil.VcsUtil;
@@ -550,10 +550,14 @@ public abstract class AbstractCommonUpdateAction extends AbstractVcsAction {
}
}
else if (! myUpdatedFiles.isEmpty()) {
- showUpdateTree(continueChainFinal && updateSuccess && noMerged, someSessionWasCancelled);
-
+ final UpdateInfoTree tree = showUpdateTree(continueChainFinal && updateSuccess && noMerged, someSessionWasCancelled);
final CommittedChangesCache cache = CommittedChangesCache.getInstance(myProject);
- cache.processUpdatedFiles(myUpdatedFiles);
+ cache.processUpdatedFiles(myUpdatedFiles, new Consumer<List<CommittedChangeList>>() {
+ @Override
+ public void consume(List<CommittedChangeList> incomingChangeLists) {
+ tree.setChangeLists(incomingChangeLists);
+ }
+ });
if (someSessionWasCancelled) {
VcsBalloonProblemNotifier.showOverChangesView(myProject, "VCS Update Incomplete" + prepareNotificationWithUpdateInfo(), MessageType.WARNING);
@@ -592,7 +596,8 @@ public abstract class AbstractCommonUpdateAction extends AbstractVcsAction {
}
}
- private void showUpdateTree(final boolean willBeContinued, final boolean wasCanceled) {
+ @NotNull
+ private UpdateInfoTree showUpdateTree(final boolean willBeContinued, final boolean wasCanceled) {
RestoreUpdateTree restoreUpdateTree = RestoreUpdateTree.getInstance(myProject);
restoreUpdateTree.registerUpdateInformation(myUpdatedFiles, myActionInfo);
final String text = getTemplatePresentation().getText() + ((willBeContinued || (myUpdateNumber > 1)) ? ("#" + myUpdateNumber) : "");
@@ -602,13 +607,7 @@ public abstract class AbstractCommonUpdateAction extends AbstractVcsAction {
updateInfoTree.setAfter(myAfter);
updateInfoTree.setCanGroupByChangeList(canGroupByChangelist(myVcsToVirtualFiles.keySet()));
- myProject.getMessageBus().connect(updateInfoTree).subscribe(CommittedChangesCache.COMMITTED_TOPIC, new CommittedChangesAdapter() {
- public void incomingChangesUpdated(final List<CommittedChangeList> receivedChanges) {
- if (receivedChanges != null) {
- updateInfoTree.setChangeLists(receivedChanges);
- }
- }
- });
+ return updateInfoTree;
}
public void onCancel() {
diff --git a/platform/vcs-impl/src/com/intellij/vcsUtil/AuthDialog.java b/platform/vcs-impl/src/com/intellij/vcsUtil/AuthDialog.java
index d3ed9a84de2c..5d6861e6f39b 100644
--- a/platform/vcs-impl/src/com/intellij/vcsUtil/AuthDialog.java
+++ b/platform/vcs-impl/src/com/intellij/vcsUtil/AuthDialog.java
@@ -25,7 +25,7 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
public class AuthDialog extends DialogWrapper {
- private AuthenticationPanel authPanel;
+ private final AuthenticationPanel authPanel;
/**
* If password if prefilled, it is expected to continue remembering it.
@@ -54,6 +54,7 @@ public class AuthDialog extends DialogWrapper {
return rememberByDefault;
}
+ @Override
protected JComponent createCenterPanel() {
return authPanel;
}
diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogSettings.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogSettings.java
index a370379b4d77..f382e23cf480 100644
--- a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogSettings.java
+++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogSettings.java
@@ -1,10 +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 com.intellij.vcs.log;
-import com.intellij.openapi.components.StoragePathMacros;
/**
* <p>Vcs Log user settings, which may have a UI representation, or be implicitly selected based on user actions.</p>
- * <p>Most of the settings are workspace-specific, i. e. they are stored in {@link StoragePathMacros#WORKSPACE_FILE workspace.xml}.</p>
+ * <p>Most of the settings are workspace-specific, i. e. they are stored in {@link com.intellij.openapi.components.StoragePathMacros#WORKSPACE_FILE workspace.xml}.</p>
*
* @author Kirill Likhodedov
*/
diff --git a/platform/vcs-log/api/vcs-log-api.iml b/platform/vcs-log/api/vcs-log-api.iml
index bdbe62ba331d..92d746615afa 100644
--- a/platform/vcs-log/api/vcs-log-api.iml
+++ b/platform/vcs-log/api/vcs-log-api.iml
@@ -10,8 +10,9 @@
<orderEntry type="module" module-name="util-rt" />
<orderEntry type="module" module-name="vcs-log-graph-api" exported="" />
<orderEntry type="module" module-name="core-api" />
- <orderEntry type="module" module-name="vcs-api" />
<orderEntry type="library" name="JUnit4" level="project" />
+ <orderEntry type="module" module-name="vcs-api-core" />
+ <orderEntry type="module" module-name="editor-ui-api" />
</component>
</module>
diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/XDebugSession.java b/platform/xdebugger-api/src/com/intellij/xdebugger/XDebugSession.java
index be71aac98d1e..33fa877064db 100644
--- a/platform/xdebugger-api/src/com/intellij/xdebugger/XDebugSession.java
+++ b/platform/xdebugger-api/src/com/intellij/xdebugger/XDebugSession.java
@@ -21,6 +21,7 @@ import com.intellij.execution.ui.ConsoleView;
import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.execution.ui.RunnerLayoutUi;
import com.intellij.openapi.Disposable;
+import com.intellij.openapi.actionSystem.DataKey;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.MessageType;
import com.intellij.xdebugger.breakpoints.XBreakpoint;
@@ -45,6 +46,7 @@ import javax.swing.event.HyperlinkListener;
* @author nik
*/
public interface XDebugSession extends AbstractDebuggerSession {
+ DataKey<XDebugSession> DATA_KEY = DataKey.create("XDebugSessionTab.XDebugSession");
@NotNull
Project getProject();
diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/XDebuggerManager.java b/platform/xdebugger-api/src/com/intellij/xdebugger/XDebuggerManager.java
index 08a30664f7dc..cb65b84af9d9 100644
--- a/platform/xdebugger-api/src/com/intellij/xdebugger/XDebuggerManager.java
+++ b/platform/xdebugger-api/src/com/intellij/xdebugger/XDebuggerManager.java
@@ -58,16 +58,24 @@ public abstract class XDebuggerManager {
public abstract XDebugSession getCurrentSession();
/**
- * Start a new debugging session. Use this method only if debugging is started by using standard 'Debug' action i.e. this methods is called
- * from {@link com.intellij.execution.runners.ProgramRunner#execute} method. Otherwise use {@link #startSessionAndShowTab} method
+ * @deprecated use {@link #startSession(com.intellij.execution.runners.ExecutionEnvironment, XDebugProcessStarter)} instead
+ * to remove in IDEA 15
*/
@NotNull
- public abstract XDebugSession startSession(@NotNull final ProgramRunner runner,
+ @Deprecated
+ public abstract XDebugSession startSession(@NotNull ProgramRunner runner,
@NotNull ExecutionEnvironment env,
@Nullable RunContentDescriptor contentToReuse,
@NotNull XDebugProcessStarter processStarter) throws ExecutionException;
/**
+ * Start a new debugging session. Use this method only if debugging is started by using standard 'Debug' action i.e. this methods is called
+ * from {@link com.intellij.execution.runners.ProgramRunner#execute} method. Otherwise use {@link #startSessionAndShowTab} method
+ */
+ @NotNull
+ public abstract XDebugSession startSession(@NotNull ExecutionEnvironment environment, @NotNull XDebugProcessStarter processStarter) throws ExecutionException;
+
+ /**
* Start a new debugging session and open 'Debug' tool window
* @param sessionName title of 'Debug' tool window
*/
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 762855510a1e..8ee2f1ee587a 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java
@@ -25,7 +25,6 @@ import com.intellij.execution.process.ProcessAdapter;
import com.intellij.execution.process.ProcessEvent;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.runners.ExecutionEnvironment;
-import com.intellij.execution.runners.ProgramRunner;
import com.intellij.execution.ui.ConsoleView;
import com.intellij.execution.ui.ConsoleViewContentType;
import com.intellij.execution.ui.RunContentDescriptor;
@@ -108,10 +107,9 @@ public class XDebugSessionImpl implements XDebugSession {
private final EventDispatcher<XDebugSessionListener> myDispatcher = EventDispatcher.create(XDebugSessionListener.class);
private final Project myProject;
private final @Nullable ExecutionEnvironment myEnvironment;
- private final @Nullable ProgramRunner myRunner;
private boolean myStopped;
private boolean myPauseActionSupported;
- private boolean myShowTabOnSuspend;
+ private final AtomicBoolean myShowTabOnSuspend;
private final List<AnAction> myRestartActions = new SmartList<AnAction>();
private final List<AnAction> myExtraStopActions = new SmartList<AnAction>();
private final List<AnAction> myExtraActions = new SmartList<AnAction>();
@@ -121,23 +119,19 @@ public class XDebugSessionImpl implements XDebugSession {
private volatile boolean breakpointsInitialized;
private boolean autoInitBreakpoints = true;
- public XDebugSessionImpl(@NotNull ExecutionEnvironment environment,
- @Nullable ProgramRunner runner,
- @NotNull XDebuggerManagerImpl debuggerManager) {
- this(environment, runner, debuggerManager, environment.getRunProfile().getName(), environment.getRunProfile().getIcon(), false);
+ public XDebugSessionImpl(@NotNull ExecutionEnvironment environment, @NotNull XDebuggerManagerImpl debuggerManager) {
+ this(environment, debuggerManager, environment.getRunProfile().getName(), environment.getRunProfile().getIcon(), false);
}
public XDebugSessionImpl(@Nullable ExecutionEnvironment environment,
- @Nullable ProgramRunner runner,
@NotNull XDebuggerManagerImpl debuggerManager,
@NotNull String sessionName,
@Nullable Icon icon,
boolean showTabOnSuspend) {
myEnvironment = environment;
- myRunner = runner;
mySessionName = sessionName;
myDebuggerManager = debuggerManager;
- myShowTabOnSuspend = showTabOnSuspend;
+ myShowTabOnSuspend = new AtomicBoolean(showTabOnSuspend);
myProject = debuggerManager.getProject();
ValueLookupManager.getInstance(myProject).startListening();
myIcon = icon;
@@ -158,7 +152,7 @@ public class XDebugSessionImpl implements XDebugSession {
}
private void assertSessionTabInitialized() {
- if (myShowTabOnSuspend) {
+ if (myShowTabOnSuspend.get()) {
LOG.error("Debug tool window isn't shown yet because debug process isn't suspended");
}
else {
@@ -176,6 +170,7 @@ public class XDebugSessionImpl implements XDebugSession {
myPauseActionSupported = isSupported;
}
+ @NotNull
public List<AnAction> getRestartActions() {
return myRestartActions;
}
@@ -186,6 +181,7 @@ public class XDebugSessionImpl implements XDebugSession {
}
}
+ @NotNull
public List<AnAction> getExtraActions() {
return myExtraActions;
}
@@ -208,7 +204,7 @@ public class XDebugSessionImpl implements XDebugSession {
@Override
public void rebuildViews() {
- if (!myShowTabOnSuspend && mySessionTab != null) {
+ if (!myShowTabOnSuspend.get() && mySessionTab != null) {
mySessionTab.rebuildViews();
}
}
@@ -262,7 +258,7 @@ public class XDebugSessionImpl implements XDebugSession {
return myCurrentPosition;
}
- public XDebugSessionTab init(final XDebugProcess process, @NotNull final XDebugSessionData sessionData) {
+ public XDebugSessionTab init(@NotNull XDebugProcess process, @NotNull XDebugSessionData sessionData, @Nullable RunContentDescriptor contentToReuse) {
LOG.assertTrue(myDebugProcess == null);
myDebugProcess = process;
mySessionData = sessionData;
@@ -279,8 +275,8 @@ public class XDebugSessionImpl implements XDebugSession {
});
//todo[nik] make 'createConsole()' method return ConsoleView
myConsoleView = (ConsoleView)myDebugProcess.createConsole();
- if (!myShowTabOnSuspend) {
- initSessionTab();
+ if (!myShowTabOnSuspend.get()) {
+ initSessionTab(contentToReuse);
}
return mySessionTab;
@@ -316,11 +312,12 @@ public class XDebugSessionImpl implements XDebugSession {
@Override
public RunnerLayoutUi getUI() {
assertSessionTabInitialized();
+ assert mySessionTab != null;
return mySessionTab.getUi();
}
- private void initSessionTab() {
- mySessionTab = new XDebugSessionTab(myProject, this, myIcon, myEnvironment, myRunner);
+ private void initSessionTab(@Nullable RunContentDescriptor contentToReuse) {
+ mySessionTab = XDebugSessionTab.create(this, myIcon, myEnvironment, contentToReuse);
myDebugProcess.sessionInitialized();
}
@@ -536,12 +533,12 @@ public class XDebugSessionImpl implements XDebugSession {
private void doResume() {
if (!myPaused.getAndSet(false)) return;
- final XSourcePosition oldPosition = myCurrentPosition;
myDispatcher.getMulticaster().beforeSessionResume();
myDebuggerManager.setActiveSession(this, null, false, null);
mySuspendContext = null;
myCurrentExecutionStack = null;
myCurrentStackFrame = null;
+ adjustMouseTrackingCounter(myCurrentPosition, -1);
myCurrentPosition = null;
myActiveNonLineBreakpoint = null;
UIUtil.invokeLaterIfNeeded(new Runnable() {
@@ -550,9 +547,6 @@ public class XDebugSessionImpl implements XDebugSession {
if (mySessionTab != null) {
mySessionTab.getUi().clearAttractionBy(XDebuggerUIConstants.LAYOUT_VIEW_BREAKPOINT_CONDITION);
}
- if (oldPosition != null) {
- adjustMouseTrackingCounter(oldPosition, -1);
- }
}
});
myDispatcher.getMulticaster().sessionResumed();
@@ -794,32 +788,37 @@ public class XDebugSessionImpl implements XDebugSession {
if (myCurrentPosition != null) {
myDebuggerManager.setActiveSession(this, myCurrentPosition, false, getPositionIconRenderer(true));
}
- UIUtil.invokeLaterIfNeeded(new Runnable() {
- @Override
- public void run() {
- if (myShowTabOnSuspend) {
- myShowTabOnSuspend = false;
- initSessionTab();
+ adjustMouseTrackingCounter(myCurrentPosition, 1);
+
+ if (myShowTabOnSuspend.compareAndSet(true, false)) {
+ UIUtil.invokeLaterIfNeeded(new Runnable() {
+ @Override
+ public void run() {
+ initSessionTab(null);
showSessionTab();
}
- if (myCurrentPosition != null) {
- adjustMouseTrackingCounter(myCurrentPosition, 1);
- }
- }
- });
+ });
+ }
+
myDispatcher.getMulticaster().sessionPaused();
}
- private void adjustMouseTrackingCounter(@NotNull XSourcePosition position, int increment) {
- if (ApplicationManager.getApplication().isUnitTestMode()) return;
+ private void adjustMouseTrackingCounter(final XSourcePosition position, final int increment) {
+ if (position == null || ApplicationManager.getApplication().isUnitTestMode()) return;
- Editor editor = XDebuggerUtilImpl.createEditor(new OpenFileDescriptor(myProject, position.getFile()));
- if (editor != null) {
- JComponent component = editor.getComponent();
- Object o = component.getClientProperty(EditorImpl.IGNORE_MOUSE_TRACKING);
- Integer value = ((o instanceof Integer) ? (Integer)o : 0) + increment;
- component.putClientProperty(EditorImpl.IGNORE_MOUSE_TRACKING, value > 0 ? value : null);
- }
+ // need to always invoke later to maintain order of increment/decrement
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ Editor editor = XDebuggerUtilImpl.createEditor(new OpenFileDescriptor(myProject, position.getFile()));
+ if (editor != null) {
+ JComponent component = editor.getComponent();
+ Object o = component.getClientProperty(EditorImpl.IGNORE_MOUSE_TRACKING);
+ Integer value = ((o instanceof Integer) ? (Integer)o : 0) + increment;
+ component.putClientProperty(EditorImpl.IGNORE_MOUSE_TRACKING, value > 0 ? value : null);
+ }
+ }
+ });
}
@Override
@@ -851,6 +850,12 @@ public class XDebugSessionImpl implements XDebugSession {
if (!myProject.isDisposed()) {
myProject.getMessageBus().syncPublisher(XDebuggerManager.TOPIC).processStopped(myDebugProcess);
}
+
+ if (mySessionTab != null) {
+ mySessionTab.detachFromSession();
+ }
+
+ adjustMouseTrackingCounter(myCurrentPosition, -1);
myCurrentPosition = null;
myCurrentExecutionStack = null;
myCurrentStackFrame = null;
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerManagerImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerManagerImpl.java
index b974150d2c56..2e6f91d43924 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerManagerImpl.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerManagerImpl.java
@@ -23,10 +23,8 @@ import com.intellij.execution.executors.DefaultDebugExecutor;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.runners.ProgramRunner;
-import com.intellij.execution.ui.ExecutionConsole;
-import com.intellij.execution.ui.RunContentDescriptor;
-import com.intellij.execution.ui.RunContentManagerImpl;
-import com.intellij.execution.ui.RunContentWithExecutorListener;
+import com.intellij.execution.runners.RunContentBuilder;
+import com.intellij.execution.ui.*;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.*;
@@ -119,11 +117,11 @@ public class XDebuggerManagerImpl extends XDebuggerManager
}
});
- messageBusConnection.subscribe(RunContentManagerImpl.RUN_CONTENT_TOPIC, new RunContentWithExecutorListener() {
+ messageBusConnection.subscribe(RunContentManager.TOPIC, new RunContentWithExecutorListener() {
@Override
- public void contentSelected(RunContentDescriptor descriptor, @NotNull Executor executor) {
- if (executor.equals(DefaultDebugExecutor.getDebugExecutorInstance())) {
- final XDebugSessionImpl session = mySessions.get(descriptor.getProcessHandler());
+ public void contentSelected(@Nullable RunContentDescriptor descriptor, @NotNull Executor executor) {
+ if (descriptor != null && executor.equals(DefaultDebugExecutor.getDebugExecutorInstance())) {
+ XDebugSessionImpl session = mySessions.get(descriptor.getProcessHandler());
if (session != null) {
session.activateSession();
}
@@ -134,8 +132,8 @@ public class XDebuggerManagerImpl extends XDebuggerManager
}
@Override
- public void contentRemoved(RunContentDescriptor descriptor, @NotNull Executor executor) {
- if (executor.equals(DefaultDebugExecutor.getDebugExecutorInstance())) {
+ public void contentRemoved(@Nullable RunContentDescriptor descriptor, @NotNull Executor executor) {
+ if (descriptor != null && executor.equals(DefaultDebugExecutor.getDebugExecutorInstance())) {
mySessions.remove(descriptor.getProcessHandler());
mySessionData.remove(descriptor);
XDebugSessionTab tab = mySessionTabs.remove(descriptor);
@@ -169,11 +167,17 @@ public class XDebuggerManagerImpl extends XDebuggerManager
@Override
@NotNull
- public XDebugSession startSession(@NotNull final ProgramRunner runner,
- @NotNull final ExecutionEnvironment environment,
- @Nullable final RunContentDescriptor contentToReuse,
- @NotNull final XDebugProcessStarter processStarter) throws ExecutionException {
- return startSession(contentToReuse, processStarter, new XDebugSessionImpl(environment, runner, this));
+ public XDebugSession startSession(@NotNull ProgramRunner runner,
+ @NotNull ExecutionEnvironment environment,
+ @Nullable RunContentDescriptor contentToReuse,
+ @NotNull XDebugProcessStarter processStarter) throws ExecutionException {
+ return startSession(contentToReuse, processStarter, new XDebugSessionImpl(RunContentBuilder.fix(environment, runner), this));
+ }
+
+ @Override
+ @NotNull
+ public XDebugSession startSession(@NotNull ExecutionEnvironment environment, @NotNull XDebugProcessStarter processStarter) throws ExecutionException {
+ return startSession(environment.getContentToReuse(), processStarter, new XDebugSessionImpl(environment, this));
}
@Override
@@ -193,10 +197,12 @@ public class XDebuggerManagerImpl extends XDebuggerManager
@NotNull
@Override
- public XDebugSession startSessionAndShowTab(@NotNull String sessionName, final Icon icon, @Nullable RunContentDescriptor contentToReuse,
+ public XDebugSession startSessionAndShowTab(@NotNull String sessionName,
+ Icon icon,
+ @Nullable RunContentDescriptor contentToReuse,
boolean showToolWindowOnSuspendOnly,
@NotNull XDebugProcessStarter starter) throws ExecutionException {
- XDebugSessionImpl session = startSession(contentToReuse, starter, new XDebugSessionImpl(null, null, this, sessionName,
+ XDebugSessionImpl session = startSession(contentToReuse, starter, new XDebugSessionImpl(null, this, sessionName,
icon, showToolWindowOnSuspendOnly));
if (!showToolWindowOnSuspendOnly) {
session.showSessionTab();
@@ -206,8 +212,9 @@ public class XDebuggerManagerImpl extends XDebuggerManager
return session;
}
- private XDebugSessionImpl startSession(final RunContentDescriptor contentToReuse, final XDebugProcessStarter processStarter,
- final XDebugSessionImpl session) throws ExecutionException {
+ private XDebugSessionImpl startSession(@Nullable RunContentDescriptor contentToReuse,
+ @NotNull XDebugProcessStarter processStarter,
+ @NotNull XDebugSessionImpl session) throws ExecutionException {
XDebugProcess process = processStarter.start(session);
myProject.getMessageBus().syncPublisher(TOPIC).processStarted(process);
@@ -222,7 +229,7 @@ public class XDebuggerManagerImpl extends XDebuggerManager
((XDebugProcessConfiguratorStarter)processStarter).configure(oldSessionData);
}
- session.init(process, oldSessionData);
+ session.init(process, oldSessionData, contentToReuse);
mySessions.put(session.getDebugProcess().getProcessHandler(), session);
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerWatchesManager.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerWatchesManager.java
index e803453eb662..4bcc6753925e 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerWatchesManager.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerWatchesManager.java
@@ -16,6 +16,7 @@
package com.intellij.xdebugger.impl;
import com.intellij.openapi.components.PersistentStateComponent;
+import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.xmlb.annotations.AbstractCollection;
import com.intellij.util.xmlb.annotations.Attribute;
@@ -67,11 +68,13 @@ public class XDebuggerWatchesManager implements PersistentStateComponent<XDebugg
watches.clear();
if (state != null) {
for (ConfigurationState expressionState : state.expressions) {
- WatchState[] states = expressionState.myExpressionStates;
- XExpression[] expressions = new XExpression[states.length];
- for (int i = 0; i < states.length; i++) {
- expressions[i] = states[i].toXExpression();
- }
+ XExpression[] expressions = ContainerUtil.mapNotNull(expressionState.myExpressionStates,
+ new Function<WatchState, XExpression>() {
+ @Override
+ public XExpression fun(WatchState state) {
+ return state.toXExpression();
+ }
+ }, new XExpression[0]);
watches.put(expressionState.myName, expressions);
}
}
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/EditBreakpointAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/EditBreakpointAction.java
index a9f15890bbea..6384629d19a8 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/EditBreakpointAction.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/EditBreakpointAction.java
@@ -19,13 +19,13 @@ import com.intellij.idea.ActionsBundle;
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.editor.Editor;
import com.intellij.openapi.editor.markup.GutterIconRenderer;
+import com.intellij.openapi.project.DumbAware;
import com.intellij.xdebugger.impl.DebuggerSupport;
import org.jetbrains.annotations.NotNull;
-public class EditBreakpointAction extends XDebuggerActionBase {
+public class EditBreakpointAction extends XDebuggerActionBase implements DumbAware {
public static class ContextAction extends AnAction {
private final GutterIconRenderer myRenderer;
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XExpressionImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XExpressionImpl.java
index b966377a47ba..d049356247b4 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XExpressionImpl.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XExpressionImpl.java
@@ -18,6 +18,7 @@ package com.intellij.xdebugger.impl.breakpoints;
import com.intellij.lang.Language;
import com.intellij.xdebugger.XExpression;
import com.intellij.xdebugger.evaluation.EvaluationMode;
+import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -65,12 +66,12 @@ public class XExpressionImpl implements XExpression {
return myMode;
}
- @Nullable
+ @Contract("null -> null; !null -> !null")
public static XExpressionImpl fromText(@Nullable String text) {
return text != null ? new XExpressionImpl(text, null, null, EvaluationMode.EXPRESSION) : null;
}
- @Nullable
+ @Contract("null, _ -> null; !null, _ -> !null")
public static XExpressionImpl fromText(@Nullable String text, EvaluationMode mode) {
return text != null ? new XExpressionImpl(text, null, null, mode) : null;
}
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XExpressionState.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XExpressionState.java
index 205cc2d9498d..65dc92e97ec1 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XExpressionState.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XExpressionState.java
@@ -16,10 +16,12 @@
package com.intellij.xdebugger.impl.breakpoints;
import com.intellij.lang.Language;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.xmlb.annotations.Attribute;
import com.intellij.util.xmlb.annotations.Text;
import com.intellij.xdebugger.XExpression;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
/**
* @author egor
@@ -65,8 +67,13 @@ public class XExpressionState {
}
}
+ @Nullable
public XExpression toXExpression() {
checkConverted();
+ // old versions may have empty expressions serialized
+ if (StringUtil.isEmptyOrSpaces(myExpression)) {
+ return null;
+ }
return new XExpressionImpl(myExpression, Language.findLanguageByID(myLanguage), myCustomInfo);
}
}
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEditorLinePainter.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEditorLinePainter.java
new file mode 100644
index 000000000000..a3aa8ec43fc5
--- /dev/null
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEditorLinePainter.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.xdebugger.impl.evaluate;
+
+import com.intellij.openapi.editor.EditorLinePainter;
+import com.intellij.openapi.editor.LineExtensionInfo;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.registry.Registry;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.ui.JBColor;
+import com.intellij.ui.SimpleColoredText;
+import com.intellij.xdebugger.frame.presentation.XValuePresentation;
+import com.intellij.xdebugger.impl.frame.XVariablesView;
+import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl;
+import com.intellij.xdebugger.impl.ui.tree.nodes.XValueTextRendererImpl;
+import org.jetbrains.annotations.NotNull;
+
+import java.awt.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public class XDebuggerEditorLinePainter extends EditorLinePainter {
+ @Override
+ public Collection<LineExtensionInfo> getLineExtensions(@NotNull Project project, @NotNull VirtualFile file, int lineNumber) {
+ if (!Registry.is("ide.debugger.inline")) {
+ return null;
+ }
+
+ Map<Pair<VirtualFile, Integer>, Set<XValueNodeImpl>> map = project.getUserData(XVariablesView.DEBUG_VARIABLES);
+ if (map != null) {
+ Set<XValueNodeImpl> values = map.get(Pair.create(file, lineNumber));
+ if (values != null && !values.isEmpty()) {
+ ArrayList<LineExtensionInfo> result = new ArrayList<LineExtensionInfo>();
+ for (XValueNodeImpl value : values) {
+ SimpleColoredText text = new SimpleColoredText();
+ XValueTextRendererImpl renderer = new XValueTextRendererImpl(text);
+ final XValuePresentation presentation = value.getValuePresentation();
+ if (presentation == null) continue;
+ if (presentation instanceof XValueCompactPresentation) {
+ ((XValueCompactPresentation)presentation).renderValue(renderer, value);
+ } else {
+ presentation.renderValue(renderer);
+ }
+ final Color color = new JBColor(new Color(61, 128, 101), new Color(61, 128, 101));
+ result.add(new LineExtensionInfo(" " + value.getName() + ": ", color, null, null, Font.PLAIN));
+ for (String s : text.getTexts()) {
+ result.add(new LineExtensionInfo(s, color, null, null, Font.PLAIN));
+ }
+ }
+ return result;
+ }
+ }
+
+ return null;
+ }
+}
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 bee9b3d91fd7..37da856156ea 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
@@ -129,6 +129,7 @@ public class XDebuggerEvaluationDialog extends DialogWrapper {
evaluate();
}
+ @Override
protected void createDefaultActions() {
super.createDefaultActions();
myOKAction = new OkAction(){
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XValueCompactPresentation.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XValueCompactPresentation.java
new file mode 100644
index 000000000000..f34b5afe1154
--- /dev/null
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XValueCompactPresentation.java
@@ -0,0 +1,28 @@
+/*
+ * 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.evaluate;
+
+import com.intellij.xdebugger.frame.presentation.XValuePresentation;
+import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public interface XValueCompactPresentation {
+ void renderValue(@NotNull XValuePresentation.XValueTextRenderer renderer, @Nullable XValueNodeImpl node);
+}
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/common/AbstractValueHint.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/common/AbstractValueHint.java
index 5a956450952a..7b860b49d255 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/common/AbstractValueHint.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/common/AbstractValueHint.java
@@ -178,6 +178,9 @@ public abstract class AbstractValueHint {
}
protected boolean showHint(final JComponent component) {
+ if (myCurrentHint != null) {
+ myCurrentHint.hide();
+ }
myCurrentHint = new LightweightHint(component);
myCurrentHint.addHintListener(new HintListener() {
@Override
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/DebuggerFramesList.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/DebuggerFramesList.java
index 41dd52bcc3b9..18ef7cecd450 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/DebuggerFramesList.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/DebuggerFramesList.java
@@ -39,6 +39,7 @@ public abstract class DebuggerFramesList extends JBList implements OccurenceNavi
getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
setCellRenderer(createListRenderer());
getSelectionModel().addListSelectionListener(new ListSelectionListener() {
+ @Override
public void valueChanged(final ListSelectionEvent e) {
if (!e.getValueIsAdjusting()) {
onFrameChanged(getSelectedValue());
@@ -49,6 +50,7 @@ public abstract class DebuggerFramesList extends JBList implements OccurenceNavi
getEmptyText().setText(XDebuggerBundle.message("debugger.frames.not.available"));
}
+ @Override
public DefaultListModel getModel() {
return (DefaultListModel)super.getModel();
}
@@ -61,19 +63,23 @@ public abstract class DebuggerFramesList extends JBList implements OccurenceNavi
return getModel().getSize();
}
+ @Override
public String getNextOccurenceActionName() {
return XDebuggerBundle.message("action.next.frame.text");
}
+ @Override
public String getPreviousOccurenceActionName() {
return XDebuggerBundle.message("action.previous.frame.text");
}
+ @Override
public OccurenceInfo goNextOccurence() {
setSelectedIndex(getSelectedIndex() + 1);
return createInfo();
}
+ @Override
public OccurenceInfo goPreviousOccurence() {
setSelectedIndex(getSelectedIndex() - 1);
return createInfo();
@@ -83,10 +89,12 @@ public abstract class DebuggerFramesList extends JBList implements OccurenceNavi
return OccurenceInfo.position(getSelectedIndex(), getElementCount());
}
+ @Override
public boolean hasNextOccurence() {
return getSelectedIndex() < getElementCount() - 1;
}
+ @Override
public boolean hasPreviousOccurence() {
return getSelectedIndex() > 0;
}
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XDebugView.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XDebugView.java
index 85ff7b2c2357..0007ec2f9997 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XDebugView.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XDebugView.java
@@ -15,14 +15,66 @@
*/
package com.intellij.xdebugger.impl.frame;
+import com.intellij.execution.ui.layout.ViewContext;
+import com.intellij.ide.DataManager;
import com.intellij.openapi.Disposable;
+import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.ui.content.ContentManager;
+import com.intellij.util.SingleAlarm;
+import com.intellij.xdebugger.XDebugSession;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.awt.*;
+import java.util.EventObject;
/**
* @author nik
*/
-public interface XDebugView extends Disposable {
- enum SessionEvent {PAUSED, BEFORE_RESUME, RESUMED, STOPPED, FRAME_CHANGED, SETTINGS_CHANGED}
+public abstract class XDebugView implements Disposable {
+ public enum SessionEvent {PAUSED, BEFORE_RESUME, RESUMED, STOPPED, FRAME_CHANGED, SETTINGS_CHANGED}
+
+ private final SingleAlarm myClearAlarm;
+ private static final int VIEW_CLEAR_DELAY = 100; //ms
+
+ public XDebugView() {
+ myClearAlarm = new SingleAlarm(new Runnable() {
+ @Override
+ public void run() {
+ clear();
+ }
+ }, VIEW_CLEAR_DELAY, this);
+ }
+
+ protected final void requestClear() {
+ myClearAlarm.cancelAndRequest();
+ }
+
+ protected final void cancelClear() {
+ myClearAlarm.cancel();
+ }
+
+ protected abstract void clear();
+
+ public abstract void processSessionEvent(@NotNull SessionEvent event);
+
+ @Nullable
+ protected static XDebugSession getSession(@NotNull EventObject e) {
+ Component component = e.getSource() instanceof Component ? (Component)e.getSource() : null;
+ return component == null ? null : getSession(component);
+ }
- void processSessionEvent(@NotNull SessionEvent event);
+ @Nullable
+ public static XDebugSession getSession(@NotNull Component component) {
+ DataContext dataContext = DataManager.getInstance().getDataContext(component);
+ ViewContext viewContext = ViewContext.CONTEXT_KEY.getData(dataContext);
+ ContentManager contentManager = viewContext == null ? null : viewContext.getContentManager();
+ if (contentManager != null) {
+ XDebugSession session = XDebugSession.DATA_KEY.getData(DataManager.getInstance().getDataContext(contentManager.getComponent()));
+ if (session != null) {
+ return session;
+ }
+ }
+ return XDebugSession.DATA_KEY.getData(dataContext);
+ }
}
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XDebugViewSessionListener.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XDebugViewSessionListener.java
index d265005d3a34..d790113b1816 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XDebugViewSessionListener.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XDebugViewSessionListener.java
@@ -15,8 +15,8 @@
*/
package com.intellij.xdebugger.impl.frame;
-import com.intellij.openapi.project.Project;
import com.intellij.ui.AppUIUtil;
+import com.intellij.xdebugger.XDebugSession;
import com.intellij.xdebugger.XDebugSessionAdapter;
import org.jetbrains.annotations.NotNull;
@@ -25,15 +25,15 @@ import org.jetbrains.annotations.NotNull;
*/
public class XDebugViewSessionListener extends XDebugSessionAdapter {
private final XDebugView myDebugView;
- private final Project myProject;
+ private final XDebugSession session;
- public XDebugViewSessionListener(@NotNull XDebugView debugView, @NotNull Project project) {
+ public XDebugViewSessionListener(@NotNull XDebugView debugView, @NotNull XDebugSession session) {
myDebugView = debugView;
- myProject = project;
+ this.session = session;
}
private void onSessionEvent(final @NotNull XDebugView.SessionEvent event) {
- AppUIUtil.invokeLaterIfProjectAlive(myProject, new Runnable() {
+ AppUIUtil.invokeLaterIfProjectAlive(session.getProject(), new Runnable() {
@Override
public void run() {
myDebugView.processSessionEvent(event);
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XDebuggerFramesList.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XDebuggerFramesList.java
index f4b6c2caee8e..9b39ad63deb8 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XDebuggerFramesList.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XDebuggerFramesList.java
@@ -27,6 +27,7 @@ import com.intellij.util.ui.UIUtil;
import com.intellij.xdebugger.XDebuggerBundle;
import com.intellij.xdebugger.XSourcePosition;
import com.intellij.xdebugger.frame.XStackFrame;
+import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
@@ -84,7 +85,7 @@ public class XDebuggerFramesList extends DebuggerFramesList {
private XStackFrame mySelectedFrame;
- public XDebuggerFramesList(Project project) {
+ public XDebuggerFramesList(@NotNull Project project) {
super(project);
doInit();
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XFramesView.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XFramesView.java
index b7c5f4bf9746..b98440b5d69f 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XFramesView.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XFramesView.java
@@ -22,6 +22,7 @@ import com.intellij.openapi.actionSystem.ActionPlaces;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.actionSystem.impl.ActionToolbarImpl;
import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.ComboBox;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.*;
@@ -29,6 +30,7 @@ import com.intellij.ui.border.CustomLineBorder;
import com.intellij.ui.components.panels.Wrapper;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashMap;
+import com.intellij.util.containers.TransferToEDTQueue;
import com.intellij.xdebugger.XDebugSession;
import com.intellij.xdebugger.frame.XExecutionStack;
import com.intellij.xdebugger.frame.XStackFrame;
@@ -53,46 +55,47 @@ import java.util.List;
/**
* @author nik
*/
-public class XFramesView implements XDebugView {
+public class XFramesView extends XDebugView {
private final JPanel myMainPanel;
private final XDebuggerFramesList myFramesList;
private final ComboBox myThreadComboBox;
private final Set<XExecutionStack> myExecutionStacks = ContainerUtil.newHashSet();
- @NotNull private final XDebugSession mySession;
private XExecutionStack mySelectedStack;
private boolean myListenersEnabled;
private final Map<XExecutionStack, StackFramesListBuilder> myBuilders = new HashMap<XExecutionStack, StackFramesListBuilder>();
private final ActionToolbarImpl myToolbar;
private final Wrapper myThreadsPanel;
private boolean myThreadsCalculated = false;
+ private final TransferToEDTQueue<Runnable> myLaterInvocator = TransferToEDTQueue.createRunnableMerger("XFramesView later invocator", 50);
- public XFramesView(@NotNull final XDebugSession session) {
- mySession = session;
-
+ public XFramesView(@NotNull Project project) {
myMainPanel = new JPanel(new BorderLayout());
- myFramesList = new XDebuggerFramesList(session.getProject());
+ myFramesList = new XDebuggerFramesList(project);
myFramesList.addListSelectionListener(new ListSelectionListener() {
@Override
- public void valueChanged(final ListSelectionEvent e) {
- if (e.getValueIsAdjusting()) return;
- processFrameSelection();
+ public void valueChanged(ListSelectionEvent e) {
+ if (myListenersEnabled && !e.getValueIsAdjusting()) {
+ processFrameSelection(e);
+ }
}
});
myFramesList.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(final MouseEvent e) {
- int i = myFramesList.locationToIndex(e.getPoint());
- if (i != -1 && myFramesList.isSelectedIndex(i)) {
- processFrameSelection();
+ if (myListenersEnabled) {
+ int i = myFramesList.locationToIndex(e.getPoint());
+ if (i != -1 && myFramesList.isSelectedIndex(i)) {
+ processFrameSelection(e);
+ }
}
}
});
- final ActionManager actionManager = ActionManager.getInstance();
myFramesList.addMouseListener(new PopupHandler() {
@Override
public void invokePopup(final Component comp, final int x, final int y) {
+ ActionManager actionManager = ActionManager.getInstance();
ActionGroup group = (ActionGroup)actionManager.getAction(XDebuggerActions.FRAMES_TREE_POPUP_GROUP);
actionManager.createActionPopupMenu(ActionPlaces.UNKNOWN, group).getComponent().show(comp, x, y);
}
@@ -103,13 +106,32 @@ public class XFramesView implements XDebugView {
myThreadComboBox = new ComboBox();
//noinspection unchecked
myThreadComboBox.setRenderer(new ThreadComboBoxRenderer(myThreadComboBox));
- myThreadComboBox.addItemListener(new MyItemListener());
+ myThreadComboBox.addItemListener(new ItemListener() {
+ @Override
+ public void itemStateChanged(final ItemEvent e) {
+ if (!myListenersEnabled) {
+ return;
+ }
+
+ if (e.getStateChange() == ItemEvent.SELECTED) {
+ Object item = e.getItem();
+ if (item instanceof XExecutionStack) {
+ XDebugSession session = getSession(e);
+ if (session != null) {
+ updateFrames((XExecutionStack)item, session);
+ }
+ }
+ }
+ }
+ });
myThreadComboBox.addPopupMenuListener(new PopupMenuListenerAdapter() {
@Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
- XSuspendContext context = mySession.getSuspendContext();
+ XDebugSession session = getSession(e);
+ XSuspendContext context = session == null ? null : session.getSuspendContext();
if (context != null && !myThreadsCalculated) {
myThreadsCalculated = true;
+ //noinspection unchecked
myThreadComboBox.addItem(null); // rendered as "Loading..."
context.computeExecutionStacks(new XSuspendContext.XExecutionStackContainer() {
@Override
@@ -130,7 +152,6 @@ public class XFramesView implements XDebugView {
@Override
public void errorOccurred(@NotNull String errorMessage) {
-
}
});
}
@@ -145,12 +166,9 @@ public class XFramesView implements XDebugView {
myToolbar = createToolbar();
myThreadsPanel = new Wrapper();
- CustomLineBorder border = new CustomLineBorder(CaptionPanel.CNT_ACTIVE_BORDER_COLOR, 0, 0, 1, 0);
- myThreadsPanel.setBorder(border);
+ myThreadsPanel.setBorder(new CustomLineBorder(CaptionPanel.CNT_ACTIVE_BORDER_COLOR, 0, 0, 1, 0));
myThreadsPanel.add(myToolbar.getComponent(), BorderLayout.EAST);
myMainPanel.add(myThreadsPanel, BorderLayout.NORTH);
-
- processSessionEvent(SessionEvent.RESUMED);
}
private ActionToolbarImpl createToolbar() {
@@ -181,9 +199,14 @@ public class XFramesView implements XDebugView {
@Override
public void processSessionEvent(@NotNull final SessionEvent event) {
- if (event == SessionEvent.BEFORE_RESUME) return;
+ if (event == SessionEvent.BEFORE_RESUME) {
+ return;
+ }
+
+ XDebugSession session = getSession(getMainPanel());
+
if (event == SessionEvent.FRAME_CHANGED) {
- XStackFrame currentStackFrame = mySession.getCurrentStackFrame();
+ XStackFrame currentStackFrame = session == null ? null : session.getCurrentStackFrame();
if (currentStackFrame != null) {
myFramesList.setSelectedValue(currentStackFrame, true);
}
@@ -196,15 +219,16 @@ public class XFramesView implements XDebugView {
}
myBuilders.clear();
mySelectedStack = null;
- XSuspendContext suspendContext = mySession.getSuspendContext();
- if (suspendContext == null || event == SessionEvent.PAUSED) {
- myThreadComboBox.removeAllItems();
- myFramesList.clear();
- myThreadsCalculated = false;
- myExecutionStacks.clear();
- if (suspendContext == null) {
- return;
- }
+ XSuspendContext suspendContext = session == null ? null : session.getSuspendContext();
+ if (suspendContext == null) {
+ requestClear();
+ return;
+ }
+
+ if (event == SessionEvent.PAUSED) {
+ // clear immediately
+ cancelClear();
+ clear();
}
XExecutionStack[] executionStacks = suspendContext.getExecutionStacks();
@@ -219,10 +243,18 @@ public class XFramesView implements XDebugView {
myThreadsPanel.add(myThreadComboBox, BorderLayout.CENTER);
}
myToolbar.setAddSeparatorFirst(!invisible);
- updateFrames(activeExecutionStack);
+ updateFrames(activeExecutionStack, session);
myListenersEnabled = true;
}
+ @Override
+ protected void clear() {
+ myThreadComboBox.removeAllItems();
+ myFramesList.clear();
+ myThreadsCalculated = false;
+ myExecutionStacks.clear();
+ }
+
private void addExecutionStacks(List<? extends XExecutionStack> executionStacks) {
for (XExecutionStack executionStack : executionStacks) {
if (!myExecutionStacks.contains(executionStack)) {
@@ -233,7 +265,7 @@ public class XFramesView implements XDebugView {
}
}
- private void updateFrames(final XExecutionStack executionStack) {
+ private void updateFrames(final XExecutionStack executionStack, @NotNull XDebugSession session) {
if (mySelectedStack == executionStack) {
return;
}
@@ -249,7 +281,7 @@ public class XFramesView implements XDebugView {
XStackFrame topFrame = executionStack.getTopFrame();
if (topFrame != null) {
myFramesList.setSelectedValue(topFrame, true);
- onFrameSelected(executionStack, topFrame);
+ session.setCurrentStackFrame(executionStack, topFrame);
}
}
}
@@ -262,32 +294,16 @@ public class XFramesView implements XDebugView {
return myFramesList;
}
- private void onFrameSelected(XExecutionStack executionStack, final @NotNull XStackFrame stackFrame) {
- mySession.setCurrentStackFrame(executionStack, stackFrame);
- }
-
public JPanel getMainPanel() {
return myMainPanel;
}
- private void processFrameSelection() {
- if (!myListenersEnabled) return;
+ private void processFrameSelection(@NotNull EventObject e) {
Object selected = myFramesList.getSelectedValue();
if (selected instanceof XStackFrame) {
- onFrameSelected(mySelectedStack, (XStackFrame)selected);
- }
- }
-
- private class MyItemListener implements ItemListener {
- @Override
- public void itemStateChanged(final ItemEvent e) {
- if (!myListenersEnabled) return;
-
- if (e.getStateChange() == ItemEvent.SELECTED) {
- Object item = e.getItem();
- if (item instanceof XExecutionStack) {
- updateFrames((XExecutionStack)item);
- }
+ XDebugSession session = getSession(e);
+ if (session != null) {
+ session.setCurrentStackFrame(mySelectedStack, (XStackFrame)selected);
}
}
}
@@ -315,7 +331,7 @@ public class XFramesView implements XDebugView {
@Override
public void addStackFrames(@NotNull final List<? extends XStackFrame> stackFrames, final boolean last) {
- ApplicationManager.getApplication().invokeLater(new Runnable() {
+ myLaterInvocator.offer(new Runnable() {
@Override
public void run() {
myStackFrames.addAll(stackFrames);
@@ -331,7 +347,7 @@ public class XFramesView implements XDebugView {
@Override
public void errorOccurred(@NotNull final String errorMessage) {
- ApplicationManager.getApplication().invokeLater(new Runnable() {
+ myLaterInvocator.offer(new Runnable() {
@Override
public void run() {
if (myErrorMessage == null) {
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XStandaloneVariablesView.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XStandaloneVariablesView.java
index f7f32ba86b9c..f91146426878 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XStandaloneVariablesView.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XStandaloneVariablesView.java
@@ -42,4 +42,12 @@ public class XStandaloneVariablesView extends XVariablesViewBase {
}
});
}
+
+ @Override
+ public void processSessionEvent(@NotNull SessionEvent event) {
+ }
+
+ @Override
+ protected void clear() {
+ }
}
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XVariablesView.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XVariablesView.java
index 31b30a8362e3..df43b1147419 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XVariablesView.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XVariablesView.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,30 +15,37 @@
*/
package com.intellij.xdebugger.impl.frame;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.xdebugger.XDebugProcess;
import com.intellij.xdebugger.XDebugSession;
import com.intellij.xdebugger.frame.XStackFrame;
import com.intellij.xdebugger.impl.XDebugSessionImpl;
import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree;
import com.intellij.xdebugger.impl.ui.tree.nodes.XDebuggerTreeNode;
+import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl;
import org.jetbrains.annotations.NotNull;
+import java.util.Map;
+import java.util.Set;
+
import static com.intellij.xdebugger.impl.ui.tree.nodes.MessageTreeNode.createInfoMessage;
/**
* @author nik
*/
-public class XVariablesView extends XVariablesViewBase implements XDebugView {
- @NotNull private final XDebugSession mySession;
+public class XVariablesView extends XVariablesViewBase {
+ public static final Key<Map<Pair<VirtualFile, Integer>, Set<XValueNodeImpl>>> DEBUG_VARIABLES = Key.create("debug.frame");
- public XVariablesView(@NotNull XDebugSession session) {
- super(session.getProject(), session.getDebugProcess().getEditorsProvider(), ((XDebugSessionImpl)session).getValueMarkers());
- mySession = session;
+ public XVariablesView(@NotNull XDebugSessionImpl session) {
+ super(session.getProject(), session.getDebugProcess().getEditorsProvider(), session.getValueMarkers());
}
@Override
public void processSessionEvent(@NotNull final SessionEvent event) {
- XStackFrame stackFrame = mySession.getCurrentStackFrame();
+ XDebugSession session = getSession(getPanel());
+ XStackFrame stackFrame = session == null ? null : session.getCurrentStackFrame();
XDebuggerTree tree = getTree();
if (event == SessionEvent.BEFORE_RESUME || event == SessionEvent.SETTINGS_CHANGED) {
@@ -50,20 +57,29 @@ public class XVariablesView extends XVariablesViewBase implements XDebugView {
tree.markNodesObsolete();
if (stackFrame != null) {
+ cancelClear();
buildTreeAndRestoreState(stackFrame);
}
else {
- tree.setSourcePosition(null);
+ requestClear();
+ }
+ }
- XDebuggerTreeNode node;
- if (!mySession.isStopped() && mySession.isPaused()) {
- node = createInfoMessage(tree, "Frame is not available");
- }
- else {
- XDebugProcess debugProcess = mySession.getDebugProcess();
- node = createInfoMessage(tree, debugProcess.getCurrentStateMessage(), debugProcess.getCurrentStateHyperlinkListener());
- }
- tree.setRoot(node, true);
+ @Override
+ protected void clear() {
+ XDebuggerTree tree = getTree();
+ tree.getProject().putUserData(DEBUG_VARIABLES, null);
+ tree.setSourcePosition(null);
+
+ XDebuggerTreeNode node;
+ XDebugSession session = getSession(getPanel());
+ if (session == null || (!session.isStopped() && session.isPaused())) {
+ node = createInfoMessage(tree, "Frame is not available");
+ }
+ else {
+ XDebugProcess debugProcess = session.getDebugProcess();
+ node = createInfoMessage(tree, debugProcess.getCurrentStateMessage(), debugProcess.getCurrentStateHyperlinkListener());
}
+ tree.setRoot(node, true);
}
}
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XVariablesViewBase.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XVariablesViewBase.java
index 33a1639ba5d7..ace9938318df 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XVariablesViewBase.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XVariablesViewBase.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,8 +16,9 @@
package com.intellij.xdebugger.impl.frame;
import com.intellij.ide.dnd.DnDManager;
-import com.intellij.openapi.Disposable;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.xdebugger.XDebuggerBundle;
import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider;
import com.intellij.xdebugger.frame.XStackFrame;
@@ -27,15 +28,18 @@ import com.intellij.xdebugger.impl.ui.tree.XDebuggerTreePanel;
import com.intellij.xdebugger.impl.ui.tree.XDebuggerTreeRestorer;
import com.intellij.xdebugger.impl.ui.tree.XDebuggerTreeState;
import com.intellij.xdebugger.impl.ui.tree.nodes.XStackFrameNode;
+import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
+import java.util.HashMap;
+import java.util.Set;
/**
* @author nik
*/
-public abstract class XVariablesViewBase implements Disposable {
+public abstract class XVariablesViewBase extends XDebugView {
protected final XDebuggerTreePanel myDebuggerTreePanel;
private XDebuggerTreeState myTreeState;
private Object myFrameEqualityObject;
@@ -51,6 +55,7 @@ public abstract class XVariablesViewBase implements Disposable {
XDebuggerTree tree = myDebuggerTreePanel.getTree();
tree.setSourcePosition(stackFrame.getSourcePosition());
tree.setRoot(new XStackFrameNode(tree, stackFrame), false);
+ tree.getProject().putUserData(XVariablesView.DEBUG_VARIABLES, new HashMap<Pair<VirtualFile, Integer>, Set<XValueNodeImpl>>());
Object newEqualityObject = stackFrame.getEqualityObject();
if (myFrameEqualityObject != null && newEqualityObject != null && myFrameEqualityObject.equals(newEqualityObject)
&& myTreeState != null) {
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 6216c1312349..c510cd17c90a 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
@@ -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.
@@ -33,6 +33,7 @@ import com.intellij.ui.border.CustomLineBorder;
import com.intellij.util.Alarm;
import com.intellij.util.ui.UIUtil;
import com.intellij.util.ui.tree.TreeUtil;
+import com.intellij.xdebugger.XDebugSession;
import com.intellij.xdebugger.XDebuggerBundle;
import com.intellij.xdebugger.XExpression;
import com.intellij.xdebugger.frame.XStackFrame;
@@ -64,20 +65,18 @@ import java.util.List;
/**
* @author nik
*/
-public class XWatchesViewImpl implements DnDNativeTarget, XWatchesView, XDebugView {
+public class XWatchesViewImpl extends XDebugView implements DnDNativeTarget, XWatchesView {
private final XDebuggerTreePanel myTreePanel;
private XDebuggerTreeState myTreeState;
private XDebuggerTreeRestorer myTreeRestorer;
private final WatchesRootNode myRootNode;
- @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;
+ public XWatchesViewImpl(@NotNull XDebugSessionImpl session) {
myTreePanel = new XDebuggerTreePanel(session.getProject(), session.getDebugProcess().getEditorsProvider(), this, null,
- XDebuggerActions.WATCHES_TREE_POPUP_GROUP, ((XDebugSessionImpl)session).getValueMarkers());
+ XDebuggerActions.WATCHES_TREE_POPUP_GROUP, session.getValueMarkers());
ActionManager actionManager = ActionManager.getInstance();
@@ -89,7 +88,7 @@ public class XWatchesViewImpl implements DnDNativeTarget, XWatchesView, XDebugVi
actionManager.getAction(XDebuggerActions.XEDIT_WATCH).registerCustomShortcutSet(f2Shortcut, tree);
DnDManager.getInstance().registerTarget(this, tree);
- myRootNode = new WatchesRootNode(tree, session, this, session.getSessionData().getWatchExpressions());
+ myRootNode = new WatchesRootNode(tree, this, session.getSessionData().getWatchExpressions());
tree.setRoot(myRootNode, false);
final ToolbarDecorator decorator = ToolbarDecorator.createDecorator(myTreePanel.getTree()).disableUpDownActions();
@@ -134,6 +133,7 @@ public class XWatchesViewImpl implements DnDNativeTarget, XWatchesView, XDebugVi
DataContext context = DataManager.getInstance().getDataContext(watchTree);
final AnActionEvent actionEvent = new AnActionEvent(null, context, "WATCH_TREE", presentation, ActionManager.getInstance(), 0);
Runnable runnable = new Runnable() {
+ @Override
public void run() {
editWatchAction.actionPerformed(actionEvent);
}
@@ -161,12 +161,12 @@ public class XWatchesViewImpl implements DnDNativeTarget, XWatchesView, XDebugVi
final FocusListener focusListener = new FocusListener() {
@Override
- public void focusGained(FocusEvent e) {
+ public void focusGained(@NotNull FocusEvent e) {
quitePeriod.addRequest(EmptyRunnable.getInstance(), UIUtil.getMultiClickInterval());
}
@Override
- public void focusLost(FocusEvent e) {
+ public void focusLost(@NotNull FocusEvent e) {
editAlarm.cancelAllRequests();
}
};
@@ -174,7 +174,7 @@ public class XWatchesViewImpl implements DnDNativeTarget, XWatchesView, XDebugVi
final TreeSelectionListener selectionListener = new TreeSelectionListener() {
@Override
- public void valueChanged(TreeSelectionEvent e) {
+ public void valueChanged(@NotNull TreeSelectionEvent e) {
quitePeriod.addRequest(EmptyRunnable.getInstance(), UIUtil.getMultiClickInterval());
}
};
@@ -219,15 +219,20 @@ public class XWatchesViewImpl implements DnDNativeTarget, XWatchesView, XDebugVi
@Override
public void addWatchExpression(@NotNull XExpression expression, int index, final boolean navigateToWatchNode) {
- myRootNode.addWatchExpression(mySession.getDebugProcess().getEvaluator(), expression, index, navigateToWatchNode);
+ XDebugSession session = getSession(getTree());
+ if (session == null) {
+ return;
+ }
+
+ myRootNode.addWatchExpression(session.getDebugProcess().getEvaluator(), expression, index, navigateToWatchNode);
updateSessionData();
if (navigateToWatchNode) {
- showWatchesTab();
+ showWatchesTab((XDebugSessionImpl)session);
}
}
- private void showWatchesTab() {
- XDebugSessionTab tab = mySession.getSessionTab();
+ private static void showWatchesTab(@NotNull XDebugSessionImpl session) {
+ XDebugSessionTab tab = session.getSessionTab();
if (tab != null) {
tab.toFront(false);
// restore watches tab if minimized
@@ -255,7 +260,6 @@ public class XWatchesViewImpl implements DnDNativeTarget, XWatchesView, XDebugVi
return;
}
- XStackFrame stackFrame = mySession.getCurrentStackFrame();
XDebuggerTree tree = myTreePanel.getTree();
if (event == SessionEvent.BEFORE_RESUME || event == SessionEvent.SETTINGS_CHANGED) {
@@ -268,7 +272,10 @@ public class XWatchesViewImpl implements DnDNativeTarget, XWatchesView, XDebugVi
}
}
+ XDebugSession session = getSession(getMainPanel());
+ XStackFrame stackFrame = session == null ? null : session.getCurrentStackFrame();
if (stackFrame != null) {
+ cancelClear();
tree.setSourcePosition(stackFrame.getSourcePosition());
myRootNode.updateWatches(stackFrame.getEvaluator());
if (myTreeState != null) {
@@ -276,11 +283,16 @@ public class XWatchesViewImpl implements DnDNativeTarget, XWatchesView, XDebugVi
}
}
else {
- tree.setSourcePosition(null);
- myRootNode.updateWatches(null);
+ requestClear();
}
}
+ @Override
+ protected void clear() {
+ getTree().setSourcePosition(null);
+ myRootNode.updateWatches(null);
+ }
+
public XDebuggerTree getTree() {
return myTreePanel.getTree();
}
@@ -290,7 +302,7 @@ public class XWatchesViewImpl implements DnDNativeTarget, XWatchesView, XDebugVi
}
@Override
- public void removeWatches(final List<? extends XDebuggerTreeNode> nodes) {
+ public void removeWatches(List<? extends XDebuggerTreeNode> nodes) {
List<? extends WatchNode> children = myRootNode.getAllChildren();
int minIndex = Integer.MAX_VALUE;
List<XDebuggerTreeNode> toRemove = new ArrayList<XDebuggerTreeNode>();
@@ -328,7 +340,11 @@ public class XWatchesViewImpl implements DnDNativeTarget, XWatchesView, XDebugVi
watchExpressions.add(child.getExpression());
}
}
- mySession.setWatchExpressions(watchExpressions.toArray(new XExpression[watchExpressions.size()]));
+
+ XDebugSession session = getSession(getTree());
+ if (session != null) {
+ ((XDebugSessionImpl)session).setWatchExpressions(watchExpressions.toArray(new XExpression[watchExpressions.size()]));
+ }
}
@Override
@@ -348,13 +364,14 @@ public class XWatchesViewImpl implements DnDNativeTarget, XWatchesView, XDebugVi
}
@Override
- public void drop(final DnDEvent aEvent) {
+ public void drop(DnDEvent aEvent) {
Object object = aEvent.getAttachedObject();
if (object instanceof XValueNodeImpl[]) {
final XValueNodeImpl[] nodes = (XValueNodeImpl[])object;
for (XValueNodeImpl node : nodes) {
String expression = node.getValueContainer().getEvaluationExpression();
if (expression != null) {
+ //noinspection ConstantConditions
addWatchExpression(XExpressionImpl.fromText(expression), -1, false);
}
}
@@ -362,6 +379,7 @@ public class XWatchesViewImpl implements DnDNativeTarget, XWatchesView, XDebugVi
else if (object instanceof EventInfo) {
String text = ((EventInfo)object).getTextForFlavor(DataFlavor.stringFlavor);
if (text != null) {
+ //noinspection ConstantConditions
addWatchExpression(XExpressionImpl.fromText(text), -1, false);
}
}
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/BreakpointEditor.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/BreakpointEditor.java
index f51ce77d3fee..79c8dc49c398 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/BreakpointEditor.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/BreakpointEditor.java
@@ -19,6 +19,7 @@ import com.intellij.codeInsight.lookup.LookupManager;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.keymap.KeymapUtil;
+import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.components.labels.LinkLabel;
import com.intellij.ui.components.labels.LinkListener;
@@ -79,7 +80,7 @@ public class BreakpointEditor {
}
});
- final AnAction doneAction = new AnAction() {
+ final AnAction doneAction = new DumbAwareAction() {
@Override
public void update(AnActionEvent e) {
super.update(e);
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 2134c0c8d4e1..053f18dd14bf 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
@@ -16,7 +16,8 @@
package com.intellij.xdebugger.impl.ui;
import com.intellij.debugger.ui.DebuggerContentInfo;
-import com.intellij.diagnostic.logging.*;
+import com.intellij.diagnostic.logging.AdditionalTabComponent;
+import com.intellij.diagnostic.logging.DebuggerLogConsoleManager;
import com.intellij.execution.ExecutionManager;
import com.intellij.execution.configurations.RunConfigurationBase;
import com.intellij.execution.configurations.RunProfile;
@@ -24,6 +25,7 @@ import com.intellij.execution.executors.DefaultDebugExecutor;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.runners.RunContentBuilder;
+import com.intellij.execution.runners.RunTab;
import com.intellij.execution.ui.*;
import com.intellij.execution.ui.layout.LayoutAttractionPolicy;
import com.intellij.execution.ui.layout.LayoutViewOptions;
@@ -48,25 +50,13 @@ import java.util.Collection;
/**
* @author nik
*/
-public abstract class DebuggerSessionTabBase extends LogConsoleManagerBase implements DebuggerLogConsoleManager {
- @NotNull private final LogFilesManager myManager;
-
- @NotNull final String mySessionName;
- @NotNull protected final RunnerLayoutUi myUi;
-
+public abstract class DebuggerSessionTabBase extends RunTab implements DebuggerLogConsoleManager {
protected ExecutionConsole myConsole;
- protected RunContentDescriptor myRunContentDescriptor;
-
- public DebuggerSessionTabBase(@NotNull Project project, @NotNull String runnerId, @NotNull final String sessionName,
- @NotNull GlobalSearchScope searchScope) {
- super(project, searchScope);
- Disposer.register(project, this);
- myManager = new LogFilesManager(project, this, this);
- mySessionName = sessionName;
+ public DebuggerSessionTabBase(@NotNull Project project, @NotNull String runnerId, @NotNull String sessionName, @NotNull GlobalSearchScope searchScope) {
+ super(project, searchScope, runnerId, XDebuggerBundle.message("xdebugger.default.content.title"), sessionName);
- myUi = RunnerLayoutUi.Factory.getInstance(project).create(
- runnerId, XDebuggerBundle.message("xdebugger.default.content.title"), sessionName, this);
+ Disposer.register(project, this);
myUi.getDefaults()
.initTabDefaults(0, XDebuggerBundle.message("xdebugger.debugger.tab.title"), null)
@@ -104,23 +94,6 @@ public abstract class DebuggerSessionTabBase extends LogConsoleManagerBase imple
return myUi;
}
- protected void registerFileMatcher(final RunProfile runConfiguration) {
- if (runConfiguration instanceof RunConfigurationBase) {
- myManager.registerFileMatcher((RunConfigurationBase)runConfiguration);
- }
- }
-
- protected void initLogConsoles(final RunProfile runConfiguration, final ProcessHandler processHandler, ExecutionConsole console) {
- if (runConfiguration instanceof RunConfigurationBase) {
- myManager.initLogConsoles((RunConfigurationBase)runConfiguration, processHandler);
- OutputFileUtil.attachDumpListener((RunConfigurationBase)runConfiguration, processHandler, console);
- }
- }
-
- protected LogFilesManager getLogManager() {
- return myManager;
- }
-
protected void attachNotificationTo(final Content content) {
if (myConsole instanceof ObservableConsoleView) {
ObservableConsoleView observable = (ObservableConsoleView)myConsole;
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 4b6bea217c54..4c3766f23f5d 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
@@ -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,11 +17,8 @@ package com.intellij.xdebugger.impl.ui;
import com.intellij.debugger.ui.DebuggerContentInfo;
import com.intellij.execution.Executor;
-import com.intellij.execution.configurations.RunProfile;
import com.intellij.execution.executors.DefaultDebugExecutor;
import com.intellij.execution.runners.ExecutionEnvironment;
-import com.intellij.execution.runners.ProgramRunner;
-import com.intellij.execution.runners.RestartAction;
import com.intellij.execution.runners.RunContentBuilder;
import com.intellij.execution.ui.ExecutionConsole;
import com.intellij.execution.ui.RunContentDescriptor;
@@ -29,11 +26,11 @@ 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.DataManager;
import com.intellij.ide.actions.ContextHelpAction;
import com.intellij.idea.ActionsBundle;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.ui.AppUIUtil;
@@ -41,7 +38,7 @@ 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.util.SystemProperties;
import com.intellij.xdebugger.XDebugSession;
import com.intellij.xdebugger.XDebuggerBundle;
import com.intellij.xdebugger.impl.XDebugSessionImpl;
@@ -57,29 +54,109 @@ import javax.swing.*;
import java.util.ArrayList;
import java.util.List;
-/**
- * @author spleaner
- */
public class XDebugSessionTab extends DebuggerSessionTabBase {
+ private static final DataKey<XDebugSessionTab> TAB_KEY = DataKey.create("XDebugSessionTab");
+
private XWatchesViewImpl myWatchesView;
private final List<XDebugView> myViews = new ArrayList<XDebugView>();
- public XDebugSessionTab(@NotNull Project project,
- @NotNull XDebugSessionImpl session,
- @Nullable Icon icon,
- @Nullable ExecutionEnvironment environment,
- @Nullable ProgramRunner runner) {
- super(project, "Debug", session.getSessionName(), GlobalSearchScope.allScope(project));
+ @Nullable
+ private XDebugSessionImpl mySession;
+ private XDebugSessionData mySessionData;
+
+ @NotNull
+ public static XDebugSessionTab create(@NotNull XDebugSessionImpl session,
+ @Nullable Icon icon,
+ @Nullable ExecutionEnvironment environment,
+ @Nullable RunContentDescriptor contentToReuse) {
+ if (contentToReuse != null && SystemProperties.getBooleanProperty("xdebugger.reuse.session.tab", false)) {
+ JComponent component = contentToReuse.getComponent();
+ if (component != null) {
+ XDebugSessionTab oldTab = TAB_KEY.getData(DataManager.getInstance().getDataContext(component));
+ if (oldTab != null) {
+ oldTab.setSession(session, environment, icon);
+ oldTab.attachToSession(session);
+ return oldTab;
+ }
+ }
+ }
+ return new XDebugSessionTab(session, icon, environment);
+ }
+
+ private XDebugSessionTab(@NotNull XDebugSessionImpl session,
+ @Nullable Icon icon,
+ @Nullable ExecutionEnvironment environment) {
+ super(session.getProject(), "Debug", session.getSessionName(), GlobalSearchScope.allScope(session.getProject()));
+
+ setSession(session, environment, icon);
+
+ myUi.addContent(createFramesContent(), 0, PlaceInGrid.left, false);
+ myUi.addContent(createVariablesContent(session), 0, PlaceInGrid.center, false);
+ myUi.addContent(createWatchesContent(session), 0, PlaceInGrid.right, false);
+
+ for (XDebugView view : myViews) {
+ Disposer.register(this, view);
+ }
+
+ attachToSession(session);
+
+ DefaultActionGroup focus = new DefaultActionGroup();
+ 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();
+ XDebugSessionImpl session = mySession;
+ if (session != null && content.isSelected() && DebuggerContentInfo.WATCHES_CONTENT.equals(ViewImpl.ID.get(content))) {
+ if (myWatchesView.rebuildNeeded()) {
+ myWatchesView.processSessionEvent(XDebugView.SessionEvent.SETTINGS_CHANGED);
+ }
+ }
+ }
+ }, this);
+
+ rebuildViews();
+ }
+
+ private void setSession(@NotNull XDebugSessionImpl session, @Nullable ExecutionEnvironment environment, @Nullable Icon icon) {
if (environment != null) {
setEnvironment(environment);
}
+
+ mySession = session;
+ mySessionData = session.getSessionData();
myConsole = session.getConsoleView();
- XDebugProcess debugProcess = session.getDebugProcess();
- myRunContentDescriptor = new RunContentDescriptor(myConsole, debugProcess.getProcessHandler(), myUi.getComponent(), mySessionName, icon);
- attachToSession(session, runner, environment, session.getSessionData(), debugProcess);
+ myRunContentDescriptor = new RunContentDescriptor(myConsole, session.getDebugProcess().getProcessHandler(), myUi.getComponent(), session.getSessionName(), icon);
}
- private Content createVariablesContent(final XDebugSession session) {
+ @Nullable
+ @Override
+ public Object getData(@NonNls String dataId) {
+ if (XWatchesView.DATA_KEY.is(dataId)) {
+ return myWatchesView;
+ }
+ else if (TAB_KEY.is(dataId)) {
+ return this;
+ }
+ else if (XDebugSessionData.DATA_KEY.is(dataId)) {
+ return mySessionData;
+ }
+
+ if (mySession != null) {
+ if (XDebugSession.DATA_KEY.is(dataId)) {
+ return mySession;
+ }
+ else if (LangDataKeys.CONSOLE_VIEW.is(dataId)) {
+ return mySession.getConsoleView();
+ }
+ }
+
+ return super.getData(dataId);
+ }
+
+ private Content createVariablesContent(@NotNull XDebugSessionImpl session) {
final XVariablesView variablesView = new XVariablesView(session);
myViews.add(variablesView);
Content result = myUi.createContent(DebuggerContentInfo.VARIABLES_CONTENT, variablesView.getPanel(),
@@ -89,27 +166,25 @@ public class XDebugSessionTab extends DebuggerSessionTabBase {
ActionGroup group = getCustomizedActionGroup(XDebuggerActions.VARIABLES_TREE_TOOLBAR_GROUP);
result.setActions(group, ActionPlaces.DEBUGGER_TOOLBAR, variablesView.getTree());
-
return result;
}
- private Content createWatchesContent(final XDebugSessionImpl session, final XDebugSessionData sessionData) {
+ private Content createWatchesContent(@NotNull XDebugSessionImpl session) {
myWatchesView = new XWatchesViewImpl(session);
myViews.add(myWatchesView);
Content watchesContent = myUi.createContent(DebuggerContentInfo.WATCHES_CONTENT, myWatchesView.getMainPanel(),
- XDebuggerBundle.message("debugger.session.tab.watches.title"), AllIcons.Debugger.Watches, null);
+ XDebuggerBundle.message("debugger.session.tab.watches.title"), AllIcons.Debugger.Watches, null);
watchesContent.setCloseable(false);
-
return watchesContent;
}
- private Content createFramesContent(final XDebugSession session) {
- final XFramesView framesView = new XFramesView(session);
+ @NotNull
+ private Content createFramesContent() {
+ XFramesView framesView = new XFramesView(getProject());
myViews.add(framesView);
Content framesContent = myUi.createContent(DebuggerContentInfo.FRAME_CONTENT, framesView.getMainPanel(),
XDebuggerBundle.message("debugger.session.tab.frames.title"), AllIcons.Debugger.Frame, null);
framesContent.setCloseable(false);
-
return framesContent;
}
@@ -132,34 +207,12 @@ public class XDebugSessionTab extends DebuggerSessionTabBase {
return myWatchesView;
}
- private void attachToSession(final @NotNull XDebugSessionImpl session, final @Nullable ProgramRunner runner,
- final @Nullable ExecutionEnvironment environment, final @NotNull XDebugSessionData sessionData,
- final @NotNull XDebugProcess debugProcess) {
- myUi.addContent(createFramesContent(session), 0, PlaceInGrid.left, false);
- myUi.addContent(createVariablesContent(session), 0, PlaceInGrid.center, false);
- myUi.addContent(createWatchesContent(session, sessionData), 0, PlaceInGrid.right, false);
+ private void attachToSession(@NotNull XDebugSessionImpl session) {
for (XDebugView view : myViews) {
- Disposer.register(this, view);
- session.addSessionListener(new XDebugViewSessionListener(view, getProject()), this);
+ session.addSessionListener(new XDebugViewSessionListener(view, session), this);
}
- myUi.getContentManager().addDataProvider(new DataProvider() {
- @Nullable
- @Override
- public Object getData(@NonNls String dataId) {
- if (XWatchesView.DATA_KEY.is(dataId)) {
- return myWatchesView;
- }
- if (LangDataKeys.CONSOLE_VIEW.is(dataId)) {
- return session.getConsoleView();
- }
- if (XDebugSessionData.DATA_KEY.is(dataId)) {
- return sessionData;
- }
- return null;
- }
- });
- XDebugTabLayouter layouter = debugProcess.createTabLayouter();
+ XDebugTabLayouter layouter = session.getDebugProcess().createTabLayouter();
Content consoleContent = layouter.registerConsoleContent(myUi, myConsole);
attachNotificationTo(consoleContent);
@@ -172,18 +225,15 @@ public class XDebugSessionTab extends DebuggerSessionTabBase {
DefaultActionGroup leftToolbar = new DefaultActionGroup();
final Executor debugExecutor = DefaultDebugExecutor.getDebugExecutorInstance();
- final Executor executor = environment != null ? environment.getExecutor() : debugExecutor;
- if (runner != null && environment != null) {
- RestartAction restartAction = new RestartAction(executor, runner, myRunContentDescriptor, environment);
- leftToolbar.add(restartAction);
- restartAction.registerShortcut(myUi.getComponent());
-
+ ExecutionEnvironment environment = getEnvironment();
+ if (environment != null) {
List<AnAction> additionalRestartActions = session.getRestartActions();
- leftToolbar.addAll(additionalRestartActions);
- if (!additionalRestartActions.isEmpty()) leftToolbar.addSeparator();
+ if (!additionalRestartActions.isEmpty()) {
+ leftToolbar.addAll(additionalRestartActions);
+ leftToolbar.addSeparator();
+ }
leftToolbar.addAll(session.getExtraActions());
}
-
leftToolbar.addAll(getCustomizedActionGroup(XDebuggerActions.TOOL_WINDOW_LEFT_TOOLBAR_GROUP));
for (AnAction action : session.getExtraStopActions()) {
@@ -216,7 +266,7 @@ public class XDebugSessionTab extends DebuggerSessionTabBase {
if (commonSettings.length > 0) {
settings.addSeparator();
}
- if (!debugProcess.isValuesCustomSorted()) {
+ if (!session.getDebugProcess().isValuesCustomSorted()) {
settings.add(new ToggleSortValuesAction(commonSettings.length == 0));
}
@@ -225,41 +275,25 @@ public class XDebugSessionTab extends DebuggerSessionTabBase {
leftToolbar.addSeparator();
leftToolbar.add(PinToolwindowTabAction.getPinAction());
- leftToolbar.add(new CloseAction(executor, myRunContentDescriptor, getProject()));
+ leftToolbar.add(new CloseAction(environment != null ? environment.getExecutor() : debugExecutor, myRunContentDescriptor, getProject()));
leftToolbar.add(new ContextHelpAction(debugExecutor.getHelpId()));
DefaultActionGroup topToolbar = new DefaultActionGroup();
topToolbar.addAll(getCustomizedActionGroup(XDebuggerActions.TOOL_WINDOW_TOP_TOOLBAR_GROUP));
- debugProcess.registerAdditionalActions(leftToolbar, topToolbar);
+ session.getDebugProcess().registerAdditionalActions(leftToolbar, topToolbar);
myUi.getOptions().setLeftToolbar(leftToolbar, ActionPlaces.DEBUGGER_TOOLBAR);
myUi.getOptions().setTopToolbar(topToolbar, ActionPlaces.DEBUGGER_TOOLBAR);
if (environment != null) {
- final RunProfile runConfiguration = environment.getRunProfile();
- registerFileMatcher(runConfiguration);
- initLogConsoles(runConfiguration, myRunContentDescriptor.getProcessHandler(), myConsole);
+ initLogConsoles(environment.getRunProfile(), myRunContentDescriptor.getProcessHandler(), myConsole);
}
-
- final DefaultActionGroup focus = new DefaultActionGroup();
- 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();
}
+ public void detachFromSession() {
+ assert mySession != null;
+ mySession = null;
+ }
@Override
@Nullable
@@ -283,4 +317,4 @@ public class XDebugSessionTab extends DebuggerSessionTabBase {
}
}
}
-} \ No newline at end of file
+}
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XValueTextProvider.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XValueTextProvider.java
new file mode 100644
index 000000000000..54ae63776e75
--- /dev/null
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XValueTextProvider.java
@@ -0,0 +1,23 @@
+/*
+ * 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.ui;
+
+/**
+ * @author egor
+ */
+public interface XValueTextProvider {
+ String getValueText();
+}
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/TreeInplaceEditor.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/TreeInplaceEditor.java
index 629385c9ad20..13fe7802481c 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/TreeInplaceEditor.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/TreeInplaceEditor.java
@@ -17,16 +17,19 @@ package com.intellij.xdebugger.impl.ui.tree;
import com.intellij.codeInsight.lookup.LookupManager;
import com.intellij.codeInsight.lookup.impl.LookupImpl;
-import com.intellij.execution.ExecutionManager;
+import com.intellij.execution.Executor;
import com.intellij.execution.ui.RunContentDescriptor;
-import com.intellij.execution.ui.RunContentListener;
import com.intellij.execution.ui.RunContentManager;
+import com.intellij.execution.ui.RunContentWithExecutorListener;
+import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.openapi.ui.popup.JBPopupFactory;
+import com.intellij.openapi.util.Disposer;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -176,23 +179,22 @@ public abstract class TreeInplaceEditor implements AWTEventListener {
}
});
- final RunContentManager contentManager = ExecutionManager.getInstance(getProject()).getContentManager();
- final RunContentListener runContentListener = new RunContentListener() {
+ final Disposable disposable = Disposer.newDisposable();
+ getProject().getMessageBus().connect(disposable).subscribe(RunContentManager.TOPIC, new RunContentWithExecutorListener() {
@Override
- public void contentSelected(RunContentDescriptor descriptor) {
+ public void contentSelected(@Nullable RunContentDescriptor descriptor, @NotNull Executor executor) {
cancelEditing();
}
@Override
- public void contentRemoved(RunContentDescriptor descriptor) {
+ public void contentRemoved(@Nullable RunContentDescriptor descriptor, @NotNull Executor executor) {
cancelEditing();
}
- };
- contentManager.addRunContentListener(runContentListener);
+ });
myRemoveActions.add(new Runnable() {
@Override
public void run() {
- contentManager.removeRunContentListener(runContentListener);
+ disposable.dispose();
}
});
@@ -246,13 +248,13 @@ public abstract class TreeInplaceEditor implements AWTEventListener {
if (id != MouseEvent.MOUSE_PRESSED && id != MouseEvent.MOUSE_RELEASED && id != MouseEvent.MOUSE_CLICKED && id != MouseEvent.MOUSE_WHEEL) {
return;
}
-
+
final Component sourceComponent = mouseEvent.getComponent();
final Point originalPoint = mouseEvent.getPoint();
final Editor editor = getEditor();
if (editor == null) return;
-
+
final LookupImpl activeLookup = (LookupImpl)LookupManager.getInstance(editor.getProject()).getActiveLookup();
if (activeLookup != null){
final Point lookupPoint = SwingUtilities.convertPoint(sourceComponent, originalPoint, activeLookup.getComponent());
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 fe32920a7ac6..9e4f471b047d 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
@@ -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,6 +18,8 @@ package com.intellij.xdebugger.impl.ui.tree;
import com.intellij.ide.dnd.aware.DnDAwareTree;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.*;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.keymap.KeymapManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Condition;
@@ -26,10 +28,12 @@ import com.intellij.openapi.vcs.changes.issueLinks.TreeLinkMouseListener;
import com.intellij.ui.DoubleClickListener;
import com.intellij.ui.PopupHandler;
import com.intellij.ui.TreeSpeedSearch;
+import com.intellij.util.SingleAlarm;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.Convertor;
import com.intellij.util.containers.TransferToEDTQueue;
import com.intellij.util.ui.TextTransferable;
+import com.intellij.util.ui.tree.TreeModelAdapter;
import com.intellij.xdebugger.XSourcePosition;
import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider;
import com.intellij.xdebugger.frame.XDebuggerTreeNodeHyperlink;
@@ -41,6 +45,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
+import javax.swing.event.TreeModelEvent;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
@@ -58,6 +63,17 @@ public class XDebuggerTree extends DnDAwareTree implements DataProvider, Disposa
private final TransferToEDTQueue<Runnable> myLaterInvocator = TransferToEDTQueue.createRunnableMerger("XDebuggerTree later invocator", 100);
private static final DataKey<XDebuggerTree> XDEBUGGER_TREE_KEY = DataKey.create("xdebugger.tree");
+ private final SingleAlarm myAlarm = new SingleAlarm(new Runnable() {
+ @Override
+ public void run() {
+ final Editor editor = FileEditorManager.getInstance(myProject).getSelectedTextEditor();
+ if (editor != null) {
+ editor.getComponent().revalidate();
+ editor.getComponent().repaint();
+ }
+ }
+ }, 100, this);
+
private static final Convertor<TreePath, String> SPEED_SEARCH_CONVERTER = new Convertor<TreePath, String>() {
@Override
public String convert(TreePath o) {
@@ -135,6 +151,27 @@ public class XDebuggerTree extends DnDAwareTree implements DataProvider, Disposa
myEditorsProvider = editorsProvider;
mySourcePosition = sourcePosition;
myTreeModel = new DefaultTreeModel(null);
+ myTreeModel.addTreeModelListener(new TreeModelAdapter() {
+ @Override
+ public void treeNodesChanged(TreeModelEvent e) {
+ updateEditor();
+ }
+
+ @Override
+ public void treeNodesInserted(TreeModelEvent e) {
+ updateEditor();
+ }
+
+ @Override
+ public void treeNodesRemoved(TreeModelEvent e) {
+ updateEditor();
+ }
+
+ @Override
+ public void treeStructureChanged(TreeModelEvent e) {
+ updateEditor();
+ }
+ });
setModel(myTreeModel);
setCellRenderer(new XDebuggerTreeRenderer());
new TreeLinkMouseListener(new XDebuggerTreeRenderer()) {
@@ -185,6 +222,10 @@ public class XDebuggerTree extends DnDAwareTree implements DataProvider, Disposa
setTransferHandler(DEFAULT_TRANSFER_HANDLER);
}
+ private void updateEditor() {
+ myAlarm.cancelAndRequest();
+ }
+
private boolean expandIfEllipsis() {
MessageTreeNode[] treeNodes = getSelectedNodes(MessageTreeNode.class, null);
if (treeNodes.length == 1) {
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XAddToWatchesAction.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XAddToWatchesAction.java
index 66f22bbfd4f1..7c77bafc6553 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XAddToWatchesAction.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XAddToWatchesAction.java
@@ -55,7 +55,7 @@ class XAddToWatchesAction extends XDebuggerTreeActionBase {
if (view == null && project != null) {
XDebugSession session = XDebuggerManager.getInstance(project).getCurrentSession();
if (session != null) {
- view = ((XDebugSessionImpl)session).getSessionTab().getWatchesView();
+ return ((XDebugSessionImpl)session).getSessionTab().getWatchesView();
}
}
return view;
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XFetchValueActionBase.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XFetchValueActionBase.java
index 3926e89ecd4c..13121c7fda16 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XFetchValueActionBase.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/actions/XFetchValueActionBase.java
@@ -22,6 +22,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.SmartList;
import com.intellij.xdebugger.frame.XFullValueEvaluator;
+import com.intellij.xdebugger.impl.ui.XValueTextProvider;
import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree;
import com.intellij.xdebugger.impl.ui.tree.nodes.HeadlessValueEvaluationCallback;
import com.intellij.xdebugger.impl.ui.tree.nodes.WatchMessageNode;
@@ -74,7 +75,14 @@ public abstract class XFetchValueActionBase extends AnAction {
XValueNodeImpl valueNode = (XValueNodeImpl)node;
XFullValueEvaluator fullValueEvaluator = valueNode.getFullValueEvaluator();
if (fullValueEvaluator == null) {
- valueCollector.add(StringUtil.notNullize(valueNode.getRawValue()));
+ String rawValue;
+ if (valueNode.getValueContainer() instanceof XValueTextProvider) {
+ rawValue = ((XValueTextProvider)valueNode.getValueContainer()).getValueText();
+ }
+ else {
+ rawValue = valueNode.getRawValue();
+ }
+ valueCollector.add(StringUtil.notNullize(rawValue));
}
else {
new CopyValueEvaluationCallback(valueNode, valueCollector).startFetchingValue(fullValueEvaluator);
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/WatchesRootNode.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/WatchesRootNode.java
index 204f45a4a02d..cf67f7d5fdb5 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/WatchesRootNode.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/WatchesRootNode.java
@@ -21,6 +21,7 @@ import com.intellij.xdebugger.evaluation.XDebuggerEvaluator;
import com.intellij.xdebugger.frame.XValue;
import com.intellij.xdebugger.impl.breakpoints.XExpressionImpl;
import com.intellij.xdebugger.impl.frame.WatchInplaceEditor;
+import com.intellij.xdebugger.impl.frame.XDebugView;
import com.intellij.xdebugger.impl.frame.XWatchesView;
import com.intellij.xdebugger.impl.ui.DebuggerUIUtil;
import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree;
@@ -37,18 +38,15 @@ import java.util.List;
* @author nik
*/
public class WatchesRootNode extends XDebuggerTreeNode {
- private final XDebugSession mySession;
private final XWatchesView myWatchesView;
private List<WatchNode> myChildren;
private List<XDebuggerTreeNode> myLoadedChildren;
private XDebuggerEvaluator myCurrentEvaluator;
- public WatchesRootNode(final @NotNull XDebuggerTree tree,
- @NotNull XDebugSession session,
+ public WatchesRootNode(@NotNull XDebuggerTree tree,
@NotNull XWatchesView watchesView,
@NotNull XExpression[] watchExpressions) {
super(tree, null, false);
- mySession = session;
myWatchesView = watchesView;
myChildren = new ArrayList<WatchNode>();
for (XExpression watchExpression : watchExpressions) {
@@ -189,7 +187,10 @@ public class WatchesRootNode extends XDebuggerTreeNode {
myChildren.set(index, messageNode);
fireNodeStructureChanged(messageNode);
}
- new WatchInplaceEditor(this, mySession, myWatchesView, messageNode, "watch", node).show();
+ XDebugSession session = XDebugView.getSession(myTree);
+ if (session != null) {
+ new WatchInplaceEditor(this, session, myWatchesView, messageNode, "watch", node).show();
+ }
}
private class MyEvaluationCallback extends XEvaluationCallbackBase {
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XDebuggerTreeNode.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XDebuggerTreeNode.java
index e01d0ad7ce79..5e3101bff21a 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XDebuggerTreeNode.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XDebuggerTreeNode.java
@@ -49,8 +49,7 @@ public abstract class XDebuggerTreeNode implements TreeNode, TreeSpeedSearch.Pat
@Override
public TreeNode getChildAt(final int childIndex) {
- if (isLeaf()) return null;
- return getChildren().get(childIndex);
+ return isLeaf() ? null : getChildren().get(childIndex);
}
@Override
@@ -64,7 +63,7 @@ public abstract class XDebuggerTreeNode implements TreeNode, TreeSpeedSearch.Pat
}
@Override
- public int getIndex(final TreeNode node) {
+ public int getIndex(@NotNull TreeNode node) {
if (isLeaf()) return -1;
return getChildren().indexOf(node);
}
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java
index b808c3ca96d8..1f3d4c77e84f 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.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,19 @@
package com.intellij.xdebugger.impl.ui.tree.nodes;
import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.AppUIUtil;
import com.intellij.ui.ColoredTextContainer;
import com.intellij.ui.SimpleTextAttributes;
import com.intellij.util.NotNullFunction;
+import com.intellij.xdebugger.XSourcePosition;
import com.intellij.xdebugger.frame.*;
import com.intellij.xdebugger.frame.presentation.XValuePresentation;
import com.intellij.xdebugger.impl.frame.XValueMarkers;
+import com.intellij.xdebugger.impl.frame.XVariablesView;
import com.intellij.xdebugger.impl.ui.DebuggerUIUtil;
import com.intellij.xdebugger.impl.ui.XDebuggerUIConstants;
import com.intellij.xdebugger.impl.ui.tree.ValueMarkup;
@@ -35,6 +40,9 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.event.MouseEvent;
import java.util.Comparator;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
/**
* @author nik
@@ -111,7 +119,28 @@ public class XValueNodeImpl extends XValueContainerNode<XValue> implements XValu
setIcon(icon);
myValuePresentation = valuePresentation;
myRawValue = XValuePresentationUtil.computeValueText(valuePresentation);
-
+ if (Registry.is("ide.debugger.inline")) {
+ try {
+ getValueContainer().computeSourcePosition(new XNavigatable() {
+ @Override
+ public void setSourcePosition(@Nullable XSourcePosition sourcePosition) {
+ Map<Pair<VirtualFile, Integer>, Set<XValueNodeImpl>> map = myTree.getProject().getUserData(XVariablesView.DEBUG_VARIABLES);
+ if (map == null || sourcePosition == null) return;
+ VirtualFile file = sourcePosition.getFile();
+ int line = sourcePosition.getLine();
+ Pair<VirtualFile, Integer> key = Pair.create(file, line);
+ Set<XValueNodeImpl> presentations = map.get(key);
+ if (presentations == null) {
+ presentations = new LinkedHashSet<XValueNodeImpl>();
+ map.put(key, presentations);
+ }
+ presentations.add(XValueNodeImpl.this);
+ }
+ });
+ }
+ catch (Exception ignore) {
+ }
+ }
updateText();
setLeaf(!hasChildren);
fireNodeChanged();
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueTextRendererImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueTextRendererImpl.java
index e8b8616e6b69..98410cf62552 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueTextRendererImpl.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueTextRendererImpl.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.
@@ -27,7 +27,7 @@ import org.jetbrains.annotations.Nullable;
/**
* @author nik
*/
-class XValueTextRendererImpl extends XValueTextRendererBase {
+public class XValueTextRendererImpl extends XValueTextRendererBase {
private final ColoredTextContainer myText;
public XValueTextRendererImpl(@NotNull ColoredTextContainer text) {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml
index 5581810b3f2c..c8854d4dbb26 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml
@@ -2363,7 +2363,7 @@
implementationClass="com.siyeh.ig.style.UnnecessaryToStringCallInspection"/>
<localInspection language="JAVA" suppressId="RedundantNoArgConstructor" shortName="UnnecessaryConstructor" bundle="com.siyeh.InspectionGadgetsBundle"
key="unnecessary.constructor.display.name" groupBundle="messages.InspectionsBundle"
- groupKey="group.names.code.style.issues" enabledByDefault="false" level="WARNING" cleanupTool="true"
+ groupKey="group.names.code.style.issues" enabledByDefault="false" level="WARNING"
implementationClass="com.siyeh.ig.style.UnnecessaryConstructorInspection"/>
<localInspection language="JAVA" shortName="UnnecessaryEnumModifier" bundle="com.siyeh.InspectionGadgetsBundle"
key="unnecessary.enum.modifier.display.name" groupBundle="messages.InspectionsBundle"
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties
index 715bf898c50a..1dfdfb9eb50a 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties
@@ -1700,7 +1700,7 @@ this.class=this class
assertequals.may.be.assertsame.display.name='assertEquals()' may be 'assertSame()'
assertequals.may.be.assertsame.problem.descriptor=<code>#ref()</code> may be 'assertSame()' #loc
logger.initialized.with.foreign.class.quickfix=Replace with ''{0}.class''
-logger.initialized.with.foreign.class.problem.descriptor=Logger initializer with foreign class <code>#ref</code> #loc
+logger.initialized.with.foreign.class.problem.descriptor=Logger initialized with foreign class <code>#ref</code> #loc
logger.initialized.with.foreign.class.display.name=Logger initialized with foreign class
logger.factory.method.name=Logger factory method name
logger.factory.class.name=Logger factory class name
@@ -2018,8 +2018,8 @@ string.concatenation.argument.to.log.call.display.name=Non-constant string conca
string.concatenation.argument.to.log.call.problem.descriptor=Non-constant string concatenation as argument to <code>#ref()</code> logging call #loc
string.concatenation.argument.to.log.call.quickfix=Replace concatenation with parameterized log message
placeholder.count.matches.argument.count.display.name=Number of placeholders does not match number of arguments in logging call
-placeholder.count.matches.argument.count.more.problem.descriptor=<code>#ref()</code> call has more arguments ({0}) than placeholders ({1}) #loc
-placeholder.count.matches.argument.count.fewer.problem.descriptor=<code>#ref()</code> call has fewer arguments ({0}) than placeholders ({1}) #loc
+placeholder.count.matches.argument.count.more.problem.descriptor=More arguments provided ({0}) than placeholders specified ({1}) in ''{2}'' #loc
+placeholder.count.matches.argument.count.fewer.problem.descriptor=Fewer arguments provided ({0}) than placeholders specified ({1}) in ''{2}'' #loc
assignment.to.superclass.field.display.name=Constructor assigns value to field defined in superclass
assignment.to.superclass.field.problem.descriptor=Assignment to field ''{0}'' defined in superclass ''{1}'' #loc
junit.rule.display.name=Malformed @Rule/@ClassRule field
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/MakeFieldFinalFix.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/MakeFieldFinalFix.java
index 80ebfa0ae7d3..00d9f04b8c02 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/MakeFieldFinalFix.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/MakeFieldFinalFix.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2007-2010 Bas Leijdekkers
+ * Copyright 2007-2014 Bas Leijdekkers
*
* 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.siyeh.ig.fixes;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
-import com.intellij.util.IncorrectOperationException;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.InspectionGadgetsFix;
import com.siyeh.ig.psiutils.FinalUtils;
@@ -61,8 +60,7 @@ public class MakeFieldFinalFix extends InspectionGadgetsFix {
}
@Override
- protected void doFix(Project project, ProblemDescriptor descriptor)
- throws IncorrectOperationException {
+ protected void doFix(Project project, ProblemDescriptor descriptor) {
final PsiElement element = descriptor.getPsiElement();
final PsiField field;
if (element instanceof PsiReferenceExpression) {
@@ -81,6 +79,7 @@ public class MakeFieldFinalFix extends InspectionGadgetsFix {
}
field = (PsiField)parent;
}
+ field.normalizeDeclaration();
final PsiModifierList modifierList = field.getModifierList();
if (modifierList == null) {
return;
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/internationalization/ImplicitDefaultCharsetUsageInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/internationalization/ImplicitDefaultCharsetUsageInspection.java
index a2a3b12bd8de..ef598f5d2216 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/internationalization/ImplicitDefaultCharsetUsageInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/internationalization/ImplicitDefaultCharsetUsageInspection.java
@@ -19,6 +19,7 @@ import com.intellij.psi.*;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
+import com.siyeh.ig.psiutils.TypeUtils;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -143,9 +144,10 @@ public class ImplicitDefaultCharsetUsageInspection extends BaseInspection {
}
private static boolean hasCharsetType(PsiVariable variable) {
- final PsiType lastType = variable.getType();
- return lastType.equalsToText(CommonClassNames.JAVA_LANG_STRING) ||
- lastType.equalsToText("java.nio.charset.Charset");
+ return TypeUtils.variableHasTypeOrSubtype(variable, CommonClassNames.JAVA_LANG_STRING,
+ "java.nio.charset.Charset",
+ "java.nio.charset.CharsetEncoder",
+ "java.nio.charset.CharsetDecoder");
}
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/logging/LoggerInitializedWithForeignClassInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/logging/LoggerInitializedWithForeignClassInspectionBase.java
index 750b723031d4..08c54abce2a1 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/logging/LoggerInitializedWithForeignClassInspectionBase.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/logging/LoggerInitializedWithForeignClassInspectionBase.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,13 +20,13 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.psi.*;
-import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
import com.siyeh.ig.PsiReplacementUtil;
+import com.siyeh.ig.psiutils.ClassUtils;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -157,7 +157,10 @@ public class LoggerInitializedWithForeignClassInspectionBase extends BaseInspect
if (expressions.length != 1) {
return;
}
- final PsiClass containingClass = PsiTreeUtil.getParentOfType(expression, PsiClass.class);
+ PsiClass containingClass = ClassUtils.getContainingClass(expression);
+ while (containingClass instanceof PsiAnonymousClass) {
+ containingClass = ClassUtils.getContainingClass(containingClass);
+ }
if (containingClass == null) {
return;
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/logging/PlaceholderCountMatchesArgumentCountInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/logging/PlaceholderCountMatchesArgumentCountInspection.java
index a2c9307fc80c..711b0edb5c4b 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/logging/PlaceholderCountMatchesArgumentCountInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/logging/PlaceholderCountMatchesArgumentCountInspection.java
@@ -45,13 +45,14 @@ public class PlaceholderCountMatchesArgumentCountInspection extends BaseInspecti
protected String buildErrorString(Object... infos) {
final Integer argumentCount = (Integer)infos[0];
final Integer placeholderCount = (Integer)infos[1];
+ final Object value = infos[2];
if (argumentCount.intValue() > placeholderCount.intValue()) {
return InspectionGadgetsBundle.message("placeholder.count.matches.argument.count.more.problem.descriptor",
- argumentCount, placeholderCount);
+ argumentCount, placeholderCount, value);
}
else {
return InspectionGadgetsBundle.message("placeholder.count.matches.argument.count.fewer.problem.descriptor",
- argumentCount, placeholderCount);
+ argumentCount, placeholderCount, value);
}
}
@@ -83,25 +84,24 @@ public class PlaceholderCountMatchesArgumentCountInspection extends BaseInspecti
if (arguments.length == 0) {
return;
}
- final PsiExpression firstArgument = arguments[0];
- final int placeholderCount;
+ PsiExpression logStringArgument = arguments[0];
final int argumentCount;
- if (InheritanceUtil.isInheritor(firstArgument.getType(), "org.slf4j.Marker")) {
+ if (InheritanceUtil.isInheritor(logStringArgument.getType(), "org.slf4j.Marker")) {
if (arguments.length < 2) {
return;
}
- final PsiExpression secondArgument = arguments[1];
- placeholderCount = countPlaceholders(secondArgument);
+ logStringArgument = arguments[1];
argumentCount = countArguments(arguments, 2);
}
else {
- placeholderCount = countPlaceholders(firstArgument);
argumentCount = countArguments(arguments, 1);
}
+ final Object value = ExpressionUtils.computeConstantExpression(logStringArgument);
+ final int placeholderCount = countPlaceholders(value);
if (placeholderCount < 0 || argumentCount < 0 || placeholderCount == argumentCount) {
return;
}
- registerMethodCallError(expression, Integer.valueOf(argumentCount), Integer.valueOf(placeholderCount));
+ registerError(logStringArgument, Integer.valueOf(argumentCount), Integer.valueOf(placeholderCount), value);
}
private static boolean hasThrowableType(PsiExpression lastArgument) {
@@ -118,8 +118,7 @@ public class PlaceholderCountMatchesArgumentCountInspection extends BaseInspecti
return InheritanceUtil.isInheritor(type, CommonClassNames.JAVA_LANG_THROWABLE);
}
- public static int countPlaceholders(PsiExpression argument) {
- final Object value = ExpressionUtils.computeConstantExpression(argument);
+ public static int countPlaceholders(Object value) {
if (!(value instanceof String)) {
return -1;
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/MethodMayBeStaticInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/MethodMayBeStaticInspectionBase.java
new file mode 100644
index 000000000000..2377e4e14c20
--- /dev/null
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/MethodMayBeStaticInspectionBase.java
@@ -0,0 +1,181 @@
+/*
+ * 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.performance;
+
+import com.intellij.codeInspection.InspectionManager;
+import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.WriteExternalException;
+import com.intellij.psi.*;
+import com.intellij.psi.search.searches.ClassInheritorsSearch;
+import com.intellij.util.Processor;
+import com.intellij.util.Query;
+import com.siyeh.InspectionGadgetsBundle;
+import com.siyeh.ig.BaseInspection;
+import com.siyeh.ig.BaseInspectionVisitor;
+import com.siyeh.ig.psiutils.ClassUtils;
+import com.siyeh.ig.psiutils.MethodUtils;
+import com.siyeh.ig.psiutils.SerializationUtils;
+import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class MethodMayBeStaticInspectionBase extends BaseInspection {
+ protected static final String IGNORE_DEFAULT_METHODS_ATTR_NAME = "m_ignoreDefaultMethods";
+ protected static final String ONLY_PRIVATE_OR_FINAL_ATTR_NAME = "m_onlyPrivateOrFinal";
+ protected static final String IGNORE_EMPTY_METHODS_ATTR_NAME = "m_ignoreEmptyMethods";
+ protected static final String REPLACE_QUALIFIER_ATTR_NAME = "m_replaceQualifier";
+ /**
+ * @noinspection PublicField
+ */
+ public boolean m_onlyPrivateOrFinal = false;
+ /**
+ * @noinspection PublicField
+ */
+ public boolean m_ignoreEmptyMethods = true;
+ public boolean m_ignoreDefaultMethods = true;
+ public boolean m_replaceQualifier = true;
+
+ @Override
+ @NotNull
+ public String getDisplayName() {
+ return InspectionGadgetsBundle.message("method.may.be.static.display.name");
+ }
+
+ @Override
+ @NotNull
+ protected String buildErrorString(Object... infos) {
+ return InspectionGadgetsBundle.message("method.may.be.static.problem.descriptor");
+ }
+
+ @Override
+ public BaseInspectionVisitor buildVisitor() {
+ return new MethodCanBeStaticVisitor();
+ }
+
+ @Override
+ public void writeSettings(@NotNull Element node) throws WriteExternalException {
+ node.addContent(new Element("option").setAttribute("name", ONLY_PRIVATE_OR_FINAL_ATTR_NAME).setAttribute("value", String.valueOf(m_onlyPrivateOrFinal)));
+ node.addContent(new Element("option").setAttribute("name", IGNORE_EMPTY_METHODS_ATTR_NAME).setAttribute("value", String.valueOf(
+ m_ignoreEmptyMethods)));
+ if (!m_ignoreDefaultMethods) {
+ node.addContent(new Element("option").setAttribute("name", IGNORE_DEFAULT_METHODS_ATTR_NAME).setAttribute("value", "false"));
+ }
+ if (!m_replaceQualifier) {
+ node.addContent(new Element("option").setAttribute("name", REPLACE_QUALIFIER_ATTR_NAME).setAttribute("value", "false"));
+ }
+ }
+
+ private class MethodCanBeStaticVisitor extends BaseInspectionVisitor {
+
+ @Override
+ public void visitMethod(@NotNull PsiMethod method) {
+ super.visitMethod(method);
+ if (method.hasModifierProperty(PsiModifier.STATIC) ||
+ method.hasModifierProperty(PsiModifier.ABSTRACT) ||
+ method.hasModifierProperty(PsiModifier.SYNCHRONIZED) ||
+ method.hasModifierProperty(PsiModifier.NATIVE)) {
+ return;
+ }
+ if (method.isConstructor() || method.getNameIdentifier() == null) {
+ return;
+ }
+ if (m_ignoreDefaultMethods && method.hasModifierProperty(PsiModifier.DEFAULT)) {
+ return;
+ }
+ if (m_ignoreEmptyMethods && MethodUtils.isEmpty(method)) {
+ return;
+ }
+ final PsiClass containingClass = ClassUtils.getContainingClass(method);
+ if (containingClass == null) {
+ return;
+ }
+ final Condition<PsiElement>[] addins = InspectionManager.CANT_BE_STATIC_EXTENSION.getExtensions();
+ for (Condition<PsiElement> addin : addins) {
+ if (addin.value(method)) {
+ return;
+ }
+ }
+ final PsiElement scope = containingClass.getScope();
+ if (!(scope instanceof PsiJavaFile) && !containingClass.hasModifierProperty(PsiModifier.STATIC) && !containingClass.isInterface()) {
+ return;
+ }
+ if (m_onlyPrivateOrFinal && !method.hasModifierProperty(PsiModifier.FINAL) && !method.hasModifierProperty(PsiModifier.PRIVATE)) {
+ return;
+ }
+ if (isExcluded(method) || MethodUtils.hasSuper(method) || MethodUtils.isOverridden(method)) {
+ return;
+ }
+ if (implementsSurprisingInterface(method)) {
+ return;
+ }
+ final MethodReferenceVisitor visitor = new MethodReferenceVisitor(method);
+ method.accept(visitor);
+ if (!visitor.areReferencesStaticallyAccessible()) {
+ return;
+ }
+ registerMethodError(method);
+ }
+
+ private boolean implementsSurprisingInterface(final PsiMethod method) {
+ final PsiClass containingClass = method.getContainingClass();
+ if (containingClass == null) {
+ return false;
+ }
+ final Query<PsiClass> search = ClassInheritorsSearch.search(containingClass, method.getUseScope(), true, true, false);
+ final boolean[] result = new boolean[1];
+ search.forEach(new Processor<PsiClass>() {
+ AtomicInteger count = new AtomicInteger(0);
+
+ @Override
+ public boolean process(PsiClass subClass) {
+ if (count.incrementAndGet() > 5) {
+ result[0] = true;
+ return false;
+ }
+ final PsiReferenceList list = subClass.getImplementsList();
+ if (list == null) {
+ return true;
+ }
+ final PsiJavaCodeReferenceElement[] referenceElements = list.getReferenceElements();
+ for (PsiJavaCodeReferenceElement referenceElement : referenceElements) {
+ final PsiElement target = referenceElement.resolve();
+ if (!(target instanceof PsiClass)) {
+ result[0] = true;
+ return false;
+ }
+ final PsiClass aClass = (PsiClass)target;
+ if (!aClass.isInterface()) {
+ result[0] = true;
+ return false;
+ }
+ if (aClass.findMethodBySignature(method, true) != null) {
+ result[0] = true;
+ return false;
+ }
+ }
+ return true;
+ }
+ });
+ return result[0];
+ }
+
+ private boolean isExcluded(PsiMethod method) {
+ return SerializationUtils.isWriteObject(method) || SerializationUtils.isReadObject(method) ||
+ SerializationUtils.isWriteReplace(method) || SerializationUtils.isReadResolve(method);
+ }
+ }
+}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/VariablePassedAsArgumentExcludedVisitor.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/VariablePassedAsArgumentExcludedVisitor.java
index 69710a084904..f7778e0a89bc 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/VariablePassedAsArgumentExcludedVisitor.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/VariablePassedAsArgumentExcludedVisitor.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.
@@ -44,49 +44,35 @@ class VariablePassedAsArgumentExcludedVisitor extends JavaRecursiveElementVisito
}
@Override
- public void visitMethodCallExpression(@NotNull PsiMethodCallExpression call) {
+ public void visitCallExpression(PsiCallExpression callExpression) {
if (passed) {
return;
}
- super.visitMethodCallExpression(call);
- final PsiExpressionList argumentList = call.getArgumentList();
- final PsiExpression[] arguments = argumentList.getExpressions();
- for (PsiExpression argument : arguments) {
- if (!VariableAccessUtils.mayEvaluateToVariable(argument, variable, myBuilderPattern)) {
- continue;
- }
- final PsiMethod method = call.resolveMethod();
- if (method != null) {
- final PsiClass aClass = method.getContainingClass();
- if (aClass != null) {
- final String name = aClass.getQualifiedName();
- if (excludes.contains(name)) {
- continue;
- }
- }
- }
- passed = true;
- }
+ super.visitCallExpression(callExpression);
+ visitCall(callExpression);
}
@Override
- public void visitNewExpression(@NotNull PsiNewExpression newExpression) {
+ public void visitEnumConstant(PsiEnumConstant enumConstant) {
if (passed) {
return;
}
- super.visitNewExpression(newExpression);
- final PsiExpressionList argumentList = newExpression.getArgumentList();
+ super.visitEnumConstant(enumConstant);
+ visitCall(enumConstant);
+ }
+
+ private void visitCall(PsiCall call) {
+ final PsiExpressionList argumentList = call.getArgumentList();
if (argumentList == null) {
return;
}
- final PsiExpression[] arguments = argumentList.getExpressions();
- for (PsiExpression argument : arguments) {
+ for (PsiExpression argument : argumentList.getExpressions()) {
if (!VariableAccessUtils.mayEvaluateToVariable(argument, variable, myBuilderPattern)) {
continue;
}
- final PsiMethod constructor = newExpression.resolveConstructor();
- if (constructor != null) {
- final PsiClass aClass = constructor.getContainingClass();
+ final PsiMethod method = call.resolveMethod();
+ if (method != null) {
+ final PsiClass aClass = method.getContainingClass();
if (aClass != null) {
final String name = aClass.getQualifiedName();
if (excludes.contains(name)) {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/VariablePassedAsArgumentVisitor.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/VariablePassedAsArgumentVisitor.java
index 7938fbc5c696..92082cea9e27 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/VariablePassedAsArgumentVisitor.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/VariablePassedAsArgumentVisitor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2011 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.
@@ -37,33 +37,29 @@ class VariablePassedAsArgumentVisitor extends JavaRecursiveElementVisitor {
}
@Override
- public void visitMethodCallExpression(@NotNull PsiMethodCallExpression call) {
+ public void visitCallExpression(PsiCallExpression callExpression) {
+ super.visitCallExpression(callExpression);
if (passed) {
return;
}
- super.visitMethodCallExpression(call);
- final PsiExpressionList argumentList = call.getArgumentList();
- final PsiExpression[] arguments = argumentList.getExpressions();
- for (PsiExpression argument : arguments) {
- if (VariableAccessUtils.mayEvaluateToVariable(argument, variable)) {
- passed = true;
- break;
- }
- }
+ visitCall(callExpression);
}
@Override
- public void visitNewExpression(@NotNull PsiNewExpression newExpression) {
+ public void visitEnumConstant(PsiEnumConstant enumConstant) {
if (passed) {
return;
}
- super.visitNewExpression(newExpression);
- final PsiExpressionList argumentList = newExpression.getArgumentList();
+ super.visitEnumConstant(enumConstant);
+ visitCall(enumConstant);
+ }
+
+ private void visitCall(PsiCall call) {
+ final PsiExpressionList argumentList = call.getArgumentList();
if (argumentList == null) {
return;
}
- final PsiExpression[] arguments = argumentList.getExpressions();
- for (PsiExpression argument : arguments) {
+ for (PsiExpression argument : argumentList.getExpressions()) {
if (VariableAccessUtils.mayEvaluateToVariable(argument, variable)) {
passed = true;
break;
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryConstructorInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryConstructorInspection.java
index 126f5021a47f..8b7e23fa1547 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryConstructorInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryConstructorInspection.java
@@ -15,7 +15,6 @@
*/
package com.siyeh.ig.style;
-import com.intellij.codeInspection.CleanupLocalInspectionTool;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel;
import com.intellij.openapi.project.Project;
@@ -30,7 +29,7 @@ import org.jetbrains.annotations.NotNull;
import javax.swing.*;
-public class UnnecessaryConstructorInspection extends BaseInspection implements CleanupLocalInspectionTool {
+public class UnnecessaryConstructorInspection extends BaseInspection {
@NonNls
private static final String SUPER_CALL_TEXT = PsiKeyword.SUPER + "();";
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/performance/MethodMayBeStaticInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/performance/MethodMayBeStaticInspection.java
index e73b6cc234d7..5936bb5433a3 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/performance/MethodMayBeStaticInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/performance/MethodMayBeStaticInspection.java
@@ -15,62 +15,22 @@
*/
package com.siyeh.ig.performance;
-import com.intellij.codeInspection.InspectionManager;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Condition;
-import com.intellij.openapi.util.WriteExternalException;
-import com.intellij.psi.*;
-import com.intellij.psi.search.searches.ClassInheritorsSearch;
+import com.intellij.psi.PsiMethod;
+import com.intellij.psi.PsiModifier;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.refactoring.makeStatic.MakeMethodStaticProcessor;
import com.intellij.refactoring.makeStatic.Settings;
-import com.intellij.util.Processor;
-import com.intellij.util.Query;
import com.siyeh.InspectionGadgetsBundle;
-import com.siyeh.ig.BaseInspection;
-import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
import com.siyeh.ig.fixes.ChangeModifierFix;
-import com.siyeh.ig.psiutils.ClassUtils;
-import com.siyeh.ig.psiutils.MethodUtils;
-import com.siyeh.ig.psiutils.SerializationUtils;
-import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
-import java.util.concurrent.atomic.AtomicInteger;
-
-public class MethodMayBeStaticInspection extends BaseInspection {
-
- private static final String IGNORE_DEFAULT_METHODS_ATTR_NAME = "m_ignoreDefaultMethods";
- private static final String ONLY_PRIVATE_OR_FINAL_ATTR_NAME = "m_onlyPrivateOrFinal";
- private static final String IGNORE_EMPTY_METHODS_ATTR_NAME = "m_ignoreEmptyMethods";
- private static final String REPLACE_QUALIFIER_ATTR_NAME = "m_replaceQualifier";
- /**
- * @noinspection PublicField
- */
- public boolean m_onlyPrivateOrFinal = false;
- /**
- * @noinspection PublicField
- */
- public boolean m_ignoreEmptyMethods = true;
- public boolean m_ignoreDefaultMethods = true;
- public boolean m_replaceQualifier = true;
-
- @Override
- @NotNull
- public String getDisplayName() {
- return InspectionGadgetsBundle.message("method.may.be.static.display.name");
- }
-
- @Override
- @NotNull
- protected String buildErrorString(Object... infos) {
- return InspectionGadgetsBundle.message("method.may.be.static.problem.descriptor");
- }
+public class MethodMayBeStaticInspection extends MethodMayBeStaticInspectionBase {
@Override
protected InspectionGadgetsFix buildFix(Object... infos) {
return new InspectionGadgetsFix() {
@@ -103,122 +63,4 @@ public class MethodMayBeStaticInspection extends BaseInspection {
optionsPanel.addCheckbox("Replace qualifier by class name", REPLACE_QUALIFIER_ATTR_NAME);
return optionsPanel;
}
-
- @Override
- public BaseInspectionVisitor buildVisitor() {
- return new MethodCanBeStaticVisitor();
- }
-
- @Override
- public void writeSettings(@NotNull Element node) throws WriteExternalException {
- node.addContent(new Element("option").setAttribute("name", ONLY_PRIVATE_OR_FINAL_ATTR_NAME).setAttribute("value", String.valueOf(m_onlyPrivateOrFinal)));
- node.addContent(new Element("option").setAttribute("name", IGNORE_EMPTY_METHODS_ATTR_NAME).setAttribute("value", String.valueOf(
- m_ignoreEmptyMethods)));
- if (!m_ignoreDefaultMethods) {
- node.addContent(new Element("option").setAttribute("name", IGNORE_DEFAULT_METHODS_ATTR_NAME).setAttribute("value", "false"));
- }
- if (!m_replaceQualifier) {
- node.addContent(new Element("option").setAttribute("name", REPLACE_QUALIFIER_ATTR_NAME).setAttribute("value", "false"));
- }
- }
-
- private class MethodCanBeStaticVisitor extends BaseInspectionVisitor {
-
- @Override
- public void visitMethod(@NotNull PsiMethod method) {
- super.visitMethod(method);
- if (method.hasModifierProperty(PsiModifier.STATIC) ||
- method.hasModifierProperty(PsiModifier.ABSTRACT) ||
- method.hasModifierProperty(PsiModifier.SYNCHRONIZED) ||
- method.hasModifierProperty(PsiModifier.NATIVE)) {
- return;
- }
- if (method.isConstructor() || method.getNameIdentifier() == null) {
- return;
- }
- if (m_ignoreDefaultMethods && method.hasModifierProperty(PsiModifier.DEFAULT)) {
- return;
- }
- if (m_ignoreEmptyMethods && MethodUtils.isEmpty(method)) {
- return;
- }
- final PsiClass containingClass = ClassUtils.getContainingClass(method);
- if (containingClass == null) {
- return;
- }
- final Condition<PsiElement>[] addins = InspectionManager.CANT_BE_STATIC_EXTENSION.getExtensions();
- for (Condition<PsiElement> addin : addins) {
- if (addin.value(method)) {
- return;
- }
- }
- final PsiElement scope = containingClass.getScope();
- if (!(scope instanceof PsiJavaFile) && !containingClass.hasModifierProperty(PsiModifier.STATIC) && !containingClass.isInterface()) {
- return;
- }
- if (m_onlyPrivateOrFinal && !method.hasModifierProperty(PsiModifier.FINAL) && !method.hasModifierProperty(PsiModifier.PRIVATE)) {
- return;
- }
- if (isExcluded(method) || MethodUtils.hasSuper(method) || MethodUtils.isOverridden(method)) {
- return;
- }
- if (implementsSurprisingInterface(method)) {
- return;
- }
- final MethodReferenceVisitor visitor = new MethodReferenceVisitor(method);
- method.accept(visitor);
- if (!visitor.areReferencesStaticallyAccessible()) {
- return;
- }
- registerMethodError(method);
- }
-
- private boolean implementsSurprisingInterface(final PsiMethod method) {
- final PsiClass containingClass = method.getContainingClass();
- if (containingClass == null) {
- return false;
- }
- final Query<PsiClass> search = ClassInheritorsSearch.search(containingClass, method.getUseScope(), true, true, false);
- final boolean[] result = new boolean[1];
- search.forEach(new Processor<PsiClass>() {
- AtomicInteger count = new AtomicInteger(0);
-
- @Override
- public boolean process(PsiClass subClass) {
- if (count.incrementAndGet() > 5) {
- result[0] = true;
- return false;
- }
- final PsiReferenceList list = subClass.getImplementsList();
- if (list == null) {
- return true;
- }
- final PsiJavaCodeReferenceElement[] referenceElements = list.getReferenceElements();
- for (PsiJavaCodeReferenceElement referenceElement : referenceElements) {
- final PsiElement target = referenceElement.resolve();
- if (!(target instanceof PsiClass)) {
- result[0] = true;
- return false;
- }
- final PsiClass aClass = (PsiClass)target;
- if (!aClass.isInterface()) {
- result[0] = true;
- return false;
- }
- if (aClass.findMethodBySignature(method, true) != null) {
- result[0] = true;
- return false;
- }
- }
- return true;
- }
- });
- return result[0];
- }
-
- private boolean isExcluded(PsiMethod method) {
- return SerializationUtils.isWriteObject(method) || SerializationUtils.isReadObject(method) ||
- SerializationUtils.isWriteReplace(method) || SerializationUtils.isReadResolve(method);
- }
- }
}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspection.java
index e79f9df5fa7d..25109cc5f26e 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspection.java
@@ -15,6 +15,7 @@
*/
package com.siyeh.ig.style;
+import com.intellij.codeInsight.javadoc.JavaDocUtil;
import com.intellij.codeInspection.CleanupLocalInspectionTool;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.diagnostic.Logger;
@@ -205,11 +206,8 @@ public class UnnecessaryFullyQualifiedNameInspection extends BaseInspection impl
return;
}
final CodeStyleSettings styleSettings = CodeStyleSettingsManager.getSettings(reference.getProject());
- if (styleSettings.USE_FQ_CLASS_NAMES_IN_JAVADOC) {
- final PsiElement containingComment = PsiTreeUtil.getParentOfType(reference, PsiDocComment.class);
- if (containingComment != null) {
- return;
- }
+ if (acceptFullyQualifiedNamesInJavadoc(reference, styleSettings)) {
+ return;
}
final PsiFile containingFile = reference.getContainingFile();
if (!(containingFile instanceof PsiJavaFile)) {
@@ -261,4 +259,14 @@ public class UnnecessaryFullyQualifiedNameInspection extends BaseInspection impl
}
}
}
+
+ public static boolean acceptFullyQualifiedNamesInJavadoc(PsiJavaCodeReferenceElement reference, CodeStyleSettings styleSettings) {
+ final PsiDocComment containingComment = PsiTreeUtil.getParentOfType(reference, PsiDocComment.class);
+ if (containingComment != null) {
+ if (styleSettings.USE_FQ_CLASS_NAMES_IN_JAVADOC || JavaDocUtil.isInsidePackageInfo(containingComment)) {
+ return true;
+ }
+ }
+ return false;
+ }
} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/mismatched_collection_query_update/MismatchedCollectionQueryUpdate.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/mismatched_collection_query_update/MismatchedCollectionQueryUpdate.java
index 5c53674cd15b..5af84ecb21e7 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/mismatched_collection_query_update/MismatchedCollectionQueryUpdate.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/mismatched_collection_query_update/MismatchedCollectionQueryUpdate.java
@@ -275,4 +275,18 @@ class SimpleAdd {
return null;
}
+}
+class EnumConstant {
+ private static final List<String> CONSTANT_ARRAY = new ArrayList();
+ static {
+ CONSTANT_ARRAY.add("asdf");
+ }
+
+ enum SomeEnum {
+ ITEM(CONSTANT_ARRAY); // passed as argument
+ private final List<String> myPatterns;
+ SomeEnum(List<String> patterns) {
+ myPatterns = patterns;
+ }
+ }
} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/mismatched_string_builder_query_update/MismatchedStringBuilderQueryUpdate.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/mismatched_string_builder_query_update/MismatchedStringBuilderQueryUpdate.java
index c8d9fb80cf19..2274472eb2fa 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/mismatched_string_builder_query_update/MismatchedStringBuilderQueryUpdate.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/mismatched_string_builder_query_update/MismatchedStringBuilderQueryUpdate.java
@@ -31,3 +31,15 @@ interface List<T> {
interface Consumer<T> {
void accept(T t);
}
+class EnumConstant {
+ private static final StringBuilder sb = new StringBuilder();
+ static {
+ sb.append("");
+ }
+
+ enum SomeEnum {
+ ITEM(sb); // passed as argument
+
+ SomeEnum(StringBuilder sb) {}
+ }
+}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/if_statement_with_identical_branches/IfStatementWithIdenticalBranches.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/if_statement_with_identical_branches/IfStatementWithIdenticalBranches.java
index 666651d71e21..fef2e0f1f6ff 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/if_statement_with_identical_branches/IfStatementWithIdenticalBranches.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/if_statement_with_identical_branches/IfStatementWithIdenticalBranches.java
@@ -162,4 +162,15 @@ class NotADup {
private static String placeOrder(int i, Object o) {
return null;
}
+
+ void m() {
+ int j;
+ <warning descr="'if' statement with identical branches">if</warning> (true) {
+ j = 2;
+ }
+ else {
+ j = 2;
+ }
+ System.out.println("j = " + j);
+ }
}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/errorhandling/try_identical_catches/TryIdenticalCatches.after.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/errorhandling/try_identical_catches/TryIdenticalCatches.after.java
index 032fa0002dea..a161e388ce3b 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/errorhandling/try_identical_catches/TryIdenticalCatches.after.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/errorhandling/try_identical_catches/TryIdenticalCatches.after.java
@@ -117,4 +117,18 @@ class TryIdenticalCatches {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}
+
+ public static void main() {
+ Throwable causeException;
+ try {
+ throw new NullPointerException();
+ } catch (final NullPointerException e) {
+ causeException = e;
+ } catch (final IllegalArgumentException e) {
+ causeException = e;
+ } catch (final IndexOutOfBoundsException e) {
+ causeException = e;
+ }
+ System.out.println("causeException = " + causeException);
+ }
} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/errorhandling/try_identical_catches/TryIdenticalCatches.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/errorhandling/try_identical_catches/TryIdenticalCatches.java
index 5d33c50de89e..09694491d69d 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/errorhandling/try_identical_catches/TryIdenticalCatches.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/errorhandling/try_identical_catches/TryIdenticalCatches.java
@@ -120,4 +120,18 @@ class TryIdenticalCatches {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}
+
+ public static void main() {
+ Throwable causeException;
+ try {
+ throw new NullPointerException();
+ } catch (final NullPointerException e) {
+ causeException = e;
+ } <warning descr="catch branch identical to 'NullPointerException' branch">catch (final IllegalArgumentException e)</warning> {
+ causeException = e;
+ } <warning descr="catch branch identical to 'NullPointerException' branch">catch (final IndexOutOfBoundsException e)</warning> {
+ causeException = e;
+ }
+ System.out.println("causeException = " + causeException);
+ }
} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/internationalization/implicit_default_charset_usage/ImplicitDefaultCharsetUsage.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/internationalization/implicit_default_charset_usage/ImplicitDefaultCharsetUsage.java
index 17dd59eadf7a..151042fa3ed9 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/internationalization/implicit_default_charset_usage/ImplicitDefaultCharsetUsage.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/internationalization/implicit_default_charset_usage/ImplicitDefaultCharsetUsage.java
@@ -1,6 +1,9 @@
package com.siyeh.igtest.internationalization.implicit_default_charset_usage;
import java.io.*;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharsetEncoder;
import java.util.ArrayList;
import java.util.Formatter;
import java.util.Locale;
@@ -37,4 +40,12 @@ class ImplicitDefaultCharsetUsage {
new Scanner("string input");
new ArrayList(10);
}
+
+ void charsetEnAndDecoders(InputStream inputStream, OutputStream outputStream) throws IOException {
+ final Charset cs = Charset.forName("UTF-8");
+ CharsetDecoder cd = cs.newDecoder();
+ InputStreamReader is = new InputStreamReader(inputStream, cd);
+ CharsetEncoder ce = cs.newEncoder();
+ final OutputStreamWriter ow = new OutputStreamWriter(outputStream, ce);
+ }
} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/logging/logger_initialized_with_foreign_class/LoggerInitializedWithForeignClass.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/logging/logger_initialized_with_foreign_class/LoggerInitializedWithForeignClass.java
new file mode 100644
index 000000000000..b252b8af1cd3
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/logging/logger_initialized_with_foreign_class/LoggerInitializedWithForeignClass.java
@@ -0,0 +1,13 @@
+import java.util.logging.*;
+
+class LoggerInitializedWithForeignClass {
+
+ void foo() {
+ new Object() {
+ void bar() {
+ Logger.getLogger(LoggerInitializedWithForeignClass.class.getName());
+ Logger.getLogger(<warning descr="Logger initialized with foreign class 'String.class'">String.class</warning>.getName());
+ }
+ };
+ }
+} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_fully_qualified_name/test1/package-info.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_fully_qualified_name/test1/package-info.java
new file mode 100644
index 000000000000..01825303d455
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_fully_qualified_name/test1/package-info.java
@@ -0,0 +1,3 @@
+/**
+ * {@link java.util.Map(java.util.function.BiConsumer)}
+*/ \ No newline at end of file
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/internationalization/ImplicitDefaultCharsetUsageInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/internationalization/ImplicitDefaultCharsetUsageInspectionTest.java
index 78822492b4bc..312e08aebcc3 100644
--- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/internationalization/ImplicitDefaultCharsetUsageInspectionTest.java
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/internationalization/ImplicitDefaultCharsetUsageInspectionTest.java
@@ -16,13 +16,22 @@
package com.siyeh.ig.internationalization;
import com.intellij.codeInspection.InspectionProfileEntry;
+import com.intellij.testFramework.LightProjectDescriptor;
import com.siyeh.ig.LightInspectionTestCase;
+import org.jetbrains.annotations.NotNull;
/**
* @author Bas Leijdekkers
*/
public class ImplicitDefaultCharsetUsageInspectionTest extends LightInspectionTestCase {
+
+ @NotNull
+ @Override
+ protected LightProjectDescriptor getProjectDescriptor() {
+ return JAVA_8;
+ }
+
@Override
protected InspectionProfileEntry getInspection() {
return new ImplicitDefaultCharsetUsageInspection();
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/logging/LoggerInitializedWithForeignClassInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/logging/LoggerInitializedWithForeignClassInspectionTest.java
new file mode 100644
index 000000000000..7f0b521fcf4e
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/logging/LoggerInitializedWithForeignClassInspectionTest.java
@@ -0,0 +1,51 @@
+/*
+ * 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.logging;
+
+import com.intellij.codeInspection.InspectionProfileEntry;
+import com.siyeh.ig.LightInspectionTestCase;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class LoggerInitializedWithForeignClassInspectionTest extends LightInspectionTestCase {
+
+ public void testLoggerInitializedWithForeignClass() {
+ doTest();
+ }
+
+ @Nullable
+ @Override
+ protected InspectionProfileEntry getInspection() {
+ final LoggerInitializedWithForeignClassInspection inspection = new LoggerInitializedWithForeignClassInspection();
+ inspection.loggerFactoryClassNames.add("java.util.logging.Logger");
+ inspection.loggerFactoryMethodNames.add("getLogger");
+ return inspection;
+ }
+
+ @Override
+ protected String[] getEnvironmentClasses() {
+ return new String[] {
+ "package java.util.logging;" +
+ "public class Logger {" +
+ " public static Logger getLogger(String name) {" +
+ " return null;" +
+ " }" +
+ "}"
+ };
+ }
+}
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/logging/PlaceholderCountMatchesArgumentCountInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/logging/PlaceholderCountMatchesArgumentCountInspectionTest.java
index 1bd7feadae45..48d120189740 100644
--- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/logging/PlaceholderCountMatchesArgumentCountInspectionTest.java
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/logging/PlaceholderCountMatchesArgumentCountInspectionTest.java
@@ -32,7 +32,7 @@ public class PlaceholderCountMatchesArgumentCountInspectionTest extends LightIns
"class X {\n" +
" void foo() {\n" +
" Logger logger = LoggerFactory.getLogger(X.class);\n" +
- " logger./*'info()' call has fewer arguments (1) than placeholders (2)*/info/**/(\"string {}{}\", 1);\n" +
+ " logger.info(/*Fewer arguments provided (1) than placeholders specified (2) in 'string {}{}'*/\"string {}{}\"/**/, 1);\n" +
" }\n" +
"}"
);
@@ -43,7 +43,7 @@ public class PlaceholderCountMatchesArgumentCountInspectionTest extends LightIns
"class X {\n" +
" void foo() {\n" +
" Logger logger = LoggerFactory.getLogger(X.class);\n" +
- " logger./*'info()' call has more arguments (1) than placeholders (0)*/info/**/(\"string\", 1);\n" +
+ " logger.info(/*More arguments provided (1) than placeholders specified (0) in 'string'*/\"string\"/**/, 1);\n" +
" }\n" +
"}"
);
@@ -107,4 +107,15 @@ public class PlaceholderCountMatchesArgumentCountInspectionTest extends LightIns
" }" +
"}");
}
+
+ public void testConstant() {
+ doTest("import org.slf4j.*;" +
+ "class X {" +
+ " Logger LOG = LoggerFactory.getLogger(X.class);" +
+ " private static final String message = \"HELLO {}\";" +
+ " void m() {" +
+ " LOG.info(/*Fewer arguments provided (0) than placeholders specified (1) in 'HELLO {}'*/message/**/);" +
+ " }" +
+ "}");
+ }
} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspectionTest.java
index 6c5a89009735..2e1b839c85d3 100644
--- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspectionTest.java
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspectionTest.java
@@ -1,11 +1,22 @@
package com.siyeh.ig.style;
+import com.intellij.psi.codeStyle.CodeStyleSettings;
+import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.siyeh.ig.IGInspectionTestCase;
public class UnnecessaryFullyQualifiedNameInspectionTest extends IGInspectionTestCase {
public void test() throws Exception {
- doTest("com/siyeh/igtest/style/unnecessary_fully_qualified_name",
- new UnnecessaryFullyQualifiedNameInspection());
+ final CodeStyleSettings styleSettings = CodeStyleSettingsManager.getSettings(getProject());
+
+ boolean inJavadoc = styleSettings.USE_FQ_CLASS_NAMES_IN_JAVADOC;
+ try {
+ styleSettings.USE_FQ_CLASS_NAMES_IN_JAVADOC = false;
+ doTest("com/siyeh/igtest/style/unnecessary_fully_qualified_name",
+ new UnnecessaryFullyQualifiedNameInspection());
+ }
+ finally {
+ styleSettings.USE_FQ_CLASS_NAMES_IN_JAVADOC = inJavadoc;
+ }
}
}
diff --git a/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/AdvancedSettingsUI.form b/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/AdvancedSettingsUI.form
index 9aba68ac9b46..b894b8ced19b 100644
--- a/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/AdvancedSettingsUI.form
+++ b/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/AdvancedSettingsUI.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.intellij.plugins.intelliLang.AdvancedSettingsUI">
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.intellij.plugins.intelliLang.AdvancedSettingsUI.AdvancedSettingsPanel">
<grid id="27dc6" binding="myRoot" layout-manager="GridLayoutManager" row-count="6" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="5" left="8" bottom="5" right="8"/>
<constraints>
diff --git a/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/AdvancedSettingsUI.java b/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/AdvancedSettingsUI.java
index e9083b065605..adb4b51057a8 100644
--- a/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/AdvancedSettingsUI.java
+++ b/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/AdvancedSettingsUI.java
@@ -44,166 +44,36 @@ import java.util.Arrays;
*/
public class AdvancedSettingsUI implements SearchableConfigurable {
private final Configuration.AdvancedConfiguration myConfiguration;
-
- @SuppressWarnings({"UnusedDeclaration", "FieldCanBeLocal"})
- private JPanel myRoot;
-
- private JRadioButton myNoInstrumentation;
- private JRadioButton myAssertInstrumentation;
- private JRadioButton myExceptionInstrumentation;
- private JPanel myLanguageAnnotationPanel;
- private JPanel myPatternAnnotationPanel;
- private JPanel mySubstAnnotationPanel;
- private JRadioButton myDfaOff;
- private JRadioButton myAnalyzeReferences;
- private JRadioButton myUseDfa;
- private JRadioButton myLookForAssignments;
- private JCheckBox myIncludeUncomputableOperandsAsCheckBox;
- private JCheckBox mySourceModificationAllowedCheckBox;
-
- private final ReferenceEditorWithBrowseButton myAnnotationField;
- private final ReferenceEditorWithBrowseButton myPatternField;
- private final ReferenceEditorWithBrowseButton mySubstField;
+ private AdvancedSettingsPanel myPanel;
+ private final Project myProject;
public AdvancedSettingsUI(@NotNull final Project project, Configuration configuration) {
+ myProject = project;
myConfiguration = configuration.getAdvancedConfiguration();
-
- myAnnotationField = new ReferenceEditorWithBrowseButton(null, project, new Function<String, Document>() {
- public Document fun(String s) {
- return PsiUtilEx.createDocument(s, project);
- }
- }, myConfiguration.getLanguageAnnotationClass());
- myAnnotationField.addActionListener(new BrowseClassListener(project, myAnnotationField));
- myAnnotationField.setEnabled(!project.isDefault());
- addField(myLanguageAnnotationPanel, myAnnotationField);
-
- myPatternField = new ReferenceEditorWithBrowseButton(null, project, new Function<String, Document>() {
- public Document fun(String s) {
- return PsiUtilEx.createDocument(s, project);
- }
- }, myConfiguration.getPatternAnnotationClass());
- myPatternField.addActionListener(new BrowseClassListener(project, myPatternField));
- myPatternField.setEnabled(!project.isDefault());
- addField(myPatternAnnotationPanel, myPatternField);
-
- mySubstField = new ReferenceEditorWithBrowseButton(null, project, new Function<String, Document>() {
- public Document fun(String s) {
- return PsiUtilEx.createDocument(s, project);
- }
- }, myConfiguration.getPatternAnnotationClass());
- mySubstField.addActionListener(new BrowseClassListener(project, mySubstField));
- mySubstField.setEnabled(!project.isDefault());
- addField(mySubstAnnotationPanel, mySubstField);
- }
- //
- /**
- * Adds textfield into placeholder panel and assigns a directly preceding label
- */
- private static void addField(JPanel panel, ReferenceEditorWithBrowseButton field) {
- panel.add(field, BorderLayout.CENTER);
-
- final Component[] components = panel.getParent().getComponents();
- final int index = Arrays.asList(components).indexOf(panel);
- if (index > 0) {
- final Component component = components[index - 1];
- if (component instanceof JLabel) {
- ((JLabel)component).setLabelFor(field);
- }
- }
}
public JComponent createComponent() {
- return myRoot;
- }
-
- @SuppressWarnings({"SimplifiableIfStatement"})
- public boolean isModified() {
- if (getInstrumentation() != myConfiguration.getInstrumentation()) {
- return true;
- }
- if (!myAnnotationField.getText().equals(myConfiguration.getLanguageAnnotationClass())) {
- return true;
- }
- if (!myPatternField.getText().equals(myConfiguration.getPatternAnnotationClass())) {
- return true;
- }
- if (!mySubstField.getText().equals(myConfiguration.getSubstAnnotationClass())) {
- return true;
- }
- if (!myConfiguration.getDfaOption().equals(getDfaOption())) {
- return true;
- }
- if (myConfiguration.isIncludeUncomputablesAsLiterals() != myIncludeUncomputableOperandsAsCheckBox.isSelected()) {
- return true;
- }
- if (myConfiguration.isSourceModificationAllowed() != mySourceModificationAllowedCheckBox.isSelected()) {
- return true;
- }
- return false;
- }
-
- @NotNull
- private Configuration.InstrumentationType getInstrumentation() {
- if (myNoInstrumentation.isSelected()) return Configuration.InstrumentationType.NONE;
- if (myAssertInstrumentation.isSelected()) return Configuration.InstrumentationType.ASSERT;
- if (myExceptionInstrumentation.isSelected()) return Configuration.InstrumentationType.EXCEPTION;
-
- assert false;
- return null;
+ myPanel = new AdvancedSettingsPanel();
+ return myPanel.myRoot;
}
+ @Override
public void apply() throws ConfigurationException {
- myConfiguration.setInstrumentationType(getInstrumentation());
- myConfiguration.setLanguageAnnotation(myAnnotationField.getText());
- myConfiguration.setPatternAnnotation(myPatternField.getText());
- myConfiguration.setSubstAnnotation(mySubstField.getText());
-
- myConfiguration.setDfaOption(getDfaOption());
- myConfiguration.setIncludeUncomputablesAsLiterals(myIncludeUncomputableOperandsAsCheckBox.isSelected());
- myConfiguration.setSourceModificationAllowed(mySourceModificationAllowedCheckBox.isSelected());
+ myPanel.apply();
}
- @NotNull
- private Configuration.DfaOption getDfaOption() {
- if (myDfaOff.isSelected()) return Configuration.DfaOption.OFF;
- if (myAnalyzeReferences.isSelected()) return Configuration.DfaOption.RESOLVE;
- if (myLookForAssignments.isSelected()) return Configuration.DfaOption.ASSIGNMENTS;
- if (myUseDfa.isSelected()) return Configuration.DfaOption.DFA;
- return Configuration.DfaOption.OFF;
+ @Override
+ public boolean isModified() {
+ return myPanel.isModified();
}
+ @Override
public void reset() {
- myAnnotationField.setText(myConfiguration.getLanguageAnnotationClass());
- myPatternField.setText(myConfiguration.getPatternAnnotationClass());
- mySubstField.setText(myConfiguration.getSubstAnnotationClass());
-
- myNoInstrumentation.setSelected(myConfiguration.getInstrumentation() == Configuration.InstrumentationType.NONE);
- myAssertInstrumentation.setSelected(myConfiguration.getInstrumentation() == Configuration.InstrumentationType.ASSERT);
- myExceptionInstrumentation.setSelected(myConfiguration.getInstrumentation() == Configuration.InstrumentationType.EXCEPTION);
-
- setDfaOption(myConfiguration.getDfaOption());
- myIncludeUncomputableOperandsAsCheckBox.setSelected(myConfiguration.isIncludeUncomputablesAsLiterals());
- mySourceModificationAllowedCheckBox.setSelected(myConfiguration.isSourceModificationAllowed());
- }
-
- private void setDfaOption(@NotNull final Configuration.DfaOption dfaOption) {
- switch (dfaOption) {
- case OFF:
- myDfaOff.setSelected(true);
- break;
- case RESOLVE:
- myAnalyzeReferences.setSelected(true);
- break;
- case ASSIGNMENTS:
- myLookForAssignments.setSelected(true);
- break;
- case DFA:
- myUseDfa.setSelected(true);
- break;
- }
+ myPanel.reset();
}
public void disposeUIResources() {
+ myPanel = null;
}
@Nls
@@ -255,4 +125,160 @@ public class AdvancedSettingsUI implements SearchableConfigurable {
}
}
}
+
+ public class AdvancedSettingsPanel {
+ @SuppressWarnings({"UnusedDeclaration", "FieldCanBeLocal"})
+ private JPanel myRoot;
+
+ private JRadioButton myNoInstrumentation;
+ private JRadioButton myAssertInstrumentation;
+ private JRadioButton myExceptionInstrumentation;
+ private JPanel myLanguageAnnotationPanel;
+ private JPanel myPatternAnnotationPanel;
+ private JPanel mySubstAnnotationPanel;
+ private JRadioButton myDfaOff;
+ private JRadioButton myAnalyzeReferences;
+ private JRadioButton myUseDfa;
+ private JRadioButton myLookForAssignments;
+ private JCheckBox myIncludeUncomputableOperandsAsCheckBox;
+ private JCheckBox mySourceModificationAllowedCheckBox;
+
+ private final ReferenceEditorWithBrowseButton myAnnotationField;
+ private final ReferenceEditorWithBrowseButton myPatternField;
+ private final ReferenceEditorWithBrowseButton mySubstField;
+
+ public AdvancedSettingsPanel() {
+ myAnnotationField = new ReferenceEditorWithBrowseButton(null, myProject, new Function<String, Document>() {
+ public Document fun(String s) {
+ return PsiUtilEx.createDocument(s, myProject);
+ }
+ }, myConfiguration.getLanguageAnnotationClass());
+ myAnnotationField.addActionListener(new BrowseClassListener(myProject, myAnnotationField));
+ myAnnotationField.setEnabled(!myProject.isDefault());
+ addField(myLanguageAnnotationPanel, myAnnotationField);
+
+ myPatternField = new ReferenceEditorWithBrowseButton(null, myProject, new Function<String, Document>() {
+ public Document fun(String s) {
+ return PsiUtilEx.createDocument(s, myProject);
+ }
+ }, myConfiguration.getPatternAnnotationClass());
+ myPatternField.addActionListener(new BrowseClassListener(myProject, myPatternField));
+ myPatternField.setEnabled(!myProject.isDefault());
+ addField(myPatternAnnotationPanel, myPatternField);
+
+ mySubstField = new ReferenceEditorWithBrowseButton(null, myProject, new Function<String, Document>() {
+ public Document fun(String s) {
+ return PsiUtilEx.createDocument(s, myProject);
+ }
+ }, myConfiguration.getPatternAnnotationClass());
+ mySubstField.addActionListener(new BrowseClassListener(myProject, mySubstField));
+ mySubstField.setEnabled(!myProject.isDefault());
+ addField(mySubstAnnotationPanel, mySubstField);
+ }
+ //
+
+ /**
+ * Adds textfield into placeholder panel and assigns a directly preceding label
+ */
+ private void addField(JPanel panel, ReferenceEditorWithBrowseButton field) {
+ panel.add(field, BorderLayout.CENTER);
+
+ final Component[] components = panel.getParent().getComponents();
+ final int index = Arrays.asList(components).indexOf(panel);
+ if (index > 0) {
+ final Component component = components[index - 1];
+ if (component instanceof JLabel) {
+ ((JLabel)component).setLabelFor(field);
+ }
+ }
+ }
+
+
+ @SuppressWarnings({"SimplifiableIfStatement"})
+ public boolean isModified() {
+ if (getInstrumentation() != myConfiguration.getInstrumentation()) {
+ return true;
+ }
+ if (!myAnnotationField.getText().equals(myConfiguration.getLanguageAnnotationClass())) {
+ return true;
+ }
+ if (!myPatternField.getText().equals(myConfiguration.getPatternAnnotationClass())) {
+ return true;
+ }
+ if (!mySubstField.getText().equals(myConfiguration.getSubstAnnotationClass())) {
+ return true;
+ }
+ if (!myConfiguration.getDfaOption().equals(getDfaOption())) {
+ return true;
+ }
+ if (myConfiguration.isIncludeUncomputablesAsLiterals() != myIncludeUncomputableOperandsAsCheckBox.isSelected()) {
+ return true;
+ }
+ if (myConfiguration.isSourceModificationAllowed() != mySourceModificationAllowedCheckBox.isSelected()) {
+ return true;
+ }
+ return false;
+ }
+
+ @NotNull
+ private Configuration.InstrumentationType getInstrumentation() {
+ if (myNoInstrumentation.isSelected()) return Configuration.InstrumentationType.NONE;
+ if (myAssertInstrumentation.isSelected()) return Configuration.InstrumentationType.ASSERT;
+ if (myExceptionInstrumentation.isSelected()) return Configuration.InstrumentationType.EXCEPTION;
+
+ assert false;
+ return null;
+ }
+
+ public void apply() throws ConfigurationException {
+ myConfiguration.setInstrumentationType(getInstrumentation());
+ myConfiguration.setLanguageAnnotation(myAnnotationField.getText());
+ myConfiguration.setPatternAnnotation(myPatternField.getText());
+ myConfiguration.setSubstAnnotation(mySubstField.getText());
+
+ myConfiguration.setDfaOption(getDfaOption());
+ myConfiguration.setIncludeUncomputablesAsLiterals(myIncludeUncomputableOperandsAsCheckBox.isSelected());
+ myConfiguration.setSourceModificationAllowed(mySourceModificationAllowedCheckBox.isSelected());
+ }
+
+ @NotNull
+ private Configuration.DfaOption getDfaOption() {
+ if (myDfaOff.isSelected()) return Configuration.DfaOption.OFF;
+ if (myAnalyzeReferences.isSelected()) return Configuration.DfaOption.RESOLVE;
+ if (myLookForAssignments.isSelected()) return Configuration.DfaOption.ASSIGNMENTS;
+ if (myUseDfa.isSelected()) return Configuration.DfaOption.DFA;
+ return Configuration.DfaOption.OFF;
+ }
+
+ public void reset() {
+ myAnnotationField.setText(myConfiguration.getLanguageAnnotationClass());
+ myPatternField.setText(myConfiguration.getPatternAnnotationClass());
+ mySubstField.setText(myConfiguration.getSubstAnnotationClass());
+
+ myNoInstrumentation.setSelected(myConfiguration.getInstrumentation() == Configuration.InstrumentationType.NONE);
+ myAssertInstrumentation.setSelected(myConfiguration.getInstrumentation() == Configuration.InstrumentationType.ASSERT);
+ myExceptionInstrumentation.setSelected(myConfiguration.getInstrumentation() == Configuration.InstrumentationType.EXCEPTION);
+
+ setDfaOption(myConfiguration.getDfaOption());
+ myIncludeUncomputableOperandsAsCheckBox.setSelected(myConfiguration.isIncludeUncomputablesAsLiterals());
+ mySourceModificationAllowedCheckBox.setSelected(myConfiguration.isSourceModificationAllowed());
+ }
+
+ private void setDfaOption(@NotNull final Configuration.DfaOption dfaOption) {
+ switch (dfaOption) {
+ case OFF:
+ myDfaOff.setSelected(true);
+ break;
+ case RESOLVE:
+ myAnalyzeReferences.setSelected(true);
+ break;
+ case ASSIGNMENTS:
+ myLookForAssignments.setSelected(true);
+ break;
+ case DFA:
+ myUseDfa.setSelected(true);
+ break;
+ }
+ }
+ }
}
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/fqnames/FullyQualifiedNamePredicate.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/fqnames/FullyQualifiedNamePredicate.java
index 5342b62db4b9..b09afbb3d776 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/fqnames/FullyQualifiedNamePredicate.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/fqnames/FullyQualifiedNamePredicate.java
@@ -21,6 +21,7 @@ import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.util.PsiTreeUtil;
import com.siyeh.ig.psiutils.ImportUtils;
+import com.siyeh.ig.style.UnnecessaryFullyQualifiedNameInspection;
import com.siyeh.ipp.base.PsiElementPredicate;
class FullyQualifiedNamePredicate implements PsiElementPredicate {
@@ -40,6 +41,11 @@ class FullyQualifiedNamePredicate implements PsiElementPredicate {
if (PsiTreeUtil.getParentOfType(element, PsiImportStatementBase.class, PsiPackageStatement.class, JavaCodeFragment.class) != null) {
return false;
}
+ final Project project = element.getProject();
+ final CodeStyleSettings codeStyleSettings = CodeStyleSettingsManager.getSettings(project);
+ if (UnnecessaryFullyQualifiedNameInspection.acceptFullyQualifiedNamesInJavadoc(referenceElement, codeStyleSettings)) {
+ return false;
+ }
final PsiElement qualifier = referenceElement.getQualifier();
if (!(qualifier instanceof PsiJavaCodeReferenceElement)) {
return false;
@@ -50,8 +56,6 @@ class FullyQualifiedNamePredicate implements PsiElementPredicate {
if (!(resolved instanceof PsiClass)) {
return false;
}
- final Project project = element.getProject();
- final CodeStyleSettings codeStyleSettings = CodeStyleSettingsManager.getSettings(project);
if (!codeStyleSettings.INSERT_INNER_CLASS_IMPORTS) {
return false;
}
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/initialization/SplitDeclarationAndInitializationIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/initialization/SplitDeclarationAndInitializationIntention.java
index 33778f99d931..3bbc7a63bd65 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/initialization/SplitDeclarationAndInitializationIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/initialization/SplitDeclarationAndInitializationIntention.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2011 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.
@@ -18,7 +18,7 @@ package com.siyeh.ipp.initialization;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
-import com.intellij.util.IncorrectOperationException;
+import com.intellij.refactoring.util.RefactoringUtil;
import com.siyeh.IntentionPowerPackBundle;
import com.siyeh.ipp.base.Intention;
import com.siyeh.ipp.base.PsiElementPredicate;
@@ -35,28 +35,14 @@ public class SplitDeclarationAndInitializationIntention extends Intention {
}
@Override
- public void processIntention(@NotNull PsiElement element)
- throws IncorrectOperationException {
+ public void processIntention(@NotNull PsiElement element) {
final PsiField field = (PsiField)element.getParent();
field.normalizeDeclaration();
- final PsiExpression initializer = field.getInitializer();
+ final PsiExpression initializer = RefactoringUtil.convertInitializerToNormalExpression(field.getInitializer(), field.getType());
if (initializer == null) {
return;
}
- final String initializerText;
- if (initializer instanceof PsiArrayInitializerExpression) {
- final PsiType type = initializer.getType();
- if (type == null) {
- initializerText = initializer.getText();
- }
- else {
- initializerText = "new " + type.getCanonicalText() +
- initializer.getText();
- }
- }
- else {
- initializerText = initializer.getText();
- }
+ final String initializerText = initializer.getText();
final PsiClass containingClass = field.getContainingClass();
if (containingClass == null) {
return;
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/initialization/ArrayInitializer.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/initialization/ArrayInitializer.java
new file mode 100644
index 000000000000..54eaa025b8e8
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/initialization/ArrayInitializer.java
@@ -0,0 +1,3 @@
+class X {
+ String s <caret>= {};
+} \ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/initialization/ArrayInitializer_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/initialization/ArrayInitializer_after.java
new file mode 100644
index 000000000000..08ebd41e6f93
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/initialization/ArrayInitializer_after.java
@@ -0,0 +1,7 @@
+class X {
+ String s;
+
+ {
+ s = {};
+ }
+} \ No newline at end of file
diff --git a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/initialization/SplitDeclarationAndInitializationIntentionTest.java b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/initialization/SplitDeclarationAndInitializationIntentionTest.java
new file mode 100644
index 000000000000..63ac3c9acf9f
--- /dev/null
+++ b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/initialization/SplitDeclarationAndInitializationIntentionTest.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.siyeh.ipp.initialization;
+
+import com.siyeh.IntentionPowerPackBundle;
+import com.siyeh.ipp.IPPTestCase;
+
+/**
+ * @see com.siyeh.ipp.initialization.SplitDeclarationAndInitializationIntention
+ * @author Bas Leijdekkers
+ */
+public class SplitDeclarationAndInitializationIntentionTest extends IPPTestCase {
+
+ public void testArrayInitializer() { doTest(); }
+
+ @Override
+ protected String getRelativePath() {
+ return "initialization";
+ }
+
+ @Override
+ protected String getIntentionName() {
+ return IntentionPowerPackBundle.message("split.declaration.and.initialization.intention.name");
+ }
+}
diff --git a/plugins/ant/src/com/intellij/lang/ant/config/impl/AntToolWindowFactory.java b/plugins/ant/src/com/intellij/lang/ant/config/impl/AntToolWindowFactory.java
index 4aa217f789bc..02d8f0696e7f 100644
--- a/plugins/ant/src/com/intellij/lang/ant/config/impl/AntToolWindowFactory.java
+++ b/plugins/ant/src/com/intellij/lang/ant/config/impl/AntToolWindowFactory.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.
@@ -22,13 +22,14 @@ import com.intellij.openapi.wm.ToolWindow;
import com.intellij.openapi.wm.ToolWindowFactory;
import com.intellij.ui.content.Content;
import com.intellij.ui.content.ContentManager;
+import org.jetbrains.annotations.NotNull;
/**
* @author yole
*/
public class AntToolWindowFactory implements ToolWindowFactory {
@Override
- public void createToolWindowContent(Project project, ToolWindow toolWindow) {
+ public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindow toolWindow) {
AntExplorer explorer = new AntExplorer(project);
final ContentManager contentManager = toolWindow.getContentManager();
final Content content = contentManager.getFactory().createContent(explorer, null, false);
diff --git a/plugins/ant/src/com/intellij/lang/ant/dom/AntDomProperty.java b/plugins/ant/src/com/intellij/lang/ant/dom/AntDomProperty.java
index 2ef2ddb9737b..3e60d22711d2 100644
--- a/plugins/ant/src/com/intellij/lang/ant/dom/AntDomProperty.java
+++ b/plugins/ant/src/com/intellij/lang/ant/dom/AntDomProperty.java
@@ -16,11 +16,13 @@
package com.intellij.lang.ant.dom;
import com.intellij.lang.properties.IProperty;
+import com.intellij.lang.properties.PropertiesImplUtil;
import com.intellij.lang.properties.psi.PropertiesFile;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.pom.references.PomService;
import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiFileSystemItem;
import com.intellij.util.PathUtil;
import com.intellij.util.containers.HashMap;
@@ -131,8 +133,9 @@ public abstract class AntDomProperty extends AntDomClasspathComponent implements
}
_propertyName = propertyName.substring(prefix.length());
}
- if (psiFile instanceof PropertiesFile) {
- final IProperty property = ((PropertiesFile)psiFile).findPropertyByKey(_propertyName);
+ final PropertiesFile pf = toPropertiesFile(psiFile);
+ if (pf != null) {
+ final IProperty property = pf.findPropertyByKey(_propertyName);
return property != null? property.getPsiElement() : null;
}
}
@@ -185,9 +188,10 @@ public abstract class AntDomProperty extends AntDomClasspathComponent implements
else { // name attrib is not specified
final PsiFileSystemItem psiFile = getFile().getValue();
if (psiFile != null) {
- if (psiFile instanceof PropertiesFile) {
+ final PropertiesFile file = toPropertiesFile(psiFile);
+ if (file != null) {
result = new HashMap<String, String>();
- for (final IProperty property : ((PropertiesFile)psiFile).getProperties()) {
+ for (final IProperty property : file.getProperties()) {
result.put(property.getUnescapedKey(), property.getUnescapedValue());
}
}
@@ -212,6 +216,7 @@ public abstract class AntDomProperty extends AntDomClasspathComponent implements
final InputStream stream = loader.getResourceAsStream(resource);
if (stream != null) {
try {
+ // todo: Remote file can be XmlPropertiesFile
final PropertiesFile propFile = (PropertiesFile)CustomAntElementsRegistry.loadContentAsFile(getXmlTag().getProject(), stream, StdFileTypes.PROPERTIES);
result = new HashMap<String, String>();
for (final IProperty property : propFile.getProperties()) {
@@ -255,4 +260,17 @@ public abstract class AntDomProperty extends AntDomClasspathComponent implements
return loader;
}
+ @Nullable
+ public PropertiesFile getPropertiesFile() {
+ return toPropertiesFile(getFile().getValue());
+ }
+
+ @Nullable
+ private static PropertiesFile toPropertiesFile(@Nullable final PsiFileSystemItem item) {
+ if (item instanceof PropertiesFile) {
+ return (PropertiesFile)item;
+ }
+ // Sometimes XmlPropertiesFile is just XmlFile, sao we should ask PropertiesImplUtil about that.
+ return item instanceof PsiFile? PropertiesImplUtil.getPropertiesFile(((PsiFile)item)) : null;
+ }
}
diff --git a/plugins/ant/src/com/intellij/lang/ant/dom/AntResolveInspection.java b/plugins/ant/src/com/intellij/lang/ant/dom/AntResolveInspection.java
index b17f29ae11ac..838d69af8027 100644
--- a/plugins/ant/src/com/intellij/lang/ant/dom/AntResolveInspection.java
+++ b/plugins/ant/src/com/intellij/lang/ant/dom/AntResolveInspection.java
@@ -25,7 +25,6 @@ import com.intellij.lang.ant.quickfix.AntCreateTargetFix;
import com.intellij.lang.ant.validation.AntInspection;
import com.intellij.lang.properties.psi.PropertiesFile;
import com.intellij.psi.PsiFile;
-import com.intellij.psi.PsiFileSystemItem;
import com.intellij.psi.PsiPolyVariantReference;
import com.intellij.psi.PsiReference;
import com.intellij.psi.xml.XmlElement;
@@ -175,9 +174,9 @@ public class AntResolveInspection extends AntInspection {
}
if (child instanceof AntDomProperty) {
final AntDomProperty property = (AntDomProperty)child;
- final PsiFileSystemItem file = property.getFile().getValue();
- if (file instanceof PropertiesFile) {
- files.add((PropertiesFile)file);
+ final PropertiesFile file = property.getPropertiesFile();
+ if (file != null) {
+ files.add(file);
}
}
}
diff --git a/plugins/ant/src/com/intellij/lang/ant/validation/AntMissingPropertiesFileInspection.java b/plugins/ant/src/com/intellij/lang/ant/validation/AntMissingPropertiesFileInspection.java
index b434b1bfc4d4..4e7ac458d6cb 100644
--- a/plugins/ant/src/com/intellij/lang/ant/validation/AntMissingPropertiesFileInspection.java
+++ b/plugins/ant/src/com/intellij/lang/ant/validation/AntMissingPropertiesFileInspection.java
@@ -18,8 +18,11 @@ package com.intellij.lang.ant.validation;
import com.intellij.lang.ant.AntBundle;
import com.intellij.lang.ant.dom.AntDomProperty;
import com.intellij.lang.properties.psi.PropertiesFile;
+import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiFileSystemItem;
+import com.intellij.psi.xml.XmlFile;
import com.intellij.util.xml.DomElement;
+import com.intellij.util.xml.GenericAttributeValue;
import com.intellij.util.xml.highlighting.DomElementAnnotationHolder;
import com.intellij.util.xml.highlighting.DomHighlightingHelper;
import org.jetbrains.annotations.Nls;
@@ -45,11 +48,21 @@ public class AntMissingPropertiesFileInspection extends AntInspection {
protected void checkDomElement(DomElement element, DomElementAnnotationHolder holder, DomHighlightingHelper helper) {
if (element instanceof AntDomProperty) {
final AntDomProperty property = (AntDomProperty)element;
- final String fileName = property.getFile().getStringValue();
+ final GenericAttributeValue<PsiFileSystemItem> fileValue = property.getFile();
+ final String fileName = fileValue.getStringValue();
if (fileName != null) {
- final PsiFileSystemItem file = property.getFile().getValue();
- if (!(file instanceof PropertiesFile)) {
- holder.createProblem(property.getFile(), AntBundle.message("file.doesnt.exist", fileName));
+ final PropertiesFile propertiesFile = property.getPropertiesFile();
+ if (propertiesFile == null) {
+ final PsiFileSystemItem file = fileValue.getValue();
+ if (file instanceof XmlFile) {
+ holder.createProblem(fileValue, AntBundle.message("file.type.xml.not.supported", fileName));
+ }
+ else if (file instanceof PsiFile) {
+ holder.createProblem(fileValue, AntBundle.message("file.type.not.supported", fileName));
+ }
+ else {
+ holder.createProblem(fileValue, AntBundle.message("file.doesnt.exist", fileName));
+ }
}
}
}
diff --git a/plugins/commander/src/com/intellij/ide/commander/CommanderToolWindowFactory.java b/plugins/commander/src/com/intellij/ide/commander/CommanderToolWindowFactory.java
index 1449ed0d32f1..11c3e596bc4d 100644
--- a/plugins/commander/src/com/intellij/ide/commander/CommanderToolWindowFactory.java
+++ b/plugins/commander/src/com/intellij/ide/commander/CommanderToolWindowFactory.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,12 +19,13 @@ import com.intellij.openapi.wm.ToolWindowFactory;
import com.intellij.openapi.wm.ToolWindow;
import com.intellij.openapi.project.Project;
import com.intellij.ui.content.ContentFactory;
+import org.jetbrains.annotations.NotNull;
/**
* @author yole
*/
public class CommanderToolWindowFactory implements ToolWindowFactory {
- public void createToolWindowContent(Project project, ToolWindow toolWindow) {
+ public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindow toolWindow) {
Commander commander = Commander.getInstance(project);
toolWindow.getContentManager().addContent(ContentFactory.SERVICE.getInstance().createContent(commander, "", false));
}
diff --git a/plugins/editorconfig/LICENSE.txt b/plugins/editorconfig/LICENSE.txt
new file mode 100644
index 000000000000..fff944099438
--- /dev/null
+++ b/plugins/editorconfig/LICENSE.txt
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2013 Kevin Bell
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE. \ No newline at end of file
diff --git a/plugins/editorconfig/editorconfig.iml b/plugins/editorconfig/editorconfig.iml
new file mode 100644
index 000000000000..8d67b1cc8c76
--- /dev/null
+++ b/plugins/editorconfig/editorconfig.iml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module relativePaths="true" type="JAVA_MODULE" version="4">
+ <component name="DevKit.ModuleBuildProperties" url="file://$MODULE_DIR$/META-INF/plugin.xml" />
+ <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-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/lib/editorconfig-core-java.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES>
+ <root url="jar://$MODULE_DIR$/lib/editorconfig-core-java.jar!/" />
+ </SOURCES>
+ </library>
+ </orderEntry>
+ <orderEntry type="module" module-name="core-api" />
+ <orderEntry type="module" module-name="platform-api" />
+ <orderEntry type="module" module-name="platform-impl" />
+ <orderEntry type="module" module-name="lang-api" />
+ </component>
+</module>
+
diff --git a/plugins/editorconfig/lib/editorconfig-core-java.jar b/plugins/editorconfig/lib/editorconfig-core-java.jar
new file mode 100644
index 000000000000..f115b7480336
--- /dev/null
+++ b/plugins/editorconfig/lib/editorconfig-core-java.jar
Binary files differ
diff --git a/plugins/editorconfig/src/META-INF/plugin.xml b/plugins/editorconfig/src/META-INF/plugin.xml
new file mode 100644
index 000000000000..2be8eb4f5473
--- /dev/null
+++ b/plugins/editorconfig/src/META-INF/plugin.xml
@@ -0,0 +1,30 @@
+<idea-plugin version="2">
+ <id>org.editorconfig.editorconfigjetbrains</id>
+ <name>EditorConfig</name>
+ <version>1.0</version>
+ <vendor url="http://editorconfig.org">Kevin Bell, JetBrains</vendor>
+
+ <description><![CDATA[
+ A JetBrains IDE plugin supporting the EditorConfig standard
+ ]]></description>
+
+ <idea-version since-build="138.1293"/>
+
+ <depends>com.intellij.modules.lang</depends>
+
+ <application-components>
+ <component>
+ <implementation-class>org.editorconfig.plugincomponents.SettingsProviderComponent</implementation-class>
+ </component>
+ </application-components>
+
+ <project-components>
+ <component>
+ <implementation-class>org.editorconfig.plugincomponents.ConfigProjectComponent</implementation-class>
+ </component>
+ </project-components>
+
+ <extensions defaultExtensionNs="com.intellij">
+ <errorHandler implementation="com.intellij.diagnostic.ITNReporter"/>
+ </extensions>
+</idea-plugin> \ No newline at end of file
diff --git a/plugins/editorconfig/src/org/editorconfig/Utils.java b/plugins/editorconfig/src/org/editorconfig/Utils.java
new file mode 100644
index 000000000000..f64d7be34d85
--- /dev/null
+++ b/plugins/editorconfig/src/org/editorconfig/Utils.java
@@ -0,0 +1,24 @@
+package org.editorconfig;
+
+import org.editorconfig.core.EditorConfig.OutPair;
+
+import java.util.List;
+
+public class Utils {
+ public static String configValueForKey(List<OutPair> outPairs, String key) {
+ for (OutPair outPair : outPairs) {
+ if (outPair.getKey().equals(key)) {
+ return outPair.getVal();
+ }
+ }
+ return "";
+ }
+
+ public static String invalidConfigMessage(String configValue, String configKey, String filePath) {
+ return "\"" + configValue + "\" is not a valid value for " + configKey + " for file " + filePath;
+ }
+
+ public static String appliedConfigMessage(String configValue, String configKey, String filePath) {
+ return "Applied \"" + configValue + "\" as " + configKey + " for file " + filePath;
+ }
+}
diff --git a/plugins/editorconfig/src/org/editorconfig/configmanagement/CodeStyleManager.java b/plugins/editorconfig/src/org/editorconfig/configmanagement/CodeStyleManager.java
new file mode 100644
index 000000000000..406e38456976
--- /dev/null
+++ b/plugins/editorconfig/src/org/editorconfig/configmanagement/CodeStyleManager.java
@@ -0,0 +1,184 @@
+package org.editorconfig.configmanagement;
+
+import com.intellij.lang.Language;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.ex.EditorEx;
+import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.fileEditor.FileEditorManager;
+import com.intellij.openapi.fileEditor.FileEditorManagerAdapter;
+import com.intellij.openapi.fileEditor.FileEditorManagerEvent;
+import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.openapi.fileTypes.LanguageFileType;
+import com.intellij.openapi.fileTypes.PlainTextLanguage;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.codeStyle.CodeStyleSettings;
+import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
+import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
+import org.editorconfig.Utils;
+import org.editorconfig.core.EditorConfig.OutPair;
+import org.editorconfig.plugincomponents.SettingsProviderComponent;
+import org.jetbrains.annotations.NotNull;
+
+import java.awt.event.WindowEvent;
+import java.awt.event.WindowFocusListener;
+import java.util.List;
+
+public class CodeStyleManager extends FileEditorManagerAdapter implements WindowFocusListener {
+ // Handles the following EditorConfig settings:
+ private static final String indentSizeKey = "indent_size";
+ private static final String tabWidthKey = "tab_width";
+ private static final String indentStyleKey = "indent_style";
+
+ private static final Logger LOG = Logger.getInstance("#org.editorconfig.configmanagement.CodeStyleManager");
+ private final CodeStyleSettingsManager codeStyleSettingsManager;
+ private final Project project;
+
+ public CodeStyleManager(Project project) {
+ codeStyleSettingsManager = CodeStyleSettingsManager.getInstance(project);
+ this.project = project;
+ }
+
+ @Override
+ public void fileOpened(@NotNull FileEditorManager source, @NotNull VirtualFile file) {
+ applySettings(file);
+ }
+
+ @Override
+ public void selectionChanged(@NotNull FileEditorManagerEvent event) {
+ final VirtualFile file = event.getNewFile();
+ applySettings(file);
+ }
+
+ @Override
+ public void windowGainedFocus(WindowEvent e) {
+ final Editor currentEditor = FileEditorManager.getInstance(project).getSelectedTextEditor();
+ if (currentEditor != null) {
+ final Document currentDocument = currentEditor.getDocument();
+ final VirtualFile currentFile = FileDocumentManager.getInstance().getFile(currentDocument);
+ applySettings(currentFile);
+ }
+ }
+
+ @Override
+ public void windowLostFocus(WindowEvent e) {
+ }
+
+ private void applySettings(final VirtualFile file) {
+ if (file != null && file.isInLocalFileSystem()) {
+ // Always drop any current temporary settings so that the defaults will be applied if
+ // this is a non-editorconfig-managed file
+ codeStyleSettingsManager.dropTemporarySettings();
+ // Prepare a new settings object, which will maintain the standard settings if no
+ // editorconfig settings apply
+ final CodeStyleSettings currentSettings = codeStyleSettingsManager.getCurrentSettings();
+ final CodeStyleSettings newSettings = new CodeStyleSettings();
+ newSettings.copyFrom(currentSettings);
+ // Get editorconfig settings
+ final String filePath = file.getCanonicalPath();
+ final SettingsProviderComponent settingsProvider = SettingsProviderComponent.getInstance();
+ final List<OutPair> outPairs = settingsProvider.getOutPairs(filePath);
+ // Apply editorconfig settings for the current editor
+ applyCodeStyleSettings(outPairs, newSettings, file);
+ codeStyleSettingsManager.setTemporarySettings(newSettings);
+ final EditorEx currentEditor = (EditorEx)FileEditorManager.getInstance(project).getSelectedTextEditor();
+ if (currentEditor != null) {
+ currentEditor.reinitSettings();
+ }
+ }
+ }
+
+ private static void applyCodeStyleSettings(final List<OutPair> outPairs, final CodeStyleSettings codeStyleSettings,
+ final VirtualFile file) {
+ // Apply indent options
+ final String indentSize = Utils.configValueForKey(outPairs, indentSizeKey);
+ final String tabWidth = Utils.configValueForKey(outPairs, tabWidthKey);
+ final String indentStyle = Utils.configValueForKey(outPairs, indentStyleKey);
+ final FileType fileType = file.getFileType();
+ final Language language = fileType instanceof LanguageFileType ? ((LanguageFileType)fileType).getLanguage() :
+ PlainTextLanguage.INSTANCE;
+ final CommonCodeStyleSettings commonSettings = codeStyleSettings.getCommonSettings(language);
+ final CommonCodeStyleSettings.IndentOptions indentOptions = commonSettings.getIndentOptions();
+ applyIndentOptions(indentOptions, indentSize, tabWidth, indentStyle, file.getCanonicalPath());
+ }
+
+ private static void applyIndentOptions(CommonCodeStyleSettings.IndentOptions indentOptions,
+ String indentSize, String tabWidth, String indentStyle, String filePath) {
+ final String calculatedIndentSize = calculateIndentSize(tabWidth, indentSize);
+ final String calculatedTabWidth = calculateTabWidth(tabWidth, indentSize);
+ if (!calculatedIndentSize.isEmpty()) {
+ if (applyIndentSize(indentOptions, calculatedIndentSize)) {
+ LOG.debug(Utils.appliedConfigMessage(calculatedIndentSize, indentSizeKey, filePath));
+ }
+ else {
+ LOG.warn(Utils.invalidConfigMessage(calculatedIndentSize, indentSizeKey, filePath));
+ }
+ }
+ if (!calculatedTabWidth.isEmpty()) {
+ if (applyTabWidth(indentOptions, calculatedTabWidth)) {
+ LOG.debug(Utils.appliedConfigMessage(calculatedTabWidth, tabWidthKey, filePath));
+ }
+ else {
+ LOG.warn(Utils.invalidConfigMessage(calculatedTabWidth, tabWidthKey, filePath));
+ }
+ }
+ if (!indentStyle.isEmpty()) {
+ if (applyIndentStyle(indentOptions, indentStyle)) {
+ LOG.debug(Utils.appliedConfigMessage(indentStyle, indentStyleKey, filePath));
+ }
+ else {
+ LOG.warn(Utils.invalidConfigMessage(indentStyle, indentStyleKey, filePath));
+ }
+ }
+ }
+
+ private static String calculateIndentSize(final String tabWidth, final String indentSize) {
+ return indentSize.equals("tab") ? tabWidth : indentSize;
+ }
+
+ private static String calculateTabWidth(final String tabWidth, final String indentSize) {
+ if (tabWidth.isEmpty() && indentSize.equals("tab")) {
+ return "";
+ }
+ else if (tabWidth.isEmpty()) {
+ return indentSize;
+ }
+ else {
+ return tabWidth;
+ }
+ }
+
+ private static boolean applyIndentSize(final CommonCodeStyleSettings.IndentOptions indentOptions, final String indentSize) {
+ try {
+ int indent = Integer.parseInt(indentSize);
+ indentOptions.INDENT_SIZE = indent;
+ indentOptions.CONTINUATION_INDENT_SIZE = indent;
+ return true;
+ }
+ catch (NumberFormatException e) {
+ return false;
+ }
+ }
+
+ private static boolean applyTabWidth(final CommonCodeStyleSettings.IndentOptions indentOptions, final String tabWidth) {
+ try {
+ indentOptions.TAB_SIZE = Integer.parseInt(tabWidth);
+ return true;
+ }
+ catch (NumberFormatException e) {
+ return false;
+ }
+ }
+
+ private static boolean applyIndentStyle(CommonCodeStyleSettings.IndentOptions indentOptions, String indentStyle) {
+ if (indentStyle.equals("tab") || indentStyle.equals("space")) {
+ indentOptions.USE_TAB_CHARACTER = indentStyle.equals("tab");
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+}
diff --git a/plugins/editorconfig/src/org/editorconfig/configmanagement/EditorSettingsManager.java b/plugins/editorconfig/src/org/editorconfig/configmanagement/EditorSettingsManager.java
new file mode 100644
index 000000000000..0a062d4d6e04
--- /dev/null
+++ b/plugins/editorconfig/src/org/editorconfig/configmanagement/EditorSettingsManager.java
@@ -0,0 +1,85 @@
+package org.editorconfig.configmanagement;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.ex.EditorSettingsExternalizable;
+import com.intellij.openapi.editor.impl.TrailingSpacesStripper;
+import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.fileEditor.FileDocumentManagerAdapter;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.vfs.VirtualFile;
+import org.editorconfig.Utils;
+import org.editorconfig.core.EditorConfig;
+import org.editorconfig.plugincomponents.SettingsProviderComponent;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class EditorSettingsManager extends FileDocumentManagerAdapter {
+ // Handles the following EditorConfig settings:
+ private static final String trimTrailingWhitespaceKey = "trim_trailing_whitespace";
+ private static final String insertFinalNewlineKey = "insert_final_newline";
+ private static final Map<String, String> trimMap;
+
+ static {
+ Map<String, String> map = new HashMap<String, String>();
+ map.put("true", EditorSettingsExternalizable.STRIP_TRAILING_SPACES_WHOLE);
+ map.put("false", EditorSettingsExternalizable.STRIP_TRAILING_SPACES_NONE);
+ trimMap = Collections.unmodifiableMap(map);
+ }
+
+ private static final Map<String, Boolean> newlineMap;
+
+ static {
+ Map<String, Boolean> map = new HashMap<String, Boolean>();
+ map.put("true", Boolean.TRUE);
+ map.put("false", Boolean.FALSE);
+ newlineMap = Collections.unmodifiableMap(map);
+ }
+
+ private static final Logger LOG = Logger.getInstance("#org.editorconfig.configmanagement.EditorSettingsManager");
+
+ @Override
+ public void beforeDocumentSaving(@NotNull Document document) {
+ // This is fired when any document is saved, regardless of whether it is part of a save-all or
+ // a save-one operation
+ final VirtualFile file = FileDocumentManager.getInstance().getFile(document);
+ applySettings(file);
+ }
+
+ private static void applySettings(VirtualFile file) {
+ if (file == null || !file.isInLocalFileSystem()) return;
+ // Get editorconfig settings
+ final String filePath = file.getCanonicalPath();
+ final SettingsProviderComponent settingsProvider = SettingsProviderComponent.getInstance();
+ final List<EditorConfig.OutPair> outPairs = settingsProvider.getOutPairs(filePath);
+ // Apply trailing spaces setting
+ final String trimTrailingWhitespace = Utils.configValueForKey(outPairs, trimTrailingWhitespaceKey);
+ applyConfigValueToUserData(file, TrailingSpacesStripper.OVERRIDE_STRIP_TRAILING_SPACES_KEY,
+ trimTrailingWhitespaceKey, trimTrailingWhitespace, trimMap);
+ // Apply final newline setting
+ final String insertFinalNewline = Utils.configValueForKey(outPairs, insertFinalNewlineKey);
+ applyConfigValueToUserData(file, TrailingSpacesStripper.OVERRIDE_ENSURE_NEWLINE_KEY,
+ insertFinalNewlineKey, insertFinalNewline, newlineMap);
+ }
+
+ private static <T> void applyConfigValueToUserData(VirtualFile file, Key<T> userDataKey, String editorConfigKey,
+ String configValue, Map<String, T> configMap) {
+ if (configValue.isEmpty()) {
+ file.putUserData(userDataKey, null);
+ }
+ else {
+ final T data = configMap.get(configValue);
+ if (data == null) {
+ LOG.warn(Utils.invalidConfigMessage(configValue, editorConfigKey, file.getCanonicalPath()));
+ }
+ else {
+ file.putUserData(userDataKey, data);
+ LOG.debug("Applied " + editorConfigKey + " settings for: " + file.getCanonicalPath());
+ }
+ }
+ }
+}
diff --git a/plugins/editorconfig/src/org/editorconfig/configmanagement/EncodingManager.java b/plugins/editorconfig/src/org/editorconfig/configmanagement/EncodingManager.java
new file mode 100644
index 000000000000..919f0861055f
--- /dev/null
+++ b/plugins/editorconfig/src/org/editorconfig/configmanagement/EncodingManager.java
@@ -0,0 +1,73 @@
+package org.editorconfig.configmanagement;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.fileEditor.FileDocumentManagerAdapter;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.vfs.encoding.EncodingProjectManager;
+import org.editorconfig.Utils;
+import org.editorconfig.core.EditorConfig.OutPair;
+import org.editorconfig.plugincomponents.SettingsProviderComponent;
+import org.jetbrains.annotations.NotNull;
+
+import java.nio.charset.Charset;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class EncodingManager extends FileDocumentManagerAdapter {
+ // Handles the following EditorConfig settings:
+ private static final String charsetKey = "charset";
+
+ private final Logger LOG = Logger.getInstance("#org.editorconfig.codestylesettings.EncodingManager");
+ private final Project project;
+
+ private static final Map<String, Charset> encodingMap;
+
+ static {
+ Map<String, Charset> map = new HashMap<String, Charset>();
+ map.put("latin1", Charset.forName("ISO-8859-1"));
+ map.put("utf-8", Charset.forName("UTF-8"));
+ map.put("utf-16be", Charset.forName("UTF-16BE"));
+ map.put("utf-16le", Charset.forName("UTF-16LE"));
+ encodingMap = Collections.unmodifiableMap(map);
+ }
+
+ private boolean isApplyingSettings;
+
+ public EncodingManager(Project project) {
+ this.project = project;
+ isApplyingSettings = false;
+ }
+
+ @Override
+ public void beforeDocumentSaving(@NotNull Document document) {
+ final VirtualFile file = FileDocumentManager.getInstance().getFile(document);
+ if (!isApplyingSettings) {
+ applySettings(file);
+ }
+ }
+
+ private void applySettings(VirtualFile file) {
+ if (file == null || !file.isInLocalFileSystem()) return;
+ // Prevent "setEncoding" calling "saveAll" from causing an endless loop
+ isApplyingSettings = true;
+ final String filePath = file.getCanonicalPath();
+ final List<OutPair> outPairs = SettingsProviderComponent.getInstance().getOutPairs(filePath);
+ final EncodingProjectManager encodingProjectManager = EncodingProjectManager.getInstance(project);
+ final String charset = Utils.configValueForKey(outPairs, charsetKey);
+ if (!charset.isEmpty()) {
+ if (encodingMap.containsKey(charset)) {
+ encodingProjectManager.setEncoding(file, encodingMap.get(charset));
+ LOG.debug(Utils.appliedConfigMessage(charset, charsetKey, filePath));
+ }
+ else {
+ LOG.warn(Utils.invalidConfigMessage(charset, charsetKey, filePath));
+ }
+ }
+ isApplyingSettings = false;
+ }
+}
diff --git a/plugins/editorconfig/src/org/editorconfig/configmanagement/LineEndingsManager.java b/plugins/editorconfig/src/org/editorconfig/configmanagement/LineEndingsManager.java
new file mode 100644
index 000000000000..1291ffd297f0
--- /dev/null
+++ b/plugins/editorconfig/src/org/editorconfig/configmanagement/LineEndingsManager.java
@@ -0,0 +1,95 @@
+package org.editorconfig.configmanagement;
+
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.fileEditor.FileDocumentManagerAdapter;
+import com.intellij.openapi.fileEditor.FileEditorManager;
+import com.intellij.openapi.fileEditor.FileEditorManagerEvent;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.wm.IdeFrame;
+import com.intellij.openapi.wm.StatusBar;
+import com.intellij.openapi.wm.StatusBarWidget;
+import com.intellij.openapi.wm.WindowManager;
+import com.intellij.openapi.wm.impl.status.LineSeparatorPanel;
+import com.intellij.util.LineSeparator;
+import org.editorconfig.Utils;
+import org.editorconfig.core.EditorConfig;
+import org.editorconfig.plugincomponents.SettingsProviderComponent;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+import java.util.Locale;
+
+/**
+ * @author Dennis.Ushakov
+ */
+public class LineEndingsManager extends FileDocumentManagerAdapter {
+ // Handles the following EditorConfig settings:
+ private static final String lineEndingsKey = "end_of_line";
+
+ private final Logger LOG = Logger.getInstance("#org.editorconfig.codestylesettings.LineEndingsManager");
+ private final Project project;
+ private boolean statusBarUpdated = false;
+
+ public LineEndingsManager(Project project) {
+ this.project = project;
+ }
+
+ @Override
+ public void beforeAllDocumentsSaving() {
+ statusBarUpdated = false;
+ }
+
+ private void updateStatusBar() {
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ IdeFrame frame = WindowManager.getInstance().getIdeFrame(project);
+ StatusBar statusBar = frame.getStatusBar();
+ StatusBarWidget widget = statusBar != null ? statusBar.getWidget("LineSeparator") : null;
+
+ if (widget instanceof LineSeparatorPanel) {
+ FileEditorManagerEvent event = new FileEditorManagerEvent(FileEditorManager.getInstance(project),
+ null, null, null, null);
+ ((LineSeparatorPanel)widget).selectionChanged(event);
+ }
+ }
+ });
+ }
+
+ @Override
+ public void beforeDocumentSaving(@NotNull Document document) {
+ VirtualFile file = FileDocumentManager.getInstance().getFile(document);
+ applySettings(file);
+ }
+
+ private void applySettings(VirtualFile file) {
+ if (file == null || !file.isInLocalFileSystem()) return;
+
+ final String filePath = file.getCanonicalPath();
+ final List<EditorConfig.OutPair> outPairs = SettingsProviderComponent.getInstance().getOutPairs(filePath);
+ final String lineEndings = Utils.configValueForKey(outPairs, lineEndingsKey);
+ if (!lineEndings.isEmpty()) {
+ try {
+ LineSeparator separator = LineSeparator.valueOf(lineEndings.toUpperCase(Locale.US));
+ String oldSeparator = file.getDetectedLineSeparator();
+ String newSeparator = separator.getSeparatorString();
+ if (!StringUtil.equals(oldSeparator, newSeparator)) {
+ file.setDetectedLineSeparator(newSeparator);
+ if (!statusBarUpdated) {
+ statusBarUpdated = true;
+ updateStatusBar();
+ }
+ LOG.debug(Utils.appliedConfigMessage(lineEndings, lineEndingsKey, filePath));
+ }
+ }
+ catch (IllegalArgumentException e) {
+ LOG.warn(Utils.invalidConfigMessage(lineEndings, lineEndingsKey, filePath));
+ }
+ }
+ }
+}
diff --git a/plugins/editorconfig/src/org/editorconfig/plugincomponents/ConfigProjectComponent.java b/plugins/editorconfig/src/org/editorconfig/plugincomponents/ConfigProjectComponent.java
new file mode 100644
index 000000000000..0d31b2bb8b2c
--- /dev/null
+++ b/plugins/editorconfig/src/org/editorconfig/plugincomponents/ConfigProjectComponent.java
@@ -0,0 +1,61 @@
+package org.editorconfig.plugincomponents;
+
+import com.intellij.AppTopics;
+import com.intellij.openapi.components.ProjectComponent;
+import com.intellij.openapi.fileEditor.FileEditorManagerListener;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.wm.IdeFrame;
+import com.intellij.openapi.wm.WindowManager;
+import com.intellij.util.messages.MessageBus;
+import org.editorconfig.configmanagement.CodeStyleManager;
+import org.editorconfig.configmanagement.EditorSettingsManager;
+import org.editorconfig.configmanagement.EncodingManager;
+import org.editorconfig.configmanagement.LineEndingsManager;
+import org.jetbrains.annotations.NotNull;
+
+import java.awt.*;
+
+public class ConfigProjectComponent implements ProjectComponent {
+ private final Project project;
+ private final CodeStyleManager codeStyleManager;
+
+ public ConfigProjectComponent(Project project) {
+ this.project = project;
+
+ // Register project-level config managers
+ MessageBus bus = project.getMessageBus();
+ codeStyleManager = new CodeStyleManager(project);
+ EditorSettingsManager editorSettingsManager = new EditorSettingsManager();
+ EncodingManager encodingManager = new EncodingManager(project);
+ LineEndingsManager lineEndingsManager = new LineEndingsManager(project);
+ bus.connect().subscribe(FileEditorManagerListener.FILE_EDITOR_MANAGER, codeStyleManager);
+ bus.connect().subscribe(AppTopics.FILE_DOCUMENT_SYNC, encodingManager);
+ bus.connect().subscribe(AppTopics.FILE_DOCUMENT_SYNC, editorSettingsManager);
+ bus.connect().subscribe(AppTopics.FILE_DOCUMENT_SYNC, lineEndingsManager);
+ }
+
+ public void initComponent() {
+ }
+
+ public void disposeComponent() {
+ }
+
+ @NotNull
+ public String getComponentName() {
+ return "ConfigProjectComponent";
+ }
+
+ public void projectOpened() {
+ // called when project is opened
+ IdeFrame frame = WindowManager.getInstance().getIdeFrame(project);
+ final Window window = (Window)frame;
+ window.addWindowFocusListener(codeStyleManager);
+ }
+
+ public void projectClosed() {
+ // called when project is being closed
+ IdeFrame frame = WindowManager.getInstance().getIdeFrame(project);
+ final Window window = (Window)frame;
+ window.removeWindowFocusListener(codeStyleManager);
+ }
+}
diff --git a/plugins/editorconfig/src/org/editorconfig/plugincomponents/SettingsProviderComponent.java b/plugins/editorconfig/src/org/editorconfig/plugincomponents/SettingsProviderComponent.java
new file mode 100644
index 000000000000..edd74ebdb22d
--- /dev/null
+++ b/plugins/editorconfig/src/org/editorconfig/plugincomponents/SettingsProviderComponent.java
@@ -0,0 +1,49 @@
+package org.editorconfig.plugincomponents;
+
+import com.intellij.openapi.components.ApplicationComponent;
+import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.diagnostic.Logger;
+import org.editorconfig.core.EditorConfig;
+import org.editorconfig.core.EditorConfig.OutPair;
+import org.editorconfig.core.EditorConfigException;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class SettingsProviderComponent implements ApplicationComponent {
+ private static final Logger LOG = Logger.getInstance("#org.editorconfig.plugincomponents.SettingsProviderComponent");
+
+ private EditorConfig editorConfig;
+
+ public SettingsProviderComponent() {
+ editorConfig = new EditorConfig();
+ }
+
+ public static SettingsProviderComponent getInstance() {
+ return ServiceManager.getService(SettingsProviderComponent.class);
+ }
+
+ public List<OutPair> getOutPairs(String filePath) {
+ final List<OutPair> outPairs;
+ try {
+ outPairs = editorConfig.getProperties(filePath);
+ return outPairs;
+ }
+ catch (EditorConfigException error) {
+ LOG.error(error);
+ return new ArrayList<OutPair>();
+ }
+ }
+
+ public void initComponent() {
+ }
+
+ public void disposeComponent() {
+ }
+
+ @NotNull
+ public String getComponentName() {
+ return "SettingsProviderComponent";
+ }
+}
diff --git a/plugins/generate-tostring/src/org/jetbrains/generate/tostring/velocity/VelocityFactory.java b/plugins/generate-tostring/src/org/jetbrains/generate/tostring/velocity/VelocityFactory.java
index c362f83afcdd..ff4a5b63c83c 100644
--- a/plugins/generate-tostring/src/org/jetbrains/generate/tostring/velocity/VelocityFactory.java
+++ b/plugins/generate-tostring/src/org/jetbrains/generate/tostring/velocity/VelocityFactory.java
@@ -17,6 +17,7 @@ package org.jetbrains.generate.tostring.velocity;
import org.apache.commons.collections.ExtendedProperties;
import org.apache.velocity.app.VelocityEngine;
+import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.runtime.log.SimpleLog4JLogSystem;
/**
@@ -25,46 +26,41 @@ import org.apache.velocity.runtime.log.SimpleLog4JLogSystem;
* Creating instances of the VelocityEngine.
*/
public class VelocityFactory {
+ private static class Holder {
+ private static final VelocityEngine engine = newVeloictyEngine();
+ }
- private static VelocityEngine engine;
+ /**
+ * Privte constructor.
+ */
+ private VelocityFactory() {
+ }
- /**
- * Privte constructor.
- */
- private VelocityFactory() {
- }
-
- /**
- * Returns a new instance of the VelocityEngine.
- * <p/>
- * The engine is initialized and outputs its logging to IDEA logging.
- *
- * @return a new velocity engine that is initialized.
- * @throws Exception error creating the VelocityEngine.
- */
- public static VelocityEngine newVeloictyEngine() throws Exception {
- ExtendedProperties prop = new ExtendedProperties();
- prop.addProperty(VelocityEngine.RUNTIME_LOG_LOGSYSTEM_CLASS, SimpleLog4JLogSystem.class.getName());
- prop.addProperty("runtime.log.logsystem.log4j.category", "GenerateToString");
- VelocityEngine velocity = new VelocityEngine();
- velocity.setExtendedProperties(prop);
- velocity.init();
- return velocity;
- }
-
- /**
- * Get's a shared instance of the VelocityEngine.
- * <p/>
- * The engine is initialized and outputs its logging to IDEA logging.
- * @return a shared instance of the engine that is initialized.
- * @throws Exception error creating the VelocityEngine.
- */
- public static VelocityEngine getVelocityEngine() throws Exception {
- if (engine == null) {
- engine = newVeloictyEngine();
- }
-
- return engine;
- }
+ /**
+ * Returns a new instance of the VelocityEngine.
+ * <p/>
+ * The engine is initialized and outputs its logging to IDEA logging.
+ *
+ * @return a new velocity engine that is initialized.
+ */
+ private static VelocityEngine newVeloictyEngine() {
+ ExtendedProperties prop = new ExtendedProperties();
+ prop.addProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS, SimpleLog4JLogSystem.class.getName());
+ prop.addProperty("runtime.log.logsystem.log4j.category", "GenerateToString");
+ VelocityEngine velocity = new VelocityEngine();
+ velocity.setExtendedProperties(prop);
+ velocity.init();
+ return velocity;
+ }
+ /**
+ * Get's a shared instance of the VelocityEngine.
+ * <p/>
+ * The engine is initialized and outputs its logging to IDEA logging.
+ *
+ * @return a shared instance of the engine that is initialized.
+ */
+ public static VelocityEngine getVelocityEngine() {
+ return Holder.engine;
+ }
} \ No newline at end of file
diff --git a/plugins/git4idea/git4idea.iml b/plugins/git4idea/git4idea.iml
index 1b6091a77419..53ee70f60eca 100644
--- a/plugins/git4idea/git4idea.iml
+++ b/plugins/git4idea/git4idea.iml
@@ -49,7 +49,7 @@
</library>
</orderEntry>
<orderEntry type="library" scope="TEST" name="Groovy" level="project" />
- <orderEntry type="module" module-name="dvcs" exported="" />
+ <orderEntry type="module" module-name="dvcs-impl" exported="" />
<orderEntry type="library" scope="TEST" name="cucumber-jvm" level="project" />
<orderEntry type="library" scope="TEST" name="cucumber-java" level="project" />
<orderEntry type="library" name="JSch" level="project" />
@@ -58,6 +58,7 @@
<orderEntry type="module" module-name="vcs-log-api" />
<orderEntry type="module" module-name="vcs-log-impl" />
<orderEntry type="module" module-name="vcs-log-graph" />
+ <orderEntry type="module" module-name="dvcs-api" exported="" />
</component>
</module>
diff --git a/plugins/git4idea/remote-servers-git/remote-servers-git.iml b/plugins/git4idea/remote-servers-git/remote-servers-git.iml
index a2ae7940093c..754094b7fb98 100644
--- a/plugins/git4idea/remote-servers-git/remote-servers-git.iml
+++ b/plugins/git4idea/remote-servers-git/remote-servers-git.iml
@@ -18,6 +18,7 @@
<orderEntry type="module" module-name="idea-ui" />
<orderEntry type="module" module-name="openapi" />
<orderEntry type="module" module-name="vcs-impl" />
+ <orderEntry type="module" module-name="dvcs-api" />
</component>
</module>
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 9846393b99a8..3ac118fe6b7f 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
@@ -15,8 +15,8 @@ import com.intellij.openapi.vcs.changes.ui.CommitChangeListDialog;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.remoteServer.agent.util.CloudAgentLoggingHandler;
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;
@@ -350,7 +350,7 @@ public class CloudGitDeploymentRuntime extends CloudDeploymentRuntime {
}
@Override
- protected CloudLoggingHandler getLoggingHandler() {
+ protected CloudAgentLoggingHandler getLoggingHandler() {
return super.getLoggingHandler();
}
diff --git a/plugins/git4idea/src/git4idea/GitContentRevision.java b/plugins/git4idea/src/git4idea/GitContentRevision.java
index 68fcb59febf2..8dd85b167980 100644
--- a/plugins/git4idea/src/git4idea/GitContentRevision.java
+++ b/plugins/git4idea/src/git4idea/GitContentRevision.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,6 +27,7 @@ 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.vcsUtil.VcsFilePathUtil;
import com.intellij.vcsUtil.VcsFileUtil;
import com.intellij.vcsUtil.VcsUtil;
import git4idea.util.GitFileUtils;
@@ -168,7 +169,7 @@ public class GitContentRevision implements ContentRevision {
boolean isDeleted, boolean canBeDeleted, boolean unescapePath) throws VcsException {
final String absolutePath = makeAbsolutePath(vcsRoot, path, unescapePath);
FilePath file = isDeleted ? VcsUtil.getFilePathForDeletedFile(absolutePath, false) : VcsUtil.getFilePath(absolutePath, false);
- if (canBeDeleted && (! SystemInfo.isFileSystemCaseSensitive) && VcsUtil.caseDiffers(file.getPath(), absolutePath)) {
+ if (canBeDeleted && (! SystemInfo.isFileSystemCaseSensitive) && VcsFilePathUtil.caseDiffers(file.getPath(), absolutePath)) {
// as for deleted file
file = FilePathImpl.createForDeletedFile(new File(absolutePath), false);
}
diff --git a/plugins/git4idea/src/git4idea/GitRevisionNumber.java b/plugins/git4idea/src/git4idea/GitRevisionNumber.java
index cd6387a4e629..06fba24f015a 100644
--- a/plugins/git4idea/src/git4idea/GitRevisionNumber.java
+++ b/plugins/git4idea/src/git4idea/GitRevisionNumber.java
@@ -15,6 +15,7 @@
*/
package git4idea;
+import com.intellij.dvcs.DvcsUtil;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
@@ -103,7 +104,7 @@ public class GitRevisionNumber implements ShortVcsRevisionNumber {
*/
@NotNull
public String getShortRev() {
- return GitUtil.getShortHash(myRevisionHash);
+ return DvcsUtil.getShortHash(myRevisionHash);
}
/**
diff --git a/plugins/git4idea/src/git4idea/GitUtil.java b/plugins/git4idea/src/git4idea/GitUtil.java
index 4ff61fb4a68b..e96d52de8ea0 100644
--- a/plugins/git4idea/src/git4idea/GitUtil.java
+++ b/plugins/git4idea/src/git4idea/GitUtil.java
@@ -102,7 +102,6 @@ public class GitUtil {
public static final String DOT_GIT = ".git";
private final static Logger LOG = Logger.getInstance(GitUtil.class);
- private static final int SHORT_HASH_LENGTH = 8;
public static final Predicate<GitBranchTrackInfo> NOT_NULL_PREDICATE = new Predicate<GitBranchTrackInfo>() {
@Override
@@ -829,17 +828,6 @@ public class GitUtil {
}
@NotNull
- public static String getShortHash(@NotNull String hash) {
- if (hash.length() == 0) return "";
- if (hash.length() == 40) return hash.substring(0, SHORT_HASH_LENGTH);
- if (hash.length() > 40) // revision string encoded with date too
- {
- return hash.substring(hash.indexOf("[") + 1, SHORT_HASH_LENGTH);
- }
- return hash;
- }
-
- @NotNull
public static String fileOrFolder(@NotNull VirtualFile file) {
if (file.isDirectory()) {
return "Folder";
diff --git a/plugins/git4idea/src/git4idea/actions/GitCompareWithBranchAction.java b/plugins/git4idea/src/git4idea/actions/GitCompareWithBranchAction.java
index f0ad3b7a5e31..8799c0e69651 100644
--- a/plugins/git4idea/src/git4idea/actions/GitCompareWithBranchAction.java
+++ b/plugins/git4idea/src/git4idea/actions/GitCompareWithBranchAction.java
@@ -15,6 +15,7 @@
*/
package git4idea.actions;
+import com.intellij.dvcs.DvcsUtil;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.Presentation;
@@ -70,7 +71,7 @@ public class GitCompareWithBranchAction extends DumbAwareAction {
String currentRevision = repository.getCurrentRevision();
LOG.assertTrue(currentRevision != null,
"Current revision is null for " + repository + ". Compare with branch shouldn't be available for fresh repository");
- head = GitUtil.getShortHash(currentRevision);
+ head = DvcsUtil.getShortHash(currentRevision);
}
else {
head = currentBranch.getName();
diff --git a/plugins/git4idea/src/git4idea/annotate/GitAnnotationProvider.java b/plugins/git4idea/src/git4idea/annotate/GitAnnotationProvider.java
index 46875b9d8c23..5ebdefd74b3a 100644
--- a/plugins/git4idea/src/git4idea/annotate/GitAnnotationProvider.java
+++ b/plugins/git4idea/src/git4idea/annotate/GitAnnotationProvider.java
@@ -46,45 +46,20 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
-/**
- * Git annotation provider implementation.
- * <p/>
- * Based on the JetBrains SVNAnnotationProvider.
- */
public class GitAnnotationProvider implements AnnotationProvider, VcsCacheableAnnotationProvider {
- /**
- * the context project
- */
private final Project myProject;
- /**
- * The author key for annotations
- */
@NonNls private static final String AUTHOR_KEY = "author";
- /**
- * The committer time key for annotations
- */
@NonNls private static final String COMMITTER_TIME_KEY = "committer-time";
private static final Logger LOG = Logger.getInstance(GitAnnotationProvider.class);
- /**
- * A constructor
- *
- * @param project a context project
- */
public GitAnnotationProvider(@NotNull Project project) {
myProject = project;
}
- /**
- * {@inheritDoc}
- */
public FileAnnotation annotate(@NotNull VirtualFile file) throws VcsException {
return annotate(file, null);
}
- /**
- * {@inheritDoc}
- */
public FileAnnotation annotate(@NotNull final VirtualFile file, final VcsFileRevision revision) throws VcsException {
if (file.isDirectory()) {
throw new VcsException("Cannot annotate a directory");
@@ -119,8 +94,8 @@ public class GitAnnotationProvider implements AnnotationProvider, VcsCacheableAn
}
};
if (ApplicationManager.getApplication().isDispatchThread()) {
- ProgressManager.getInstance()
- .runProcessWithProgressSynchronously(command, GitBundle.getString("annotate.action.name"), false, myProject);
+ ProgressManager.getInstance().runProcessWithProgressSynchronously(command, GitBundle.getString("annotate.action.name"), false,
+ myProject);
}
else {
command.run();
@@ -132,16 +107,6 @@ public class GitAnnotationProvider implements AnnotationProvider, VcsCacheableAn
return annotation[0];
}
- /**
- * Calculate annotations
- *
- * @param repositoryFilePath the file path in the repository
- * @param revision the revision to checkout
- * @param revisions the revision list from history
- * @param file a virtual file for the action
- * @return a file annotation object
- * @throws VcsException if there is a problem with running git
- */
private GitFileAnnotation annotate(final FilePath repositoryFilePath,
final VcsFileRevision revision,
final List<VcsFileRevision> revisions,
@@ -159,7 +124,7 @@ public class GitAnnotationProvider implements AnnotationProvider, VcsCacheableAn
h.endOptions();
h.addRelativePaths(repositoryFilePath);
String output = h.run();
- GitFileAnnotation annotation = new GitFileAnnotation(myProject, file, revision == null, revision == null ? null : revision.getRevisionNumber());
+ GitFileAnnotation annotation = new GitFileAnnotation(myProject, file, revision == null ? null : revision.getRevisionNumber());
class CommitInfo {
Date date;
String author;
@@ -229,7 +194,7 @@ public class GitAnnotationProvider implements AnnotationProvider, VcsCacheableAn
String annotatedContent,
boolean forCurrentRevision, VcsRevisionNumber revisionNumber) {
final GitFileAnnotation gitFileAnnotation =
- new GitFileAnnotation(myProject, vcsAnnotation.getFilePath().getVirtualFile(), forCurrentRevision, revisionNumber);
+ new GitFileAnnotation(myProject, vcsAnnotation.getFilePath().getVirtualFile(), revisionNumber);
gitFileAnnotation.addLogEntries(session.getRevisionList());
final VcsLineAnnotationData basicAnnotation = vcsAnnotation.getBasicAnnotation();
final int size = basicAnnotation.getNumLines();
@@ -252,9 +217,6 @@ public class GitAnnotationProvider implements AnnotationProvider, VcsCacheableAn
return gitFileAnnotation;
}
- /**
- * {@inheritDoc}
- */
public boolean isAnnotationValid(VcsFileRevision rev) {
return true;
}
diff --git a/plugins/git4idea/src/git4idea/annotate/GitFileAnnotation.java b/plugins/git4idea/src/git4idea/annotate/GitFileAnnotation.java
index 4dfe4da19de0..0c1df6a50a5b 100644
--- a/plugins/git4idea/src/git4idea/annotate/GitFileAnnotation.java
+++ b/plugins/git4idea/src/git4idea/annotate/GitFileAnnotation.java
@@ -15,7 +15,6 @@
*/
package git4idea.annotate;
-import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.VcsKey;
@@ -23,6 +22,7 @@ import com.intellij.openapi.vcs.annotate.*;
import com.intellij.openapi.vcs.history.VcsFileRevision;
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.ObjectUtils;
import com.intellij.util.text.DateFormatUtil;
import git4idea.GitRevisionNumber;
import git4idea.GitVcs;
@@ -32,45 +32,24 @@ import org.jetbrains.annotations.Nullable;
import java.util.*;
-/**
- * Git file annotation implementation
- * <p/>
- * Based on the JetBrains SVNAnnotationProvider.
- */
public class GitFileAnnotation extends FileAnnotation {
- private final static Logger LOG = Logger.getInstance("#git4idea.annotate.GitFileAnnotation");
-
- /**
- * annotated content
- */
- private final StringBuffer myContentBuffer = new StringBuffer();
- /**
- * The currently annotated lines
- */
- private final ArrayList<LineInfo> myLines = new ArrayList<LineInfo>();
- /**
- * The project reference
- */
+ private final StringBuffer myContentBuffer = new StringBuffer(); // annotated content
+ private final ArrayList<LineInfo> myLines = new ArrayList<LineInfo>(); // The currently annotated lines
private final Project myProject;
private final VcsRevisionNumber myBaseRevision;
- /**
- * Map from revision numbers to revisions
- */
- private final Map<VcsRevisionNumber, VcsFileRevision> myRevisionMap = new HashMap<VcsRevisionNumber, VcsFileRevision>();
+ @NotNull private final Map<VcsRevisionNumber, VcsFileRevision> myRevisionMap = new HashMap<VcsRevisionNumber, VcsFileRevision>();
+ @NotNull private final VirtualFile myFile;
+ @NotNull private final GitVcs myVcs;
- /**
- * the virtual file for which annotations are generated
- */
- private final VirtualFile myFile;
-
- private final LineAnnotationAspect DATE_ASPECT = new GitAnnotationAspect(GitAnnotationAspect.DATE, true) {
+ private final LineAnnotationAspect DATE_ASPECT = new GitAnnotationAspect(LineAnnotationAspect.DATE, true) {
+ @Override
public String doGetValue(LineInfo info) {
final Date date = info.getDate();
return date == null ? "" : DateFormatUtil.formatPrettyDate(date);
}
};
- private final LineAnnotationAspect REVISION_ASPECT = new GitAnnotationAspect(GitAnnotationAspect.REVISION, false) {
+ private final LineAnnotationAspect REVISION_ASPECT = new GitAnnotationAspect(LineAnnotationAspect.REVISION, false) {
@Override
protected String doGetValue(LineInfo lineInfo) {
final GitRevisionNumber revision = lineInfo.getRevision();
@@ -78,101 +57,78 @@ public class GitFileAnnotation extends FileAnnotation {
}
};
- private final LineAnnotationAspect AUTHOR_ASPECT = new GitAnnotationAspect(GitAnnotationAspect.AUTHOR, true) {
+ private final LineAnnotationAspect AUTHOR_ASPECT = new GitAnnotationAspect(LineAnnotationAspect.AUTHOR, true) {
@Override
protected String doGetValue(LineInfo lineInfo) {
final String author = lineInfo.getAuthor();
return author == null ? "" : author;
}
};
- private final GitVcs myVcs;
- /**
- * A constructor
- *
- * @param project the project of annotation provider
- * @param file the git root
- * @param monitorFlag if false the file system will not be listened for changes (used for annotated files from the repository).
- * @param revision
- */
- public GitFileAnnotation(@NotNull final Project project, @NotNull VirtualFile file, final boolean monitorFlag, final VcsRevisionNumber revision) {
+ public GitFileAnnotation(@NotNull final Project project,
+ @NotNull VirtualFile file,
+ final VcsRevisionNumber revision) {
super(project);
myProject = project;
- myVcs = GitVcs.getInstance(myProject);
+ myVcs = ObjectUtils.assertNotNull(GitVcs.getInstance(myProject));
myFile = file;
myBaseRevision = revision == null ? (myVcs.getDiffProvider().getCurrentRevision(file)) : revision;
}
- /**
- * Add revisions to the list (from log)
- *
- * @param revisions revisions to add
- */
public void addLogEntries(List<VcsFileRevision> revisions) {
for (VcsFileRevision vcsFileRevision : revisions) {
myRevisionMap.put(vcsFileRevision.getRevisionNumber(), vcsFileRevision);
}
}
- /**
- * {@inheritDoc}
- */
+ @Override
public void dispose() {
}
- /**
- * {@inheritDoc}
- */
+ @Override
public LineAnnotationAspect[] getAspects() {
return new LineAnnotationAspect[]{REVISION_ASPECT, DATE_ASPECT, AUTHOR_ASPECT};
}
- /**
- * {@inheritDoc}
- */
+ @Override
public String getToolTip(final int lineNumber) {
if (myLines.size() <= lineNumber || lineNumber < 0) {
return "";
}
final LineInfo info = myLines.get(lineNumber);
- if (info == null) {
- return "";
- }
VcsFileRevision fileRevision = myRevisionMap.get(info.getRevision());
if (fileRevision != null) {
- return GitBundle
- .message("annotation.tool.tip", info.getRevision().asString(), info.getAuthor(), info.getDate(),
- fileRevision.getCommitMessage());
+ return GitBundle.message("annotation.tool.tip", info.getRevision().asString(), info.getAuthor(), info.getDate(),
+ fileRevision.getCommitMessage());
}
else {
return "";
}
}
- /**
- * {@inheritDoc}
- */
+ @Override
public String getAnnotatedContent() {
return myContentBuffer.toString();
}
- /**
- * {@inheritDoc}
- */
+ @Override
public List<VcsFileRevision> getRevisions() {
final List<VcsFileRevision> result = new ArrayList<VcsFileRevision>(myRevisionMap.values());
Collections.sort(result, new Comparator<VcsFileRevision>() {
- public int compare(final VcsFileRevision o1, final VcsFileRevision o2) {
+ @Override
+ public int compare(@NotNull VcsFileRevision o1, @NotNull VcsFileRevision o2) {
return -1 * o1.getRevisionNumber().compareTo(o2.getRevisionNumber());
}
});
return result;
}
+ @Override
public boolean revisionsNotEmpty() {
return ! myRevisionMap.isEmpty();
}
+ @Override
public AnnotationSourceSwitcher getAnnotationSourceSwitcher() {
return null;
}
@@ -182,19 +138,16 @@ public class GitFileAnnotation extends FileAnnotation {
return myLines.size();
}
- /**
- * {@inheritDoc}
- */
+ @Override
public VcsRevisionNumber getLineRevisionNumber(final int lineNumber) {
if (lineNumberCheck(lineNumber)) {
return null;
}
- final LineInfo lineInfo = myLines.get(lineNumber);
- return lineInfo == null ? null : lineInfo.getRevision();
+ return myLines.get(lineNumber).getRevision();
}
private boolean lineNumberCheck(int lineNumber) {
- return myLines.size() <= lineNumber || lineNumber < 0 || myLines.get(lineNumber) == null;
+ return myLines.size() <= lineNumber || lineNumber < 0;
}
@Override
@@ -202,13 +155,13 @@ public class GitFileAnnotation extends FileAnnotation {
if (lineNumberCheck(lineNumber)) {
return null;
}
- final LineInfo lineInfo = myLines.get(lineNumber);
- return lineInfo == null ? null : lineInfo.getDate();
+ return myLines.get(lineNumber).getDate();
}
/**
* Get revision number for the line.
*/
+ @Override
public VcsRevisionNumber originalRevision(int lineNumber) {
return getLineRevisionNumber(lineNumber);
}
@@ -248,6 +201,7 @@ public class GitFileAnnotation extends FileAnnotation {
super(id, showByDefault);
}
+ @Override
public String getValue(int lineNumber) {
if (lineNumberCheck(lineNumber)) {
return "";
@@ -262,10 +216,8 @@ public class GitFileAnnotation extends FileAnnotation {
@Override
protected void showAffectedPaths(int lineNum) {
if (lineNum >= 0 && lineNum < myLines.size()) {
- final LineInfo info = myLines.get(lineNum);
- if (info != null) {
- ShowAllAffectedGenericAction.showSubmittedFiles(myProject, info.getRevision(), myFile, GitVcs.getKey());
- }
+ LineInfo info = myLines.get(lineNum);
+ ShowAllAffectedGenericAction.showSubmittedFiles(myProject, info.getRevision(), myFile, GitVcs.getKey());
}
}
}
@@ -274,54 +226,31 @@ public class GitFileAnnotation extends FileAnnotation {
* Line information
*/
static class LineInfo {
- /**
- * date of the change
- */
private final Date myDate;
- /**
- * revision number
- */
private final GitRevisionNumber myRevision;
- /**
- * the author of the change
- */
private final String myAuthor;
- /**
- * A constructor
- *
- * @param date date of the change
- * @param revision revision number
- * @param author the author of the change
- */
- public LineInfo(final Date date, final GitRevisionNumber revision, final String author) {
+ public LineInfo(Date date, GitRevisionNumber revision, String author) {
myDate = date;
myRevision = revision;
myAuthor = author;
}
- /**
- * @return the revision date
- */
public Date getDate() {
return myDate;
}
- /**
- * @return the revision number
- */
public GitRevisionNumber getRevision() {
return myRevision;
}
- /**
- * @return the author of the change
- */
public String getAuthor() {
return myAuthor;
}
}
+ @NotNull
+ @Override
public VirtualFile getFile() {
return myFile;
}
diff --git a/plugins/git4idea/src/git4idea/history/GitDiffFromHistoryHandler.java b/plugins/git4idea/src/git4idea/history/GitDiffFromHistoryHandler.java
index a6488d4ce3d0..d0f051c50475 100644
--- a/plugins/git4idea/src/git4idea/history/GitDiffFromHistoryHandler.java
+++ b/plugins/git4idea/src/git4idea/history/GitDiffFromHistoryHandler.java
@@ -15,6 +15,7 @@
*/
package git4idea.history;
+import com.intellij.dvcs.DvcsUtil;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.actionSystem.impl.SimpleDataContext;
import com.intellij.openapi.components.ServiceManager;
@@ -116,7 +117,7 @@ public class GitDiffFromHistoryHandler extends BaseDiffFromHistoryHandler<GitFil
@NotNull
@Override
protected String getPresentableName(@NotNull GitFileRevision revision) {
- return GitUtil.getShortHash(revision.getHash());
+ return DvcsUtil.getShortHash(revision.getHash());
}
@NotNull
@@ -301,7 +302,7 @@ public class GitDiffFromHistoryHandler extends BaseDiffFromHistoryHandler<GitFil
@NotNull private final GitFileRevision myParentRevision;
public ShowDiffWithParentAction(@NotNull FilePath filePath, @NotNull GitFileRevision rev, @NotNull GitFileRevision parent) {
- super(GitUtil.getShortHash(parent.getHash()));
+ super(DvcsUtil.getShortHash(parent.getHash()));
myFilePath = filePath;
myRevision = rev;
myParentRevision = parent;
diff --git a/plugins/git4idea/src/git4idea/i18n/GitBundle.properties b/plugins/git4idea/src/git4idea/i18n/GitBundle.properties
index 03803fbf985c..f89657535f8a 100644
--- a/plugins/git4idea/src/git4idea/i18n/GitBundle.properties
+++ b/plugins/git4idea/src/git4idea/i18n/GitBundle.properties
@@ -416,20 +416,6 @@ unstash.unstashing=Unstashing...
unstash.view.tooltip=View selected stash
unstash.view=&View
unstashing.title=UnStashing changes...
-update.locally.modified.files.tooltip=Locally modified files.
-update.locally.modified.files=&Files:
-update.locally.modified.git.root=Git Root:
-update.locally.modified.message=<html><p>The following files under this root are locally modified. <br/>\
- Possible reasons: uncommitted changes; a problem with crlf conversion; {0} configuration file auto-save.</p>\
- <p><ul>\
- <li>Press <b>Revert Files</b> to discard these local changes and continue the update process.</li>\
- <li>Press <b>Cancel</b> to cancel the update process. <br/> Use Auto-Stash option to stash local changes before update and restore them after it.</li>\
- </ul></p> \
- </html>
-update.locally.modified.rescan.tooltip=<html>Rescan the repository to check for locally modified files again.<br/>Use this button if you have resolved the problem manually.</html>
-update.locally.modified.rescan=Re&scan
-update.locally.modified.revert=Revert Files
-update.locally.modified.title=Locally modified files are detected
update.options.display.name=Git Update Settings
update.options.no.commit=No &Commit
update.options.save.before.update=Clean working tree before update
diff --git a/plugins/git4idea/src/git4idea/push/GitPushDialog.java b/plugins/git4idea/src/git4idea/push/GitPushDialog.java
index 56476078f692..f12b7b407c89 100644
--- a/plugins/git4idea/src/git4idea/push/GitPushDialog.java
+++ b/plugins/git4idea/src/git4idea/push/GitPushDialog.java
@@ -15,6 +15,7 @@
*/
package git4idea.push;
+import com.intellij.dvcs.DvcsUtil;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.diagnostic.Logger;
@@ -219,7 +220,7 @@ public class GitPushDialog extends DialogWrapper {
private static String logMessageForCommits(GitCommitsByRepoAndBranch commitsToPush) {
StringBuilder logMessage = new StringBuilder();
for (GitCommit commit : commitsToPush.getAllCommits()) {
- logMessage.append(GitUtil.getShortHash(commit.getId().toString()));
+ logMessage.append(DvcsUtil.getShortHash(commit.getId().toString()));
}
return logMessage.toString();
}
diff --git a/plugins/git4idea/src/git4idea/push/GitPushLog.java b/plugins/git4idea/src/git4idea/push/GitPushLog.java
index 99d3c1350698..e3659554bdf2 100644
--- a/plugins/git4idea/src/git4idea/push/GitPushLog.java
+++ b/plugins/git4idea/src/git4idea/push/GitPushLog.java
@@ -29,7 +29,6 @@ import com.intellij.openapi.vcs.changes.ui.ChangesBrowser;
import com.intellij.ui.*;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Consumer;
-import com.intellij.util.text.DateFormatUtil;
import com.intellij.util.ui.UIUtil;
import com.intellij.util.ui.tree.TreeUtil;
import git4idea.GitBranch;
@@ -336,12 +335,12 @@ class GitPushLog extends JPanel implements TypeSafeDataProvider {
@NotNull
private static String getDateString(@NotNull GitCommit commit) {
- return DateFormatUtil.formatPrettyDateTime(commit.getTimestamp()) + " ";
+ return DvcsUtil.getDateString(commit);
}
@NotNull
private static String getHashString(@NotNull GitCommit commit) {
- return GitUtil.getShortHash(commit.getId().toString());
+ return DvcsUtil.getShortHash(commit.getId().toString());
}
private static class MyTreeCellRenderer extends CheckboxTree.CheckboxTreeCellRenderer {
diff --git a/plugins/git4idea/src/git4idea/rebase/GitRebaser.java b/plugins/git4idea/src/git4idea/rebase/GitRebaser.java
index aabf913fbf61..d5a0470d1667 100644
--- a/plugins/git4idea/src/git4idea/rebase/GitRebaser.java
+++ b/plugins/git4idea/src/git4idea/rebase/GitRebaser.java
@@ -30,6 +30,7 @@ import git4idea.commands.*;
import git4idea.merge.GitConflictResolver;
import git4idea.update.GitUpdateResult;
import git4idea.util.GitUIUtil;
+import git4idea.util.LocalChangesWouldBeOverwrittenHelper;
import git4idea.util.StringScanner;
import git4idea.util.UntrackedFilesNotifier;
import org.jetbrains.annotations.NotNull;
@@ -43,6 +44,8 @@ import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
+import static git4idea.commands.GitLocalChangesWouldBeOverwrittenDetector.Operation.CHECKOUT;
+
/**
* @author Kirill Likhodedov
*/
@@ -77,7 +80,9 @@ public class GitRebaser {
final GitRebaseProblemDetector rebaseConflictDetector = new GitRebaseProblemDetector();
rebaseHandler.addLineListener(rebaseConflictDetector);
GitUntrackedFilesOverwrittenByOperationDetector untrackedFilesDetector = new GitUntrackedFilesOverwrittenByOperationDetector(root);
+ GitLocalChangesWouldBeOverwrittenDetector localChangesDetector = new GitLocalChangesWouldBeOverwrittenDetector(root, CHECKOUT);
rebaseHandler.addLineListener(untrackedFilesDetector);
+ rebaseHandler.addLineListener(localChangesDetector);
String progressTitle = "Rebasing";
GitTask rebaseTask = new GitTask(myProject, rebaseHandler, progressTitle);
@@ -108,7 +113,7 @@ public class GitRebaser {
});
if (failure.get()) {
- updateResult.set(handleRebaseFailure(rebaseHandler, root, rebaseConflictDetector, untrackedFilesDetector));
+ updateResult.set(handleRebaseFailure(rebaseHandler, root, rebaseConflictDetector, untrackedFilesDetector, localChangesDetector));
}
}
finally {
@@ -333,19 +338,27 @@ public class GitRebaser {
}
@NotNull
- public GitUpdateResult handleRebaseFailure(@NotNull GitLineHandler handler, @NotNull VirtualFile root,
+ public GitUpdateResult handleRebaseFailure(@NotNull GitLineHandler handler,
+ @NotNull VirtualFile root,
@NotNull GitRebaseProblemDetector rebaseConflictDetector,
- @NotNull GitMessageWithFilesDetector untrackedWouldBeOverwrittenDetector) {
+ @NotNull GitMessageWithFilesDetector untrackedWouldBeOverwrittenDetector,
+ @NotNull GitLocalChangesWouldBeOverwrittenDetector localChangesDetector) {
if (rebaseConflictDetector.isMergeConflict()) {
LOG.info("handleRebaseFailure merge conflict");
final boolean allMerged = new GitRebaser.ConflictResolver(myProject, myGit, root, this).merge();
return allMerged ? GitUpdateResult.SUCCESS_WITH_RESOLVED_CONFLICTS : GitUpdateResult.INCOMPLETE;
- } else if (untrackedWouldBeOverwrittenDetector.wasMessageDetected()) {
+ }
+ else if (untrackedWouldBeOverwrittenDetector.wasMessageDetected()) {
LOG.info("handleRebaseFailure: untracked files would be overwritten by checkout");
UntrackedFilesNotifier.notifyUntrackedFilesOverwrittenBy(myProject, root,
untrackedWouldBeOverwrittenDetector.getRelativeFilePaths(), "rebase", null);
return GitUpdateResult.ERROR;
- } else {
+ }
+ else if (localChangesDetector.wasMessageDetected()) {
+ LocalChangesWouldBeOverwrittenHelper.showErrorNotification(myProject, root, "rebase", localChangesDetector.getRelativeFilePaths());
+ return GitUpdateResult.ERROR;
+ }
+ else {
LOG.info("handleRebaseFailure error " + handler.errors());
GitUIUtil.notifyImportantError(myProject, "Rebase error", GitUIUtil.stringifyErrors(handler.errors()));
return GitUpdateResult.ERROR;
diff --git a/plugins/git4idea/src/git4idea/repo/GitRepositoryImpl.java b/plugins/git4idea/src/git4idea/repo/GitRepositoryImpl.java
index e401334416d6..1444f44c0288 100644
--- a/plugins/git4idea/src/git4idea/repo/GitRepositoryImpl.java
+++ b/plugins/git4idea/src/git4idea/repo/GitRepositoryImpl.java
@@ -19,11 +19,13 @@ import com.intellij.dvcs.repo.RepositoryImpl;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
+import com.intellij.openapi.vcs.AbstractVcs;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import git4idea.GitLocalBranch;
import git4idea.GitPlatformFacade;
import git4idea.GitUtil;
+import git4idea.GitVcs;
import git4idea.branch.GitBranchesCollection;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -135,6 +137,12 @@ public class GitRepositoryImpl extends RepositoryImpl implements GitRepository {
return myInfo.getState();
}
+ @Nullable
+ @Override
+ public AbstractVcs getVcs() {
+ return GitVcs.getInstance(getProject());
+ }
+
/**
* @return local and remote branches in this repository.
*/
diff --git a/plugins/git4idea/src/git4idea/reset/GitNewResetDialog.java b/plugins/git4idea/src/git4idea/reset/GitNewResetDialog.java
index 5e2cb18e7c7e..58363b917992 100644
--- a/plugins/git4idea/src/git4idea/reset/GitNewResetDialog.java
+++ b/plugins/git4idea/src/git4idea/reset/GitNewResetDialog.java
@@ -15,6 +15,7 @@
*/
package git4idea.reset;
+import com.intellij.dvcs.DvcsUtil;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
@@ -26,7 +27,6 @@ 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;
@@ -117,7 +117,7 @@ public class GitNewResetDialog extends DialogWrapper {
@NotNull
private static String getTargetText(@NotNull VcsFullCommitDetails commit) {
- String commitMessage = StringUtil.shortenTextWithEllipsis(commit.getSubject(), 20, 0);
+ String commitMessage = StringUtil.escapeXml(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());
}
@@ -127,7 +127,7 @@ public class GitNewResetDialog extends DialogWrapper {
String currentRevision = repository.getCurrentRevision();
assert currentRevision != null;
String text = repository.getCurrentBranch() == null ?
- "HEAD (" + GitUtil.getShortHash(currentRevision) + ")" :
+ "HEAD (" + DvcsUtil.getShortHash(currentRevision) + ")" :
repository.getCurrentBranch().getName();
return "<b>" + text + "</b>";
}
diff --git a/plugins/git4idea/src/git4idea/ui/GitCommitListPanel.java b/plugins/git4idea/src/git4idea/ui/GitCommitListPanel.java
index dcd1c3182b47..94d01022c83e 100644
--- a/plugins/git4idea/src/git4idea/ui/GitCommitListPanel.java
+++ b/plugins/git4idea/src/git4idea/ui/GitCommitListPanel.java
@@ -15,6 +15,7 @@
*/
package git4idea.ui;
+import com.intellij.dvcs.DvcsUtil;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.vcs.VcsDataKeys;
import com.intellij.openapi.vcs.changes.Change;
@@ -28,7 +29,6 @@ import com.intellij.util.ui.ColumnInfo;
import com.intellij.util.ui.ListTableModel;
import com.intellij.util.ui.UIUtil;
import git4idea.GitCommit;
-import git4idea.GitUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -198,7 +198,7 @@ public class GitCommitListPanel extends JPanel implements TypeSafeDataProvider {
}
private static String getHash(GitCommit commit) {
- return GitUtil.getShortHash(commit.getId().toString());
+ return DvcsUtil.getShortHash(commit.getId().toString());
}
private static String getAuthor(GitCommit commit) {
diff --git a/plugins/git4idea/src/git4idea/ui/GitUnstashDialog.java b/plugins/git4idea/src/git4idea/ui/GitUnstashDialog.java
index eccaa446b0ed..44e4f1fab4b9 100644
--- a/plugins/git4idea/src/git4idea/ui/GitUnstashDialog.java
+++ b/plugins/git4idea/src/git4idea/ui/GitUnstashDialog.java
@@ -51,6 +51,7 @@ import git4idea.merge.GitConflictResolver;
import git4idea.repo.GitRepository;
import git4idea.stash.GitStashUtils;
import git4idea.util.GitUIUtil;
+import git4idea.util.LocalChangesWouldBeOverwrittenHelper;
import git4idea.util.UntrackedFilesNotifier;
import git4idea.validators.GitBranchNameValidator;
import org.jetbrains.annotations.NotNull;
@@ -68,6 +69,8 @@ import java.util.HashSet;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
+import static git4idea.commands.GitLocalChangesWouldBeOverwrittenDetector.Operation.MERGE;
+
/**
* The unstash dialog
*/
@@ -349,7 +352,9 @@ public class GitUnstashDialog extends DialogWrapper {
}
});
GitUntrackedFilesOverwrittenByOperationDetector untrackedFilesDetector = new GitUntrackedFilesOverwrittenByOperationDetector(root);
+ GitLocalChangesWouldBeOverwrittenDetector localChangesDetector = new GitLocalChangesWouldBeOverwrittenDetector(root, MERGE);
h.addLineListener(untrackedFilesDetector);
+ h.addLineListener(localChangesDetector);
GitUtil.workingTreeChangeStarted(myProject);
try {
@@ -371,6 +376,8 @@ public class GitUnstashDialog extends DialogWrapper {
} else if (untrackedFilesDetector.wasMessageDetected()) {
UntrackedFilesNotifier.notifyUntrackedFilesOverwrittenBy(myProject, root, untrackedFilesDetector.getRelativeFilePaths(),
"unstash", null);
+ } else if (localChangesDetector.wasMessageDetected()) {
+ LocalChangesWouldBeOverwrittenHelper.showErrorDialog(myProject, root, "unstash", localChangesDetector.getRelativeFilePaths());
} else if (!res.success()) {
GitUIUtil.showOperationErrors(myProject, h.errors(), h.printableCommandLine());
}
diff --git a/plugins/git4idea/src/git4idea/ui/branch/GitBranchPopup.java b/plugins/git4idea/src/git4idea/ui/branch/GitBranchPopup.java
index bd9c8fb3a1b3..1cb7cf6a66c9 100644
--- a/plugins/git4idea/src/git4idea/ui/branch/GitBranchPopup.java
+++ b/plugins/git4idea/src/git4idea/ui/branch/GitBranchPopup.java
@@ -45,14 +45,8 @@ import javax.swing.event.HyperlinkEvent;
import java.util.List;
/**
- * <p>
* The popup which allows to quickly switch and control Git branches.
- * </p>
- * <p>
- * Use {@link #asListPopup()} to achieve the {@link ListPopup} itself.
- * </p>
- *
- * @author Kirill Likhodedov
+ * <p/>
*/
class GitBranchPopup {
@@ -160,32 +154,28 @@ class GitBranchPopup {
}
private void notifyAboutSyncedBranches() {
- VcsNotifier.getInstance(myProject).notifyImportantInfo("Synchronous branch control enabled",
- "You have several Git roots in the project and they all are checked out at the same branch. " +
- "We've enabled synchronous branch control for the project. <br/>" +
- "If you wish to control branches in different roots separately, you may <a href='settings'>disable</a> the setting.",
- new NotificationListener() {
- @Override
- public void hyperlinkUpdate(@NotNull Notification notification,
- @NotNull HyperlinkEvent event) {
- if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
- ShowSettingsUtil.getInstance().showSettingsDialog(myProject, myVcs
- .getConfigurable().getDisplayName());
- if (myVcsSettings.getSyncSetting() == GitBranchSyncSetting.DONT) {
- notification.expire();
- }
- }
- }
- }
- );
+ String description = "You have several Git roots in the project and they all are checked out at the same branch. " +
+ "We've enabled synchronous branch control for the project. <br/>" +
+ "If you wish to control branches in different roots separately, " +
+ "you may <a href='settings'>disable</a> the setting.";
+ NotificationListener listener = new NotificationListener() {
+ @Override
+ public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) {
+ if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
+ ShowSettingsUtil.getInstance().showSettingsDialog(myProject, myVcs.getConfigurable().getDisplayName());
+ if (myVcsSettings.getSyncSetting() == GitBranchSyncSetting.DONT) {
+ notification.expire();
+ }
+ }
+ }
+ };
+ VcsNotifier.getInstance(myProject).notifyImportantInfo("Synchronous branch control enabled", description, listener);
}
private ActionGroup createActions() {
DefaultActionGroup popupGroup = new DefaultActionGroup(null, false);
-
GitRepositoryManager repositoryManager = myRepositoryManager;
if (repositoryManager.moreThanOneRoot()) {
-
if (userWantsSyncControl()) {
fillWithCommonRepositoryActions(popupGroup, repositoryManager);
}
@@ -196,7 +186,6 @@ class GitBranchPopup {
else {
fillPopupWithCurrentRepositoryActions(popupGroup, null);
}
-
popupGroup.addSeparator();
return popupGroup;
}
diff --git a/plugins/git4idea/src/git4idea/ui/branch/GitBranchPopupActions.java b/plugins/git4idea/src/git4idea/ui/branch/GitBranchPopupActions.java
index dbd3f8c902e5..b3cba24540de 100644
--- a/plugins/git4idea/src/git4idea/ui/branch/GitBranchPopupActions.java
+++ b/plugins/git4idea/src/git4idea/ui/branch/GitBranchPopupActions.java
@@ -36,10 +36,6 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-/**
- *
- * @author Kirill Likhodedov
- */
class GitBranchPopupActions {
private final Project myProject;
@@ -123,7 +119,7 @@ class GitBranchPopupActions {
public void update(AnActionEvent e) {
if (myRepository.isFresh()) {
e.getPresentation().setEnabled(false);
- e.getPresentation().setDescription("Checkout is not possible before the first commit.");
+ e.getPresentation().setDescription("Checkout is not possible before the first commit");
}
}
}
diff --git a/plugins/git4idea/src/git4idea/update/GitRebaseUpdater.java b/plugins/git4idea/src/git4idea/update/GitRebaseUpdater.java
index 04ed3ac845ca..e22c15076170 100644
--- a/plugins/git4idea/src/git4idea/update/GitRebaseUpdater.java
+++ b/plugins/git4idea/src/git4idea/update/GitRebaseUpdater.java
@@ -18,12 +18,10 @@ package git4idea.update;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Ref;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.VcsNotifier;
import com.intellij.openapi.vcs.update.UpdatedFiles;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.util.ui.UIUtil;
import git4idea.GitBranch;
import git4idea.GitUtil;
import git4idea.branch.GitBranchPair;
@@ -78,42 +76,12 @@ public class GitRebaseUpdater extends GitUpdater {
return dest.getName();
}
- // TODO
- //if (!checkLocallyModified(myRoot)) {
- // cancel();
- // updateSucceeded.set(false);
- //}
-
-
- // TODO: show at any case of update successfullibility, also don't show here but for all roots
- //if (mySkippedCommits.size() > 0) {
- // GitSkippedCommits.showSkipped(myProject, mySkippedCommits);
- //}
-
public void cancel() {
myRebaser.abortRebase(myRoot);
myProgressIndicator.setText2("Refreshing files for the root " + myRoot.getPath());
myRoot.refresh(false, true);
}
- /**
- * Check and process locally modified files
- *
- * @param root the project root
- * @param ex the exception holder
- */
- protected boolean checkLocallyModified(final VirtualFile root) throws VcsException {
- final Ref<Boolean> cancelled = new Ref<Boolean>(false);
- UIUtil.invokeAndWaitIfNeeded(new Runnable() {
- public void run() {
- if (!GitUpdateLocallyModifiedDialog.showIfNeeded(myProject, root)) {
- cancelled.set(true);
- }
- }
- });
- return !cancelled.get();
- }
-
@Override
public String toString() {
return "Rebase updater";
diff --git a/plugins/git4idea/src/git4idea/update/GitUpdateLocallyModifiedDialog.form b/plugins/git4idea/src/git4idea/update/GitUpdateLocallyModifiedDialog.form
deleted file mode 100644
index a97507f24ec9..000000000000
--- a/plugins/git4idea/src/git4idea/update/GitUpdateLocallyModifiedDialog.form
+++ /dev/null
@@ -1,71 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="git4idea.update.GitUpdateLocallyModifiedDialog">
- <grid id="27dc6" binding="myRootPanel" layout-manager="GridLayoutManager" row-count="3" 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="514" height="322"/>
- </constraints>
- <properties/>
- <border type="none"/>
- <children>
- <component id="62c84" 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="git4idea/i18n/GitBundle" key="update.locally.modified.git.root"/>
- </properties>
- </component>
- <component id="24443" class="javax.swing.JLabel" binding="myGitRoot">
- <constraints>
- <grid row="0" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="0" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
- </constraints>
- <properties>
- <text value=""/>
- </properties>
- </component>
- <component id="e43af" class="javax.swing.JLabel" binding="myDescriptionLabel">
- <constraints>
- <grid row="1" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
- </constraints>
- <properties>
- <text value=""/>
- </properties>
- </component>
- <scrollpane class="com.intellij.ui.components.JBScrollPane" id="bde6e">
- <constraints>
- <grid row="2" column="1" row-span="1" col-span="1" vsize-policy="7" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
- </constraints>
- <properties/>
- <border type="none"/>
- <children>
- <component id="5d604" class="com.intellij.ui.components.JBList" binding="myFilesList" default-binding="true">
- <constraints/>
- <properties>
- <toolTipText resource-bundle="git4idea/i18n/GitBundle" key="update.locally.modified.files.tooltip"/>
- </properties>
- </component>
- </children>
- </scrollpane>
- <component id="8f763" class="javax.swing.JButton" binding="myRescanButton" default-binding="true">
- <constraints>
- <grid row="2" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="1" fill="1" indent="0" use-parent-layout="false"/>
- </constraints>
- <properties>
- <text resource-bundle="git4idea/i18n/GitBundle" key="update.locally.modified.rescan"/>
- <toolTipText resource-bundle="git4idea/i18n/GitBundle" key="update.locally.modified.rescan.tooltip"/>
- </properties>
- </component>
- <component id="ab434" class="javax.swing.JLabel">
- <constraints>
- <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="9" fill="0" indent="0" use-parent-layout="false"/>
- </constraints>
- <properties>
- <labelFor value="bde6e"/>
- <text resource-bundle="git4idea/i18n/GitBundle" key="update.locally.modified.files"/>
- <verticalAlignment value="0"/>
- </properties>
- </component>
- </children>
- </grid>
-</form>
diff --git a/plugins/git4idea/src/git4idea/update/GitUpdateLocallyModifiedDialog.java b/plugins/git4idea/src/git4idea/update/GitUpdateLocallyModifiedDialog.java
deleted file mode 100644
index c3384cea20b0..000000000000
--- a/plugins/git4idea/src/git4idea/update/GitUpdateLocallyModifiedDialog.java
+++ /dev/null
@@ -1,211 +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 git4idea.update;
-
-import com.intellij.openapi.application.ApplicationNamesInfo;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.DialogWrapper;
-import com.intellij.openapi.vcs.FilePath;
-import com.intellij.openapi.vcs.VcsException;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.util.ui.UIUtil;
-import com.intellij.vcsUtil.VcsUtil;
-import git4idea.GitUtil;
-import git4idea.commands.GitCommand;
-import git4idea.commands.GitSimpleHandler;
-import git4idea.util.StringScanner;
-import git4idea.i18n.GitBundle;
-import git4idea.rollback.GitRollbackEnvironment;
-import git4idea.util.GitUIUtil;
-
-import javax.swing.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-/**
- * The dialog that displays locally modified files during update process
- */
-public class GitUpdateLocallyModifiedDialog extends DialogWrapper {
- /**
- * The rescan button
- */
- private JButton myRescanButton;
- /**
- * The list of files to revert
- */
- private JList myFilesList;
-
- private JLabel myDescriptionLabel;
- /**
- * The git root label
- */
- private JLabel myGitRoot;
- /**
- * The root panel
- */
- private JPanel myRootPanel;
- /**
- * The collection with locally modified files
- */
- private final List<String> myLocallyModifiedFiles;
-
- /**
- * The constructor
- *
- * @param project the current project
- * @param root the vcs root
- * @param locallyModifiedFiles the collection of locally modified files to use
- */
- protected GitUpdateLocallyModifiedDialog(final Project project, final VirtualFile root, List<String> locallyModifiedFiles) {
- super(project, true);
- myLocallyModifiedFiles = locallyModifiedFiles;
- setTitle(GitBundle.getString("update.locally.modified.title"));
- myGitRoot.setText(root.getPresentableUrl());
- myFilesList.setModel(new DefaultListModel());
- setOKButtonText(GitBundle.getString("update.locally.modified.revert"));
- syncListModel();
- myRescanButton.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- myLocallyModifiedFiles.clear();
- try {
- scanFiles(project, root, myLocallyModifiedFiles);
- }
- catch (VcsException ex) {
- GitUIUtil.showOperationError(project, ex, "Checking for locally modified files");
- }
- }
- });
- myDescriptionLabel
- .setText(GitBundle.message("update.locally.modified.message", ApplicationNamesInfo.getInstance().getFullProductName()));
- init();
- }
-
- /**
- * Refresh list model according to the current content of the collection
- */
- private void syncListModel() {
- DefaultListModel listModel = (DefaultListModel)myFilesList.getModel();
- listModel.removeAllElements();
- for (String p : myLocallyModifiedFiles) {
- listModel.addElement(p);
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- protected JComponent createCenterPanel() {
- return myRootPanel;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- protected String getDimensionServiceKey() {
- return getClass().getName();
- }
-
- /**
- * Scan working tree and detect locally modified files
- *
- * @param project the project to scan
- * @param root the root to scan
- * @param files the collection with files
- * @throws VcsException if there problem with running git or working tree is dirty in unsupported way
- */
- private static void scanFiles(Project project, VirtualFile root, List<String> files) throws VcsException {
- String rootPath = root.getPath();
- GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.DIFF);
- h.addParameters("--name-status");
- h.setSilent(true);
- h.setStdoutSuppressed(true);
- StringScanner s = new StringScanner(h.run());
- while (s.hasMoreData()) {
- if (s.isEol()) {
- s.line();
- continue;
- }
- if (s.tryConsume("M\t")) {
- String path = rootPath + "/" + GitUtil.unescapePath(s.line());
- files.add(path);
- }
- else {
- throw new VcsException("Working tree is dirty in unsupported way: " + s.line());
- }
- }
- }
-
-
- /**
- * Show the dialog if needed
- *
- * @param project the project
- * @param root the vcs root
- * @return true if showing is not needed or operation completed successfully
- */
- public static boolean showIfNeeded(final Project project, final VirtualFile root) {
- final ArrayList<String> files = new ArrayList<String>();
- try {
- scanFiles(project, root, files);
- final AtomicBoolean rc = new AtomicBoolean(true);
- if (!files.isEmpty()) {
- UIUtil.invokeAndWaitIfNeeded(new Runnable() {
- public void run() {
- GitUpdateLocallyModifiedDialog d = new GitUpdateLocallyModifiedDialog(project, root, files);
- d.show();
- rc.set(d.isOK());
- }
- });
- if (rc.get()) {
- if (!files.isEmpty()) {
- revertFiles(project, root, files);
- }
- }
- }
- return rc.get();
- }
- catch (final VcsException e) {
- UIUtil.invokeAndWaitIfNeeded(new Runnable() {
- public void run() {
- GitUIUtil.showOperationError(project, e, "Checking for locally modified files");
- }
- });
- return false;
- }
- }
-
- /**
- * Revert files from the list
- *
- * @param project the project
- * @param root the vcs root
- * @param files the files to revert
- */
- private static void revertFiles(Project project, VirtualFile root, ArrayList<String> files) throws VcsException {
- // TODO consider deleted files
- GitRollbackEnvironment rollback = GitRollbackEnvironment.getInstance(project);
- ArrayList<FilePath> list = new ArrayList<FilePath>(files.size());
- for (String p : files) {
- list.add(VcsUtil.getFilePath(p));
- }
- rollback.revert(root, list);
- }
-}
diff --git a/plugins/git4idea/src/git4idea/util/LocalChangesWouldBeOverwrittenHelper.java b/plugins/git4idea/src/git4idea/util/LocalChangesWouldBeOverwrittenHelper.java
index 021ce824b9a7..7659c50e362a 100644
--- a/plugins/git4idea/src/git4idea/util/LocalChangesWouldBeOverwrittenHelper.java
+++ b/plugins/git4idea/src/git4idea/util/LocalChangesWouldBeOverwrittenHelper.java
@@ -35,12 +35,12 @@ import java.util.List;
public class LocalChangesWouldBeOverwrittenHelper {
@NotNull
- public static String getErrorNotificationDescription() {
+ private static String getErrorNotificationDescription() {
return getErrorDescription(true);
}
@NotNull
- public static String getErrorDialogDescription() {
+ private static String getErrorDialogDescription() {
return getErrorDescription(false);
}
@@ -56,7 +56,7 @@ public class LocalChangesWouldBeOverwrittenHelper {
}
}
- public static void showErrorNotification(@NotNull final Project project, @NotNull VirtualFile root, @NotNull final String operationName,
+ public static void showErrorNotification(@NotNull final Project project, @NotNull final VirtualFile root, @NotNull final String operationName,
@NotNull final Collection<String> relativeFilePaths) {
final Collection<String> absolutePaths = GitUtil.toAbsolute(root, relativeFilePaths);
final List<Change> changes = GitUtil.findLocalChangesForPaths(project, root, absolutePaths, false);
@@ -66,20 +66,33 @@ public class LocalChangesWouldBeOverwrittenHelper {
@Override
protected void hyperlinkActivated(@NotNull Notification notification,
@NotNull HyperlinkEvent e) {
- String title = "Local Changes Prevent from " + StringUtil.capitalize(operationName);
- String description = getErrorDialogDescription();
- if (changes.isEmpty()) {
- GitUtil.showPathsInDialog(project, absolutePaths, title, description);
- }
- else {
- DialogBuilder builder = new DialogBuilder(project);
- builder.setNorthPanel(new MultiLineLabel(description));
- builder.setCenterPanel(new ChangesBrowserWithRollback(project, changes));
- builder.addOkAction();
- builder.setTitle(title);
- builder.show();
- }
+ showErrorDialog(project, operationName, changes, absolutePaths);
}
});
}
+
+ public static void showErrorDialog(@NotNull Project project, @NotNull VirtualFile root, @NotNull String operationName,
+ @NotNull Collection<String> relativeFilePaths) {
+ Collection<String> absolutePaths = GitUtil.toAbsolute(root, relativeFilePaths);
+ List<Change> changes = GitUtil.findLocalChangesForPaths(project, root, absolutePaths, false);
+ showErrorDialog(project, operationName, changes, absolutePaths);
+ }
+
+ private static void showErrorDialog(@NotNull Project project, @NotNull String operationName, @NotNull List<Change> changes,
+ @NotNull Collection<String> absolutePaths) {
+ String title = "Local Changes Prevent from " + StringUtil.capitalize(operationName);
+ String description = getErrorDialogDescription();
+ if (changes.isEmpty()) {
+ GitUtil.showPathsInDialog(project, absolutePaths, title, description);
+ }
+ else {
+ DialogBuilder builder = new DialogBuilder(project);
+ builder.setNorthPanel(new MultiLineLabel(description));
+ builder.setCenterPanel(new ChangesBrowserWithRollback(project, changes));
+ builder.addOkAction();
+ builder.setTitle(title);
+ builder.show();
+ }
+ }
+
}
diff --git a/plugins/git4idea/tests/git4idea/history/GitHistoryUtilsTest.java b/plugins/git4idea/tests/git4idea/history/GitHistoryUtilsTest.java
index 29072ea53940..bdf87b265427 100644
--- a/plugins/git4idea/tests/git4idea/history/GitHistoryUtilsTest.java
+++ b/plugins/git4idea/tests/git4idea/history/GitHistoryUtilsTest.java
@@ -38,9 +38,9 @@ import java.io.File;
import java.io.IOException;
import java.util.*;
+import static com.intellij.dvcs.DvcsUtil.getShortHash;
import static com.intellij.openapi.vcs.Executor.overwrite;
import static com.intellij.openapi.vcs.Executor.touch;
-import static git4idea.GitUtil.getShortHash;
import static git4idea.test.GitExecutor.*;
import static git4idea.test.GitTestUtil.USER_EMAIL;
import static git4idea.test.GitTestUtil.USER_NAME;
diff --git a/plugins/git4idea/tests/git4idea/log/GitRefManagerTest.java b/plugins/git4idea/tests/git4idea/log/GitRefManagerTest.java
index 14d88315c596..2ce560800066 100644
--- a/plugins/git4idea/tests/git4idea/log/GitRefManagerTest.java
+++ b/plugins/git4idea/tests/git4idea/log/GitRefManagerTest.java
@@ -3,6 +3,7 @@ package git4idea.log;
import com.intellij.mock.MockVirtualFile;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.vcs.AbstractVcs;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.testFramework.UsefulTestCase;
import com.intellij.util.Function;
@@ -285,6 +286,12 @@ public class GitRefManagerTest extends UsefulTestCase {
@Nullable
@Override
+ public AbstractVcs getVcs() {
+ return null;
+ }
+
+ @Nullable
+ @Override
public String getCurrentRevision() {
throw new UnsupportedOperationException();
}
diff --git a/plugins/github/github.iml b/plugins/github/github.iml
index 54d546aa0886..7866631c1521 100644
--- a/plugins/github/github.iml
+++ b/plugins/github/github.iml
@@ -18,7 +18,8 @@
<orderEntry type="module" module-name="platform-impl" />
<orderEntry type="module" module-name="util" />
<orderEntry type="library" name="gson" level="project" />
- <orderEntry type="module" module-name="dvcs" />
+ <orderEntry type="module" module-name="dvcs-impl" />
+ <orderEntry type="module" module-name="dvcs-api" />
<orderEntry type="module" module-name="testFramework" scope="TEST" />
<orderEntry type="module" module-name="xml-openapi" />
<orderEntry type="module" module-name="xml" />
diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java
index bfceb0ceec39..719f8b956432 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java
@@ -48,6 +48,7 @@ import org.jetbrains.plugins.github.util.*;
import java.io.IOException;
import java.util.Collections;
+import static git4idea.commands.GitLocalChangesWouldBeOverwrittenDetector.Operation.CHECKOUT;
import static org.jetbrains.plugins.github.util.GithubUtil.setVisibleEnabled;
/**
@@ -256,7 +257,9 @@ public class GithubRebaseAction extends DumbAwareAction {
final GitUntrackedFilesOverwrittenByOperationDetector untrackedFilesDetector =
new GitUntrackedFilesOverwrittenByOperationDetector(root);
+ final GitLocalChangesWouldBeOverwrittenDetector localChangesDetector = new GitLocalChangesWouldBeOverwrittenDetector(root, CHECKOUT);
handler.addLineListener(untrackedFilesDetector);
+ handler.addLineListener(localChangesDetector);
GitTask pullTask = new GitTask(project, handler, "Rebasing from upstream/master");
pullTask.setProgressIndicator(indicator);
@@ -271,7 +274,8 @@ public class GithubRebaseAction extends DumbAwareAction {
@Override
protected void onFailure() {
- GitUpdateResult result = rebaser.handleRebaseFailure(handler, root, rebaseConflictDetector, untrackedFilesDetector);
+ GitUpdateResult result = rebaser.handleRebaseFailure(handler, root, rebaseConflictDetector,
+ untrackedFilesDetector, localChangesDetector);
repositoryManager.updateRepository(root);
if (result == GitUpdateResult.NOTHING_TO_UPDATE ||
result == GitUpdateResult.SUCCESS ||
diff --git a/plugins/google-app-engine/source/com/intellij/appengine/facet/AppEngineFacetEditor.java b/plugins/google-app-engine/source/com/intellij/appengine/facet/AppEngineFacetEditor.java
index 6e45480f1156..a01878f1e29d 100644
--- a/plugins/google-app-engine/source/com/intellij/appengine/facet/AppEngineFacetEditor.java
+++ b/plugins/google-app-engine/source/com/intellij/appengine/facet/AppEngineFacetEditor.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.
@@ -60,6 +60,7 @@ public class AppEngineFacetEditor extends FacetEditorTab {
myContext = context;
mySdkEditor = new AppEngineSdkEditor(myContext.getProject());
validatorsManager.registerValidator(new FacetEditorValidator() {
+ @NotNull
@Override
public ValidationResult check() {
return AppEngineSdkUtil.checkPath(mySdkEditor.getPath());
diff --git a/plugins/gradle/src/META-INF/plugin.xml b/plugins/gradle/src/META-INF/plugin.xml
index f15f424a10b8..f00346625e81 100644
--- a/plugins/gradle/src/META-INF/plugin.xml
+++ b/plugins/gradle/src/META-INF/plugin.xml
@@ -106,6 +106,7 @@
<applicationService serviceImplementation="org.jetbrains.plugins.gradle.service.GradleInstallationManager"/>
+ <applicationService serviceImplementation="org.jetbrains.plugins.gradle.settings.GradleSystemSettings"/>
<projectService serviceImplementation="org.jetbrains.plugins.gradle.settings.GradleSettings"/>
<projectService serviceImplementation="org.jetbrains.plugins.gradle.settings.GradleLocalSettings"/>
<projectService serviceImplementation="org.jetbrains.plugins.gradle.service.project.GradleNotification"/>
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/test/runner/events/BeforeSuiteEvent.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/test/runner/events/BeforeSuiteEvent.java
index 85e06cdc7dda..c9a69b0987d6 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/test/runner/events/BeforeSuiteEvent.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/test/runner/events/BeforeSuiteEvent.java
@@ -47,10 +47,10 @@ public class BeforeSuiteEvent extends AbstractTestEvent {
getConsoleManager().getTestsMap().put(testId, testProxy);
final SMTestProxy parentTestProxy = getConsoleManager().getTestsMap().get(parentTestId);
if (parentTestProxy != null) {
- parentTestProxy.addChild(testProxy);
addToInvokeLater(new Runnable() {
@Override
public void run() {
+ parentTestProxy.addChild(testProxy);
getResultsViewer().onSuiteStarted(testProxy);
}
});
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/test/runner/events/BeforeTestEvent.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/test/runner/events/BeforeTestEvent.java
index bd512bc65b8a..8b7976406e2f 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/test/runner/events/BeforeTestEvent.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/test/runner/events/BeforeTestEvent.java
@@ -46,12 +46,22 @@ public class BeforeTestEvent extends AbstractTestEvent {
getConsoleManager().getTestsMap().put(testId, testProxy);
if (StringUtil.isEmpty(parentTestId)) {
- getResultsViewer().getTestsRootNode().addChild(testProxy);
+ addToInvokeLater(new Runnable() {
+ @Override
+ public void run() {
+ getResultsViewer().getTestsRootNode().addChild(testProxy);
+ }
+ });
}
else {
final SMTestProxy parentTestProxy = getConsoleManager().getTestsMap().get(parentTestId);
if (parentTestProxy != null) {
- parentTestProxy.addChild(testProxy);
+ addToInvokeLater(new Runnable() {
+ @Override
+ public void run() {
+ parentTestProxy.addChild(testProxy);
+ }
+ });
}
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleSettings.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleSettings.java
index d85e6cf1a742..db1569965d4a 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleSettings.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleSettings.java
@@ -30,26 +30,24 @@ import java.util.Set;
/**
* Holds shared project-level gradle-related settings (should be kept at the '*.ipr' or under '.idea').
- *
+ *
* @author peter
*/
@State(
- name = "GradleSettings",
- storages = {
- @Storage(file = StoragePathMacros.PROJECT_FILE),
- @Storage(file = StoragePathMacros.PROJECT_CONFIG_DIR + "/gradle.xml", scheme = StorageScheme.DIRECTORY_BASED)
- }
+ name = "GradleSettings",
+ storages = {
+ @Storage(file = StoragePathMacros.PROJECT_FILE),
+ @Storage(file = StoragePathMacros.PROJECT_CONFIG_DIR + "/gradle.xml", scheme = StorageScheme.DIRECTORY_BASED)
+ }
)
public class GradleSettings extends AbstractExternalSystemSettings<GradleSettings, GradleProjectSettings, GradleSettingsListener>
- implements PersistentStateComponent<GradleSettings.MyState>
-{
+ implements PersistentStateComponent<GradleSettings.MyState> {
- @Nullable private String myServiceDirectoryPath;
- @Nullable private String myGradleVmOptions;
- private boolean myIsOfflineWork;
+ private final GradleSystemSettings mySystemSettings;
public GradleSettings(@NotNull Project project) {
super(GradleSettingsListener.TOPIC, project);
+ mySystemSettings = GradleSystemSettings.getInstance();
}
@NotNull
@@ -65,9 +63,6 @@ public class GradleSettings extends AbstractExternalSystemSettings<GradleSetting
@Override
protected void copyExtraSettingsFrom(@NotNull GradleSettings settings) {
- myServiceDirectoryPath = settings.getServiceDirectoryPath();
- myGradleVmOptions = settings.getGradleVmOptions();
- myIsOfflineWork = settings.isOfflineWork();
}
@SuppressWarnings("unchecked")
@@ -76,58 +71,52 @@ public class GradleSettings extends AbstractExternalSystemSettings<GradleSetting
public GradleSettings.MyState getState() {
MyState state = new MyState();
fillState(state);
- state.serviceDirectoryPath = myServiceDirectoryPath;
- state.gradleVmOptions = myGradleVmOptions;
- state.offlineWork = myIsOfflineWork;
return state;
}
@Override
public void loadState(MyState state) {
super.loadState(state);
- myServiceDirectoryPath = state.serviceDirectoryPath;
- myGradleVmOptions = state.gradleVmOptions;
- myIsOfflineWork = state.offlineWork;
}
/**
* @return service directory path (if defined). 'Service directory' is a directory which is used internally by gradle during
- * calls to the tooling api. E.g. it holds downloaded binaries (dependency jars). We allow to define it because there
- * is a possible situation when a user wants to configure particular directory to be excluded from anti-virus protection
- * in order to increase performance
+ * calls to the tooling api. E.g. it holds downloaded binaries (dependency jars). We allow to define it because there
+ * is a possible situation when a user wants to configure particular directory to be excluded from anti-virus protection
+ * in order to increase performance
*/
@Nullable
public String getServiceDirectoryPath() {
- return myServiceDirectoryPath;
+ return mySystemSettings.getServiceDirectoryPath();
}
public void setServiceDirectoryPath(@Nullable String newPath) {
+ String myServiceDirectoryPath = mySystemSettings.getServiceDirectoryPath();
if (!Comparing.equal(myServiceDirectoryPath, newPath)) {
- String oldPath = myServiceDirectoryPath;
- myServiceDirectoryPath = newPath;
- getPublisher().onServiceDirectoryPathChange(oldPath, newPath);
- }
+ mySystemSettings.setServiceDirectoryPath(newPath);
+ getPublisher().onServiceDirectoryPathChange(myServiceDirectoryPath, newPath);
+ }
}
@Nullable
public String getGradleVmOptions() {
- return myGradleVmOptions;
+ return mySystemSettings.getGradleVmOptions();
}
-
+
public void setGradleVmOptions(@Nullable String gradleVmOptions) {
+ String myGradleVmOptions = mySystemSettings.getGradleVmOptions();
if (!Comparing.equal(myGradleVmOptions, gradleVmOptions)) {
- String old = myGradleVmOptions;
- myGradleVmOptions = gradleVmOptions;
- getPublisher().onGradleVmOptionsChange(old, gradleVmOptions);
+ mySystemSettings.setGradleVmOptions(gradleVmOptions);
+ getPublisher().onGradleVmOptionsChange(myGradleVmOptions, gradleVmOptions);
}
}
public boolean isOfflineWork() {
- return myIsOfflineWork;
+ return mySystemSettings.isOfflineWork();
}
public void setOfflineWork(boolean isOfflineWork) {
- myIsOfflineWork = isOfflineWork;
+ mySystemSettings.setOfflineWork(isOfflineWork);
}
@Override
@@ -143,9 +132,6 @@ public class GradleSettings extends AbstractExternalSystemSettings<GradleSetting
public static class MyState implements State<GradleProjectSettings> {
private Set<GradleProjectSettings> myProjectSettings = ContainerUtilRt.newTreeSet();
- public String serviceDirectoryPath;
- public String gradleVmOptions;
- public boolean offlineWork;
@AbstractCollection(surroundWithTag = false, elementTypes = {GradleProjectSettings.class})
public Set<GradleProjectSettings> getLinkedExternalProjectsSettings() {
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleSystemSettings.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleSystemSettings.java
new file mode 100644
index 000000000000..b24bd24cbf0d
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleSystemSettings.java
@@ -0,0 +1,92 @@
+/*
+ * 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.settings;
+
+import com.intellij.openapi.components.*;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 14/8/2014
+ */
+@State(
+ name = "GradleSystemSettings",
+ storages = {
+ @Storage(file = StoragePathMacros.APP_CONFIG + "/gradle.settings.xml")
+ }
+)
+public class GradleSystemSettings implements PersistentStateComponent<GradleSystemSettings.MyState> {
+
+ @Nullable private String myServiceDirectoryPath;
+ @Nullable private String myGradleVmOptions;
+ private boolean myIsOfflineWork;
+
+ @NotNull
+ public static GradleSystemSettings getInstance() {
+ return ServiceManager.getService(GradleSystemSettings.class);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Nullable
+ @Override
+ public GradleSystemSettings.MyState getState() {
+ MyState state = new MyState();
+ state.serviceDirectoryPath = myServiceDirectoryPath;
+ state.gradleVmOptions = myGradleVmOptions;
+ state.offlineWork = myIsOfflineWork;
+ return state;
+ }
+
+ @Override
+ public void loadState(MyState state) {
+ myServiceDirectoryPath = state.serviceDirectoryPath;
+ myGradleVmOptions = state.gradleVmOptions;
+ myIsOfflineWork = state.offlineWork;
+ }
+
+ @Nullable
+ public String getServiceDirectoryPath() {
+ return myServiceDirectoryPath;
+ }
+
+ public void setServiceDirectoryPath(@Nullable String newPath) {
+ myServiceDirectoryPath = newPath;
+ }
+
+ @Nullable
+ public String getGradleVmOptions() {
+ return myGradleVmOptions;
+ }
+
+ public void setGradleVmOptions(@Nullable String gradleVmOptions) {
+ myGradleVmOptions = gradleVmOptions;
+ }
+
+ public boolean isOfflineWork() {
+ return myIsOfflineWork;
+ }
+
+ public void setOfflineWork(boolean isOfflineWork) {
+ myIsOfflineWork = isOfflineWork;
+ }
+
+ public static class MyState {
+ public String serviceDirectoryPath;
+ public String gradleVmOptions;
+ public boolean offlineWork;
+ }
+} \ No newline at end of file
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/annotator/inspections/GroovySingletonAnnotationInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/annotator/inspections/GroovySingletonAnnotationInspection.java
index e44ade2d6bd7..f43de1fbb993 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/annotator/inspections/GroovySingletonAnnotationInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/annotator/inspections/GroovySingletonAnnotationInspection.java
@@ -36,6 +36,7 @@ import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
public class GroovySingletonAnnotationInspection extends BaseInspection {
public static final String SINGLETON = GroovyCommonClassNames.GROOVY_LANG_SINGLETON;
+ @NotNull
@Override
protected BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyAssignabilityCheckInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyAssignabilityCheckInspection.java
index 1d44e8978934..005e5e38a7a0 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyAssignabilityCheckInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyAssignabilityCheckInspection.java
@@ -30,6 +30,7 @@ import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiSubstitutorImpl;
import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.Function;
import com.intellij.util.IncorrectOperationException;
@@ -67,6 +68,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrReturnState
import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrThrowStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.clauses.GrForInClause;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.*;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrLiteral;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrString;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrIndexProperty;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression;
@@ -85,6 +87,7 @@ import org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.ClosureParameterEnhan
import org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.ClosureParamsEnhancer;
import org.jetbrains.plugins.groovy.lang.psi.util.*;
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
+import org.jetbrains.plugins.groovy.spock.SpockUtils;
import javax.swing.*;
import java.util.ArrayList;
@@ -768,6 +771,8 @@ public class GroovyAssignabilityCheckInspection extends BaseInspection {
private void checkOperator(CallInfo<? extends GrBinaryExpression> info) {
if (hasErrorElements(info.getCall())) return;
+ if (isSpockTimesOperator(info.getCall())) return;
+
GroovyResolveResult[] results = info.multiResolve();
GroovyResolveResult resolveResult = info.advancedResolve();
@@ -787,6 +792,20 @@ public class GroovyAssignabilityCheckInspection extends BaseInspection {
}
}
+ private static boolean isSpockTimesOperator(GrBinaryExpression call) {
+ if (call.getOperationTokenType() == GroovyTokenTypes.mSTAR && PsiUtil.isExpressionStatement(call)) {
+ GrExpression operand = call.getLeftOperand();
+ if (operand instanceof GrLiteral && TypesUtil.isNumericType(operand.getType())) {
+ PsiClass aClass = PsiUtil.getContextClass(call);
+ if (InheritanceUtil.isInheritor(aClass, false, SpockUtils.SPEC_CLASS_NAME)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
private static boolean isOperatorWithSimpleTypes(GrBinaryExpression binary, GroovyResolveResult result) {
if (result.getElement() != null && result.isApplicable()) {
return false;
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyAssignmentCanBeOperatorAssignmentInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyAssignmentCanBeOperatorAssignmentInspection.java
index a419af33b55a..2fe54796e192 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyAssignmentCanBeOperatorAssignmentInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyAssignmentCanBeOperatorAssignmentInspection.java
@@ -102,13 +102,14 @@ public class GroovyAssignmentCanBeOperatorAssignmentInspection
return lhs.getText() + ' ' + signText + "= " + rhsRhs.getText();
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new ReplaceAssignmentWithOperatorAssignmentVisitor();
}
@Override
- public GroovyFix buildFix(PsiElement location) {
+ public GroovyFix buildFix(@NotNull PsiElement location) {
return new ReplaceAssignmentWithOperatorAssignmentFix(
(GrAssignmentExpression) location);
}
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyAssignmentToForLoopParameterInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyAssignmentToForLoopParameterInspection.java
index 595a653dd63b..a031735e0e36 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyAssignmentToForLoopParameterInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyAssignmentToForLoopParameterInspection.java
@@ -53,6 +53,7 @@ public class GroovyAssignmentToForLoopParameterInspection extends BaseInspection
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyNestedAssignmentInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyNestedAssignmentInspection.java
index e191302f55b1..0a7a3808a959 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyNestedAssignmentInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyNestedAssignmentInspection.java
@@ -45,6 +45,7 @@ public class GroovyNestedAssignmentInspection extends BaseInspection {
return "Nested assignment expression #loc";
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyResultOfAssignmentUsedInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyResultOfAssignmentUsedInspection.java
index 8a459b1e2d15..efdd32fb904b 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyResultOfAssignmentUsedInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyResultOfAssignmentUsedInspection.java
@@ -45,6 +45,7 @@ public class GroovyResultOfAssignmentUsedInspection extends BaseInspection {
return "Result of assignment expression used #loc";
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyConstructorNamedArgumentsInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyConstructorNamedArgumentsInspection.java
index 6941d89878cc..13ee4c229cc0 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyConstructorNamedArgumentsInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyConstructorNamedArgumentsInspection.java
@@ -49,6 +49,7 @@ public class GroovyConstructorNamedArgumentsInspection extends BaseInspection {
return true;
}
+ @NotNull
@Override
protected BaseInspectionVisitor buildVisitor() {
return new MyVisitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyDivideByZeroInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyDivideByZeroInspection.java
index e5db424089fa..02b8f38a9fe8 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyDivideByZeroInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyDivideByZeroInspection.java
@@ -55,6 +55,7 @@ public class GroovyDivideByZeroInspection extends BaseInspection {
return true;
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyDocCheckInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyDocCheckInspection.java
index 1145def39ff8..a4263ea34798 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyDocCheckInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyDocCheckInspection.java
@@ -59,6 +59,7 @@ public class GroovyDocCheckInspection extends BaseInspection {
return true;
}
+ @NotNull
@Override
protected BaseInspectionVisitor buildVisitor() {
return new BaseInspectionVisitor() {
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyInfiniteLoopStatementInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyInfiniteLoopStatementInspection.java
index bd5a2b202ee4..d6dede4fdabf 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyInfiniteLoopStatementInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyInfiniteLoopStatementInspection.java
@@ -51,6 +51,7 @@ public class GroovyInfiniteLoopStatementInspection extends BaseInspection {
return true;
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyInfiniteRecursionInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyInfiniteRecursionInspection.java
index 62ad7165a153..7fc52f210c1b 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyInfiniteRecursionInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyInfiniteRecursionInspection.java
@@ -51,6 +51,7 @@ public class GroovyInfiniteRecursionInspection extends BaseInspection {
return true;
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyLabeledStatementInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyLabeledStatementInspection.java
index 49d173d5584a..4d1856c3d151 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyLabeledStatementInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyLabeledStatementInspection.java
@@ -29,6 +29,7 @@ import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
* @author Maxim.Medvedev
*/
public class GroovyLabeledStatementInspection extends BaseInspection {
+ @NotNull
@Override
protected BaseInspectionVisitor buildVisitor() {
return new MyVisitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyNonShortCircuitBooleanInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyNonShortCircuitBooleanInspection.java
index c81175e3070b..d3c8de759037 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyNonShortCircuitBooleanInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyNonShortCircuitBooleanInspection.java
@@ -60,7 +60,7 @@ public class GroovyNonShortCircuitBooleanInspection extends BaseInspection {
}
@Override
- public GroovyFix buildFix(PsiElement location) {
+ public GroovyFix buildFix(@NotNull PsiElement location) {
return new NonShortCircuitBooleanFix();
}
@@ -96,6 +96,7 @@ public class GroovyNonShortCircuitBooleanInspection extends BaseInspection {
}
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyResultOfObjectAllocationIgnoredInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyResultOfObjectAllocationIgnoredInspection.java
index 19c83142d04c..920878223090 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyResultOfObjectAllocationIgnoredInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyResultOfObjectAllocationIgnoredInspection.java
@@ -57,6 +57,7 @@ public class GroovyResultOfObjectAllocationIgnoredInspection extends BaseInspect
return true;
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/NewInstanceOfSingletonInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/NewInstanceOfSingletonInspection.java
index 479f79f74cda..74162fe82c34 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/NewInstanceOfSingletonInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/bugs/NewInstanceOfSingletonInspection.java
@@ -41,6 +41,7 @@ import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
public class NewInstanceOfSingletonInspection extends BaseInspection {
private static final Logger LOG = Logger.getInstance(NewInstanceOfSingletonInspection.class);
+ @NotNull
@Override
protected BaseInspectionVisitor buildVisitor() {
return new BaseInspectionVisitor() {
@@ -67,7 +68,7 @@ public class NewInstanceOfSingletonInspection extends BaseInspection {
}
@Override
- protected GroovyFix buildFix(final PsiElement location) {
+ protected GroovyFix buildFix(@NotNull final PsiElement location) {
final GrCodeReferenceElement refElement = ((GrNewExpression)location).getReferenceElement();
LOG.assertTrue(refElement != null);
final GrTypeDefinition singleton = (GrTypeDefinition)refElement.resolve();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/ClashingTraitMethodsInspectionBase.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/ClashingTraitMethodsInspectionBase.java
new file mode 100644
index 000000000000..4195dd9a11ae
--- /dev/null
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/ClashingTraitMethodsInspectionBase.java
@@ -0,0 +1,153 @@
+/*
+ * 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.codeInspection.confusing;
+
+import com.intellij.codeInspection.LocalQuickFix;
+import com.intellij.codeInspection.ProblemHighlightType;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.HierarchicalMethodSignature;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiMethod;
+import com.intellij.psi.PsiModifier;
+import com.intellij.psi.util.PsiFormatUtil;
+import com.intellij.psi.util.PsiFormatUtilBase;
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.groovy.codeInspection.BaseInspection;
+import org.jetbrains.plugins.groovy.codeInspection.BaseInspectionVisitor;
+import org.jetbrains.plugins.groovy.codeInspection.GroovyFix;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
+import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrTraitMethod;
+import org.jetbrains.plugins.groovy.lang.psi.util.GrTraitUtil;
+
+import java.util.Collection;
+import java.util.List;
+
+public abstract class ClashingTraitMethodsInspectionBase extends BaseInspection {
+ protected static final Logger LOG = Logger.getInstance(ClashingTraitMethodsInspectionBase.class);
+
+ @NotNull
+ protected static List<ClashingMethod> collectClassingMethods(@NotNull GrTypeDefinition typeDefinition) {
+ Collection<HierarchicalMethodSignature> visibleSignatures = typeDefinition.getVisibleSignatures();
+
+ List<ClashingMethod> clashingMethods = ContainerUtil.newArrayList();
+ for (HierarchicalMethodSignature signature : visibleSignatures) {
+ PsiMethod method = signature.getMethod();
+ if (method instanceof GrTraitMethod && method.getContainingClass() == typeDefinition) {
+ List<HierarchicalMethodSignature> superSignatures = signature.getSuperSignatures();
+ if (superSignatures.size() > 1) {
+ List<GrTypeDefinition> traits = ContainerUtil.newArrayList();
+ for (HierarchicalMethodSignature superSignature : superSignatures) {
+ PsiMethod superMethod = superSignature.getMethod();
+ PsiClass superClass = superMethod.getContainingClass();
+ if (GrTraitUtil.isTrait(superClass) &&
+ !superMethod.getModifierList().hasExplicitModifier(PsiModifier.ABSTRACT)) {
+ traits.add((GrTypeDefinition)superClass);
+ }
+ }
+
+ if (traits.size() > 1) {
+ clashingMethods.add(new ClashingMethod(signature, traits));
+ }
+ }
+ }
+ }
+
+ return clashingMethods;
+ }
+
+ @NotNull
+ private static List<PsiClass> collectImplementedTraits(@NotNull GrTypeDefinition typeDefinition) {
+ return ContainerUtil.findAll(typeDefinition.getSupers(), new Condition<PsiClass>() {
+ @Override
+ public boolean value(PsiClass aClass) {
+ return GrTraitUtil.isTrait(aClass);
+ }
+ });
+ }
+
+ @NotNull
+ @Override
+ protected BaseInspectionVisitor buildVisitor() {
+ return new BaseInspectionVisitor() {
+ @Override
+ public void visitTypeDefinition(GrTypeDefinition typeDefinition) {
+ super.visitTypeDefinition(typeDefinition);
+
+ List<PsiClass> superTraits = collectImplementedTraits(typeDefinition);
+
+ if (superTraits.size() < 2) return;
+
+ List<ClashingMethod> clashingMethods = collectClassingMethods(typeDefinition);
+
+ for (ClashingMethod clashing : clashingMethods) {
+ registerError(typeDefinition.getNameIdentifierGroovy(), buildWarning(clashing), new LocalQuickFix[]{getFix()}, ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
+ }
+ }
+
+ @NotNull
+ private String buildWarning(@NotNull ClashingMethod entry) {
+ return "Traits " + buildTraitString(entry) + " contain clashing methods with signature " + buildSignatureString(entry);
+ }
+
+ @NotNull
+ private String buildSignatureString(@NotNull ClashingMethod entry) {
+ HierarchicalMethodSignature signature = entry.getSignature();
+ return PsiFormatUtil.formatMethod(signature.getMethod(), signature.getSubstitutor(),
+ PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_PARAMETERS,
+ PsiFormatUtilBase.SHOW_TYPE);
+ }
+
+ @NotNull
+ private String buildTraitString(@NotNull ClashingMethod entry) {
+ return StringUtil.join(entry.getSuperTraits(), new Function<GrTypeDefinition, String>() {
+ @Override
+ public String fun(GrTypeDefinition tr) {
+ return tr.getName();
+ }
+ }, ", ");
+ }
+ };
+ }
+
+ @NotNull
+ protected LocalQuickFix getFix(){
+ return GroovyFix.EMPTY_FIX;
+ }
+
+ protected static class ClashingMethod {
+ private final HierarchicalMethodSignature mySignature;
+ private final List<GrTypeDefinition> mySuperTraits;
+
+ public ClashingMethod(@NotNull HierarchicalMethodSignature signature, @NotNull List<GrTypeDefinition> superTraits) {
+ mySignature = signature;
+ mySuperTraits = superTraits;
+ }
+
+ @NotNull
+ public HierarchicalMethodSignature getSignature() {
+ return mySignature;
+ }
+
+ @NotNull
+ public List<GrTypeDefinition> getSuperTraits() {
+ return mySuperTraits;
+ }
+ }
+}
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GrDeprecatedAPIUsageInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GrDeprecatedAPIUsageInspection.java
index 916ec5408d90..b8aa7570e08b 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GrDeprecatedAPIUsageInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GrDeprecatedAPIUsageInspection.java
@@ -62,6 +62,7 @@ public class GrDeprecatedAPIUsageInspection extends BaseInspection {
return "GrDeprecatedAPIUsage";
}
+ @NotNull
@Override
protected BaseInspectionVisitor buildVisitor() {
return new BaseInspectionVisitor() {
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GrPackageInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GrPackageInspection.java
index 2b561b239112..8a1a6007f314 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GrPackageInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GrPackageInspection.java
@@ -79,6 +79,7 @@ public class GrPackageInspection extends BaseInspection {
}
+ @NotNull
@Override
protected BaseInspectionVisitor buildVisitor() {
return new BaseInspectionVisitor() {
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GrUnusedIncDecInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GrUnusedIncDecInspection.java
index b5dc34e2318a..60ad30f642d5 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GrUnusedIncDecInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GrUnusedIncDecInspection.java
@@ -51,6 +51,7 @@ import java.util.List;
*/
public class GrUnusedIncDecInspection extends BaseInspection {
private static final Logger LOG = Logger.getInstance(GrUnusedIncDecInspection.class);
+ @NotNull
@Override
protected BaseInspectionVisitor buildVisitor() {
return new GrUnusedIncDecInspectionVisitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyConditionalInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyConditionalInspection.java
index 6b532066f1f5..55b314ef6b81 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyConditionalInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyConditionalInspection.java
@@ -45,6 +45,7 @@ public class GroovyConditionalInspection extends BaseInspection {
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyDoubleNegationInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyDoubleNegationInspection.java
index 7b22f17b289c..b293326196df 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyDoubleNegationInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyDoubleNegationInspection.java
@@ -56,7 +56,7 @@ public class GroovyDoubleNegationInspection extends BaseInspection {
@Override
@Nullable
- protected GroovyFix buildFix(PsiElement location) {
+ protected GroovyFix buildFix(@NotNull PsiElement location) {
return new DoubleNegationFix();
}
@@ -105,6 +105,7 @@ public class GroovyDoubleNegationInspection extends BaseInspection {
}
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new DoubleNegationVisitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyEmptyStatementBodyInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyEmptyStatementBodyInspection.java
index 4dd95e9e3b61..af8f89ad4aed 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyEmptyStatementBodyInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyEmptyStatementBodyInspection.java
@@ -53,6 +53,7 @@ public class GroovyEmptyStatementBodyInspection extends BaseInspection {
}
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyNegatedConditionalInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyNegatedConditionalInspection.java
index e28e499cfb28..e6611c083e8b 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyNegatedConditionalInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyNegatedConditionalInspection.java
@@ -47,6 +47,7 @@ public class GroovyNegatedConditionalInspection extends BaseInspection {
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyNegatedIfInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyNegatedIfInspection.java
index 471428f83a13..611c292ae6d1 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyNegatedIfInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyNegatedIfInspection.java
@@ -47,6 +47,7 @@ public class GroovyNegatedIfInspection extends BaseInspection {
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyNestedConditionalInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyNestedConditionalInspection.java
index 621247d6563c..108c0ebd897b 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyNestedConditionalInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyNestedConditionalInspection.java
@@ -46,6 +46,7 @@ public class GroovyNestedConditionalInspection extends BaseInspection {
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyNestedSwitchInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyNestedSwitchInspection.java
index 72a16dda7ed6..ad289110f4f2 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyNestedSwitchInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyNestedSwitchInspection.java
@@ -46,6 +46,7 @@ public class GroovyNestedSwitchInspection extends BaseInspection {
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyOctalIntegerInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyOctalIntegerInspection.java
index e3bb3025508b..c9e587135a17 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyOctalIntegerInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyOctalIntegerInspection.java
@@ -45,6 +45,7 @@ public class GroovyOctalIntegerInspection extends BaseInspection {
return "Octal integer #ref #loc";
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new BaseInspectionVisitor() {
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyOverlyComplexArithmeticExpressionInspectionBase.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyOverlyComplexArithmeticExpressionInspectionBase.java
index 3d09c275ee3f..24b4d0ebb853 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyOverlyComplexArithmeticExpressionInspectionBase.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyOverlyComplexArithmeticExpressionInspectionBase.java
@@ -60,6 +60,7 @@ public class GroovyOverlyComplexArithmeticExpressionInspectionBase extends BaseI
return "Overly complex arithmetic expression #loc";
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyOverlyComplexBooleanExpressionInspectionBase.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyOverlyComplexBooleanExpressionInspectionBase.java
index 73c74fb52d1f..6a4d9c0d54da 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyOverlyComplexBooleanExpressionInspectionBase.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyOverlyComplexBooleanExpressionInspectionBase.java
@@ -54,6 +54,7 @@ public class GroovyOverlyComplexBooleanExpressionInspectionBase extends BaseInsp
return "Overly complex boolean expression #loc";
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyPointlessBooleanInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyPointlessBooleanInspection.java
index 8fe93903b567..7d1c46820771 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyPointlessBooleanInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyPointlessBooleanInspection.java
@@ -59,6 +59,7 @@ public class GroovyPointlessBooleanInspection extends BaseInspection {
return true;
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new PointlessBooleanExpressionVisitor();
@@ -162,7 +163,7 @@ public class GroovyPointlessBooleanInspection extends BaseInspection {
}
@Override
- public GroovyFix buildFix(PsiElement location) {
+ public GroovyFix buildFix(@NotNull PsiElement location) {
return new BooleanLiteralComparisonFix();
}
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyResultOfIncrementOrDecrementUsedInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyResultOfIncrementOrDecrementUsedInspection.java
index a750d6cf8f60..92e86425b685 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyResultOfIncrementOrDecrementUsedInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/confusing/GroovyResultOfIncrementOrDecrementUsedInspection.java
@@ -47,6 +47,7 @@ public class GroovyResultOfIncrementOrDecrementUsedInspection extends BaseInspec
return "Result of increment or decrement expression used #loc";
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyBreakInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyBreakInspection.java
index 1ab73ccb92a6..9cb990edbf5c 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyBreakInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyBreakInspection.java
@@ -47,6 +47,7 @@ public class GroovyBreakInspection extends BaseInspection {
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyConditionalCanBeElvisInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyConditionalCanBeElvisInspection.java
index 9904a95466ae..a8d1678312ca 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyConditionalCanBeElvisInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyConditionalCanBeElvisInspection.java
@@ -53,7 +53,7 @@ public class GroovyConditionalCanBeElvisInspection extends BaseInspection {
}
@Override
- public GroovyFix buildFix(PsiElement location) {
+ public GroovyFix buildFix(@NotNull PsiElement location) {
return new GroovyFix() {
@Override
@NotNull
@@ -193,6 +193,7 @@ public class GroovyConditionalCanBeElvisInspection extends BaseInspection {
return false;
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyConditionalWithIdenticalBranchesInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyConditionalWithIdenticalBranchesInspection.java
index 010d92ce95f2..bf26bfcc505e 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyConditionalWithIdenticalBranchesInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyConditionalWithIdenticalBranchesInspection.java
@@ -51,7 +51,7 @@ public class GroovyConditionalWithIdenticalBranchesInspection extends BaseInspec
}
@Override
- public GroovyFix buildFix(PsiElement location) {
+ public GroovyFix buildFix(@NotNull PsiElement location) {
return new CollapseConditionalFix();
}
@@ -72,6 +72,7 @@ public class GroovyConditionalWithIdenticalBranchesInspection extends BaseInspec
}
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyConstantConditionalInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyConstantConditionalInspection.java
index fb722f1e415d..a695bfce2c40 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyConstantConditionalInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyConstantConditionalInspection.java
@@ -46,6 +46,7 @@ public class GroovyConstantConditionalInspection extends BaseInspection {
return true;
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new ConstantConditionalExpressionVisitor();
@@ -72,7 +73,7 @@ public class GroovyConstantConditionalInspection extends BaseInspection {
}
@Override
- public GroovyFix buildFix(PsiElement location) {
+ public GroovyFix buildFix(@NotNull PsiElement location) {
return new ConstantConditionalFix();
}
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyConstantIfStatementInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyConstantIfStatementInspection.java
index d03f36f9f1fa..09dd8abbd7d4 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyConstantIfStatementInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyConstantIfStatementInspection.java
@@ -53,13 +53,14 @@ public class GroovyConstantIfStatementInspection extends BaseInspection {
return "#ref statement can be simplified #loc";
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new ConstantIfStatementVisitor();
}
@Override
- public GroovyFix buildFix(PsiElement location) {
+ public GroovyFix buildFix(@NotNull PsiElement location) {
return new ConstantIfStatementFix();
}
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyContinueInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyContinueInspection.java
index ddbd809a4fb5..0f582df06bfe 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyContinueInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyContinueInspection.java
@@ -45,6 +45,7 @@ public class GroovyContinueInspection extends BaseInspection {
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyFallthroughInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyFallthroughInspection.java
index 01871afa1ec8..d203771f827b 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyFallthroughInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyFallthroughInspection.java
@@ -59,6 +59,7 @@ public class GroovyFallthroughInspection extends BaseInspection {
return true;
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyIfStatementWithIdenticalBranchesInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyIfStatementWithIdenticalBranchesInspection.java
index 02d779807d40..62b1371282a8 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyIfStatementWithIdenticalBranchesInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyIfStatementWithIdenticalBranchesInspection.java
@@ -51,7 +51,7 @@ public class GroovyIfStatementWithIdenticalBranchesInspection extends BaseInspec
}
@Override
- public GroovyFix buildFix(PsiElement location) {
+ public GroovyFix buildFix(@NotNull PsiElement location) {
return new CollapseIfFix();
}
@@ -73,6 +73,7 @@ public class GroovyIfStatementWithIdenticalBranchesInspection extends BaseInspec
}
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new IfStatementWithIdenticalBranchesVisitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyIfStatementWithTooManyBranchesInspectionBase.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyIfStatementWithTooManyBranchesInspectionBase.java
index 078728b03410..d5f8c3b0e9dc 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyIfStatementWithTooManyBranchesInspectionBase.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyIfStatementWithTooManyBranchesInspectionBase.java
@@ -63,6 +63,7 @@ public class GroovyIfStatementWithTooManyBranchesInspectionBase extends BaseInsp
return "'#ref' statement with too many branches (" + branches + ") #loc";
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyLoopStatementThatDoesntLoopInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyLoopStatementThatDoesntLoopInspection.java
index 38e155dd2d61..fa8fa75f27cd 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyLoopStatementThatDoesntLoopInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyLoopStatementThatDoesntLoopInspection.java
@@ -48,6 +48,7 @@ public class GroovyLoopStatementThatDoesntLoopInspection extends BaseInspection
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyReturnFromClosureCanBeImplicitInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyReturnFromClosureCanBeImplicitInspection.java
index 24230816d8a8..5f10109a5b14 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyReturnFromClosureCanBeImplicitInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyReturnFromClosureCanBeImplicitInspection.java
@@ -55,6 +55,7 @@ public class GroovyReturnFromClosureCanBeImplicitInspection extends BaseInspecti
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
@@ -62,7 +63,7 @@ public class GroovyReturnFromClosureCanBeImplicitInspection extends BaseInspecti
@Override
@Nullable
- protected GroovyFix buildFix(PsiElement location) {
+ protected GroovyFix buildFix(@NotNull PsiElement location) {
return new MakeReturnImplicitFix();
}
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovySwitchStatementWithNoDefaultInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovySwitchStatementWithNoDefaultInspection.java
index f8ea7794d15b..f76d79ab8fcd 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovySwitchStatementWithNoDefaultInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovySwitchStatementWithNoDefaultInspection.java
@@ -46,6 +46,7 @@ public class GroovySwitchStatementWithNoDefaultInspection extends BaseInspection
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyTrivialConditionalInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyTrivialConditionalInspection.java
index 277c77316e69..a65f3b6f987a 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyTrivialConditionalInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyTrivialConditionalInspection.java
@@ -49,6 +49,7 @@ public class GroovyTrivialConditionalInspection extends BaseInspection {
return true;
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new UnnecessaryConditionalExpressionVisitor();
@@ -73,7 +74,7 @@ public class GroovyTrivialConditionalInspection extends BaseInspection {
}
@Override
- public GroovyFix buildFix(PsiElement location) {
+ public GroovyFix buildFix(@NotNull PsiElement location) {
return new TrivialConditionalFix();
}
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyTrivialIfInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyTrivialIfInspection.java
index 6487e8e97aca..4be923268b10 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyTrivialIfInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyTrivialIfInspection.java
@@ -51,6 +51,7 @@ public class GroovyTrivialIfInspection extends BaseInspection {
return CONTROL_FLOW;
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new TrivialIfVisitor();
@@ -67,7 +68,7 @@ public class GroovyTrivialIfInspection extends BaseInspection {
}
@Override
- public GroovyFix buildFix(PsiElement location) {
+ public GroovyFix buildFix(@NotNull PsiElement location) {
return new TrivialIfFix();
}
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyUnnecessaryContinueInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyUnnecessaryContinueInspection.java
index 145f543ad82c..bd90f8c5223e 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyUnnecessaryContinueInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyUnnecessaryContinueInspection.java
@@ -60,6 +60,7 @@ public class GroovyUnnecessaryContinueInspection extends BaseInspection {
return true;
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
@@ -67,7 +68,7 @@ public class GroovyUnnecessaryContinueInspection extends BaseInspection {
@Override
@Nullable
- protected GroovyFix buildFix(PsiElement location) {
+ protected GroovyFix buildFix(@NotNull PsiElement location) {
return new UnnecessaryContinueFix();
}
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyUnnecessaryReturnInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyUnnecessaryReturnInspection.java
index 6b2bc77a1503..2f492048abfc 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyUnnecessaryReturnInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyUnnecessaryReturnInspection.java
@@ -59,6 +59,7 @@ public class GroovyUnnecessaryReturnInspection extends BaseInspection {
return true;
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
@@ -66,7 +67,7 @@ public class GroovyUnnecessaryReturnInspection extends BaseInspection {
@Override
@Nullable
- protected GroovyFix buildFix(PsiElement location) {
+ protected GroovyFix buildFix(@NotNull PsiElement location) {
return new UnnecessaryReturnFix();
}
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyContinueOrBreakFromFinallyBlockInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyContinueOrBreakFromFinallyBlockInspection.java
index 1064f818dfc2..e4b5d0aab68e 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyContinueOrBreakFromFinallyBlockInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyContinueOrBreakFromFinallyBlockInspection.java
@@ -48,6 +48,7 @@ public class GroovyContinueOrBreakFromFinallyBlockInspection extends BaseInspect
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyEmptyFinallyBlockInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyEmptyFinallyBlockInspection.java
index ad0d3e2dfa7a..b35d3ff87695 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyEmptyFinallyBlockInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyEmptyFinallyBlockInspection.java
@@ -47,6 +47,7 @@ public class GroovyEmptyFinallyBlockInspection extends BaseInspection {
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyEmptyTryBlockInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyEmptyTryBlockInspection.java
index e2a6baf3bf68..5fc9fc2515c1 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyEmptyTryBlockInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyEmptyTryBlockInspection.java
@@ -47,6 +47,7 @@ public class GroovyEmptyTryBlockInspection extends BaseInspection {
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyReturnFromFinallyBlockInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyReturnFromFinallyBlockInspection.java
index 93f70311452c..ae614fd8c508 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyReturnFromFinallyBlockInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyReturnFromFinallyBlockInspection.java
@@ -46,6 +46,7 @@ public class GroovyReturnFromFinallyBlockInspection extends BaseInspection {
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyThrowFromFinallyBlockInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyThrowFromFinallyBlockInspection.java
index 2d790cf9819f..8c1bcf810a56 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyThrowFromFinallyBlockInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyThrowFromFinallyBlockInspection.java
@@ -45,6 +45,7 @@ public class GroovyThrowFromFinallyBlockInspection extends BaseInspection {
return "'#ref' inside 'finally' block #loc";
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyUnusedCatchParameterInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyUnusedCatchParameterInspection.java
index beb4b6d742a8..8fcfd554c4b2 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyUnusedCatchParameterInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyUnusedCatchParameterInspection.java
@@ -47,6 +47,7 @@ public class GroovyUnusedCatchParameterInspection extends BaseInspection {
return "Unused catch parameter";
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/gpath/GroovyListGetCanBeKeyedAccessInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/gpath/GroovyListGetCanBeKeyedAccessInspection.java
index 7da69f949c27..875799171d53 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/gpath/GroovyListGetCanBeKeyedAccessInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/gpath/GroovyListGetCanBeKeyedAccessInspection.java
@@ -58,13 +58,14 @@ public class GroovyListGetCanBeKeyedAccessInspection extends BaseInspection {
return "Call to '#ref' can be keyed access #loc";
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
}
@Override
- public GroovyFix buildFix(PsiElement location) {
+ public GroovyFix buildFix(@NotNull PsiElement location) {
return new ReplaceWithPropertyAccessFix();
}
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/gpath/GroovyListSetCanBeKeyedAccessInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/gpath/GroovyListSetCanBeKeyedAccessInspection.java
index 598212ec0b1d..71840254a02c 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/gpath/GroovyListSetCanBeKeyedAccessInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/gpath/GroovyListSetCanBeKeyedAccessInspection.java
@@ -58,13 +58,14 @@ public class GroovyListSetCanBeKeyedAccessInspection extends BaseInspection {
return "Call to '#ref' can be keyed access #loc";
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
}
@Override
- public GroovyFix buildFix(PsiElement location) {
+ public GroovyFix buildFix(@NotNull PsiElement location) {
return new ReplaceWithPropertyAccessFix();
}
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/gpath/GroovyMapGetCanBeKeyedAccessInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/gpath/GroovyMapGetCanBeKeyedAccessInspection.java
index 638d641af234..621dfe82693a 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/gpath/GroovyMapGetCanBeKeyedAccessInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/gpath/GroovyMapGetCanBeKeyedAccessInspection.java
@@ -58,13 +58,14 @@ public class GroovyMapGetCanBeKeyedAccessInspection extends BaseInspection {
return "Call to '#ref' can be keyed access #loc";
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
}
@Override
- public GroovyFix buildFix(PsiElement location) {
+ public GroovyFix buildFix(@NotNull PsiElement location) {
return new ReplaceWithPropertyAccessFix();
}
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/gpath/GroovyMapPutCanBeKeyedAccessInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/gpath/GroovyMapPutCanBeKeyedAccessInspection.java
index 851a7429088b..afaa3ff66548 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/gpath/GroovyMapPutCanBeKeyedAccessInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/gpath/GroovyMapPutCanBeKeyedAccessInspection.java
@@ -59,13 +59,14 @@ public class GroovyMapPutCanBeKeyedAccessInspection extends BaseInspection {
return "Call to '#ref' can be keyed access #loc";
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
}
@Override
- public GroovyFix buildFix(PsiElement location) {
+ public GroovyFix buildFix(@NotNull PsiElement location) {
return fix;
}
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyMethodParameterCountInspectionBase.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyMethodParameterCountInspectionBase.java
index 09fc336bb607..fbdedbb6660a 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyMethodParameterCountInspectionBase.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyMethodParameterCountInspectionBase.java
@@ -49,6 +49,7 @@ public class GroovyMethodParameterCountInspectionBase extends GroovyMethodMetric
return "Method '#ref' contains too many parameters (" + args[0] + '>' + args[1] + ')';
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyMethodWithMoreThanThreeNegationsInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyMethodWithMoreThanThreeNegationsInspection.java
index d4c58fa2150a..5dede4ef0da3 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyMethodWithMoreThanThreeNegationsInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyMethodWithMoreThanThreeNegationsInspection.java
@@ -40,6 +40,7 @@ public class GroovyMethodWithMoreThanThreeNegationsInspection extends BaseInspec
return "Method '#ref' has too many negations (" + args[0] + " > 3)";
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyMultipleReturnPointsPerMethodInspectionBase.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyMultipleReturnPointsPerMethodInspectionBase.java
index 3291d2d4d25d..14dcdf0533f4 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyMultipleReturnPointsPerMethodInspectionBase.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyMultipleReturnPointsPerMethodInspectionBase.java
@@ -56,6 +56,7 @@ public class GroovyMultipleReturnPointsPerMethodInspectionBase extends GroovyMet
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new MultipleReturnPointsVisitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyOverlyComplexMethodInspectionBase.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyOverlyComplexMethodInspectionBase.java
index ffe5997675a1..f6b0f96f89f7 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyOverlyComplexMethodInspectionBase.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyOverlyComplexMethodInspectionBase.java
@@ -48,6 +48,7 @@ public class GroovyOverlyComplexMethodInspectionBase extends GroovyMethodMetricI
return "Method '#ref' is overly complex ( cyclomatic complexity =" + args[0] + '>' + args[1] + ')';
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyOverlyLongMethodInspectionBase.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyOverlyLongMethodInspectionBase.java
index 7e04ae727bb6..a437483499ed 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyOverlyLongMethodInspectionBase.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyOverlyLongMethodInspectionBase.java
@@ -48,6 +48,7 @@ public class GroovyOverlyLongMethodInspectionBase extends GroovyMethodMetricInsp
return "Method '#ref' is too long ( statement count =" + args[0] + '>' + args[1] + ')';
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyOverlyNestedMethodInspectionBase.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyOverlyNestedMethodInspectionBase.java
index 74aac333b984..7e11ca2d6ac1 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyOverlyNestedMethodInspectionBase.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/metrics/GroovyOverlyNestedMethodInspectionBase.java
@@ -48,6 +48,7 @@ public class GroovyOverlyNestedMethodInspectionBase extends GroovyMethodMetricIn
return "Method '#ref' is overly nested ( nesting depth =" + args[0] + '>' + args[1] + ')';
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyConstantNamingConventionInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyConstantNamingConventionInspection.java
index 108d7bfedf26..64e6d14d15a2 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyConstantNamingConventionInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyConstantNamingConventionInspection.java
@@ -35,7 +35,7 @@ public class GroovyConstantNamingConventionInspection extends ConventionInspecti
}
@Override
- protected GroovyFix buildFix(PsiElement location) {
+ protected GroovyFix buildFix(@NotNull PsiElement location) {
return GroovyQuickFixFactory.getInstance().createRenameFix();
}
@@ -71,6 +71,7 @@ public class GroovyConstantNamingConventionInspection extends ConventionInspecti
return DEFAULT_MAX_LENGTH;
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new NamingConventionsVisitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyInstanceMethodNamingConventionInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyInstanceMethodNamingConventionInspection.java
index c53e1c04eec2..c65afa809b03 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyInstanceMethodNamingConventionInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyInstanceMethodNamingConventionInspection.java
@@ -36,7 +36,7 @@ public class GroovyInstanceMethodNamingConventionInspection extends ConventionIn
}
@Override
- protected GroovyFix buildFix(PsiElement location) {
+ protected GroovyFix buildFix(@NotNull PsiElement location) {
return GroovyQuickFixFactory.getInstance().createRenameFix();
}
@@ -72,6 +72,7 @@ public class GroovyInstanceMethodNamingConventionInspection extends ConventionIn
return DEFAULT_MAX_LENGTH;
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new NamingConventionsVisitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyInstanceVariableNamingConventionInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyInstanceVariableNamingConventionInspection.java
index dc286dec8bc9..297d28129271 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyInstanceVariableNamingConventionInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyInstanceVariableNamingConventionInspection.java
@@ -35,7 +35,7 @@ public class GroovyInstanceVariableNamingConventionInspection extends Convention
}
@Override
- protected GroovyFix buildFix(PsiElement location) {
+ protected GroovyFix buildFix(@NotNull PsiElement location) {
return GroovyQuickFixFactory.getInstance().createRenameFix();
}
@@ -71,6 +71,7 @@ public class GroovyInstanceVariableNamingConventionInspection extends Convention
return DEFAULT_MAX_LENGTH;
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new NamingConventionsVisitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyLocalVariableNamingConventionInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyLocalVariableNamingConventionInspection.java
index 6a623d82476c..48dad65f51c4 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyLocalVariableNamingConventionInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyLocalVariableNamingConventionInspection.java
@@ -38,7 +38,7 @@ public class GroovyLocalVariableNamingConventionInspection extends ConventionIns
}
@Override
- protected GroovyFix buildFix(PsiElement location) {
+ protected GroovyFix buildFix(@NotNull PsiElement location) {
return GroovyQuickFixFactory.getInstance().createRenameFix();
}
@@ -74,6 +74,7 @@ public class GroovyLocalVariableNamingConventionInspection extends ConventionIns
return DEFAULT_MAX_LENGTH;
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new NamingConventionsVisitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyParameterNamingConventionInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyParameterNamingConventionInspection.java
index 5d56f06b3f78..a3e319e2c950 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyParameterNamingConventionInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyParameterNamingConventionInspection.java
@@ -36,7 +36,7 @@ public class GroovyParameterNamingConventionInspection extends ConventionInspect
}
@Override
- protected GroovyFix buildFix(PsiElement location) {
+ protected GroovyFix buildFix(@NotNull PsiElement location) {
return GroovyQuickFixFactory.getInstance().createRenameFix();
}
@@ -72,6 +72,7 @@ public class GroovyParameterNamingConventionInspection extends ConventionInspect
return DEFAULT_MAX_LENGTH;
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new NamingConventionsVisitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyStaticMethodNamingConventionInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyStaticMethodNamingConventionInspection.java
index 63446a369064..db69c140ba4f 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyStaticMethodNamingConventionInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyStaticMethodNamingConventionInspection.java
@@ -35,7 +35,7 @@ public class GroovyStaticMethodNamingConventionInspection extends ConventionInsp
}
@Override
- protected GroovyFix buildFix(PsiElement location) {
+ protected GroovyFix buildFix(@NotNull PsiElement location) {
return GroovyQuickFixFactory.getInstance().createRenameFix();
}
@@ -71,6 +71,7 @@ public class GroovyStaticMethodNamingConventionInspection extends ConventionInsp
return DEFAULT_MAX_LENGTH;
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new NamingConventionsVisitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyStaticVariableNamingConventionInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyStaticVariableNamingConventionInspection.java
index 68014a67e61a..4718df33a1fa 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyStaticVariableNamingConventionInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/naming/GroovyStaticVariableNamingConventionInspection.java
@@ -35,7 +35,7 @@ public class GroovyStaticVariableNamingConventionInspection extends ConventionIn
}
@Override
- protected GroovyFix buildFix(PsiElement location) {
+ protected GroovyFix buildFix(@NotNull PsiElement location) {
return GroovyQuickFixFactory.getInstance().createRenameFix();
}
@@ -71,6 +71,7 @@ public class GroovyStaticVariableNamingConventionInspection extends ConventionIn
return DEFAULT_MAX_LENGTH;
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new NamingConventionsVisitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyAccessToStaticFieldLockedOnInstanceInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyAccessToStaticFieldLockedOnInstanceInspection.java
index f059080470e6..293091e536f8 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyAccessToStaticFieldLockedOnInstanceInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyAccessToStaticFieldLockedOnInstanceInspection.java
@@ -56,6 +56,7 @@ public class GroovyAccessToStaticFieldLockedOnInstanceInspection
return "Access to static field <code>#ref</code> locked on instance data #loc";
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyBusyWaitInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyBusyWaitInspection.java
index 890e539350ff..36203c188a76 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyBusyWaitInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyBusyWaitInspection.java
@@ -47,6 +47,7 @@ public class GroovyBusyWaitInspection extends BaseInspection {
return "Call to <code>Thread.#ref()</code> in a loop, probably busy-waiting #loc";
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new BusyWaitVisitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyDoubleCheckedLockingInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyDoubleCheckedLockingInspection.java
index 4721f40c0734..c1b829ecc21d 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyDoubleCheckedLockingInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyDoubleCheckedLockingInspection.java
@@ -71,6 +71,7 @@ public class GroovyDoubleCheckedLockingInspection extends BaseInspection {
);
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new DoubleCheckedLockingVisitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyEmptySyncBlockInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyEmptySyncBlockInspection.java
index 121f867b7e37..db421ff40a50 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyEmptySyncBlockInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyEmptySyncBlockInspection.java
@@ -47,6 +47,7 @@ public class GroovyEmptySyncBlockInspection extends BaseInspection {
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyNestedSynchronizedStatementInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyNestedSynchronizedStatementInspection.java
index 53080fdb8e4d..646ca65b3998 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyNestedSynchronizedStatementInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyNestedSynchronizedStatementInspection.java
@@ -50,6 +50,7 @@ public class GroovyNestedSynchronizedStatementInspection extends BaseInspection
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyNotifyWhileNotSynchronizedInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyNotifyWhileNotSynchronizedInspection.java
index adb8d6563f57..0589b659c426 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyNotifyWhileNotSynchronizedInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyNotifyWhileNotSynchronizedInspection.java
@@ -55,6 +55,7 @@ public class GroovyNotifyWhileNotSynchronizedInspection extends BaseInspection {
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyPublicFieldAccessedInSynchronizedContextInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyPublicFieldAccessedInSynchronizedContextInspection.java
index c46b33ac4a58..ccf799ddd86d 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyPublicFieldAccessedInSynchronizedContextInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyPublicFieldAccessedInSynchronizedContextInspection.java
@@ -47,6 +47,7 @@ public class GroovyPublicFieldAccessedInSynchronizedContextInspection
return "Non-private field <code>#ref</code> accessed in synchronized context #loc";
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new PublicFieldAccessedInSynchronizedContextVisitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovySynchronizationOnNonFinalFieldInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovySynchronizationOnNonFinalFieldInspection.java
index f5b9b1f047d6..bacafcdb799d 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovySynchronizationOnNonFinalFieldInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovySynchronizationOnNonFinalFieldInspection.java
@@ -55,6 +55,7 @@ public class GroovySynchronizationOnNonFinalFieldInspection extends BaseInspecti
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovySynchronizationOnThisInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovySynchronizationOnThisInspection.java
index ab8dd421098e..e343fa62397d 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovySynchronizationOnThisInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovySynchronizationOnThisInspection.java
@@ -48,6 +48,7 @@ public class GroovySynchronizationOnThisInspection extends BaseInspection {
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovySynchronizationOnVariableInitializedWithLiteralInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovySynchronizationOnVariableInitializedWithLiteralInspection.java
index 34b239e4faaa..6464e6654780 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovySynchronizationOnVariableInitializedWithLiteralInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovySynchronizationOnVariableInitializedWithLiteralInspection.java
@@ -54,6 +54,7 @@ public class GroovySynchronizationOnVariableInitializedWithLiteralInspection ext
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovySynchronizedMethodInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovySynchronizedMethodInspection.java
index 75767a0fea6b..b8b3e34b1d7c 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovySynchronizedMethodInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovySynchronizedMethodInspection.java
@@ -46,6 +46,7 @@ public class GroovySynchronizedMethodInspection extends BaseInspection {
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovySystemRunFinalizersOnExitInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovySystemRunFinalizersOnExitInspection.java
index 8acd2d3585b1..8629e23787d9 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovySystemRunFinalizersOnExitInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovySystemRunFinalizersOnExitInspection.java
@@ -48,6 +48,7 @@ public class GroovySystemRunFinalizersOnExitInspection extends BaseInspection {
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyThreadStopSuspendResumeInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyThreadStopSuspendResumeInspection.java
index e65e23b1f709..072fb29fbec5 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyThreadStopSuspendResumeInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyThreadStopSuspendResumeInspection.java
@@ -60,6 +60,7 @@ public class GroovyThreadStopSuspendResumeInspection extends BaseInspection {
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyUnconditionalWaitInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyUnconditionalWaitInspection.java
index 445e34da38c4..2e24f21654d2 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyUnconditionalWaitInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyUnconditionalWaitInspection.java
@@ -53,6 +53,7 @@ public class GroovyUnconditionalWaitInspection extends BaseInspection {
return "Unconditional call to <code>#ref()</code> #loc";
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new UnconditionalWaitVisitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyUnsynchronizedMethodOverridesSynchronizedMethodInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyUnsynchronizedMethodOverridesSynchronizedMethodInspection.java
index 83e822ce663d..9b539bd8185d 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyUnsynchronizedMethodOverridesSynchronizedMethodInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyUnsynchronizedMethodOverridesSynchronizedMethodInspection.java
@@ -52,6 +52,7 @@ public class GroovyUnsynchronizedMethodOverridesSynchronizedMethodInspection ext
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyWaitCallNotInLoopInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyWaitCallNotInLoopInspection.java
index e86a1028e92e..7e0a0080ac68 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyWaitCallNotInLoopInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyWaitCallNotInLoopInspection.java
@@ -51,6 +51,7 @@ public class GroovyWaitCallNotInLoopInspection extends BaseInspection {
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyWaitWhileNotSynchronizedInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyWaitWhileNotSynchronizedInspection.java
index acacf2954e0a..41c25bc8b51b 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyWaitWhileNotSynchronizedInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyWaitWhileNotSynchronizedInspection.java
@@ -56,6 +56,7 @@ public class GroovyWaitWhileNotSynchronizedInspection extends BaseInspection {
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyWhileLoopSpinsOnFieldInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyWhileLoopSpinsOnFieldInspection.java
index 0949348a92da..6ce007026ea0 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyWhileLoopSpinsOnFieldInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/threading/GroovyWhileLoopSpinsOnFieldInspection.java
@@ -69,6 +69,7 @@ public class GroovyWhileLoopSpinsOnFieldInspection extends BaseInspection {
this, "ignoreNonEmtpyLoops");
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new WhileLoopSpinsOnFieldVisitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/untypedUnresolvedAccess/GrUnresolvedAccessChecker.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/untypedUnresolvedAccess/GrUnresolvedAccessChecker.java
index 2978b652f544..ef9dafc585a5 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/untypedUnresolvedAccess/GrUnresolvedAccessChecker.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/untypedUnresolvedAccess/GrUnresolvedAccessChecker.java
@@ -435,10 +435,11 @@ public class GrUnresolvedAccessChecker {
PsiClass targetClass = QuickfixUtil.findTargetClass(refExpr, compileStatic);
if (targetClass == null) return;
+ if (!compileStatic) {
+ addDynamicAnnotation(info, refExpr, key);
+ }
+
if (!(targetClass instanceof SyntheticElement) || (targetClass instanceof GroovyScriptClass)) {
- if (!compileStatic) {
- addDynamicAnnotation(info, refExpr, key);
- }
QuickFixAction.registerQuickFixAction(info, GroovyQuickFixFactory.getInstance().createCreateFieldFromUsageFix(refExpr), key);
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/validity/GroovyDuplicateSwitchBranchInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/validity/GroovyDuplicateSwitchBranchInspection.java
index 7a064ffa8030..bead894b4201 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/validity/GroovyDuplicateSwitchBranchInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/validity/GroovyDuplicateSwitchBranchInspection.java
@@ -56,6 +56,7 @@ public class GroovyDuplicateSwitchBranchInspection extends BaseInspection {
return "Duplicate switch case '#ref' #loc";
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/validity/GroovyUnreachableStatementInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/validity/GroovyUnreachableStatementInspection.java
index 83c75cd9f4c8..0c64951c26f4 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/validity/GroovyUnreachableStatementInspection.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/validity/GroovyUnreachableStatementInspection.java
@@ -53,6 +53,7 @@ public class GroovyUnreachableStatementInspection extends BaseInspection {
return true;
}
+ @NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/dsl/GroovyDslFileIndex.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/dsl/GroovyDslFileIndex.java
index ae0b7566fe34..cbc6fa29d853 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/dsl/GroovyDslFileIndex.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/dsl/GroovyDslFileIndex.java
@@ -467,7 +467,7 @@ public class GroovyDslFileIndex extends ScalarIndexExtension<String> {
}
@Override
- public boolean acceptInput(final VirtualFile file) {
+ public boolean acceptInput(@NotNull final VirtualFile file) {
return StringUtil.endsWith(file.getNameSequence(), ".gdsl");
}
}
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrDelegatesToUtil.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrDelegatesToUtil.java
index 313065afc5d7..f60256de8397 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrDelegatesToUtil.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrDelegatesToUtil.java
@@ -16,6 +16,7 @@
package org.jetbrains.plugins.groovy.lang.psi.impl.statements.blocks;
import com.intellij.psi.*;
+import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.ArrayUtil;
@@ -168,7 +169,7 @@ public class GrDelegatesToUtil {
final PsiType baseType = signature.getParameters()[param].getType();
final PsiClass baseClass = PsiUtil.resolveClassInClassTypeOnly(baseType);
- if (baseClass != null && psiClass.isInheritor(baseClass, true)) {
+ if (baseClass != null && InheritanceUtil.isInheritorOrSelf(psiClass, baseClass, true)) {
final PsiTypeParameter[] typeParameters = baseClass.getTypeParameters();
if (genericIndex < typeParameters.length) {
final PsiSubstitutor superClassSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(baseClass, psiClass, substitutor);
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInsight/GroovyMarkerTypes.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInsight/GroovyMarkerTypes.java
index 3dc41bf408f5..38fac33ae3a3 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInsight/GroovyMarkerTypes.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInsight/GroovyMarkerTypes.java
@@ -23,6 +23,7 @@ import com.intellij.codeInsight.daemon.impl.PsiElementListNavigator;
import com.intellij.codeInsight.navigation.ListBackgroundUpdaterTask;
import com.intellij.ide.util.MethodCellRenderer;
import com.intellij.ide.util.PsiElementListCellRenderer;
+import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ReadActionProcessor;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
@@ -159,9 +160,14 @@ public class GroovyMarkerTypes {
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
@Override
public void run() {
- for (GrAccessorMethod method : GroovyPropertyUtils.getFieldAccessors(field)) {
- OverridingMethodsSearch.search(method, true).forEach(collectProcessor);
- }
+ ApplicationManager.getApplication().runReadAction(new Runnable() {
+ @Override
+ public void run() {
+ for (GrAccessorMethod method : GroovyPropertyUtils.getFieldAccessors(field)) {
+ OverridingMethodsSearch.search(method, true).forEach(collectProcessor);
+ }
+ }
+ });
}
}, "Searching for overriding methods", true, field.getProject(), (JComponent)e.getComponent())) {
return;
@@ -272,17 +278,22 @@ public class GroovyMarkerTypes {
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
@Override
public void run() {
- for (GrMethod m : PsiImplUtil.getMethodOrReflectedMethods(method)) {
- OverridingMethodsSearch.search(m, true).forEach(new ReadActionProcessor<PsiMethod>() {
- @Override
- public boolean processInReadAction(PsiMethod psiMethod) {
- if (psiMethod instanceof GrReflectedMethod) {
- psiMethod = ((GrReflectedMethod)psiMethod).getBaseMethod();
- }
- return collectProcessor.execute(psiMethod);
+ ApplicationManager.getApplication().runReadAction(new Runnable() {
+ @Override
+ public void run() {
+ for (GrMethod m : PsiImplUtil.getMethodOrReflectedMethods(method)) {
+ OverridingMethodsSearch.search(m, true).forEach(new ReadActionProcessor<PsiMethod>() {
+ @Override
+ public boolean processInReadAction(PsiMethod psiMethod) {
+ if (psiMethod instanceof GrReflectedMethod) {
+ psiMethod = ((GrReflectedMethod)psiMethod).getBaseMethod();
+ }
+ return collectProcessor.execute(psiMethod);
+ }
+ });
}
- });
- }
+ }
+ });
}
}, MarkerType.SEARCHING_FOR_OVERRIDING_METHODS, true, method.getProject(), (JComponent)e.getComponent())) {
return;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyQuickFixFactoryImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyQuickFixFactoryImpl.java
index 1be4df43ba72..8bb41490a3b4 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyQuickFixFactoryImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyQuickFixFactoryImpl.java
@@ -26,6 +26,7 @@ import org.jetbrains.plugins.groovy.codeInspection.bugs.AddClassToExtendsFix;
import org.jetbrains.plugins.groovy.codeInspection.bugs.AddMethodFix;
import org.jetbrains.plugins.groovy.codeInspection.confusing.ReplaceWithImportFix;
import org.jetbrains.plugins.groovy.codeInspection.local.RemoveUnusedGrParameterFix;
+import org.jetbrains.plugins.groovy.codeInspection.naming.RenameFix;
import org.jetbrains.plugins.groovy.dsl.InvestigateFix;
import org.jetbrains.plugins.groovy.lang.GrCreateClassKind;
import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement;
@@ -101,7 +102,7 @@ public class GroovyQuickFixFactoryImpl extends GroovyQuickFixFactory {
@Override
public GroovyFix createRenameFix() {
- return GroovyQuickFixFactory.getInstance().createRenameFix();
+ return new RenameFix();
}
@Override
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/confusing/ClashingTraitMethodsInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/confusing/ClashingTraitMethodsInspection.java
index b5579e186613..60be41f0309b 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/confusing/ClashingTraitMethodsInspection.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/confusing/ClashingTraitMethodsInspection.java
@@ -1,168 +1,47 @@
+/*
+ * 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.codeInspection.confusing;
import com.intellij.codeInsight.generation.OverrideImplementUtil;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
-import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
-import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Condition;
-import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.psi.*;
-import com.intellij.psi.util.PsiFormatUtil;
-import com.intellij.psi.util.PsiFormatUtilBase;
-import com.intellij.util.Function;
-import com.intellij.util.containers.ContainerUtil;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiMethod;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.plugins.groovy.codeInspection.BaseInspection;
-import org.jetbrains.plugins.groovy.codeInspection.BaseInspectionVisitor;
import org.jetbrains.plugins.groovy.codeInspection.GroovyInspectionBundle;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrTraitMethod;
-import org.jetbrains.plugins.groovy.lang.psi.util.GrTraitUtil;
-import java.util.Collection;
import java.util.List;
/**
* Created by Max Medvedev on 03/06/14
*/
-public class ClashingTraitMethodsInspection extends BaseInspection {
- private static final Logger LOG = Logger.getInstance(ClashingTraitMethodsInspection.class);
+public class ClashingTraitMethodsInspection extends ClashingTraitMethodsInspectionBase {
@NotNull
@Override
- protected BaseInspectionVisitor buildVisitor() {
- return new BaseInspectionVisitor() {
- @Override
- public void visitTypeDefinition(GrTypeDefinition typeDefinition) {
- super.visitTypeDefinition(typeDefinition);
-
- List<PsiClass> superTraits = collectImplementedTraits(typeDefinition);
-
- if (superTraits.size() < 2) return;
-
- List<ClashingMethod> clashingMethods = collectClassingMethods(typeDefinition);
-
- for (ClashingMethod clashing : clashingMethods) {
- registerError(typeDefinition.getNameIdentifierGroovy(), buildWarning(clashing), new LocalQuickFix[]{new MyQuickFix()}, ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
- }
- }
-
- @NotNull
- private String buildWarning(@NotNull ClashingMethod entry) {
- return "Traits " + buildTraitString(entry) + " contain clashing methods with signature " + buildSignatureString(entry);
- }
-
- @NotNull
- private String buildSignatureString(@NotNull ClashingMethod entry) {
- HierarchicalMethodSignature signature = entry.getSignature();
- return PsiFormatUtil.formatMethod(signature.getMethod(), signature.getSubstitutor(),
- PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_PARAMETERS,
- PsiFormatUtilBase.SHOW_TYPE);
- }
-
- @NotNull
- private String buildTraitString(@NotNull ClashingMethod entry) {
- return StringUtil.join(entry.getSuperTraits(), new Function<GrTypeDefinition, String>() {
- public String fun(GrTypeDefinition tr) {
- return tr.getName();
- }
- }, ", ");
- }
- };
- }
-
- @NotNull
- private static List<ClashingMethod> collectClassingMethods(@NotNull GrTypeDefinition typeDefinition) {
- Collection<HierarchicalMethodSignature> visibleSignatures = typeDefinition.getVisibleSignatures();
-
- List<ClashingMethod> clashingMethods = ContainerUtil.newArrayList();
- for (HierarchicalMethodSignature signature : visibleSignatures) {
- PsiMethod method = signature.getMethod();
- if (method instanceof GrTraitMethod && method.getContainingClass() == typeDefinition) {
- List<HierarchicalMethodSignature> superSignatures = signature.getSuperSignatures();
- if (superSignatures.size() > 1) {
- List<GrTypeDefinition> traits = ContainerUtil.newArrayList();
- for (HierarchicalMethodSignature superSignature : superSignatures) {
- PsiMethod superMethod = superSignature.getMethod();
- PsiClass superClass = superMethod.getContainingClass();
- if (GrTraitUtil.isTrait(superClass) &&
- !superMethod.getModifierList().hasExplicitModifier(PsiModifier.ABSTRACT)) {
- traits.add((GrTypeDefinition)superClass);
- }
- }
-
- if (traits.size() > 1) {
- clashingMethods.add(new ClashingMethod(signature, traits));
- }
- }
- }
- }
-
- return clashingMethods;
- }
-
- @NotNull
- private static List<PsiClass> collectImplementedTraits(@NotNull GrTypeDefinition typeDefinition) {
- return ContainerUtil.findAll(typeDefinition.getSupers(), new Condition<PsiClass>() {
- @Override
- public boolean value(PsiClass aClass) {
- return GrTraitUtil.isTrait(aClass);
- }
- });
- }
-
- private static class ClashingMethod {
- private final HierarchicalMethodSignature mySignature;
- private final List<GrTypeDefinition> mySuperTraits;
-
- public ClashingMethod(@NotNull HierarchicalMethodSignature signature, @NotNull List<GrTypeDefinition> superTraits) {
- mySignature = signature;
- mySuperTraits = superTraits;
- }
-
- @NotNull
- public HierarchicalMethodSignature getSignature() {
- return mySignature;
- }
-
- @NotNull
- public List<GrTypeDefinition> getSuperTraits() {
- return mySuperTraits;
- }
+ protected LocalQuickFix getFix(){
+ return new MyQuickFix();
}
private static class MyQuickFix implements LocalQuickFix {
- private static final int MAX_SIGNATURE_LENGTH = 50;
-
- private static String buildSignature(HierarchicalMethodSignature signature, int maxLength) {
- StringBuilder result = new StringBuilder();
- result.append(signature.getName());
-
- PsiType[] params = signature.getParameterTypes();
-
- if (params.length == 0) {
- result.append("()");
- return result.toString();
- }
-
- result.append("(");
-
- for (PsiType param : params) {
- if (result.length() >= maxLength - "...)".length()) {
- result.append("...)");
- return result.toString();
- }
- result.append(param.getPresentableText());
- result.append(", ");
- }
- result.replace(result.length() - ", ".length(), result.length(), ")");
- return result.toString();
- }
-
@NotNull
@Override
public String getName() {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeStyle/GroovyLanguageCodeStyleSettingsProvider.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeStyle/GroovyLanguageCodeStyleSettingsProvider.java
index 1e28d0c8935e..4ce07a3d3fff 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeStyle/GroovyLanguageCodeStyleSettingsProvider.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeStyle/GroovyLanguageCodeStyleSettingsProvider.java
@@ -49,6 +49,7 @@ public class GroovyLanguageCodeStyleSettingsProvider extends LanguageCodeStyleSe
@NotNull SettingsType settingsType) {
if (settingsType == SettingsType.WRAPPING_AND_BRACES_SETTINGS) {
consumer.showStandardOptions(
+ "RIGHT_MARGIN",
"KEEP_LINE_BREAKS",
"KEEP_FIRST_COLUMN_COMMENT",
"KEEP_CONTROL_STATEMENT_IN_ONE_LINE",
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/griffon/GriffonDebuggerRunner.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/griffon/GriffonDebuggerRunner.java
index 898f429659f3..2d424b2f58d9 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/griffon/GriffonDebuggerRunner.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/griffon/GriffonDebuggerRunner.java
@@ -22,7 +22,6 @@ import com.intellij.execution.configurations.*;
import com.intellij.execution.executors.DefaultDebugExecutor;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.ui.RunContentDescriptor;
-import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
/**
@@ -42,10 +41,7 @@ public class GriffonDebuggerRunner extends GenericDebuggerRunner {
@Override
- protected RunContentDescriptor createContentDescriptor(Project project,
- RunProfileState state,
- RunContentDescriptor contentToReuse,
- ExecutionEnvironment env) throws ExecutionException {
+ protected RunContentDescriptor createContentDescriptor(@NotNull RunProfileState state, @NotNull ExecutionEnvironment environment) throws ExecutionException {
final JavaCommandLine javaCommandLine = (JavaCommandLine)state;
final JavaParameters params = javaCommandLine.getJavaParameters();
@@ -68,11 +64,8 @@ public class GriffonDebuggerRunner extends GenericDebuggerRunner {
}
if (address == null) {
- return super.createContentDescriptor(project, state, contentToReuse, env);
+ return super.createContentDescriptor(state, environment);
}
-
- RemoteConnection connection = new RemoteConnection(true, "127.0.0.1", address, false);
- return attachVirtualMachine(project, state, contentToReuse, env, connection, true);
+ return attachVirtualMachine(state, environment, new RemoteConnection(true, "127.0.0.1", address, false), true);
}
-
-}
+} \ No newline at end of file
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovySmartCompletionContributor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovySmartCompletionContributor.java
index 4b5459ff432e..55ab68f7f822 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovySmartCompletionContributor.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovySmartCompletionContributor.java
@@ -415,9 +415,13 @@ public class GroovySmartCompletionContributor extends CompletionContributor {
}
}
- final LookupItem item = PsiTypeLookupItem.createLookupItem(GenericsUtil.eliminateWildcards(type), place, isDiamond, ChooseTypeExpression.IMPORT_FIXER);
- if (item.getObject() instanceof PsiClass) {
+ final PsiTypeLookupItem item = PsiTypeLookupItem.createLookupItem(GenericsUtil.eliminateWildcards(type), place, isDiamond, ChooseTypeExpression.IMPORT_FIXER);
+ Object object = item.getObject();
+ if (object instanceof PsiClass) {
JavaCompletionUtil.setShowFQN(item);
+ if (((PsiClass)object).hasModifierProperty(PsiModifier.ABSTRACT)) {
+ item.setIndicateAnonymous(true);
+ }
}
item.setInsertHandler(new AfterNewClassInsertHandler((PsiClassType)type, true));
return item;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/projectView/MvcProjectViewPane.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/projectView/MvcProjectViewPane.java
index 32db531b212e..f32d77131d82 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/projectView/MvcProjectViewPane.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/projectView/MvcProjectViewPane.java
@@ -352,6 +352,7 @@ public class MvcProjectViewPane extends AbstractProjectViewPSIPane implements Id
}
}
+ @NotNull
@Override
public PsiDirectory[] getDirectories() {
return getSelectedDirectories();
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/projectView/MvcToolWindowDescriptor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/projectView/MvcToolWindowDescriptor.java
index 945bb9c8f24b..35171ccda212 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/projectView/MvcToolWindowDescriptor.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/projectView/MvcToolWindowDescriptor.java
@@ -51,7 +51,7 @@ public abstract class MvcToolWindowDescriptor implements ToolWindowFactory, Cond
}
@Override
- public void createToolWindowContent(Project project, ToolWindow toolWindow) {
+ public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindow toolWindow) {
toolWindow.setAvailable(true, null);
toolWindow.setToHideOnEmptyContent(true);
toolWindow.setTitle(myFramework.getDisplayName());
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/memberPullUp/GrPullUpHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/memberPullUp/GrPullUpHandler.java
index 83d2a4088645..19480e0d80e8 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/memberPullUp/GrPullUpHandler.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/memberPullUp/GrPullUpHandler.java
@@ -17,6 +17,7 @@ package org.jetbrains.plugins.groovy.refactoring.memberPullUp;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ScrollType;
@@ -170,9 +171,16 @@ public class GrPullUpHandler implements RefactoringActionHandler, GrPullUpDialog
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
@Override
public void run() {
- final PsiDirectory targetDirectory = superClass.getContainingFile().getContainingDirectory();
- final PsiPackage targetPackage = targetDirectory != null ? JavaDirectoryService.getInstance().getPackage(targetDirectory) : null;
- conflicts.putAllValues(GrPullUpConflictsUtil.checkConflicts(infos, mySubclass, superClass, targetPackage, targetDirectory, dialog.getContainmentVerifier()));
+ ApplicationManager.getApplication().runReadAction(new Runnable() {
+ @Override
+ public void run() {
+ final PsiDirectory targetDirectory = superClass.getContainingFile().getContainingDirectory();
+ final PsiPackage targetPackage =
+ targetDirectory != null ? JavaDirectoryService.getInstance().getPackage(targetDirectory) : null;
+ conflicts.putAllValues(GrPullUpConflictsUtil.checkConflicts(infos, mySubclass, superClass, targetPackage, targetDirectory,
+ dialog.getContainmentVerifier()));
+ }
+ });
}
}, RefactoringBundle.message("detecting.possible.conflicts"), true, myProject)) {
return false;
diff --git a/plugins/groovy/structuralsearch-groovy/testSrc/com/intellij/structuralsearch/GroovyStructuralSearchTest.java b/plugins/groovy/structuralsearch-groovy/testSrc/com/intellij/structuralsearch/GroovyStructuralSearchTest.java
index 8990fba2716e..18505d018747 100644
--- a/plugins/groovy/structuralsearch-groovy/testSrc/com/intellij/structuralsearch/GroovyStructuralSearchTest.java
+++ b/plugins/groovy/structuralsearch-groovy/testSrc/com/intellij/structuralsearch/GroovyStructuralSearchTest.java
@@ -25,7 +25,6 @@ import java.util.List;
/**
* @author Eugene.Kudelevsky
*/
-@Bombed(day = 14, month = Calendar.JULY)
public class GroovyStructuralSearchTest extends StructuralSearchTestCase {
public void test1() throws Exception {
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 28b2e26949ad..e227a1b34663 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTestCase.java
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTestCase.java
@@ -25,6 +25,7 @@ import com.intellij.execution.executors.DefaultRunExecutor;
import com.intellij.execution.impl.DefaultJavaProgramRunner;
import com.intellij.execution.process.*;
import com.intellij.execution.runners.ExecutionEnvironment;
+import com.intellij.execution.runners.ExecutionEnvironmentBuilder;
import com.intellij.execution.runners.ProgramRunner;
import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.openapi.Disposable;
@@ -234,7 +235,7 @@ public abstract class GroovyCompilerTestCase extends JavaCodeInsightFixtureTestC
ProgramRunner runner,
RunProfile configuration) throws ExecutionException {
final Executor executor = Executor.EXECUTOR_EXTENSION_NAME.findExtension(executorClass);
- final ExecutionEnvironment environment = new ExecutionEnvironment(configuration, executor, getProject(), null);
+ final ExecutionEnvironment environment = new ExecutionEnvironmentBuilder(getProject(), executor).runProfile(configuration).build();
final Semaphore semaphore = new Semaphore();
semaphore.down();
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/formatter/WrappingTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/formatter/WrappingTest.groovy
index 79d79edc42de..4d585dbf7f6f 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/formatter/WrappingTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/formatter/WrappingTest.groovy
@@ -16,6 +16,7 @@
package org.jetbrains.plugins.groovy.lang.formatter
import com.intellij.psi.codeStyle.CommonCodeStyleSettings
+import org.jetbrains.plugins.groovy.GroovyLanguage
/**
* @author Max Medvedev
@@ -24,7 +25,7 @@ class WrappingTest extends GroovyFormatterTestCase {
@Override
protected void setUp() throws Exception {
super.setUp()
- myTempSettings.RIGHT_MARGIN = 10
+ myTempSettings.setRightMargin(GroovyLanguage.INSTANCE, 10);
}
void testWrapChainedMethodCalls() {
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveWithDelegatesToTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveWithDelegatesToTest.groovy
index 9762f6772016..96be1fe5be02 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveWithDelegatesToTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveWithDelegatesToTest.groovy
@@ -681,6 +681,24 @@ def staticOnWrapper() {
''', 'List')
}
+ void testClassTest() {
+ assertScript('''
+class DelegatesToTest {
+ void create(@DelegatesTo.Target Class type, @DelegatesTo(genericTypeIndex = 0, strategy = Closure.OWNER_FIRST) Closure closure) {}
+
+
+ void doit() {
+ create(Person) {
+ a<caret>ge = 30 // IDEA 12.1.6 can resolve this property, 13.1.3 can't
+ }
+ }
+}
+
+class Person {
+ int age
+}
+''', 'Person')
+ }
void assertScript(String text, String resolvedClass) {
myFixture.configureByText('_a.groovy', text)
diff --git a/plugins/hg4idea/hg4idea.iml b/plugins/hg4idea/hg4idea.iml
index 7f5074895e4f..93b5a5109bde 100644
--- a/plugins/hg4idea/hg4idea.iml
+++ b/plugins/hg4idea/hg4idea.iml
@@ -16,9 +16,10 @@
<orderEntry type="module" module-name="vcs-impl" />
<orderEntry type="module" module-name="platform-impl" />
<orderEntry type="library" name="Guava" level="project" />
- <orderEntry type="module" module-name="dvcs" />
+ <orderEntry type="module" module-name="dvcs-impl" />
<orderEntry type="module" module-name="vcs-log-api" />
<orderEntry type="module" module-name="vcs-log-impl" />
+ <orderEntry type="module" module-name="dvcs-api" />
</component>
</module>
diff --git a/plugins/hg4idea/src/META-INF/plugin.xml b/plugins/hg4idea/src/META-INF/plugin.xml
index 9ccc175803f5..26b69326a703 100644
--- a/plugins/hg4idea/src/META-INF/plugin.xml
+++ b/plugins/hg4idea/src/META-INF/plugin.xml
@@ -21,6 +21,7 @@
<vcs name="hg4idea" vcsClass="org.zmlx.hg4idea.HgVcs" displayName="Mercurial" administrativeAreaName=".hg"/>
<checkoutProvider implementation="org.zmlx.hg4idea.provider.HgCheckoutProvider"/>
<vcsRootChecker implementation="org.zmlx.hg4idea.roots.HgRootChecker"/>
+ <pushSupport implementation="org.zmlx.hg4idea.push.HgPushSupport"/>
<errorHandler implementation="com.intellij.diagnostic.ITNReporter"/>
<vcsPopupProvider implementation="org.zmlx.hg4idea.provider.HgQuickListProvider"/>
<logProvider implementation="org.zmlx.hg4idea.log.HgLogProvider"/>
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAbstractGlobalAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAbstractGlobalAction.java
index d38bc7bfc6a7..d6282ebe8786 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAbstractGlobalAction.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAbstractGlobalAction.java
@@ -29,7 +29,9 @@ import org.zmlx.hg4idea.util.HgUtil;
import javax.swing.*;
import java.lang.reflect.InvocationTargetException;
+import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import java.util.List;
abstract class HgAbstractGlobalAction extends AnAction {
@@ -48,12 +50,17 @@ abstract class HgAbstractGlobalAction extends AnAction {
if (project == null) {
return;
}
- VirtualFile file = event.getData(CommonDataKeys.VIRTUAL_FILE);
- HgRepositoryManager repositoryManager = HgUtil.getRepositoryManager(project);
- HgRepository repo = file != null ? repositoryManager.getRepositoryForFile(file): HgUtil.getCurrentRepository(project);
+ VirtualFile[] files = event.getData(CommonDataKeys.VIRTUAL_FILE_ARRAY);
+ final HgRepositoryManager repositoryManager = HgUtil.getRepositoryManager(project);
List<HgRepository> repositories = repositoryManager.getRepositories();
if (!repositories.isEmpty()) {
- execute(project, repositories, repo);
+ List<HgRepository> selectedRepositories = (files == null || files.length == 0)
+ ?
+ Collections.singletonList(HgUtil.getCurrentRepository(project))
+ : HgActionUtil.collectRepositoriesFromFiles(repositoryManager,
+ Arrays.asList(files));
+
+ execute(project, repositories, selectedRepositories);
}
}
@@ -66,7 +73,7 @@ abstract class HgAbstractGlobalAction extends AnAction {
protected abstract void execute(@NotNull Project project,
@NotNull Collection<HgRepository> repositories,
- @Nullable HgRepository selectedRepo);
+ @NotNull List<HgRepository> selectedRepositories);
public static void handleException(@Nullable Project project, @NotNull Exception e) {
handleException(project, "Error", e);
@@ -102,16 +109,4 @@ abstract class HgAbstractGlobalAction extends AnAction {
return true;
}
- @Nullable
- public static HgRepository getSelectedRepositoryFromEvent(AnActionEvent e) {
- final DataContext dataContext = e.getDataContext();
- final Project project = CommonDataKeys.PROJECT.getData(dataContext);
- if (project == null) {
- return null;
- }
- VirtualFile file = e.getData(CommonDataKeys.VIRTUAL_FILE);
- HgRepositoryManager repositoryManager = HgUtil.getRepositoryManager(project);
- return file != null ? repositoryManager.getRepositoryForFile(file) : HgUtil.getCurrentRepository(project);
- }
-
}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAbstractGlobalSingleRepoAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAbstractGlobalSingleRepoAction.java
new file mode 100644
index 000000000000..bfb2d7715e68
--- /dev/null
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAbstractGlobalSingleRepoAction.java
@@ -0,0 +1,47 @@
+/*
+ * 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.zmlx.hg4idea.action;
+
+import com.intellij.openapi.project.Project;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.zmlx.hg4idea.repo.HgRepository;
+
+import javax.swing.*;
+import java.util.Collection;
+import java.util.List;
+
+public abstract class HgAbstractGlobalSingleRepoAction extends HgAbstractGlobalAction {
+
+ public HgAbstractGlobalSingleRepoAction(Icon icon) {
+ super(icon);
+ }
+
+ public HgAbstractGlobalSingleRepoAction() {
+ super();
+ }
+
+ @Override
+ protected void execute(@NotNull Project project,
+ @NotNull Collection<HgRepository> repositories,
+ @NotNull List<HgRepository> selectedRepositories) {
+ execute(project, repositories, selectedRepositories.isEmpty() ? null : selectedRepositories.get(0));
+ }
+
+ protected abstract void execute(@NotNull Project project,
+ @NotNull Collection<HgRepository> repositories,
+ @Nullable HgRepository selectedRepo);
+}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgActionUtil.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgActionUtil.java
new file mode 100644
index 000000000000..6abebd587787
--- /dev/null
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgActionUtil.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 org.zmlx.hg4idea.action;
+
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.actionSystem.CommonDataKeys;
+import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
+import com.sun.istack.internal.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.zmlx.hg4idea.repo.HgRepository;
+import org.zmlx.hg4idea.repo.HgRepositoryManager;
+import org.zmlx.hg4idea.util.HgUtil;
+
+import java.util.Collection;
+import java.util.List;
+
+public class HgActionUtil {
+
+ @NotNull
+ public static List<HgRepository> collectRepositoriesFromFiles(@NotNull final HgRepositoryManager repositoryManager,
+ @NotNull Collection<VirtualFile> files) {
+ return ContainerUtil.mapNotNull(files, new Function<VirtualFile, HgRepository>() {
+ @Override
+ public HgRepository fun(VirtualFile file) {
+ return repositoryManager.getRepositoryForFile(file);
+ }
+ });
+ }
+
+ @Nullable
+ public static HgRepository getSelectedRepositoryFromEvent(AnActionEvent e) {
+ final DataContext dataContext = e.getDataContext();
+ final Project project = CommonDataKeys.PROJECT.getData(dataContext);
+ if (project == null) {
+ return null;
+ }
+ VirtualFile file = e.getData(CommonDataKeys.VIRTUAL_FILE);
+ HgRepositoryManager repositoryManager = HgUtil.getRepositoryManager(project);
+ return file != null ? repositoryManager.getRepositoryForFile(file) : HgUtil.getCurrentRepository(project);
+ }
+}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchesAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchesAction.java
index b8a10ed92116..d799cde1705c 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchesAction.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchesAction.java
@@ -22,7 +22,7 @@ import org.zmlx.hg4idea.repo.HgRepository;
import java.util.Collection;
-public class HgBranchesAction extends HgAbstractGlobalAction {
+public class HgBranchesAction extends HgAbstractGlobalSingleRepoAction {
@Override
protected void execute(@NotNull Project project, @NotNull Collection<HgRepository> repositories, @Nullable HgRepository selectedRepo) {
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCreateTagAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCreateTagAction.java
index 5c97e3ca9f39..c8734e8109f4 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCreateTagAction.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCreateTagAction.java
@@ -25,7 +25,7 @@ import org.zmlx.hg4idea.util.HgErrorUtil;
import java.util.Collection;
-public class HgCreateTagAction extends HgAbstractGlobalAction {
+public class HgCreateTagAction extends HgAbstractGlobalSingleRepoAction {
public void execute(@NotNull final Project project,
@NotNull Collection<HgRepository> repositories,
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgMerge.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgMerge.java
index 1743e7e5b56e..45ff24e382ce 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgMerge.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgMerge.java
@@ -33,7 +33,7 @@ import org.zmlx.hg4idea.ui.HgMergeDialog;
import java.util.Collection;
-public class HgMerge extends HgAbstractGlobalAction {
+public class HgMerge extends HgAbstractGlobalSingleRepoAction {
@Override
public void execute(@NotNull final Project project,
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgProcessRebaseAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgProcessRebaseAction.java
index 342369f0a9bb..84e9d5b1beaf 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgProcessRebaseAction.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgProcessRebaseAction.java
@@ -18,10 +18,10 @@ package org.zmlx.hg4idea.action;
import com.intellij.openapi.actionSystem.AnActionEvent;
import org.zmlx.hg4idea.repo.HgRepository;
-public abstract class HgProcessRebaseAction extends HgAbstractGlobalAction {
+public abstract class HgProcessRebaseAction extends HgAbstractGlobalSingleRepoAction {
protected static boolean isRebasing(AnActionEvent e) {
- HgRepository repository = HgAbstractGlobalAction.getSelectedRepositoryFromEvent(e);
+ HgRepository repository = HgActionUtil.getSelectedRepositoryFromEvent(e);
return repository != null && repository.getState() == HgRepository.State.REBASING;
}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgPullAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgPullAction.java
index d5a934e1d86d..74beff13eb81 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgPullAction.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgPullAction.java
@@ -24,7 +24,7 @@ import org.zmlx.hg4idea.ui.HgPullDialog;
import java.util.Collection;
-public class HgPullAction extends HgAbstractGlobalAction {
+public class HgPullAction extends HgAbstractGlobalSingleRepoAction {
public HgPullAction() {
super(AllIcons.Actions.CheckOut);
}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgPushAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgPushAction.java
index 1b5704f1d0f4..232b2ef7fa73 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgPushAction.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgPushAction.java
@@ -12,14 +12,14 @@
// limitations under the License.
package org.zmlx.hg4idea.action;
+import com.intellij.dvcs.push.ui.VcsPushDialog;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import org.zmlx.hg4idea.HgPusher;
import org.zmlx.hg4idea.repo.HgRepository;
import java.util.Collection;
+import java.util.List;
public class HgPushAction extends HgAbstractGlobalAction {
public HgPushAction() {
@@ -29,7 +29,7 @@ public class HgPushAction extends HgAbstractGlobalAction {
@Override
public void execute(@NotNull final Project project,
@NotNull Collection<HgRepository> repositories,
- @Nullable final HgRepository selectedRepo) {
- new HgPusher(project).showDialogAndPush(repositories, selectedRepo);
+ @NotNull final List<HgRepository> selectedRepositories) {
+ new VcsPushDialog(project, selectedRepositories).show();
}
}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgRunConflictResolverAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgRunConflictResolverAction.java
index 938413e95356..279747c5278b 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgRunConflictResolverAction.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgRunConflictResolverAction.java
@@ -25,7 +25,7 @@ import org.zmlx.hg4idea.ui.HgRunConflictResolverDialog;
import java.util.Collection;
-public class HgRunConflictResolverAction extends HgAbstractGlobalAction {
+public class HgRunConflictResolverAction extends HgAbstractGlobalSingleRepoAction {
@Override
public void execute(@NotNull final Project project, @NotNull Collection<HgRepository> repositories, @Nullable HgRepository selectedRepo) {
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgUpdateToAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgUpdateToAction.java
index 7e1025921234..415cd223bd1f 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgUpdateToAction.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgUpdateToAction.java
@@ -29,7 +29,7 @@ import org.zmlx.hg4idea.util.HgErrorUtil;
import java.util.Collection;
-public class HgUpdateToAction extends HgAbstractGlobalAction {
+public class HgUpdateToAction extends HgAbstractGlobalSingleRepoAction {
@Override
protected void execute(@NotNull Project project, @NotNull Collection<HgRepository> repositories, @Nullable HgRepository selectedRepo) {
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgIdentifyCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgIdentifyCommand.java
index c719d9174d39..4acbc1f72370 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgIdentifyCommand.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgIdentifyCommand.java
@@ -31,7 +31,7 @@ public class HgIdentifyCommand {
public HgCommandResult execute(@NotNull ModalityState state) {
final List<String> arguments = new LinkedList<String>();
arguments.add(source);
- final HgRemoteCommandExecutor executor = new HgRemoteCommandExecutor(project, source, state);
+ final HgRemoteCommandExecutor executor = new HgRemoteCommandExecutor(project, source, state, false);
executor.setSilent(true);
return executor.executeInCurrentThread(null, "identify", arguments);
}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgOutgoingCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgOutgoingCommand.java
index 64f155064ead..578af65a6b56 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgOutgoingCommand.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgOutgoingCommand.java
@@ -12,11 +12,19 @@
// limitations under the License.
package org.zmlx.hg4idea.command;
+import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.zmlx.hg4idea.execution.HgCommandResult;
+import org.zmlx.hg4idea.execution.HgRemoteCommandExecutor;
+import org.zmlx.hg4idea.log.HgHistoryUtil;
import org.zmlx.hg4idea.util.HgUtil;
+import java.util.LinkedList;
+import java.util.List;
+
public class HgOutgoingCommand extends HgRemoteChangesetsCommand {
public HgOutgoingCommand(Project project) {
@@ -27,4 +35,23 @@ public class HgOutgoingCommand extends HgRemoteChangesetsCommand {
protected String getRepositoryUrl(VirtualFile root) {
return HgUtil.getRepositoryDefaultPushPath(project, root);
}
+
+ @Nullable
+ public HgCommandResult execute(@NotNull VirtualFile repo,
+ @NotNull String template,
+ @NotNull String source,
+ @NotNull String destination,
+ boolean doNotShowAuthorizationRequest) {
+
+ List<String> arguments = new LinkedList<String>();
+ arguments.add("-n");
+ arguments.add("--template");
+ arguments.add(template);
+ arguments.add(HgHistoryUtil.prepareParameter("rev", source));
+ arguments.add(destination);
+ HgRemoteCommandExecutor commandExecutor =
+ new HgRemoteCommandExecutor(project, destination, ModalityState.any(), doNotShowAuthorizationRequest);
+ commandExecutor.setOutputAlwaysSuppressed(true);
+ return commandExecutor.executeInCurrentThread(repo, "outgoing", arguments);
+ }
}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/execution/HgCommandAuthenticator.java b/plugins/hg4idea/src/org/zmlx/hg4idea/execution/HgCommandAuthenticator.java
index 14f6c981777b..01f9083da808 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/execution/HgCommandAuthenticator.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/execution/HgCommandAuthenticator.java
@@ -39,10 +39,13 @@ class HgCommandAuthenticator {
private GetPasswordRunnable myGetPassword;
private final Project myProject;
private boolean myForceAuthorization;
+ //todo replace silent mode and/or force authorization
+ private boolean mySilentMode;
- public HgCommandAuthenticator(Project project, boolean forceAuthorization) {
+ public HgCommandAuthenticator(Project project, boolean forceAuthorization, boolean silent) {
myProject = project;
myForceAuthorization = forceAuthorization;
+ mySilentMode = silent;
}
public void saveCredentials() {
@@ -71,7 +74,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);
+ GetPasswordRunnable runnable = new GetPasswordRunnable(project, proposedLogin, uri, path, myForceAuthorization, mySilentMode);
ApplicationManager.getApplication().invokeAndWait(runnable, state == null ? ModalityState.defaultModalityState() : state);
myGetPassword = runnable;
return runnable.isOk();
@@ -96,19 +99,27 @@ class HgCommandAuthenticator {
@Nullable private String myURL;
private boolean myRememberPassword;
private boolean myForceAuthorization;
+ private final boolean mySilent;
- public GetPasswordRunnable(Project project, String proposedLogin, String uri, String path, boolean forceAuthorization) {
+ public GetPasswordRunnable(Project project,
+ String proposedLogin,
+ String uri,
+ String path,
+ boolean forceAuthorization, boolean silent) {
this.myProject = project;
this.myProposedLogin = proposedLogin;
this.myURL = uri + path;
this.myForceAuthorization = forceAuthorization;
+ mySilent = silent;
}
-
+
public void run() {
// find if we've already been here
final HgVcs vcs = HgVcs.getInstance(myProject);
- if (vcs == null) { return; }
+ if (vcs == null) {
+ return;
+ }
@NotNull final HgGlobalSettings hgGlobalSettings = vcs.getGlobalSettings();
@Nullable String rememberedLoginsForUrl = null;
@@ -128,11 +139,14 @@ class HgCommandAuthenticator {
final String key = keyForUrlAndLogin(myURL, login);
try {
final PasswordSafeImpl passwordSafe = (PasswordSafeImpl)PasswordSafe.getInstance();
- password = passwordSafe.getMemoryProvider().getPassword(myProject, HgCommandAuthenticator.class, key);
- if (password == null) {
+ if (mySilent) {
+ password = passwordSafe.getMemoryProvider().getPassword(myProject, HgCommandAuthenticator.class, key);
+ }
+ else {
password = passwordSafe.getPassword(myProject, HgCommandAuthenticator.class, key);
}
- } catch (PasswordSafeException e) {
+ }
+ catch (PasswordSafeException e) {
LOG.info("Couldn't get password for key [" + key + "]", e);
}
}
@@ -146,7 +160,13 @@ class HgCommandAuthenticator {
return;
}
- final AuthDialog dialog = new AuthDialog(myProject, HgVcsMessages.message("hg4idea.dialog.login.password.required"), HgVcsMessages.message("hg4idea.dialog.login.description", myURL),
+ if (mySilent) {
+ ok = false;
+ return;
+ }
+
+ final AuthDialog dialog = new AuthDialog(myProject, HgVcsMessages.message("hg4idea.dialog.login.password.required"),
+ HgVcsMessages.message("hg4idea.dialog.login.description", myURL),
login, password, true);
dialog.show();
if (dialog.isOK()) {
@@ -182,5 +202,4 @@ class HgCommandAuthenticator {
private static String keyForUrlAndLogin(String stringUrl, String login) {
return login + ":" + stringUrl;
}
-
}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/execution/HgRemoteCommandExecutor.java b/plugins/hg4idea/src/org/zmlx/hg4idea/execution/HgRemoteCommandExecutor.java
index fdab67fbed6f..ce139cb16d9e 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/execution/HgRemoteCommandExecutor.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/execution/HgRemoteCommandExecutor.java
@@ -30,16 +30,22 @@ import java.util.List;
public class HgRemoteCommandExecutor extends HgCommandExecutor {
@Nullable private ModalityState myState;
+ final boolean myIgnoreAuthorizationRequest;
public HgRemoteCommandExecutor(@NotNull Project project, @Nullable String destination) {
- this(project, destination, null);
+ this(project, destination, null, false);
+ }
+
+ public HgRemoteCommandExecutor(@NotNull Project project, @Nullable String destination, boolean ignoreAuthorizationRequest) {
+ this(project, destination, null, ignoreAuthorizationRequest);
}
public HgRemoteCommandExecutor(@NotNull Project project,
@Nullable String destination,
- @Nullable ModalityState state) {
+ @Nullable ModalityState state, boolean ignoreAuthorizationRequest) {
super(project, destination);
myState = state;
+ myIgnoreAuthorizationRequest = ignoreAuthorizationRequest;
}
@Nullable
@@ -48,7 +54,7 @@ public class HgRemoteCommandExecutor extends HgCommandExecutor {
HgCommandResult result = executeInCurrentThread(repo, operation, arguments, false);
- if (HgErrorUtil.isAuthorizationError(result)) {
+ if (!myIgnoreAuthorizationRequest && HgErrorUtil.isAuthorizationError(result)) {
if (HgErrorUtil.hasAuthorizationInDestinationPath(myDestination)) {
new HgCommandResultNotifier(myProject)
.notifyError(result, "Authorization failed", "Your hgrc file settings have wrong username or password in [paths].\n" +
@@ -62,11 +68,11 @@ public class HgRemoteCommandExecutor extends HgCommandExecutor {
@Nullable
private HgCommandResult executeInCurrentThread(@Nullable final VirtualFile repo,
- @NotNull final String operation,
- @Nullable final List<String> arguments,
- boolean forceAuthorization) {
+ @NotNull final String operation,
+ @Nullable final List<String> arguments,
+ boolean forceAuthorization) {
- PassReceiver passReceiver = new PassReceiver(myProject, forceAuthorization, myState);
+ PassReceiver passReceiver = new PassReceiver(myProject, forceAuthorization, myIgnoreAuthorizationRequest, myState);
SocketServer passServer = new SocketServer(passReceiver);
try {
int passPort = passServer.start();
@@ -109,11 +115,13 @@ public class HgRemoteCommandExecutor extends HgCommandExecutor {
private final Project myProject;
private HgCommandAuthenticator myAuthenticator;
private boolean myForceAuthorization;
+ private boolean mySilentMode;
@Nullable private ModalityState myState;
- private PassReceiver(Project project, boolean forceAuthorization, @Nullable ModalityState state) {
+ private PassReceiver(Project project, boolean forceAuthorization, boolean silent, @Nullable ModalityState state) {
myProject = project;
myForceAuthorization = forceAuthorization;
+ mySilentMode = silent;
myState = state;
}
@@ -129,7 +137,7 @@ public class HgRemoteCommandExecutor extends HgCommandExecutor {
String path = new String(readDataBlock(dataInputStream));
String proposedLogin = new String(readDataBlock(dataInputStream));
- HgCommandAuthenticator authenticator = new HgCommandAuthenticator(myProject, myForceAuthorization);
+ HgCommandAuthenticator authenticator = new HgCommandAuthenticator(myProject, myForceAuthorization, mySilentMode);
boolean ok = authenticator.promptForAuthentication(myProject, proposedLogin, uri, path, myState);
if (ok) {
myAuthenticator = authenticator;
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgHistoryUtil.java b/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgHistoryUtil.java
index dfb576f98ab3..de565484e2d5 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgHistoryUtil.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgHistoryUtil.java
@@ -94,25 +94,35 @@ public class HgHistoryUtil {
}
/**
- * <p>Get & parse hg log detailed output with commits, their parents and their changes.</p>
+ * <p>Get & parse hg log detailed output with commits, their parents and their changes.
+ * For null destination return log command result</p>
* <p/>
* <p>Warning: this is method is efficient by speed, but don't query too much, because the whole log output is retrieved at once,
* and it can occupy too much memory. The estimate is ~600Kb for 1000 commits.</p>
*/
@NotNull
- public static List<? extends VcsFullCommitDetails> history(@NotNull final Project project, @NotNull final VirtualFile root, int limit,
+ public static List<? extends VcsFullCommitDetails> history(@NotNull final Project project,
+ @NotNull final VirtualFile root,
+ int limit,
@NotNull List<String> parameters) throws VcsException {
- final VcsLogObjectsFactory factory = getObjectsFactoryWithDisposeCheck(project);
- if (factory == null) {
- return Collections.emptyList();
- }
HgVcs hgvcs = HgVcs.getInstance(project);
assert hgvcs != null;
final HgVersion version = hgvcs.getVersion();
String[] templates = HgBaseLogParser.constructFullTemplateArgument(true, version);
HgCommandResult result = getLogResult(project, root, version, limit, parameters, HgChangesetUtil.makeTemplate(templates));
+ return createFullCommitsFromResult(project, root, result, version, false);
+ }
+
+ public static List<? extends VcsFullCommitDetails> createFullCommitsFromResult(@NotNull Project project,
+ @NotNull VirtualFile root,
+ @Nullable HgCommandResult result,
+ @NotNull HgVersion version, boolean silent) {
+ final VcsLogObjectsFactory factory = getObjectsFactoryWithDisposeCheck(project);
+ if (factory == null) {
+ return Collections.emptyList();
+ }
List<HgFileRevision> hgRevisions =
- getCommitRecords(project, result, new HgFileRevisionLogParser(project, getOriginalHgFile(project, root), version));
+ getCommitRecords(project, result, new HgFileRevisionLogParser(project, getOriginalHgFile(project, root), version), silent);
List<VcsFullCommitDetails> vcsFullCommitDetailsList = new ArrayList<VcsFullCommitDetails>();
for (HgFileRevision revision : hgRevisions) {
@@ -184,6 +194,13 @@ public class HgHistoryUtil {
public static <CommitInfo> List<CommitInfo> getCommitRecords(@NotNull Project project,
@Nullable HgCommandResult result,
@NotNull Function<String, CommitInfo> converter) {
+ return getCommitRecords(project, result, converter, false);
+ }
+
+ @NotNull
+ public static <CommitInfo> List<CommitInfo> getCommitRecords(@NotNull Project project,
+ @Nullable HgCommandResult result,
+ @NotNull Function<String, CommitInfo> converter, boolean silent) {
final List<CommitInfo> revisions = new LinkedList<CommitInfo>();
if (result == null) {
return revisions;
@@ -192,7 +209,12 @@ public class HgHistoryUtil {
List<String> errors = result.getErrorLines();
if (errors != null && !errors.isEmpty()) {
if (result.getExitValue() != 0) {
- VcsNotifier.getInstance(project).notifyError(HgVcsMessages.message("hg4idea.error.log.command.execution"), errors.toString());
+ if (silent) {
+ LOG.warn(errors.toString());
+ }
+ else {
+ VcsNotifier.getInstance(project).notifyError(HgVcsMessages.message("hg4idea.error.log.command.execution"), errors.toString());
+ }
return Collections.emptyList();
}
LOG.warn(errors.toString());
@@ -331,4 +353,8 @@ public class HgHistoryUtil {
}
return branchHeads;
}
+
+ public static String prepareParameter(String paramName, String value) {
+ return "--" + paramName + "=" + value; // no value escaping needed, because the parameter itself will be quoted by GeneralCommandLine
+ }
}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgLogProvider.java b/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgLogProvider.java
index 4adec9dff515..3b989e448b61 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgLogProvider.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgLogProvider.java
@@ -180,11 +180,11 @@ public class HgLogProvider implements VcsLogProvider {
boolean atLeastOneBranchExists = false;
for (String branchName : filterCollection.getBranchFilter().getBranchNames()) {
if (branchName.equals(TIP_REFERENCE) || branchExists(repository, branchName)) {
- filterParameters.add(prepareParameter("branch", branchName));
+ filterParameters.add(HgHistoryUtil.prepareParameter("branch", branchName));
atLeastOneBranchExists = true;
}
else if (branchName.equals(HEAD_REFERENCE)) {
- filterParameters.add(prepareParameter("branch", "."));
+ filterParameters.add(HgHistoryUtil.prepareParameter("branch", "."));
filterParameters.add("-r");
filterParameters.add("::."); //all ancestors for current revision;
atLeastOneBranchExists = true;
@@ -197,7 +197,7 @@ public class HgLogProvider implements VcsLogProvider {
if (filterCollection.getUserFilter() != null) {
for (String authorName : filterCollection.getUserFilter().getUserNames(root)) {
- filterParameters.add(prepareParameter("user", authorName));
+ filterParameters.add(HgHistoryUtil.prepareParameter("user", authorName));
}
}
@@ -223,7 +223,7 @@ public class HgLogProvider implements VcsLogProvider {
if (filterCollection.getTextFilter() != null) {
String textFilter = filterCollection.getTextFilter().getText();
- filterParameters.add(prepareParameter("keyword", textFilter));
+ filterParameters.add(HgHistoryUtil.prepareParameter("keyword", textFilter));
}
if (filterCollection.getStructureFilter() != null) {
@@ -262,10 +262,6 @@ public class HgLogProvider implements VcsLogProvider {
return HgHistoryUtil.getDescendingHeadsOfBranches(myProject, root, commitHash);
}
- private static String prepareParameter(String paramName, String value) {
- return "--" + paramName + "=" + value; // no value escaping needed, because the parameter itself will be quoted by GeneralCommandLine
- }
-
private static boolean branchExists(@NotNull HgRepository repository, @NotNull String branchName) {
return repository.getBranches().keySet().contains(branchName) ||
HgUtil.getNamesWithoutHashes(repository.getBookmarks()).contains(branchName);
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/commit/HgCheckinEnvironment.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/commit/HgCheckinEnvironment.java
index c60e46c63ced..06b74148156e 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/commit/HgCheckinEnvironment.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/commit/HgCheckinEnvironment.java
@@ -13,6 +13,7 @@
package org.zmlx.hg4idea.provider.commit;
import com.intellij.dvcs.DvcsCommitAdditionalComponent;
+import com.intellij.dvcs.push.ui.VcsPushDialog;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.progress.ProgressIndicator;
@@ -37,6 +38,7 @@ import com.intellij.vcsUtil.VcsUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.zmlx.hg4idea.*;
+import org.zmlx.hg4idea.action.HgActionUtil;
import org.zmlx.hg4idea.command.*;
import org.zmlx.hg4idea.execution.HgCommandException;
import org.zmlx.hg4idea.execution.HgCommandExecutor;
@@ -132,13 +134,12 @@ public class HgCheckinEnvironment implements CheckinEnvironment {
// push if needed
if (myNextCommitIsPushed && exceptions.isEmpty()) {
- final VirtualFile preselectedRepo = repositoriesMap.size() == 1 ? repositoriesMap.keySet().iterator().next() : null;
+ final Set<VirtualFile> preselectedFiles = repositoriesMap.keySet();
HgRepositoryManager repositoryManager = HgUtil.getRepositoryManager(myProject);
- final HgRepository repo = preselectedRepo != null ? repositoryManager.getRepositoryForFile(preselectedRepo) : null;
- final Collection<HgRepository> repositories = repositoryManager.getRepositories();
+ final List<HgRepository> preselectedRepositories = HgActionUtil.collectRepositoriesFromFiles(repositoryManager, preselectedFiles);
UIUtil.invokeLaterIfNeeded(new Runnable() {
public void run() {
- new HgPusher(myProject).showDialogAndPush(repositories, repo);
+ new VcsPushDialog(myProject, preselectedRepositories).show();
}
});
}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgOutgoingCommitsProvider.java b/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgOutgoingCommitsProvider.java
new file mode 100644
index 000000000000..70055cafe1a1
--- /dev/null
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgOutgoingCommitsProvider.java
@@ -0,0 +1,90 @@
+/*
+ * 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.zmlx.hg4idea.push;
+
+import com.intellij.dvcs.push.*;
+import com.intellij.dvcs.repo.Repository;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.vcs.log.VcsFullCommitDetails;
+import org.jetbrains.annotations.NotNull;
+import org.zmlx.hg4idea.HgVcs;
+import org.zmlx.hg4idea.command.HgOutgoingCommand;
+import org.zmlx.hg4idea.execution.HgCommandResult;
+import org.zmlx.hg4idea.log.HgBaseLogParser;
+import org.zmlx.hg4idea.log.HgHistoryUtil;
+import org.zmlx.hg4idea.util.HgChangesetUtil;
+import org.zmlx.hg4idea.util.HgErrorUtil;
+import org.zmlx.hg4idea.util.HgVersion;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class HgOutgoingCommitsProvider extends OutgoingCommitsProvider {
+
+
+ private static final Logger LOG = Logger.getInstance(HgOutgoingCommitsProvider.class);
+ private static final String LOGIN_AND_REFRESH_LINK = "Enter Password & Refresh";
+
+ @NotNull
+ @Override
+ public OutgoingResult getOutgoingCommits(@NotNull final Repository repository,
+ @NotNull final PushSpec pushSpec,
+ boolean initial) {
+ final Project project = repository.getProject();
+ HgVcs hgvcs = HgVcs.getInstance(project);
+ assert hgvcs != null;
+ final HgVersion version = hgvcs.getVersion();
+ String[] templates = HgBaseLogParser.constructFullTemplateArgument(true, version);
+ HgOutgoingCommand hgOutgoingCommand = new HgOutgoingCommand(project);
+ HgTarget hgTarget = (HgTarget)pushSpec.getTarget();
+ List<VcsError> errors = new ArrayList<VcsError>();
+ if (hgTarget == null || StringUtil.isEmptyOrSpaces(hgTarget.myTarget)) {
+ errors.add(new VcsError("Hg push path could not be empty."));
+ return new OutgoingResult(Collections.<VcsFullCommitDetails>emptyList(), errors);
+ }
+ HgCommandResult result = hgOutgoingCommand
+ .execute(repository.getRoot(), HgChangesetUtil.makeTemplate(templates), pushSpec.getSource().getPresentation(),
+ hgTarget.myTarget, initial);
+ if (result == null) {
+ errors.add(new VcsError("Couldn't execute hg outgoing command for " + repository));
+ return new OutgoingResult(Collections.<VcsFullCommitDetails>emptyList(), errors);
+ }
+ List<String> resultErrors = result.getErrorLines();
+ if (resultErrors != null && !resultErrors.isEmpty() && result.getExitValue() != 0) {
+ for (String error : resultErrors) {
+ if (HgErrorUtil.isAbortLine(error)) {
+ if (HgErrorUtil.isAuthorizationError(error)) {
+ VcsError authorizationError =
+ new VcsError(error + "<a href='authenticate'>" + LOGIN_AND_REFRESH_LINK + "</a>", new VcsErrorHandler() {
+ public void handleError(@NotNull CommitLoader commitLoader) {
+ commitLoader.reloadCommits();
+ }
+ });
+ errors.add(authorizationError);
+ }
+ else {
+ errors.add(new VcsError(error));
+ }
+ }
+ }
+ LOG.warn(resultErrors.toString());
+ }
+ return new OutgoingResult(HgHistoryUtil.createFullCommitsFromResult(project, repository.getRoot(), result, version, true), errors);
+ }
+}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPushOptionsPanel.java b/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPushOptionsPanel.java
new file mode 100644
index 000000000000..336f8ff1aa4c
--- /dev/null
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPushOptionsPanel.java
@@ -0,0 +1,51 @@
+/*
+ * 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.zmlx.hg4idea.push;
+
+import com.intellij.dvcs.push.VcsPushOptionsPanel;
+import com.intellij.openapi.ui.ComboBox;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ActionListener;
+
+public class HgPushOptionsPanel extends VcsPushOptionsPanel {
+
+ private final ComboBox myReferenceStrategyCombobox;
+
+ public HgPushOptionsPanel() {
+ setLayout(new BorderLayout());
+ myReferenceStrategyCombobox = new ComboBox();
+ HgVcsPushOptionValue[] values = HgVcsPushOptionValue.values();
+ DefaultComboBoxModel comboModel = new DefaultComboBoxModel(values);
+ myReferenceStrategyCombobox.setModel(comboModel);
+ JLabel referenceStrategyLabel = new JLabel("Export Bookmarks: ");
+ add(referenceStrategyLabel, BorderLayout.WEST);
+ add(myReferenceStrategyCombobox, BorderLayout.CENTER);
+ }
+
+ @Override
+ @NotNull
+ public HgVcsPushOptionValue getValue() {
+ return (HgVcsPushOptionValue)myReferenceStrategyCombobox.getSelectedItem();
+ }
+
+ @Override
+ public void addValueChangeListener(ActionListener listener) {
+ myReferenceStrategyCombobox.addActionListener(listener);
+ }
+}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPushSource.java b/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPushSource.java
new file mode 100644
index 000000000000..babd49c9b31d
--- /dev/null
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPushSource.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.zmlx.hg4idea.push;
+
+import com.intellij.dvcs.push.PushSource;
+import org.jetbrains.annotations.NotNull;
+
+public class HgPushSource implements PushSource {
+ @NotNull private String myBranch;
+
+ public HgPushSource(@NotNull String branch) {
+ myBranch = branch;
+ }
+
+ @NotNull
+ @Override
+ public String getPresentation() {
+ return myBranch;
+ }
+
+ @NotNull
+ public String getBranch() {
+ return myBranch; // presentation may differ from branch
+ }
+}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPushSupport.java b/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPushSupport.java
new file mode 100644
index 000000000000..4bfa134a5e26
--- /dev/null
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPushSupport.java
@@ -0,0 +1,109 @@
+/*
+ * 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.zmlx.hg4idea.push;
+
+import com.intellij.dvcs.push.*;
+import com.intellij.dvcs.repo.Repository;
+import com.intellij.dvcs.repo.RepositoryManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vcs.AbstractVcs;
+import com.intellij.util.Function;
+import com.intellij.util.ObjectUtils;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.zmlx.hg4idea.HgVcs;
+import org.zmlx.hg4idea.repo.HgRepository;
+import org.zmlx.hg4idea.util.HgUtil;
+
+import java.util.Collection;
+
+public class HgPushSupport extends PushSupport<HgRepository> {
+
+ @NotNull private final Project myProject;
+ @NotNull private final HgVcs myVcs;
+
+ public HgPushSupport(@NotNull Project project) {
+ myProject = project;
+ myVcs = ObjectUtils.assertNotNull(HgVcs.getInstance(myProject));
+ }
+
+ @NotNull
+ @Override
+ public AbstractVcs getVcs() {
+ return myVcs;
+ }
+
+ @NotNull
+ @Override
+ public Pusher getPusher() {
+ return new HgPusher();
+ }
+
+ @NotNull
+ @Override
+ public OutgoingCommitsProvider getOutgoingCommitsProvider() {
+ return new HgOutgoingCommitsProvider();
+ }
+
+ @Nullable
+ @Override
+ public HgTarget getDefaultTarget(@NotNull HgRepository repository) {
+ String defaultPushPath = repository.getRepositoryConfig().getDefaultPushPath();
+ return defaultPushPath == null ? null : new HgTarget(defaultPushPath);
+ }
+
+ @NotNull
+ @Override
+ public Collection<String> getTargetNames(@NotNull HgRepository repository) {
+ return ContainerUtil.map(repository.getRepositoryConfig().getPaths(), new Function<String, String>() {
+ @Override
+ public String fun(String s) {
+ return HgUtil.removePasswordIfNeeded(s);
+ }
+ });
+ }
+
+ @NotNull
+ @Override
+ public HgPushSource getSource(@NotNull HgRepository repository) {
+ String localBranch = HgUtil.getActiveBranchName(repository);
+ return new HgPushSource(localBranch);
+ }
+
+ @Override
+ public HgTarget createTarget(@NotNull HgRepository repository, @NotNull String targetName) {
+ return new HgTarget(targetName);
+ }
+
+ @NotNull
+ @Override
+ public RepositoryManager<HgRepository> getRepositoryManager() {
+ return HgUtil.getRepositoryManager(myProject);
+ }
+
+ @Nullable
+ public VcsPushOptionsPanel getVcsPushOptionsPanel() {
+ return new HgPushOptionsPanel();
+ }
+
+ @Override
+ @Nullable
+ public VcsError validate(@NotNull Repository repository, @Nullable String targetToValidate) {
+ return StringUtil.isEmptyOrSpaces(targetToValidate) ? new VcsError("Please, specify remote push path for repository!") : null;
+ }
+}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgPusher.java b/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPusher.java
index 2b6108dddbbc..f019035a373f 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgPusher.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPusher.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.
@@ -13,16 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.zmlx.hg4idea;
+package org.zmlx.hg4idea.push;
+import com.intellij.dvcs.push.PushSpec;
+import com.intellij.dvcs.push.Pusher;
+import com.intellij.dvcs.push.VcsPushOptionValue;
+import com.intellij.dvcs.repo.Repository;
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.MessageType;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.VcsNotifier;
-import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -31,52 +31,54 @@ import org.zmlx.hg4idea.command.HgPushCommand;
import org.zmlx.hg4idea.execution.HgCommandResult;
import org.zmlx.hg4idea.execution.HgCommandResultHandler;
import org.zmlx.hg4idea.repo.HgRepository;
-import org.zmlx.hg4idea.ui.HgPushDialog;
-import java.util.Collection;
import java.util.List;
-import java.util.concurrent.atomic.AtomicReference;
+import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-public class HgPusher {
+public class HgPusher extends Pusher {
private static final Logger LOG = Logger.getInstance(HgPusher.class);
- private static Pattern PUSH_COMMITS_PATTERN = Pattern.compile(".*added (\\d+) changesets.*");
+ private static final String ONE = "one";
+ private static Pattern PUSH_COMMITS_PATTERN = Pattern.compile(".*(?:added|pushed) (\\d+|" + ONE + ") changeset.*");
// hg push command has definite exit values for some cases:
// mercurial returns 0 if push was successful, 1 if nothing to push. see hg push --help
private static int PUSH_SUCCEEDED_EXIT_VALUE = 0;
private static int NOTHING_TO_PUSH_EXIT_VALUE = 1;
- private final Project myProject;
-
- public HgPusher(Project project) {
- myProject = project;
- }
-
- public void showDialogAndPush (@NotNull Collection<HgRepository> repositories,@Nullable final HgRepository selectedRepo) {
-
- if (repositories.isEmpty()) {
- VcsBalloonProblemNotifier.showOverChangesView(myProject, "No Mercurial repositories in the project", MessageType.ERROR);
- return;
- }
- final AtomicReference<HgPushCommand> pushCommand = new AtomicReference<HgPushCommand>();
- final HgPushDialog dialog = new HgPushDialog(myProject, repositories, selectedRepo);
- dialog.show();
- if (dialog.isOK()) {
- pushCommand.set(preparePushCommand(myProject, dialog));
- new Task.Backgroundable(myProject, "Pushing...", false) {
- @Override
- public void run(@NotNull ProgressIndicator indicator) {
- if (pushCommand.get() != null) {
- push(myProject, pushCommand.get());
- }
+ @Override
+ public void push(@NotNull Map<Repository, PushSpec> pushSpecs, @Nullable VcsPushOptionValue vcsPushOptionValue, boolean force) {
+ for (Map.Entry<Repository, PushSpec> entry : pushSpecs.entrySet()) {
+ Repository repository = entry.getKey();
+ HgRepository hgRepository = (HgRepository)repository;
+ PushSpec hgSpec = entry.getValue();
+ HgTarget destination = (HgTarget)hgSpec.getTarget();
+ if (destination == null) {
+ continue;
+ }
+ HgPushSource source = (HgPushSource)hgSpec.getSource();
+ Project project = repository.getProject();
+ final HgPushCommand pushCommand = new HgPushCommand(project, repository.getRoot(), destination.myTarget);
+ pushCommand.setIsNewBranch(true); // set always true, because it just allow mercurial to create a new one if needed
+ pushCommand.setForce(force);
+ String branchName = source.getBranch();
+ if (branchName.equals(hgRepository.getCurrentBookmark())) {
+ if (vcsPushOptionValue == HgVcsPushOptionValue.Current) {
+ pushCommand.setBookmarkName(branchName);
+ }
+ else {
+ pushCommand.setRevision(branchName);
}
- }.queue();
+ }
+ else {
+ pushCommand.setBranchName(branchName);
+ }
+ push(project, pushCommand);
}
}
- private static void push(final Project project, HgPushCommand command) {
+ public static void push(@NotNull final Project project, @NotNull HgPushCommand command) {
final VirtualFile repo = command.getRepo();
command.execute(new HgCommandResultHandler() {
@Override
@@ -91,9 +93,11 @@ public class HgPusher {
String successDescription = String.format("Pushed %d %s [%s]", commitsNum, StringUtil.pluralize("commit", commitsNum),
repo.getPresentableName());
VcsNotifier.getInstance(project).notifySuccess(successTitle, successDescription);
- } else if (result.getExitValue() == NOTHING_TO_PUSH_EXIT_VALUE) {
+ }
+ else if (result.getExitValue() == NOTHING_TO_PUSH_EXIT_VALUE) {
VcsNotifier.getInstance(project).notifySuccess("Nothing to push");
- } else {
+ }
+ else {
new HgCommandResultNotifier(project).notifyError(result, "Push failed",
"Failed to push to [" + repo.getPresentableName() + "]");
}
@@ -101,17 +105,7 @@ public class HgPusher {
});
}
- private static HgPushCommand preparePushCommand(Project project, HgPushDialog dialog) {
- final HgPushCommand command = new HgPushCommand(project, dialog.getRepository().getRoot(), dialog.getTarget());
- command.setRevision(dialog.getRevision());
- command.setForce(dialog.isForce());
- command.setBranchName(dialog.getBranch());
- command.setBookmarkName(dialog.getBookmarkName());
- command.setIsNewBranch(dialog.isNewBranch());
- return command;
- }
-
- private static int getNumberOfPushedCommits(HgCommandResult result) {
+ private static int getNumberOfPushedCommits(@NotNull HgCommandResult result) {
int numberOfCommitsInAllSubrepos = 0;
final List<String> outputLines = result.getOutputLines();
for (String outputLine : outputLines) {
@@ -119,7 +113,8 @@ public class HgPusher {
final Matcher matcher = PUSH_COMMITS_PATTERN.matcher(outputLine);
if (matcher.matches()) {
try {
- numberOfCommitsInAllSubrepos += Integer.parseInt(matcher.group(1));
+ String numberOfCommits = matcher.group(1);
+ numberOfCommitsInAllSubrepos += ONE.equals(numberOfCommits) ? 1 : Integer.parseInt(numberOfCommits);
}
catch (NumberFormatException e) {
LOG.error("getNumberOfPushedCommits ", e);
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgTarget.java b/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgTarget.java
new file mode 100644
index 000000000000..8f5aca3838ca
--- /dev/null
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgTarget.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 org.zmlx.hg4idea.push;
+
+import com.intellij.dvcs.push.PushTarget;
+import org.jetbrains.annotations.NotNull;
+import org.zmlx.hg4idea.util.HgUtil;
+
+public class HgTarget implements PushTarget {
+ @NotNull String myTarget;
+
+ public HgTarget(@NotNull String name) {
+ myTarget = name;
+ }
+
+ @Override
+ @NotNull
+ public String getPresentation() {
+ return HgUtil.removePasswordIfNeeded(myTarget);
+ }
+}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgVcsPushOptionValue.java b/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgVcsPushOptionValue.java
new file mode 100644
index 000000000000..5b35e7f5e6e0
--- /dev/null
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgVcsPushOptionValue.java
@@ -0,0 +1,22 @@
+/*
+ * 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.zmlx.hg4idea.push;
+
+import com.intellij.dvcs.push.VcsPushOptionValue;
+
+public enum HgVcsPushOptionValue implements VcsPushOptionValue {
+ None, Current
+}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepositoryImpl.java b/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepositoryImpl.java
index 77c81ee80993..b670fb056c0c 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepositoryImpl.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepositoryImpl.java
@@ -21,6 +21,7 @@ import com.intellij.openapi.Disposable;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
+import com.intellij.openapi.vcs.AbstractVcs;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.vcs.log.Hash;
@@ -96,6 +97,12 @@ public class HgRepositoryImpl extends RepositoryImpl implements HgRepository {
return myInfo.getState();
}
+ @Nullable
+ @Override
+ public AbstractVcs getVcs() {
+ return HgVcs.getInstance(getProject());
+ }
+
@Override
@NotNull
public String getCurrentBranch() {
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgErrorUtil.java b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgErrorUtil.java
index 1810370588b7..7592f5830ee5 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgErrorUtil.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgErrorUtil.java
@@ -43,7 +43,7 @@ public final class HgErrorUtil {
}
final List<String> errorLines = result.getErrorLines();
for (String line : errorLines) {
- if (!StringUtil.isEmptyOrSpaces(line) && line.trim().startsWith("abort:")) {
+ if (isAbortLine(line)) {
return true;
}
}
@@ -55,8 +55,7 @@ public final class HgErrorUtil {
return false;
}
String line = getLastErrorLine(result);
- return !StringUtil.isEmptyOrSpaces(line) && (line.contains("authorization required") || line.contains("authorization failed")
- );
+ return isAuthorizationError(line);
}
@Nullable
@@ -119,4 +118,12 @@ public final class HgErrorUtil {
Matcher matcher = UNCOMMITTED_PATTERN.matcher(result.getRawError());
return matcher.matches();
}
+
+ public static boolean isAuthorizationError(String line) {
+ return !StringUtil.isEmptyOrSpaces(line) && (line.contains("authorization required") || line.contains("authorization failed"));
+ }
+
+ public static boolean isAbortLine(String line) {
+ return !StringUtil.isEmptyOrSpaces(line) && line.trim().startsWith("abort:");
+ }
}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java
index 1cc100efb029..3bb14721f0a8 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java
@@ -32,6 +32,7 @@ import com.intellij.openapi.vcs.*;
import com.intellij.openapi.vcs.changes.*;
import com.intellij.openapi.vcs.history.FileHistoryPanelImpl;
import com.intellij.openapi.vcs.history.VcsFileRevisionEx;
+import com.intellij.openapi.vcs.vfs.AbstractVcsVirtualFile;
import com.intellij.openapi.vcs.vfs.VcsVirtualFile;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.openapi.vfs.LocalFileSystem;
@@ -474,7 +475,7 @@ public abstract class HgUtil {
*/
@Nullable
public static VirtualFile convertToLocalVirtualFile(@Nullable VirtualFile file) {
- if (!(file instanceof VcsVirtualFile)) {
+ if (!(file instanceof AbstractVcsVirtualFile)) {
return file;
}
LocalFileSystem lfs = LocalFileSystem.getInstance();
@@ -583,11 +584,16 @@ public abstract class HgUtil {
if (state != HgRepository.State.NORMAL) {
branchText += state.toString() + " ";
}
+ return branchText + getActiveBranchName(repository);
+ }
+
+ @NotNull
+ public static String getActiveBranchName(@NotNull HgRepository repository) {
String branchOrBookMarkName = repository.getCurrentBookmark();
if (StringUtil.isEmptyOrSpaces(branchOrBookMarkName)) {
branchOrBookMarkName = repository.getCurrentBranch();
}
- return branchText + branchOrBookMarkName;
+ return branchOrBookMarkName;
}
@NotNull
diff --git a/plugins/java-i18n/src/META-INF/plugin.xml b/plugins/java-i18n/src/META-INF/plugin.xml
index b352a2f78e08..dca09990aeac 100644
--- a/plugins/java-i18n/src/META-INF/plugin.xml
+++ b/plugins/java-i18n/src/META-INF/plugin.xml
@@ -26,6 +26,7 @@
<psi.referenceContributor implementation="com.intellij.lang.properties.PropertiesReferenceContributor"/>
<lang.foldingBuilder language="JAVA" implementationClass="com.intellij.codeInspection.i18n.folding.PropertyFoldingBuilder" order="FIRST"/>
<gotoDeclarationHandler implementation="com.intellij.codeInspection.i18n.folding.I18nMessageGotoDeclarationHandler" order="FIRST"/>
+ <inlineActionHandler implementation="com.intellij.refactoring.inline.InlinePropertyHandler"/>
<localInspection shortName="HardCodedStringLiteral" bundle="messages.CodeInsightBundle" key="inspection.i18n.display.name"
groupBundle="messages.InspectionsBundle" groupKey="group.names.internationalization.issues" enabledByDefault="false" level="WARNING"
diff --git a/plugins/java-i18n/src/com/intellij/refactoring/inline/InlinePropertyHandler.java b/plugins/java-i18n/src/com/intellij/refactoring/inline/InlinePropertyHandler.java
new file mode 100644
index 000000000000..151b8e605f8c
--- /dev/null
+++ b/plugins/java-i18n/src/com/intellij/refactoring/inline/InlinePropertyHandler.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.refactoring.inline;
+
+import com.intellij.lang.properties.IProperty;
+import com.intellij.lang.properties.PropertiesBundle;
+import com.intellij.lang.properties.references.PropertyReference;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.WriteCommandAction;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.*;
+import com.intellij.psi.search.searches.ReferencesSearch;
+import com.intellij.refactoring.HelpID;
+import com.intellij.refactoring.RefactoringBundle;
+import com.intellij.refactoring.listeners.RefactoringEventData;
+import com.intellij.refactoring.listeners.RefactoringEventListener;
+import com.intellij.refactoring.util.CommonRefactoringUtil;
+import com.intellij.refactoring.util.RefactoringMessageDialog;
+import com.intellij.util.Processor;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.FilteringIterator;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+
+/**
+ * @author gregsh
+ */
+public class InlinePropertyHandler extends JavaInlineActionHandler {
+ public static final String REFACTORING_NAME = PropertiesBundle.message("inline.property.refactoring");
+ public static final String REFACTORING_ID = "refactoring.inline.property";
+
+ public boolean canInlineElement(PsiElement element) {
+ if (element instanceof PsiJavaToken && ((PsiJavaToken)element).getTokenType() == JavaTokenType.STRING_LITERAL) {
+ PsiReference[] references = element.getParent().getReferences();
+ return ContainerUtil.find(references, FilteringIterator.instanceOf(PropertyReference.class)) != null;
+ }
+ return element instanceof IProperty;
+ }
+
+ public void inlineElement(final Project project, Editor editor, PsiElement psiElement) {
+ if (!(psiElement instanceof IProperty)) return;
+
+ IProperty property = (IProperty)psiElement;
+ final String propertyValue = property.getValue();
+ if (propertyValue == null) return;
+
+ final List<PsiElement> occurrences = Collections.synchronizedList(ContainerUtil.<PsiElement>newArrayList());
+ final Collection<PsiFile> containingFiles = Collections.synchronizedSet(new HashSet<PsiFile>());
+ containingFiles.add(psiElement.getContainingFile());
+ boolean result = ReferencesSearch.search(psiElement).forEach(
+ new Processor<PsiReference>() {
+ public boolean process(final PsiReference psiReference) {
+ PsiElement element = psiReference.getElement();
+ PsiElement parent = element.getParent();
+ if (parent instanceof PsiExpressionList && parent.getParent() instanceof PsiMethodCallExpression) {
+ if (((PsiExpressionList)parent).getExpressions().length == 1) {
+ occurrences.add(parent.getParent());
+ containingFiles.add(element.getContainingFile());
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+ );
+
+ if (!result) {
+ CommonRefactoringUtil.showErrorHint(project, editor, "Property has non-method usages", REFACTORING_NAME, null);
+ }
+ if (occurrences.isEmpty()) {
+ CommonRefactoringUtil.showErrorHint(project, editor, "Property has no usages", REFACTORING_NAME, null);
+ return;
+ }
+
+ if (!ApplicationManager.getApplication().isUnitTestMode()) {
+ String occurrencesString = RefactoringBundle.message("occurrences.string", occurrences.size());
+ String question = PropertiesBundle.message("inline.property.confirmation", property.getName(), propertyValue) + " " + occurrencesString;
+ RefactoringMessageDialog dialog = new RefactoringMessageDialog(REFACTORING_NAME, question, HelpID.INLINE_VARIABLE,
+ "OptionPane.questionIcon", true, project);
+ dialog.show();
+ if (!dialog.isOK()) {
+ return;
+ }
+ }
+
+ final RefactoringEventData data = new RefactoringEventData();
+ data.addElement(psiElement.copy());
+
+ new WriteCommandAction.Simple(project, REFACTORING_NAME, containingFiles.toArray(new PsiFile[containingFiles.size()])) {
+ @Override
+ protected void run() throws Throwable {
+ project.getMessageBus().syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC).refactoringStarted(REFACTORING_ID, data);
+ PsiLiteral stringLiteral = (PsiLiteral)JavaPsiFacade.getInstance(getProject()).getElementFactory().
+ createExpressionFromText("\"" + StringUtil.escapeStringCharacters(propertyValue) + "\"", null);
+ for (PsiElement occurrence : occurrences) {
+ occurrence.replace(stringLiteral.copy());
+ }
+ project.getMessageBus().syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC).refactoringDone(REFACTORING_ID, null);
+ }
+ }.execute();
+ }
+}
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderEditor.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderEditor.java
index f0c1eccd86f1..a0a90efe9c74 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderEditor.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderEditor.java
@@ -11,11 +11,13 @@ import com.intellij.openapi.editor.event.DocumentEvent;
import com.intellij.openapi.fileEditor.*;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
-import com.intellij.openapi.ui.VerticalFlowLayout;
import com.intellij.openapi.util.UserDataHolderBase;
import com.intellij.openapi.vfs.ReadonlyStatusHandler;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.HyperlinkLabel;
+import com.intellij.ui.ScrollPaneFactory;
+import com.intellij.util.ExceptionUtil;
+import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -42,8 +44,10 @@ public class SceneBuilderEditor extends UserDataHolderBase implements FileEditor
private final CardLayout myLayout = new CardLayout();
private final JPanel myPanel = new JPanel(myLayout);
- private final JPanel myErrorPanel = new JPanel(new VerticalFlowLayout(VerticalFlowLayout.TOP, 10, 5, true, false));
+ //private final JPanel myErrorPanel = new JPanel(new VerticalFlowLayout(VerticalFlowLayout.TOP, 10, 5, true, false));
+ private final JPanel myErrorPanel = new JPanel(new BorderLayout());
private final HyperlinkLabel myErrorLabel = new HyperlinkLabel();
+ private JTextArea myErrorStack;
private final Document myDocument;
private final ExternalChangeListener myChangeListener;
@@ -72,11 +76,19 @@ public class SceneBuilderEditor extends UserDataHolderBase implements FileEditor
}
});
- myErrorPanel.add(myErrorLabel);
+ myErrorStack = new JTextArea(50, 20);
+ myErrorStack.setEditable(false);
+
+ myErrorPanel.add(myErrorLabel, BorderLayout.NORTH);
+ myErrorPanel.add(ScrollPaneFactory.createScrollPane(myErrorStack), BorderLayout.CENTER);
myPanel.add(myErrorPanel);
}
private void showErrorPage(State state, Throwable e) {
+ if (e != null) {
+ LOG.info(e);
+ }
+
removeSceneBuilder();
if (e == null) {
@@ -93,12 +105,21 @@ public class SceneBuilderEditor extends UserDataHolderBase implements FileEditor
}
myErrorLabel.setIcon(Messages.getWarningIcon());
}
+
+ myErrorStack.setText(null);
+ myErrorStack.setVisible(false);
}
else {
- myErrorLabel.setHyperlinkText("Error: " + e.getMessage(), "", "");
+ String message = e.getMessage();
+ if (message == null) {
+ message = e.getClass().getName();
+ }
+
+ myErrorLabel.setHyperlinkText("Error: " + message, "", "");
myErrorLabel.setIcon(Messages.getErrorIcon());
- LOG.info(e);
+ myErrorStack.setText(ExceptionUtil.getThrowableText(e));
+ myErrorStack.setVisible(true);
}
myLayout.show(myPanel, ERROR_CARD);
}
@@ -139,8 +160,12 @@ public class SceneBuilderEditor extends UserDataHolderBase implements FileEditor
}
@Override
- public void handleError(Throwable e) {
- showErrorPage(null, e);
+ public void handleError(final Throwable e) {
+ UIUtil.invokeLaterIfNeeded(new Runnable() {
+ public void run() {
+ showErrorPage(null, e);
+ }
+ });
}
private void initSceneBuilder(boolean choosePathIfEmpty) {
diff --git a/plugins/junit/src/com/intellij/execution/junit/TestPackage.java b/plugins/junit/src/com/intellij/execution/junit/TestPackage.java
index 558b2e88dbda..3d3c2da89143 100644
--- a/plugins/junit/src/com/intellij/execution/junit/TestPackage.java
+++ b/plugins/junit/src/com/intellij/execution/junit/TestPackage.java
@@ -27,7 +27,7 @@ import com.intellij.execution.process.ProcessAdapter;
import com.intellij.execution.process.ProcessEvent;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.runners.ExecutionEnvironmentBuilder;
-import com.intellij.execution.runners.ProgramRunner;
+import com.intellij.execution.runners.ExecutionUtil;
import com.intellij.execution.testframework.SourceScope;
import com.intellij.execution.testframework.TestSearchScope;
import com.intellij.openapi.application.ApplicationManager;
@@ -43,7 +43,6 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.ui.popup.Balloon;
import com.intellij.openapi.util.Comparing;
-import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.wm.ToolWindowId;
import com.intellij.openapi.wm.ToolWindowManager;
@@ -438,12 +437,10 @@ public class TestPackage extends TestObject {
if (moduleByName != null) {
myConfiguration.getConfigurationModule().setModule(moduleByName);
try {
- final Executor executor = myConsoleProperties.isDebug() ? DefaultDebugExecutor.getDebugExecutorInstance()
- : DefaultRunExecutor.getRunExecutorInstance();
- final ProgramRunner runner = RunnerRegistry.getInstance().getRunner(executor.getId(), myConfiguration);
- assert runner != null;
- runner.execute(new ExecutionEnvironmentBuilder(myEnvironment).setContentToReuse(null).build());
- final Balloon balloon = myToolWindowManager.getToolWindowBalloon(myTestRunDebugId);
+ Executor executor = myConsoleProperties.isDebug() ? DefaultDebugExecutor.getDebugExecutorInstance()
+ : DefaultRunExecutor.getRunExecutorInstance();
+ ExecutionEnvironmentBuilder.create(myProject, executor, myConfiguration).contentToReuse(null).buildAndExecute();
+ Balloon balloon = myToolWindowManager.getToolWindowBalloon(myTestRunDebugId);
if (balloon != null) {
balloon.hide();
}
diff --git a/plugins/junit_rt/src/com/intellij/junit4/JUnit4IdeaTestRunner.java b/plugins/junit_rt/src/com/intellij/junit4/JUnit4IdeaTestRunner.java
index a1201c65a4d5..3fba1a3d9b7a 100644
--- a/plugins/junit_rt/src/com/intellij/junit4/JUnit4IdeaTestRunner.java
+++ b/plugins/junit_rt/src/com/intellij/junit4/JUnit4IdeaTestRunner.java
@@ -92,7 +92,13 @@ public class JUnit4IdeaTestRunner implements IdeaTestRunner {
}
private static Description getFilteredDescription(Request request, Description description) throws NoSuchFieldException, IllegalAccessException {
- final Field field = FilterRequest.class.getDeclaredField("fFilter");
+ Field field;
+ try {
+ field = FilterRequest.class.getDeclaredField("fFilter");
+ }
+ catch (NoSuchFieldException e) {
+ field = FilterRequest.class.getDeclaredField("filter");
+ }
field.setAccessible(true);
final Filter filter = (Filter)field.get(request);
final String filterDescription = filter.describe();
@@ -125,7 +131,13 @@ public class JUnit4IdeaTestRunner implements IdeaTestRunner {
}
private static Description getSuiteMethodDescription(Request request, Description description) throws NoSuchFieldException, IllegalAccessException {
- final Field field = ClassRequest.class.getDeclaredField("fTestClass");
+ Field field;
+ try {
+ field = ClassRequest.class.getDeclaredField("fTestClass");
+ }
+ catch (NoSuchFieldException e) {
+ field = ClassRequest.class.getDeclaredField("testClass");
+ }
field.setAccessible(true);
final Description methodDescription = Description.createSuiteDescription((Class)field.get(request));
for (Iterator iterator = description.getChildren().iterator(); iterator.hasNext();) {
diff --git a/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestRunnerUtil.java b/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestRunnerUtil.java
index d22ea44f2d8f..1bab2d69e1c5 100644
--- a/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestRunnerUtil.java
+++ b/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestRunnerUtil.java
@@ -352,12 +352,18 @@ public class JUnit4TestRunnerUtil {
for (Iterator iterator = children.iterator(); iterator.hasNext(); ) {
Object child = iterator.next();
try {
+ Class aClass = child.getClass();
Field f;
try {
- f = child.getClass().getDeclaredField("fName");
+ f = aClass.getDeclaredField("fName");
}
catch (NoSuchFieldException e) {
- continue;
+ try {
+ f = aClass.getDeclaredField("name");
+ }
+ catch (NoSuchFieldException e1) {
+ continue;
+ }
}
f.setAccessible(true);
String fName = (String)f.get(child);
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenResumeAction.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenResumeAction.java
index 927b087a9fce..6d58aa895f6a 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenResumeAction.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenResumeAction.java
@@ -301,7 +301,7 @@ public class MavenResumeAction extends AnAction {
runConfiguration.getRunnerParameters().setGoals(goals);
- myRunner.execute(new ExecutionEnvironmentBuilder(myEnvironment).setContentToReuse(null).setRunProfile(runConfiguration).build());
+ myRunner.execute(new ExecutionEnvironmentBuilder(myEnvironment).contentToReuse(null).runProfile(runConfiguration).build());
}
catch (RunCanceledByUserException ignore) {
}
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunConfigurationType.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunConfigurationType.java
index 3747107fb223..bada6c044354 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunConfigurationType.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunConfigurationType.java
@@ -59,10 +59,12 @@ public class MavenRunConfigurationType implements ConfigurationType {
*/
MavenRunConfigurationType() {
myFactory = new ConfigurationFactory(this) {
+ @Override
public RunConfiguration createTemplateConfiguration(Project project) {
return new MavenRunConfiguration(project, this, "");
}
+ @Override
public RunConfiguration createTemplateConfiguration(Project project, RunManager runManager) {
return new MavenRunConfiguration(project, this, "");
}
@@ -99,22 +101,27 @@ public class MavenRunConfigurationType implements ConfigurationType {
};
}
+ @Override
public String getDisplayName() {
return RunnerBundle.message("maven.run.configuration.name");
}
+ @Override
public String getConfigurationTypeDescription() {
return RunnerBundle.message("maven.run.configuration.description");
}
+ @Override
public Icon getIcon() {
return MavenIcons.Phase;
}
+ @Override
public ConfigurationFactory[] getConfigurationFactories() {
return new ConfigurationFactory[]{myFactory};
}
+ @Override
@NonNls
@NotNull
public String getId() {
@@ -187,29 +194,26 @@ public class MavenRunConfigurationType implements ConfigurationType {
ProgramRunner runner = DefaultJavaProgramRunner.getInstance();
Executor executor = DefaultRunExecutor.getRunExecutorInstance();
- ExecutionEnvironment env = new ExecutionEnvironment(executor, runner, configSettings, project);
-
try {
- runner.execute(env, callback);
+ runner.execute(new ExecutionEnvironment(executor, runner, configSettings, project), callback);
}
catch (ExecutionException e) {
MavenUtil.showError(project, "Failed to execute Maven goal", e);
}
}
+ @NotNull
public static RunnerAndConfigurationSettings createRunnerAndConfigurationSettings(@Nullable MavenGeneralSettings generalSettings,
- @Nullable MavenRunnerSettings runnerSettings,
- MavenRunnerParameters params,
- Project project) {
+ @Nullable MavenRunnerSettings runnerSettings,
+ MavenRunnerParameters params,
+ Project project) {
MavenRunConfigurationType type = ConfigurationTypeUtil.findConfigurationType(MavenRunConfigurationType.class);
- final RunnerAndConfigurationSettings settings = RunManagerEx.getInstanceEx(project)
- .createConfiguration(generateName(project, params), type.myFactory);
+ RunnerAndConfigurationSettings settings = RunManager.getInstance(project).createRunConfiguration(generateName(project, params), type.myFactory);
MavenRunConfiguration runConfiguration = (MavenRunConfiguration)settings.getConfiguration();
runConfiguration.setRunnerParameters(params);
runConfiguration.setGeneralSettings(generalSettings);
runConfiguration.setRunnerSettings(runnerSettings);
-
return settings;
}
}
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/actions/MavenRunConfigurationMenu.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/actions/MavenRunConfigurationMenu.java
index 4566689ed55e..7cbccc6b4a7a 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/actions/MavenRunConfigurationMenu.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/actions/MavenRunConfigurationMenu.java
@@ -29,9 +29,7 @@ public class MavenRunConfigurationMenu extends DefaultActionGroup implements Dum
Executor[] executors = ExecutorRegistry.getInstance().getRegisteredExecutors();
for (int i = executors.length; --i >= 0; ) {
final ProgramRunner runner = RunnerRegistry.getInstance().getRunner(executors[i].getId(), settings.getConfiguration());
-
AnAction action = new ExecuteMavenRunConfigurationAction(executors[i], runner != null, project, settings);
-
addAction(action, Constraints.FIRST);
}
@@ -57,9 +55,9 @@ public class MavenRunConfigurationMenu extends DefaultActionGroup implements Dum
@Override
public void actionPerformed(AnActionEvent event) {
- if (!myEnabled) return;
-
- ProgramRunnerUtil.executeConfiguration(myProject, mySettings, myExecutor);
+ if (myEnabled) {
+ ProgramRunnerUtil.executeConfiguration(myProject, mySettings, myExecutor);
+ }
}
@Override
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenProjectImportProvider.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenProjectImportProvider.java
index b54da50c1396..f74a98a3476b 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenProjectImportProvider.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenProjectImportProvider.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.
@@ -43,8 +43,11 @@ public class MavenProjectImportProvider extends ProjectImportProvider {
public ModuleWizardStep[] createSteps(final WizardContext wizardContext) {
final ProjectWizardStepFactory stepFactory = ProjectWizardStepFactory.getInstance();
- return new ModuleWizardStep[]{new MavenProjectImportStep(wizardContext), new SelectProfilesStep(wizardContext),
+ return new ModuleWizardStep[]{
+ new MavenProjectImportStep(wizardContext),
+ new SelectProfilesStep(wizardContext),
new SelectImportedProjectsStep<MavenProject>(wizardContext) {
+ @Override
protected String getElementText(final MavenProject project) {
final StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(project.getMavenId());
@@ -71,15 +74,20 @@ public class MavenProjectImportProvider extends ProjectImportProvider {
return !MavenProjectsManager.getInstance(project).isIgnored(mavenProject);
}
+ @Override
public void updateDataModel() {
super.updateDataModel();
getWizardContext().setProjectName(((MavenProjectBuilder)getBuilder()).getSuggestedProjectName());
}
+ @Override
public String getHelpId() {
return "reference.dialogs.new.project.import.maven.page3";
}
- }, stepFactory.createProjectJdkStep(wizardContext), stepFactory.createNameAndLocationStep(wizardContext)};
+ },
+ stepFactory.createProjectJdkStep(wizardContext),
+ stepFactory.createNameAndLocationStep(wizardContext)
+ };
}
@Override
diff --git a/plugins/properties/properties-psi-api/resources/messages/PropertiesBundle.properties b/plugins/properties/properties-psi-api/resources/messages/PropertiesBundle.properties
index 06e0c2e3ae03..61b69161c5e3 100644
--- a/plugins/properties/properties-psi-api/resources/messages/PropertiesBundle.properties
+++ b/plugins/properties/properties-psi-api/resources/messages/PropertiesBundle.properties
@@ -50,4 +50,7 @@ new.property.dialog.name.prompt.text=Enter new property key name
resource.bundle.renamer=Rename resource bundle properties files
resource.bundle.renamer.dialog.description=Rename resource bundle properties files with the following names to:
resource.bundle.renamer.entity.name=Resource bundle
-resource.bundle.renamer.option=Rename bound &resource bundle \ No newline at end of file
+resource.bundle.renamer.option=Rename bound &resource bundle
+
+inline.property.refactoring=Inline Property
+inline.property.confirmation=Inline property ''{0}'' with value ''{1}''?
diff --git a/plugins/properties/properties-psi-impl/properties-psi-impl.iml b/plugins/properties/properties-psi-impl/properties-psi-impl.iml
index 76596cc333fe..d297116cb114 100644
--- a/plugins/properties/properties-psi-impl/properties-psi-impl.iml
+++ b/plugins/properties/properties-psi-impl/properties-psi-impl.iml
@@ -14,8 +14,8 @@
<orderEntry type="module" module-name="xml-psi-api" />
<orderEntry type="module" module-name="xml-psi-impl" />
<orderEntry type="module" module-name="indexing-impl" />
- <orderEntry type="module" module-name="lang-impl" />
<orderEntry type="module" module-name="structure-view-impl" />
+ <orderEntry type="module" module-name="analysis-impl" />
</component>
</module>
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 8f5084b87391..f667b1a93da0 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
@@ -61,7 +61,13 @@ public class PropertiesImplUtil extends PropertiesUtil {
@Nullable
private static ResourceBundle getResourceBundle(@NotNull final String baseName, @NotNull final PsiDirectory baseDirectory) {
PropertiesFile defaultPropertiesFile = null;
- for (final PsiFile psiFile : baseDirectory.getFiles()) {
+ final PsiFile[] files = ApplicationManager.getApplication().runReadAction(new Computable<PsiFile[]>() {
+ @Override
+ public PsiFile[] compute() {
+ return baseDirectory.getFiles();
+ }
+ });
+ for (final PsiFile psiFile : files) {
if (baseName.equals(getBaseName(psiFile))) {
final PropertiesFile propertiesFile = getPropertiesFile(psiFile);
if (propertiesFile != null) {
diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/editor/ResourceBundleEditorViewElement.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/editor/ResourceBundleEditorViewElement.java
index 58932d1fd4c5..8a8d3b0390d4 100644
--- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/editor/ResourceBundleEditorViewElement.java
+++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/editor/ResourceBundleEditorViewElement.java
@@ -16,9 +16,7 @@
package com.intellij.lang.properties.editor;
-import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
-import org.jetbrains.annotations.NotNull;
/**
* @author Dmitry Batkovich
diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/editor/ResourceBundlePropertyStructureViewElement.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/editor/ResourceBundlePropertyStructureViewElement.java
index ed660536d052..724a794ca3bb 100644
--- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/editor/ResourceBundlePropertyStructureViewElement.java
+++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/editor/ResourceBundlePropertyStructureViewElement.java
@@ -24,6 +24,7 @@ import com.intellij.lang.properties.IProperty;
import com.intellij.lang.properties.PropertiesHighlighter;
import com.intellij.lang.properties.PropertiesUtil;
import com.intellij.lang.properties.ResourceBundle;
+import com.intellij.lang.properties.psi.Property;
import com.intellij.navigation.ColoredItemPresentation;
import com.intellij.navigation.ItemPresentation;
import com.intellij.openapi.editor.colors.EditorColorsManager;
@@ -69,8 +70,8 @@ public class ResourceBundlePropertyStructureViewElement implements StructureView
}
@Override
- public String getValue() {
- return myProperty.getName();
+ public Property getValue() {
+ return (Property)myProperty.getPsiElement();
}
@Override
diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/structureView/GroupByWordPrefixes.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/structureView/GroupByWordPrefixes.java
index b67f6bfbea3f..efdbeaf3e863 100644
--- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/structureView/GroupByWordPrefixes.java
+++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/structureView/GroupByWordPrefixes.java
@@ -16,6 +16,7 @@
package com.intellij.lang.properties.structureView;
import com.intellij.icons.AllIcons;
+import com.intellij.ide.structureView.StructureViewTreeElement;
import com.intellij.ide.util.treeView.AbstractTreeNode;
import com.intellij.ide.util.treeView.smartTree.*;
import com.intellij.lang.properties.IProperty;
@@ -65,14 +66,14 @@ public class GroupByWordPrefixes implements Grouper, Sorter {
parentPrefixLength = 0;
}
for (TreeElement element : children) {
- String text = null;
- if (element instanceof PropertiesStructureViewElement) {
- IProperty property = ((PropertiesStructureViewElement)element).getValue();
- text = property.getUnescapedKey();
+ if (!(element instanceof StructureViewTreeElement)) {
+ continue;
}
- else if (element instanceof ResourceBundlePropertyStructureViewElement) {
- text = ((ResourceBundlePropertyStructureViewElement)element).getValue();
+ final Object value = ((StructureViewTreeElement)element).getValue();
+ if (!(value instanceof IProperty)) {
+ continue;
}
+ final String text = ((IProperty) value).getUnescapedKey();
if (text == null) continue;
LOG.assertTrue(text.startsWith(parentPrefix) || text.startsWith(mySeparator));
List<String> words = StringUtil.split(text, mySeparator);
diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/structureView/PropertiesPrefixGroup.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/structureView/PropertiesPrefixGroup.java
index 61b3c0202619..c4958502c25a 100644
--- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/structureView/PropertiesPrefixGroup.java
+++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/structureView/PropertiesPrefixGroup.java
@@ -16,11 +16,13 @@
package com.intellij.lang.properties.structureView;
import com.intellij.icons.AllIcons;
+import com.intellij.ide.structureView.StructureViewTreeElement;
import com.intellij.ide.util.treeView.smartTree.Group;
import com.intellij.ide.util.treeView.smartTree.TreeElement;
import com.intellij.lang.properties.IProperty;
import com.intellij.lang.properties.editor.ResourceBundleEditorViewElement;
import com.intellij.lang.properties.editor.ResourceBundlePropertyStructureViewElement;
+import com.intellij.lang.properties.psi.Property;
import com.intellij.navigation.ItemPresentation;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.text.StringUtil;
@@ -90,20 +92,14 @@ public class PropertiesPrefixGroup implements Group, ResourceBundleEditorViewEle
Collection<TreeElement> result = new ArrayList<TreeElement>();
List<String> prefixWords = StringUtil.split(myPrefix, mySeparator);
for (TreeElement treeElement : myProperties) {
- String key;
- if (treeElement instanceof PropertiesStructureViewElement) {
- PropertiesStructureViewElement propertiesElement = (PropertiesStructureViewElement)treeElement;
- IProperty property = propertiesElement.getValue();
-
- key = property.getUnescapedKey();
- }
- else if (treeElement instanceof ResourceBundlePropertyStructureViewElement) {
- key = ((ResourceBundlePropertyStructureViewElement)treeElement).getValue();
+ if (!(treeElement instanceof StructureViewTreeElement)) {
+ continue;
}
- else {
+ final Object value = ((StructureViewTreeElement)treeElement).getValue();
+ if (!(value instanceof IProperty)) {
continue;
}
-
+ final String key = ((IProperty) value).getUnescapedKey();
if (key == null || key.equals(myPrefix)) {
continue;
}
diff --git a/plugins/properties/src/com/intellij/lang/properties/editor/NewPropertyAction.java b/plugins/properties/src/com/intellij/lang/properties/editor/NewPropertyAction.java
index d25b780bd769..2218b7598884 100644
--- a/plugins/properties/src/com/intellij/lang/properties/editor/NewPropertyAction.java
+++ b/plugins/properties/src/com/intellij/lang/properties/editor/NewPropertyAction.java
@@ -60,7 +60,7 @@ class NewPropertyAction extends AnAction {
prefix = null;
separator = null;
} else {
- final ResourceBundleEditorViewElement selectedElement = resourceBundleEditor.getSelectedElement();
+ final ResourceBundleEditorViewElement selectedElement = resourceBundleEditor.getSelectedElementIfOnlyOne();
if (selectedElement == null) {
return;
}
diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/editor/ResourceBundleAsVirtualFile.java b/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleAsVirtualFile.java
index 36915e7e6962..36915e7e6962 100644
--- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/editor/ResourceBundleAsVirtualFile.java
+++ b/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleAsVirtualFile.java
diff --git a/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleEditor.java b/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleEditor.java
index e9eb9e9f72d2..39e9ed67e7b2 100644
--- a/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleEditor.java
+++ b/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleEditor.java
@@ -57,7 +57,10 @@ import com.intellij.ui.JBColor;
import com.intellij.ui.JBSplitter;
import com.intellij.ui.components.JBScrollPane;
import com.intellij.util.Alarm;
+import com.intellij.util.Function;
import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.NullableFunction;
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.ContainerUtilRt;
import com.intellij.util.containers.Stack;
import com.intellij.util.ui.UIUtil;
@@ -129,7 +132,7 @@ public class ResourceBundleEditor extends UserDataHolderBase implements FileEdit
@Override
public void valueChanged(TreeSelectionEvent e) {
// filter out temp unselect/select events
- if (getSelectedProperty() == null) return;
+ if (Comparing.equal(e.getNewLeadSelectionPath(), e.getOldLeadSelectionPath()) || getSelectedProperty() == null) return;
if (!arePropertiesEquivalent(selectedProperty, getSelectedProperty()) ||
!Comparing.equal(selectedPropertiesFile, getSelectedPropertiesFile())) {
@@ -167,7 +170,7 @@ public class ResourceBundleEditor extends UserDataHolderBase implements FileEdit
TreeElement[] children = myStructureViewComponent.getTreeModel().getRoot().getChildren();
if (children.length != 0) {
TreeElement child = children[0];
- String propName = ((ResourceBundlePropertyStructureViewElement)child).getValue();
+ String propName = ((ResourceBundlePropertyStructureViewElement)child).getValue().getUnescapedKey();
setState(new ResourceBundleEditorState(propName));
}
myDataProviderPanel = new DataProviderPanel(splitPanel);
@@ -245,7 +248,7 @@ public class ResourceBundleEditor extends UserDataHolderBase implements FileEdit
DefaultMutableTreeNode node = toCheck.pop();
final ResourceBundleEditorViewElement element = getSelectedElement(node);
String value = element instanceof ResourceBundlePropertyStructureViewElement
- ? ((ResourceBundlePropertyStructureViewElement)element).getValue()
+ ? ((ResourceBundlePropertyStructureViewElement)element).getValue().getUnescapedKey()
: null;
if (propertyName.equals(value)) {
nodeToSelect = node;
@@ -570,13 +573,21 @@ public class ResourceBundleEditor extends UserDataHolderBase implements FileEdit
document.replaceString(0, document.getTextLength(), text);
}
- @Nullable
- private DefaultMutableTreeNode getSelectedNode() {
+ @NotNull
+ private Collection<DefaultMutableTreeNode> getSelectedNodes() {
+ if (!isValid()) {
+ return Collections.emptyList();
+ }
JTree tree = myStructureViewComponent.getTree();
- if (tree == null) return null;
- TreePath selected = tree.getSelectionModel().getSelectionPath();
- if (selected == null) return null;
- return (DefaultMutableTreeNode)selected.getLastPathComponent();
+ if (tree == null) return Collections.emptyList();
+ TreePath[] selected = tree.getSelectionModel().getSelectionPaths();
+ if (selected == null || selected.length == 0) return Collections.emptyList();
+ return ContainerUtil.map(selected, new Function<TreePath, DefaultMutableTreeNode>() {
+ @Override
+ public DefaultMutableTreeNode fun(TreePath treePath) {
+ return (DefaultMutableTreeNode)treePath.getLastPathComponent();
+ }
+ });
}
@Nullable
@@ -587,25 +598,34 @@ public class ResourceBundleEditor extends UserDataHolderBase implements FileEdit
@Nullable
private IProperty getSelectedProperty() {
- final DefaultMutableTreeNode selectedNode = getSelectedNode();
- if (selectedNode == null) {
+ final Collection<DefaultMutableTreeNode> selectedNode = getSelectedNodes();
+ if (selectedNode.isEmpty()) {
return null;
}
- final ResourceBundleEditorViewElement element = getSelectedElement(selectedNode);
+ final ResourceBundleEditorViewElement element = getSelectedElement(ContainerUtil.getFirstItem(selectedNode));
return element instanceof ResourceBundlePropertyStructureViewElement ? ((ResourceBundlePropertyStructureViewElement)element).getProperty()
: null;
}
+ @NotNull
+ public Collection<ResourceBundleEditorViewElement> getSelectedElements() {
+ final Collection<DefaultMutableTreeNode> selectedNodes = getSelectedNodes();
+ return ContainerUtil.mapNotNull(selectedNodes, new NullableFunction<DefaultMutableTreeNode, ResourceBundleEditorViewElement>() {
+ @Nullable
+ @Override
+ public ResourceBundleEditorViewElement fun(DefaultMutableTreeNode selectedNode) {
+ Object userObject = selectedNode.getUserObject();
+ if (!(userObject instanceof AbstractTreeNode)) return null;
+ Object value = ((AbstractTreeNode)userObject).getValue();
+ return value instanceof ResourceBundleEditorViewElement ? (ResourceBundleEditorViewElement) value : null;
+ }
+ });
+ }
+
@Nullable
- public ResourceBundleEditorViewElement getSelectedElement() {
- final DefaultMutableTreeNode selectedNode = getSelectedNode();
- if (selectedNode == null) {
- return null;
- }
- Object userObject = selectedNode.getUserObject();
- if (!(userObject instanceof AbstractTreeNode)) return null;
- Object value = ((AbstractTreeNode)userObject).getValue();
- return value instanceof ResourceBundleEditorViewElement ? (ResourceBundleEditorViewElement) value : null;
+ public ResourceBundleEditorViewElement getSelectedElementIfOnlyOne() {
+ final Collection<ResourceBundleEditorViewElement> selectedElements = getSelectedElements();
+ return selectedElements.size() == 1 ? ContainerUtil.getFirstItem(selectedElements) : null;
}
@Override
diff --git a/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleStructureViewComponent.java b/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleStructureViewComponent.java
index 0985f35a5e12..da376abe05b2 100644
--- a/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleStructureViewComponent.java
+++ b/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleStructureViewComponent.java
@@ -25,7 +25,6 @@ import com.intellij.lang.properties.psi.Property;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.ide.CopyPasteManager;
-import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiNamedElement;
@@ -34,10 +33,13 @@ import com.intellij.refactoring.safeDelete.SafeDeleteHandler;
import com.intellij.ui.PopupHandler;
import com.intellij.usages.UsageTarget;
import com.intellij.usages.UsageView;
+import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import java.awt.datatransfer.StringSelection;
import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
import java.util.List;
/**
@@ -74,9 +76,17 @@ class ResourceBundleStructureViewComponent extends PropertiesGroupingStructureVi
} else if (PlatformDataKeys.FILE_EDITOR.is(dataId)) {
return getFileEditor();
} else if (LangDataKeys.PSI_ELEMENT_ARRAY.is(dataId)) {
- final ResourceBundleEditorViewElement selectedElement = ((ResourceBundleEditor)getFileEditor()).getSelectedElement();
- if (selectedElement != null) {
- return selectedElement.getPsiElements();
+ final Collection<ResourceBundleEditorViewElement> selectedElements = ((ResourceBundleEditor)getFileEditor()).getSelectedElements();
+ if (selectedElements.isEmpty()) {
+ return null;
+ } else if (selectedElements.size() == 1) {
+ return ContainerUtil.getFirstItem(selectedElements).getPsiElements();
+ } else {
+ final List<PsiElement> psiElements = new ArrayList<PsiElement>();
+ for (ResourceBundleEditorViewElement selectedElement : selectedElements) {
+ Collections.addAll(psiElements, selectedElement.getPsiElements());
+ }
+ return psiElements.toArray(new PsiElement[psiElements.size()]);
}
} else if (PlatformDataKeys.DELETE_ELEMENT_PROVIDER.is(dataId)) {
final PsiElement[] psiElements = LangDataKeys.PSI_ELEMENT_ARRAY.getData(this);
diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/editor/ResourceBundleUtil.java b/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleUtil.java
index e4a35e7e677c..e4a35e7e677c 100644
--- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/editor/ResourceBundleUtil.java
+++ b/plugins/properties/src/com/intellij/lang/properties/editor/ResourceBundleUtil.java
diff --git a/plugins/properties/src/com/intellij/lang/properties/refactoring/rename/ResourceBundleFromEditorRenameHandler.java b/plugins/properties/src/com/intellij/lang/properties/refactoring/rename/ResourceBundleFromEditorRenameHandler.java
index 0c04bec80620..e105195cb9b3 100644
--- a/plugins/properties/src/com/intellij/lang/properties/refactoring/rename/ResourceBundleFromEditorRenameHandler.java
+++ b/plugins/properties/src/com/intellij/lang/properties/refactoring/rename/ResourceBundleFromEditorRenameHandler.java
@@ -74,7 +74,7 @@ public class ResourceBundleFromEditorRenameHandler implements RenameHandler {
public void invoke(final @NotNull Project project, Editor editor, final PsiFile file, DataContext dataContext) {
final ResourceBundleEditor resourceBundleEditor = (ResourceBundleEditor)PlatformDataKeys.FILE_EDITOR.getData(dataContext);
assert resourceBundleEditor != null;
- final ResourceBundleEditorViewElement selectedElement = resourceBundleEditor.getSelectedElement();
+ final ResourceBundleEditorViewElement selectedElement = resourceBundleEditor.getSelectedElementIfOnlyOne();
if (selectedElement != null) {
CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() {
@Override
diff --git a/plugins/svn4idea/src/META-INF/plugin.xml b/plugins/svn4idea/src/META-INF/plugin.xml
index e831d0550a80..5a441dc89565 100644
--- a/plugins/svn4idea/src/META-INF/plugin.xml
+++ b/plugins/svn4idea/src/META-INF/plugin.xml
@@ -76,7 +76,7 @@
<reference id="Vcs.ShowTabbedFileHistory"/>
<reference id="Vcs.ShowHistoryForBlock"/>
<reference id="Annotate"/>
- <action id="Subversion.Copy" class="org.jetbrains.idea.svn.actions.CreateBranchOrTagAction"/>
+ <action id="Subversion.Copy" class="org.jetbrains.idea.svn.branchConfig.CreateBranchOrTagAction"/>
<separator/>
<action id="Subversion.Lock" class="org.jetbrains.idea.svn.actions.LockAction"/>
<action id="Subversion.Unlock" class="org.jetbrains.idea.svn.actions.UnlockAction"/>
@@ -122,16 +122,16 @@
<applicationService serviceInterface="org.jetbrains.idea.svn.SvnApplicationSettings"
serviceImplementation="org.jetbrains.idea.svn.SvnApplicationSettings"/>
<projectService serviceImplementation="org.jetbrains.idea.svn.SvnConfiguration"/>
- <projectService serviceInterface="org.jetbrains.idea.svn.SvnBranchConfigurationManager"
- serviceImplementation="org.jetbrains.idea.svn.SvnBranchConfigurationManager"/>
+ <projectService serviceInterface="org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationManager"
+ serviceImplementation="org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationManager"/>
<projectService serviceInterface="org.jetbrains.idea.svn.history.LoadedRevisionsCache"
serviceImplementation="org.jetbrains.idea.svn.history.LoadedRevisionsCache"/>
<projectService serviceInterface="org.jetbrains.idea.svn.mergeinfo.SvnMergeInfoCache"
serviceImplementation="org.jetbrains.idea.svn.mergeinfo.SvnMergeInfoCache"/>
- <projectService serviceInterface="org.jetbrains.idea.svn.SvnLoadedBrachesStorage"
- serviceImplementation="org.jetbrains.idea.svn.SvnLoadedBrachesStorage"/>
- <applicationService serviceInterface="org.jetbrains.idea.svn.SvnBranchMapperManager"
- serviceImplementation="org.jetbrains.idea.svn.SvnBranchMapperManager"/>
+ <projectService serviceInterface="org.jetbrains.idea.svn.branchConfig.SvnLoadedBranchesStorage"
+ serviceImplementation="org.jetbrains.idea.svn.branchConfig.SvnLoadedBranchesStorage"/>
+ <applicationService serviceInterface="org.jetbrains.idea.svn.branchConfig.SvnBranchMapperManager"
+ serviceImplementation="org.jetbrains.idea.svn.branchConfig.SvnBranchMapperManager"/>
<applicationService serviceInterface="org.jetbrains.idea.svn.dialogs.browserCache.SvnRepositoryCache"
serviceImplementation="org.jetbrains.idea.svn.dialogs.browserCache.SvnRepositoryCache"/>
<applicationService serviceInterface="org.jetbrains.idea.svn.dialogs.browserCache.Loader"
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/RootsToWorkingCopies.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/RootsToWorkingCopies.java
index 06138b345b74..c33dd38f2eba 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/RootsToWorkingCopies.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/RootsToWorkingCopies.java
@@ -105,7 +105,7 @@ public class RootsToWorkingCopies implements VcsListener {
@CalledInBackground
@Nullable
- public WorkingCopy getWcRoot(final VirtualFile root) {
+ public WorkingCopy getWcRoot(@NotNull VirtualFile root) {
assert (! ApplicationManager.getApplication().isDispatchThread()) || ApplicationManager.getApplication().isUnitTestMode();
synchronized (myLock) {
@@ -117,7 +117,7 @@ public class RootsToWorkingCopies implements VcsListener {
}
@Nullable
- private WorkingCopy calculateRoot(final VirtualFile root) {
+ private WorkingCopy calculateRoot(@NotNull VirtualFile root) {
File workingCopyRoot = SvnUtil.getWorkingCopyRootNew(new File(root.getPath()));
WorkingCopy workingCopy = null;
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBundle.properties b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBundle.properties
index df545b0373a1..3f4ae40677ae 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBundle.properties
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBundle.properties
@@ -526,6 +526,7 @@ action.Subversion.integrate.changes.alien.commit.changelist.title=Integrated
action.Subversion.integrate.changes.dialog.add.wc.text=Add
action.Subversion.integrate.changes.dialog.remove.wc.text=Remove
action.Subversion.integrate.changes.message.files.up.to.date.text=All files are up to date
+action.Subversion.integrate.changes.collecting.changes.to.commit.task.title=Collecting changes to commit
action.Subversion.integrate.changes.error.unable.to.collect.changes.text=Error while collecting changes to commit: {0}
error.cannot.load.revisions=Can not load revision list
action.Subversion.integrate.changes.message.canceled.text=Integration was canceled
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProviderContext.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProviderContext.java
index 9ae90c722cb3..1fc5f9ce075a 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProviderContext.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProviderContext.java
@@ -27,6 +27,7 @@ import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.actions.AbstractShowPropertiesDiffAction;
+import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationManager;
import org.jetbrains.idea.svn.info.Info;
import org.jetbrains.idea.svn.lock.Lock;
import org.jetbrains.idea.svn.status.Status;
@@ -244,7 +245,13 @@ class SvnChangeProviderContext implements StatusReceiver {
myChangelistBuilder.processLocallyDeletedFile(createLocallyDeletedChange(filePath, status));
}
else if (status.is(StatusType.STATUS_IGNORED)) {
- if (!myVcs.isWcRoot(filePath)) {
+ if (filePath.getVirtualFile() == null) {
+ filePath.hardRefresh();
+ }
+ if (filePath.getVirtualFile() == null) {
+ LOG.error("No virtual file for ignored file: " + filePath.getPresentableUrl() + ", isNonLocal: " + filePath.isNonLocal());
+ }
+ else if (!myVcs.isWcRoot(filePath)) {
myChangelistBuilder.processIgnoredFile(filePath.getVirtualFile());
}
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java
index 6f5013c4a929..9d8df6591268 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java
@@ -30,6 +30,7 @@ import org.jetbrains.idea.svn.api.Depth;
import org.jetbrains.idea.svn.auth.SvnAuthenticationManager;
import org.jetbrains.idea.svn.auth.SvnAuthenticationProvider;
import org.jetbrains.idea.svn.auth.SvnInteractiveAuthenticationProvider;
+import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationManager;
import org.jetbrains.idea.svn.config.SvnServerFileKeys;
import org.jetbrains.idea.svn.diff.DiffOptions;
import org.jetbrains.idea.svn.update.MergeRootInfo;
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileUrlMappingImpl.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileUrlMappingImpl.java
index 11838314acbd..5c660643dc66 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileUrlMappingImpl.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileUrlMappingImpl.java
@@ -221,11 +221,16 @@ public class SvnFileUrlMappingImpl implements SvnFileUrlMapping, PersistentState
}
public void realRefresh(final Runnable afterRefreshCallback) {
- final SvnVcs vcs = SvnVcs.getInstance(myProject);
- final VirtualFile[] roots = myHelper.executeDefended(myProject);
- final SvnRootsDetector rootsDetector = new SvnRootsDetector(vcs, this, myNestedCopiesHolder);
- // do not send additional request for nested copies when in init state
- rootsDetector.detectCopyRoots(roots, init(), afterRefreshCallback);
+ if (myProject.isDisposed()) {
+ afterRefreshCallback.run();
+ }
+ else {
+ final SvnVcs vcs = SvnVcs.getInstance(myProject);
+ final VirtualFile[] roots = myHelper.executeDefended(myProject);
+ final SvnRootsDetector rootsDetector = new SvnRootsDetector(vcs, this, myNestedCopiesHolder);
+ // do not send additional request for nested copies when in init state
+ rootsDetector.detectCopyRoots(roots, init(), afterRefreshCallback);
+ }
}
public void applyDetectionResult(@NotNull SvnRootsDetector.Result result) {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnScopeZipper.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnScopeZipper.java
index a5612a69172a..d4c98221a567 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnScopeZipper.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnScopeZipper.java
@@ -19,22 +19,25 @@ import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.FilePathImpl;
import com.intellij.openapi.vcs.changes.VcsDirtyScope;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
-import java.util.*;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
public class SvnScopeZipper implements Runnable {
- private final VcsDirtyScope myIn;
- private final List<FilePath> myRecursiveDirs;
+
+ @NotNull private final VcsDirtyScope myIn;
+ @NotNull private final List<FilePath> myRecursiveDirs;
// instead of set and heavy equals of file path
- private final Map<String, MyDirNonRecursive> myNonRecursiveDirs;
- // those alone in their immediate parent
- private final List<FilePath> mySingleFiles;
+ @NotNull private final Map<String, MyDirNonRecursive> myNonRecursiveDirs;
- public SvnScopeZipper(final VcsDirtyScope in) {
+ public SvnScopeZipper(@NotNull VcsDirtyScope in) {
myIn = in;
- myRecursiveDirs = new ArrayList<FilePath>(in.getRecursivelyDirtyDirectories());
- myNonRecursiveDirs = new HashMap<String, MyDirNonRecursive>();
- mySingleFiles = new ArrayList<FilePath>();
+ myRecursiveDirs = ContainerUtil.newArrayList(in.getRecursivelyDirtyDirectories());
+ myNonRecursiveDirs = ContainerUtil.newHashMap();
}
public void run() {
@@ -46,85 +49,72 @@ public class SvnScopeZipper implements Runnable {
final VirtualFile vFile = file.getVirtualFile();
// todo take care about this 'not valid' - right now keeping things as they used to be
final MyDirNonRecursive me = createOrGet(file);
- me.setInterestedInParent(true);
if (vFile != null && vFile.isValid()) {
for (VirtualFile child : vFile.getChildren()) {
me.add(new FilePathImpl(child));
}
}
}
- final FilePath parent = file.getParentPath();
- if (parent != null) {
- final MyDirNonRecursive item = createOrGet(parent);
- item.add(file);
+ else {
+ final FilePath parent = file.getParentPath();
+ if (parent != null) {
+ final MyDirNonRecursive item = createOrGet(parent);
+ item.add(file);
+ }
}
}
-
- // move alone files into a separate list
- /*for (Iterator<Map.Entry<String, MyDirNonRecursive>> iterator = myNonRecursiveDirs.entrySet().iterator(); iterator.hasNext();) {
- final Map.Entry<String, MyDirNonRecursive> entry = iterator.next();
- final MyDirNonRecursive item = entry.getValue();
- if ((! item.isInterestedInParent()) && (item.getChildrenList().size() == 1)) {
- iterator.remove();
- mySingleFiles.add(item.getChildrenList().iterator().next());
- }
- }*/
}
- private MyDirNonRecursive createOrGet(final FilePath parent) {
- final String key = getKey(parent);
- final MyDirNonRecursive result = myNonRecursiveDirs.get(key);
- if (result != null) return result;
- final MyDirNonRecursive newItem = new MyDirNonRecursive(parent);
- myNonRecursiveDirs.put(key, newItem);
- return newItem;
+ @NotNull
+ private MyDirNonRecursive createOrGet(@NotNull FilePath parent) {
+ String key = getKey(parent);
+ MyDirNonRecursive result = myNonRecursiveDirs.get(key);
+
+ if (result == null) {
+ result = new MyDirNonRecursive(parent);
+ myNonRecursiveDirs.put(key, result);
+ }
+
+ return result;
}
+ @NotNull
public List<FilePath> getRecursiveDirs() {
return myRecursiveDirs;
}
+ @NotNull
public Map<String, MyDirNonRecursive> getNonRecursiveDirs() {
return myNonRecursiveDirs;
}
- public List<FilePath> getSingleFiles() {
- return mySingleFiles;
+ public static String getKey(@NotNull FilePath path) {
+ return path.getPresentableUrl();
}
static class MyDirNonRecursive {
- private boolean myInterestedInParent;
- private final FilePath myDir;
+
+ @NotNull private final FilePath myDir;
// instead of set and heavy equals of file path
- private final Map<String, FilePath> myChildren;
+ @NotNull private final Map<String, FilePath> myChildren;
- private MyDirNonRecursive(final FilePath dir) {
+ private MyDirNonRecursive(@NotNull FilePath dir) {
myDir = dir;
- myChildren = new HashMap<String, FilePath>();
- }
-
- public boolean isInterestedInParent() {
- return myInterestedInParent;
- }
-
- public void setInterestedInParent(boolean interestedInParent) {
- myInterestedInParent = interestedInParent;
+ myChildren = ContainerUtil.newHashMap();
}
- public void add(final FilePath path) {
+ public void add(@NotNull FilePath path) {
myChildren.put(getKey(path), path);
}
+ @NotNull
public Collection<FilePath> getChildrenList() {
return myChildren.values();
}
+ @NotNull
public FilePath getDir() {
return myDir;
}
}
-
- public static String getKey(final FilePath path) {
- return path.getPresentableUrl();
- }
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java
index 43407f4b2064..aaf46003c1dd 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java
@@ -49,6 +49,7 @@ import org.jetbrains.idea.svn.api.Depth;
import org.jetbrains.idea.svn.api.EventAction;
import org.jetbrains.idea.svn.api.ProgressEvent;
import org.jetbrains.idea.svn.api.ProgressTracker;
+import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationManager;
import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew;
import org.jetbrains.idea.svn.browse.DirectoryEntry;
import org.jetbrains.idea.svn.browse.DirectoryEntryConsumer;
@@ -58,11 +59,15 @@ import org.jetbrains.idea.svn.info.Info;
import org.jetbrains.idea.svn.status.Status;
import org.tmatesoft.sqljet.core.SqlJetException;
import org.tmatesoft.sqljet.core.table.SqlJetDb;
-import org.tmatesoft.svn.core.*;
+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.internal.util.SVNPathUtil;
import org.tmatesoft.svn.core.internal.wc.SVNFileUtil;
import org.tmatesoft.svn.core.internal.wc2.SvnWcGeneration;
-import org.tmatesoft.svn.core.wc.*;
+import org.tmatesoft.svn.core.wc.SVNRevision;
+import org.tmatesoft.svn.core.wc.SVNWCUtil;
import org.tmatesoft.svn.core.wc2.SvnOperationFactory;
import org.tmatesoft.svn.core.wc2.SvnTarget;
@@ -343,7 +348,7 @@ public class SvnUtil {
for (T committable : committables) {
final RootUrlInfo path = vcs.getSvnFileUrlMapping().getWcRootForFilePath(convertor.convert(committable));
if (path == null) {
- result.putValue(new Pair<SVNURL, WorkingCopyFormat>(null, null), committable);
+ result.putValue(Pair.create((SVNURL)null, WorkingCopyFormat.UNKNOWN), committable);
} else {
result.putValue(Pair.create(path.getRepositoryUrlUrl(), path.getFormat()), committable);
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java
index b44fd16f979f..e5018f3319d5 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java
@@ -68,6 +68,7 @@ import org.jetbrains.idea.svn.api.CmdClientFactory;
import org.jetbrains.idea.svn.api.Depth;
import org.jetbrains.idea.svn.api.SvnKitClientFactory;
import org.jetbrains.idea.svn.auth.SvnAuthenticationNotifier;
+import org.jetbrains.idea.svn.branchConfig.SvnLoadedBranchesStorage;
import org.jetbrains.idea.svn.checkin.SvnCheckinEnvironment;
import org.jetbrains.idea.svn.checkout.SvnCheckoutProvider;
import org.jetbrains.idea.svn.commandLine.SvnBindException;
@@ -81,7 +82,6 @@ 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;
@@ -89,7 +89,10 @@ import org.jetbrains.idea.svn.status.StatusType;
import org.jetbrains.idea.svn.svnkit.SvnKitManager;
import org.jetbrains.idea.svn.update.SvnIntegrateEnvironment;
import org.jetbrains.idea.svn.update.SvnUpdateEnvironment;
-import org.tmatesoft.svn.core.*;
+import org.tmatesoft.svn.core.SVNErrorCode;
+import org.tmatesoft.svn.core.SVNException;
+import org.tmatesoft.svn.core.SVNNodeKind;
+import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.internal.wc.SVNAdminUtil;
import org.tmatesoft.svn.core.wc.SVNRevision;
import org.tmatesoft.svn.core.wc2.SvnTarget;
@@ -145,7 +148,7 @@ public class SvnVcs extends AbstractVcs<CommittedChangeList> {
private final RootsToWorkingCopies myRootsToWorkingCopies;
private final SvnAuthenticationNotifier myAuthNotifier;
- private final SvnLoadedBrachesStorage myLoadedBranchesStorage;
+ private final SvnLoadedBranchesStorage myLoadedBranchesStorage;
private final SvnExecutableChecker myChecker;
@@ -157,7 +160,7 @@ public class SvnVcs extends AbstractVcs<CommittedChangeList> {
private final boolean myLogExceptions;
- public SvnVcs(final Project project, MessageBus bus, SvnConfiguration svnConfiguration, final SvnLoadedBrachesStorage storage) {
+ public SvnVcs(final Project project, MessageBus bus, SvnConfiguration svnConfiguration, final SvnLoadedBranchesStorage storage) {
super(project, VCS_NAME);
myLoadedBranchesStorage = storage;
@@ -723,9 +726,10 @@ public class SvnVcs extends AbstractVcs<CommittedChangeList> {
return WorkingCopyFormat.UNKNOWN.equals(format) ? SvnFormatSelector.findRootAndGetFormat(ioFile) : format;
}
- public boolean isWcRoot(FilePath filePath) {
+ public boolean isWcRoot(@NotNull FilePath filePath) {
boolean isWcRoot = false;
- WorkingCopy wcRoot = myRootsToWorkingCopies.getWcRoot(filePath.getVirtualFile());
+ VirtualFile file = filePath.getVirtualFile();
+ WorkingCopy wcRoot = file != null ? myRootsToWorkingCopies.getWcRoot(file) : null;
if (wcRoot != null) {
isWcRoot = wcRoot.getFile().getAbsolutePath().equals(filePath.getIOFile().getAbsolutePath());
}
@@ -917,7 +921,7 @@ public class SvnVcs extends AbstractVcs<CommittedChangeList> {
}
@Override
- public boolean isVcsBackgroundOperationsAllowed(VirtualFile root) {
+ public boolean isVcsBackgroundOperationsAllowed(@NotNull VirtualFile root) {
// TODO: Currently myAuthNotifier.isAuthenticatedFor directly uses SVNKit to check credentials - so assume for now that background
// TODO: operations are always allowed for command line. As sometimes this leads to errors - for instance, incoming changes are not
// TODO: displayed in "Incoming" tab - incoming changes are collected using command line but not displayed because
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/AbstractIntegrateChangesAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/AbstractIntegrateChangesAction.java
index ff0f158f32a8..468399e93679 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/AbstractIntegrateChangesAction.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/AbstractIntegrateChangesAction.java
@@ -24,6 +24,7 @@ import com.intellij.openapi.vcs.changes.committed.CommittedChangesBrowserUseCase
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.SvnBundle;
+import org.jetbrains.idea.svn.branchConfig.SelectBranchPopup;
import org.jetbrains.idea.svn.integrate.MergerFactory;
import org.jetbrains.idea.svn.integrate.SelectedCommittedStuffChecker;
import org.jetbrains.idea.svn.integrate.SvnIntegrateChangesActionPerformer;
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 ddd9bd572f0e..ee4f807c2570 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SvnMergeProvider.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SvnMergeProvider.java
@@ -26,6 +26,7 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.vcsUtil.VcsRunnable;
import com.intellij.vcsUtil.VcsUtil;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.idea.svn.SvnPropertyKeys;
import org.jetbrains.idea.svn.SvnRevisionNumber;
import org.jetbrains.idea.svn.SvnUtil;
import org.jetbrains.idea.svn.SvnVcs;
@@ -33,7 +34,6 @@ 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.wc.SVNRevision;
import org.tmatesoft.svn.core.wc2.SvnTarget;
@@ -162,8 +162,8 @@ public class SvnMergeProvider implements MergeProvider {
File ioFile = new File(file.getPath());
PropertyClient client = vcs.getFactory(ioFile).createPropertyClient();
- PropertyValue value = client.getProperty(SvnTarget.fromFile(ioFile), SVNProperty.MIME_TYPE, false, SVNRevision.WORKING);
- if (value != null && SVNProperty.isBinaryMimeType(value.toString())) {
+ PropertyValue value = client.getProperty(SvnTarget.fromFile(ioFile), SvnPropertyKeys.SVN_MIME_TYPE, false, SVNRevision.WORKING);
+ if (value != null && isBinaryMimeType(value.toString())) {
return true;
}
}
@@ -173,4 +173,8 @@ public class SvnMergeProvider implements MergeProvider {
return false;
}
+
+ private static boolean isBinaryMimeType(@NotNull String mimeType) {
+ return !mimeType.startsWith("text/");
+ }
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/SvnAnnotationProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/SvnAnnotationProvider.java
index a615fd4e3afa..e40569d720de 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/SvnAnnotationProvider.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/SvnAnnotationProvider.java
@@ -70,7 +70,7 @@ public class SvnAnnotationProvider implements AnnotationProvider, VcsCacheableAn
if (! svnRevision.isValid()) {
throw new VcsException("Can not get last changed revision for file: " + file.getPath() + "\nPlease run svn info for this file and file an issue.");
}
- return annotate(file, new SvnFileRevision(myVcs, currentRevision, currentRevision, null, null, null, null, null, file.getCharset()),
+ return annotate(file, new SvnFileRevision(myVcs, currentRevision, currentRevision, null, null, null, null, null),
lastChangedRevision.getRevisionNumber(), true);
}
@@ -438,7 +438,7 @@ public class SvnAnnotationProvider implements AnnotationProvider, VcsCacheableAn
myProgress.checkCanceled();
myProgress.setText2(SvnBundle.message("progress.text2.revision.processed", logEntry.getRevision()));
}
- myResult.setRevision(logEntry.getRevision(), new SvnFileRevision(myVcs, SVNRevision.UNDEFINED, logEntry, myUrl, "", myCharset));
+ myResult.setRevision(logEntry.getRevision(), new SvnFileRevision(myVcs, SVNRevision.UNDEFINED, logEntry, myUrl, ""));
}
});
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/SvnAuthenticationNotifier.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/SvnAuthenticationNotifier.java
index 57c835daef2f..ffc21a011334 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/SvnAuthenticationNotifier.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/SvnAuthenticationNotifier.java
@@ -223,7 +223,7 @@ public class SvnAuthenticationNotifier extends GenericNotifierImpl<SvnAuthentica
/**
* Bases on presence of notifications!
*/
- public ThreeState isAuthenticatedFor(final VirtualFile vf) {
+ public ThreeState isAuthenticatedFor(@NotNull VirtualFile vf) {
final WorkingCopy wcCopy = myRootsToWorkingCopies.getWcRoot(vf);
if (wcCopy == null) return ThreeState.UNSURE;
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/BranchConfigurationDialog.form b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/BranchConfigurationDialog.form
index a416aa145505..b68010c827db 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/BranchConfigurationDialog.form
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/BranchConfigurationDialog.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.idea.svn.dialogs.BranchConfigurationDialog">
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.idea.svn.branchConfig.BranchConfigurationDialog">
<grid id="27dc6" binding="myTopPanel" 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>
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/BranchConfigurationDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/BranchConfigurationDialog.java
index 50ddd9615d41..0e0fce947088 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/BranchConfigurationDialog.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/BranchConfigurationDialog.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.jetbrains.idea.svn.dialogs;
+package org.jetbrains.idea.svn.branchConfig;
import com.intellij.openapi.actionSystem.ActionToolbarPosition;
import com.intellij.openapi.project.Project;
@@ -32,12 +32,8 @@ import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.*;
-import org.jetbrains.idea.svn.branchConfig.InfoReliability;
-import org.jetbrains.idea.svn.branchConfig.InfoStorage;
-import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigManager;
-import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew;
import org.jetbrains.idea.svn.commandLine.SvnBindException;
-import org.jetbrains.idea.svn.integrate.SvnBranchItem;
+import org.jetbrains.idea.svn.dialogs.SelectLocationDialog;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.internal.util.SVNURLUtil;
@@ -59,7 +55,7 @@ public class BranchConfigurationDialog extends DialogWrapper {
private JList myLocationList;
private JPanel myListPanel;
private JLabel myErrorPrompt;
- private final SvnBranchConfigManager mySvnBranchConfigManager;
+ private final NewRootBunch mySvnBranchConfigManager;
private final VirtualFile myRoot;
public BranchConfigurationDialog(@NotNull final Project project,
@@ -115,7 +111,7 @@ public class BranchConfigurationDialog extends DialogWrapper {
if (!configuration.getBranchUrls().contains(selectedUrl)) {
configuration
.addBranches(selectedUrl, new InfoStorage<List<SvnBranchItem>>(new ArrayList<SvnBranchItem>(), InfoReliability.empty));
- mySvnBranchConfigManager.reloadBranches(myRoot, selectedUrl, null);
+ mySvnBranchConfigManager.reloadBranchesAsync(myRoot, selectedUrl, InfoReliability.setByUser);
listModel.fireItemAdded();
myLocationList.setSelectedIndex(listModel.getSize() - 1);
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/BranchesLoader.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/BranchesLoader.java
index 10f4574c7f39..ba0288da9699 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/BranchesLoader.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/BranchesLoader.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,16 @@
package org.jetbrains.idea.svn.branchConfig;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.vcs.VcsException;
+import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier;
+import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.svn.SvnConfiguration;
import org.jetbrains.idea.svn.SvnVcs;
import org.jetbrains.idea.svn.api.Depth;
import org.jetbrains.idea.svn.browse.DirectoryEntry;
import org.jetbrains.idea.svn.browse.DirectoryEntryConsumer;
-import org.jetbrains.idea.svn.integrate.SvnBranchItem;
import org.tmatesoft.svn.core.*;
import org.tmatesoft.svn.core.wc.SVNLogClient;
import org.tmatesoft.svn.core.wc.SVNRevision;
@@ -33,27 +35,60 @@ import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
-public class BranchesLoader {
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public class BranchesLoader implements Runnable {
+ @NotNull private final Project myProject;
+ @NotNull private final NewRootBunch myBunch;
+ @NotNull private final VirtualFile myRoot;
+ @NotNull private final String myUrl;
+ @NotNull private final InfoReliability myInfoReliability;
+ private final boolean myPassive;
+
+ public BranchesLoader(@NotNull Project project,
+ @NotNull NewRootBunch bunch,
+ @NotNull String url,
+ @NotNull InfoReliability infoReliability,
+ @NotNull VirtualFile root,
+ boolean passive) {
+ myProject = project;
+ myBunch = bunch;
+ myUrl = url;
+ myInfoReliability = infoReliability;
+ myRoot = root;
+ myPassive = passive;
+ }
- private BranchesLoader() {
+ public void run() {
+ try {
+ List<SvnBranchItem> branches = loadBranches();
+ myBunch.updateBranches(myRoot, myUrl, new InfoStorage<List<SvnBranchItem>>(branches, myInfoReliability));
+ }
+ catch (VcsException e) {
+ showError(e);
+ }
+ catch (SVNException e) {
+ showError(e);
+ }
}
- public static List<SvnBranchItem> loadBranches(final Project project, final String url, boolean passive) throws SVNException,
- VcsException {
- final SvnConfiguration configuration = SvnConfiguration.getInstance(project);
- final SvnVcs vcs = SvnVcs.getInstance(project);
- SVNURL branchesUrl = SVNURL.parseURIEncoded(url);
+ @NotNull
+ public List<SvnBranchItem> loadBranches() throws SVNException, VcsException {
+ final SvnConfiguration configuration = SvnConfiguration.getInstance(myProject);
+ final SvnVcs vcs = SvnVcs.getInstance(myProject);
+ SVNURL branchesUrl = SVNURL.parseURIEncoded(myUrl);
List<SvnBranchItem> result = new LinkedList<SvnBranchItem>();
SvnTarget target = SvnTarget.fromURL(branchesUrl);
- if (!passive) {
+ if (!myPassive) {
// TODO: Implement ability to specify interactive/non-interactive auth mode for clients
DirectoryEntryConsumer handler = createConsumer(branchesUrl, result);
vcs.getFactory(target).createBrowseClient().list(target, SVNRevision.HEAD, Depth.IMMEDIATES, handler);
}
else {
ISVNDirEntryHandler handler = createHandler(branchesUrl, result);
- SVNLogClient client = vcs.getSvnKitManager().createLogClient(configuration.getPassiveAuthenticationManager(project));
+ SVNLogClient client = vcs.getSvnKitManager().createLogClient(configuration.getPassiveAuthenticationManager(myProject));
client
.doList(target.getURL(), target.getPegRevision(), SVNRevision.HEAD, false, SVNDepth.IMMEDIATES, SVNDirEntry.DIRENT_ALL, handler);
}
@@ -62,6 +97,13 @@ public class BranchesLoader {
return result;
}
+ private void showError(Exception e) {
+ // already logged inside
+ if (InfoReliability.setByUser.equals(myInfoReliability)) {
+ VcsBalloonProblemNotifier.showOverChangesView(myProject, "Branches load error: " + e.getMessage(), MessageType.ERROR);
+ }
+ }
+
@NotNull
private static ISVNDirEntryHandler createHandler(@NotNull final SVNURL branchesUrl, @NotNull final List<SvnBranchItem> result) {
return new ISVNDirEntryHandler() {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/ConfigureBranchesAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/ConfigureBranchesAction.java
index 1993a1caa0fe..3615c4b4792d 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/ConfigureBranchesAction.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/ConfigureBranchesAction.java
@@ -13,12 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.jetbrains.idea.svn.actions;
+package org.jetbrains.idea.svn.branchConfig;
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.project.DumbAware;
import com.intellij.openapi.project.Project;
@@ -28,7 +27,6 @@ import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
import icons.SvnIcons;
import org.jetbrains.idea.svn.SvnBundle;
import org.jetbrains.idea.svn.SvnVcs;
-import org.jetbrains.idea.svn.dialogs.BranchConfigurationDialog;
import org.jetbrains.idea.svn.history.SvnChangeList;
public class ConfigureBranchesAction extends AnAction implements DumbAware {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CreateBranchOrTagAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/CreateBranchOrTagAction.java
index c6f633416a15..da1557922a44 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CreateBranchOrTagAction.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/CreateBranchOrTagAction.java
@@ -15,7 +15,7 @@
*/
-package org.jetbrains.idea.svn.actions;
+package org.jetbrains.idea.svn.branchConfig;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.application.Application;
@@ -35,10 +35,10 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.svn.SvnBundle;
import org.jetbrains.idea.svn.SvnStatusUtil;
import org.jetbrains.idea.svn.SvnVcs;
+import org.jetbrains.idea.svn.actions.BasicAction;
import org.jetbrains.idea.svn.checkin.CommitEventHandler;
import org.jetbrains.idea.svn.checkin.IdeaCommitHandler;
import org.jetbrains.idea.svn.commandLine.SvnBindException;
-import org.jetbrains.idea.svn.dialogs.CreateBranchOrTagDialog;
import org.jetbrains.idea.svn.update.AutoSvnUpdater;
import org.jetbrains.idea.svn.update.SingleRootSwitcher;
import org.tmatesoft.svn.core.SVNErrorCode;
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/CreateBranchOrTagDialog.form b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/CreateBranchOrTagDialog.form
index 6dfcae6c9f6f..96eaeaaf2c4c 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/CreateBranchOrTagDialog.form
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/CreateBranchOrTagDialog.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.idea.svn.dialogs.CreateBranchOrTagDialog">
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.idea.svn.branchConfig.CreateBranchOrTagDialog">
<grid id="9287c" binding="myTopPanel" layout-manager="GridBagLayout">
<constraints>
<xy x="10" y="10" width="561" height="502"/>
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/CreateBranchOrTagDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/CreateBranchOrTagDialog.java
index a09de54fdbc4..95ae986dd72d 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/CreateBranchOrTagDialog.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/CreateBranchOrTagDialog.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.jetbrains.idea.svn.dialogs;
+package org.jetbrains.idea.svn.branchConfig;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.diagnostic.Logger;
@@ -33,10 +33,9 @@ import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.svn.RootUrlInfo;
-import org.jetbrains.idea.svn.SvnBranchConfigurationManager;
import org.jetbrains.idea.svn.SvnBundle;
import org.jetbrains.idea.svn.SvnVcs;
-import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew;
+import org.jetbrains.idea.svn.dialogs.SelectLocationDialog;
import org.jetbrains.idea.svn.info.Info;
import org.jetbrains.idea.svn.update.SvnRevisionPanel;
import org.tmatesoft.svn.core.internal.util.SVNEncodingUtil;
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/DefaultBranchConfigInitializer.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/DefaultBranchConfigInitializer.java
new file mode 100644
index 000000000000..37b78459448c
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/DefaultBranchConfigInitializer.java
@@ -0,0 +1,155 @@
+/*
+ * 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.branchConfig;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vcs.VcsException;
+import com.intellij.openapi.vfs.VfsUtilCore;
+import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.NonNls;
+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.Depth;
+import org.jetbrains.idea.svn.browse.DirectoryEntry;
+import org.jetbrains.idea.svn.browse.DirectoryEntryConsumer;
+import org.tmatesoft.svn.core.SVNException;
+import org.tmatesoft.svn.core.SVNURL;
+import org.tmatesoft.svn.core.internal.util.SVNPathUtil;
+import org.tmatesoft.svn.core.wc.SVNRevision;
+import org.tmatesoft.svn.core.wc2.SvnTarget;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+* @author Konstantin Kolosovsky.
+*/
+public class DefaultBranchConfigInitializer implements Runnable {
+
+ private static final Logger LOG = Logger.getInstance(DefaultBranchConfigInitializer.class);
+
+ @NonNls private static final String DEFAULT_TRUNK_NAME = "trunk";
+ @NonNls private static final String DEFAULT_BRANCHES_NAME = "branches";
+ @NonNls private static final String DEFAULT_TAGS_NAME = "tags";
+
+ @NotNull private final Project myProject;
+ @NotNull private final NewRootBunch myBunch;
+ @NotNull private final VirtualFile myRoot;
+
+ public DefaultBranchConfigInitializer(@NotNull Project project, @NotNull NewRootBunch bunch, @NotNull VirtualFile root) {
+ myProject = project;
+ myRoot = root;
+ myBunch = bunch;
+ }
+
+ public void run() {
+ SvnBranchConfigurationNew configuration = getDefaultConfiguration();
+
+ if (configuration != null) {
+ for (String url : configuration.getBranchUrls()) {
+ myBunch.reloadBranchesAsync(myRoot, url, InfoReliability.defaultValues);
+ }
+
+ myBunch.updateForRoot(myRoot, new InfoStorage<SvnBranchConfigurationNew>(configuration, InfoReliability.defaultValues), false);
+ }
+ }
+
+ @Nullable
+ public SvnBranchConfigurationNew getDefaultConfiguration() {
+ SvnBranchConfigurationNew result = null;
+ SvnVcs vcs = SvnVcs.getInstance(myProject);
+ SVNURL rootUrl = SvnUtil.getUrl(vcs, VfsUtilCore.virtualToIoFile(myRoot));
+
+ if (rootUrl != null) {
+ try {
+ result = getDefaultConfiguration(vcs, rootUrl);
+ }
+ catch (SVNException e) {
+ LOG.info(e);
+ }
+ catch (VcsException e) {
+ LOG.info(e);
+ }
+ }
+ else {
+ LOG.info("Directory is not a working copy: " + myRoot.getPresentableUrl());
+ }
+
+ return result;
+ }
+
+ @NotNull
+ private static SvnBranchConfigurationNew getDefaultConfiguration(@NotNull SvnVcs vcs, @NotNull SVNURL url)
+ throws SVNException, VcsException {
+ SvnBranchConfigurationNew result = new SvnBranchConfigurationNew();
+ result.setTrunkUrl(url.toString());
+
+ SVNURL branchLocationsParent = getBranchLocationsParent(url);
+ if (branchLocationsParent != null) {
+ SvnTarget target = SvnTarget.fromURL(branchLocationsParent);
+
+ vcs.getFactory(target).createBrowseClient().list(target, SVNRevision.HEAD, Depth.IMMEDIATES, createHandler(result, target.getURL()));
+ }
+
+ return result;
+ }
+
+ @Nullable
+ private static SVNURL getBranchLocationsParent(@NotNull SVNURL url) throws SVNException {
+ while (!hasEmptyName(url) && !hasDefaultName(url)) {
+ url = url.removePathTail();
+ }
+
+ return hasDefaultName(url) ? url.removePathTail() : null;
+ }
+
+ private static boolean hasEmptyName(@NotNull SVNURL url) {
+ return StringUtil.isEmpty(SVNPathUtil.tail(url.getPath()));
+ }
+
+ private static boolean hasDefaultName(@NotNull SVNURL url) {
+ String name = SVNPathUtil.tail(url.getPath());
+
+ return name.equalsIgnoreCase(DEFAULT_TRUNK_NAME) ||
+ name.equalsIgnoreCase(DEFAULT_BRANCHES_NAME) ||
+ name.equalsIgnoreCase(DEFAULT_TAGS_NAME);
+ }
+
+ @NotNull
+ private static DirectoryEntryConsumer createHandler(@NotNull final SvnBranchConfigurationNew result, @NotNull final SVNURL rootPath) {
+ return new DirectoryEntryConsumer() {
+
+ @Override
+ public void consume(final DirectoryEntry entry) throws SVNException {
+ if (entry.isDirectory()) {
+ SVNURL childUrl = rootPath.appendPath(entry.getName(), false);
+
+ if (StringUtil.endsWithIgnoreCase(entry.getName(), DEFAULT_TRUNK_NAME)) {
+ result.setTrunkUrl(childUrl.toString());
+ }
+ else {
+ result.addBranches(childUrl.toString(),
+ new InfoStorage<List<SvnBranchItem>>(new ArrayList<SvnBranchItem>(0), InfoReliability.defaultValues));
+ }
+ }
+ }
+ };
+ }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/DefaultConfigLoader.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/DefaultConfigLoader.java
deleted file mode 100644
index d52798e6bfc3..000000000000
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/DefaultConfigLoader.java
+++ /dev/null
@@ -1,113 +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 org.jetbrains.idea.svn.branchConfig;
-
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.openapi.vcs.VcsException;
-import com.intellij.openapi.vfs.VirtualFile;
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import org.jetbrains.idea.svn.SvnVcs;
-import org.jetbrains.idea.svn.api.Depth;
-import org.jetbrains.idea.svn.browse.DirectoryEntry;
-import org.jetbrains.idea.svn.browse.DirectoryEntryConsumer;
-import org.jetbrains.idea.svn.info.Info;
-import org.jetbrains.idea.svn.integrate.SvnBranchItem;
-import org.tmatesoft.svn.core.*;
-import org.tmatesoft.svn.core.internal.util.SVNPathUtil;
-import org.tmatesoft.svn.core.wc.SVNRevision;
-import org.tmatesoft.svn.core.wc2.SvnTarget;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-
-public class DefaultConfigLoader {
-
- private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.branchConfig.DefaultConfigLoader");
-
- @NonNls private static final String DEFAULT_TRUNK_NAME = "trunk";
- @NonNls private static final String DEFAULT_BRANCHES_NAME = "branches";
- @NonNls private static final String DEFAULT_TAGS_NAME = "tags";
-
- private DefaultConfigLoader() {
- }
-
- @Nullable
- public static SvnBranchConfigurationNew loadDefaultConfiguration(final Project project, final VirtualFile vcsRoot) {
- try {
- final SvnVcs vcs = SvnVcs.getInstance(project);
-
- File rootFile = new File(vcsRoot.getPath());
- final Info info = vcs.getInfo(rootFile);
- if (info == null || info.getURL() == null) {
- LOG.info("Directory is not a working copy: " + vcsRoot.getPresentableUrl());
- return null;
- }
- SVNURL baseUrl = info.getURL();
-
- final SvnBranchConfigurationNew result = new SvnBranchConfigurationNew();
- result.setTrunkUrl(baseUrl.toString());
- while(true) {
- final String s = SVNPathUtil.tail(baseUrl.getPath());
- if (s.equalsIgnoreCase(DEFAULT_TRUNK_NAME) || s.equalsIgnoreCase(DEFAULT_BRANCHES_NAME) || s.equalsIgnoreCase(DEFAULT_TAGS_NAME)) {
- SVNURL rootPath = baseUrl.removePathTail();
- SvnTarget target = SvnTarget.fromURL(rootPath);
-
- vcs.getFactory(target).createBrowseClient().list(target, SVNRevision.HEAD, Depth.IMMEDIATES, createHandler(result, rootPath));
- break;
- }
- if (SVNPathUtil.removeTail(baseUrl.getPath()).length() == 0) {
- break;
- }
- baseUrl = baseUrl.removePathTail();
- }
- return result;
- }
- catch (SVNException e) {
- LOG.info(e);
- return null;
- }
- catch (VcsException e) {
- LOG.info(e);
- return null;
- }
- }
-
- @NotNull
- private static DirectoryEntryConsumer createHandler(final SvnBranchConfigurationNew result, final SVNURL rootPath) {
- return new DirectoryEntryConsumer() {
-
- @Override
- public void consume(final DirectoryEntry entry) throws SVNException {
- if (entry.isDirectory()) {
- SVNURL childUrl = rootPath.appendPath(entry.getName(), false);
-
- if (StringUtil.endsWithIgnoreCase(entry.getName(), DEFAULT_TRUNK_NAME)) {
- result.setTrunkUrl(childUrl.toString());
- }
- else {
- result.addBranches(childUrl.toString(),
- new InfoStorage<List<SvnBranchItem>>(new ArrayList<SvnBranchItem>(0), InfoReliability.defaultValues));
- }
- }
- }
- };
- }
-}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/InfoStorage.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/InfoStorage.java
index 493721e3a8d1..fe10696768c1 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/InfoStorage.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/InfoStorage.java
@@ -15,9 +15,6 @@
*/
package org.jetbrains.idea.svn.branchConfig;
-import com.intellij.util.PairConsumer;
-import org.jetbrains.annotations.Nullable;
-
public class InfoStorage<T> {
public T myT;
public InfoReliability myInfoReliability;
@@ -27,14 +24,15 @@ public class InfoStorage<T> {
myInfoReliability = infoReliability;
}
- public void accept(final InfoStorage<T> infoStorage, @Nullable final PairConsumer<T, T> callbackOnUpdate) {
- if (infoStorage.myInfoReliability.shouldOverride(myInfoReliability)) {
- if (callbackOnUpdate != null) {
- callbackOnUpdate.consume(myT, infoStorage.myT);
- }
+ public boolean accept(final InfoStorage<T> infoStorage) {
+ boolean override = infoStorage.myInfoReliability.shouldOverride(myInfoReliability);
+
+ if (override) {
myT = infoStorage.myT;
myInfoReliability = infoStorage.myInfoReliability;
}
+
+ return override;
}
public T getValue() {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/NewRootBunch.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/NewRootBunch.java
index 2c7444ed85b0..6f7f4185a815 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/NewRootBunch.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/NewRootBunch.java
@@ -15,31 +15,23 @@
*/
package org.jetbrains.idea.svn.branchConfig;
-import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressManagerQueue;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.vcs.CalledInBackground;
-import com.intellij.openapi.vcs.VcsException;
-import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.util.Consumer;
-import com.intellij.util.PairConsumer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import org.jetbrains.idea.svn.integrate.SvnBranchItem;
+import org.jetbrains.idea.svn.SvnVcs;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNURL;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
// synch is here
-public class NewRootBunch implements SvnBranchConfigManager {
+public class NewRootBunch {
private final static Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.branchConfig.NewRootBunch");
private final Object myLock = new Object();
private final Project myProject;
@@ -52,17 +44,31 @@ public class NewRootBunch implements SvnBranchConfigManager {
myMap = new HashMap<VirtualFile, InfoStorage<SvnBranchConfigurationNew>>();
}
- public void updateForRoot(@NotNull final VirtualFile root, @NotNull final InfoStorage<SvnBranchConfigurationNew> config,
- @Nullable final PairConsumer<SvnBranchConfigurationNew, SvnBranchConfigurationNew> callbackOnUpdate) {
+ public void updateForRoot(@NotNull final VirtualFile root,
+ @NotNull final InfoStorage<SvnBranchConfigurationNew> config,
+ boolean reload) {
synchronized (myLock) {
+ final SvnBranchConfigurationNew previous;
+ boolean override;
final InfoStorage<SvnBranchConfigurationNew> existing = myMap.get(root);
+
if (existing == null) {
+ previous = null;
+ override = true;
myMap.put(root, config);
- if (callbackOnUpdate != null) {
- callbackOnUpdate.consume(null, config.getValue());
- }
- } else {
- existing.accept(config, callbackOnUpdate);
+ }
+ else {
+ previous = existing.getValue();
+ override = existing.accept(config);
+ }
+
+ if (reload && override) {
+ myBranchesLoader.run(new Runnable() {
+ @Override
+ public void run() {
+ reloadBranches(root, previous, config.getValue());
+ }
+ });
}
}
}
@@ -88,17 +94,44 @@ public class NewRootBunch implements SvnBranchConfigManager {
result = new SvnBranchConfigurationNew();
myMap.put(root, new InfoStorage<SvnBranchConfigurationNew>(result, InfoReliability.empty));
myBranchesLoader.run(new DefaultBranchConfigInitializer(myProject, this, root));
- } else {
+ }
+ else {
result = value.getValue();
}
return result;
}
}
- public void reloadBranches(@NotNull final VirtualFile root, @NotNull final String branchParentUrl,
- final Consumer<List<SvnBranchItem>> callback) {
- ApplicationManager.getApplication().executeOnPooledThread(new BranchesLoadRunnable(myProject, this, branchParentUrl,
- InfoReliability.setByUser, root, callback, true));
+ public void reloadBranchesAsync(@NotNull final VirtualFile root,
+ @NotNull final String branchLocation,
+ @NotNull final InfoReliability reliability) {
+ ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
+ @Override
+ public void run() {
+ reloadBranches(root, branchLocation, reliability, true);
+ }
+ });
+ }
+
+ public void reloadBranches(@NotNull VirtualFile root, @Nullable SvnBranchConfigurationNew prev, @NotNull SvnBranchConfigurationNew next) {
+ final Set<String> oldUrls = (prev == null) ? Collections.<String>emptySet() : new HashSet<String>(prev.getBranchUrls());
+ final SvnVcs vcs = SvnVcs.getInstance(myProject);
+ if (!vcs.isVcsBackgroundOperationsAllowed(root)) return;
+
+ for (String newBranchUrl : next.getBranchUrls()) {
+ // check if cancel had been put
+ if (!vcs.isVcsBackgroundOperationsAllowed(root)) return;
+ if (!oldUrls.contains(newBranchUrl)) {
+ reloadBranches(root, newBranchUrl, InfoReliability.defaultValues, true);
+ }
+ }
+ }
+
+ public void reloadBranches(@NotNull VirtualFile root,
+ @NotNull String branchLocation,
+ @NotNull InfoReliability reliability,
+ boolean passive) {
+ new BranchesLoader(myProject, this, branchLocation, reliability, root, passive).run();
}
@Nullable
@@ -108,28 +141,11 @@ public class NewRootBunch implements SvnBranchConfigManager {
try {
final SvnBranchConfigurationNew configuration = myMap.get(root).getValue();
final String group = configuration.getGroupToLoadToReachUrl(svnurl);
- final Runnable runnable = new Runnable() {
- public void run() {
- final SvnBranchConfigurationNew reloadedConfiguration = myMap.get(root).getValue();
- try {
- result.set(reloadedConfiguration.getWorkingBranch(svnurl));
- }
- catch (SVNException e) {
- //
- }
- }
- };
- if (group == null) {
- runnable.run();
- } else {
- new BranchesLoadRunnable(myProject, this, group, InfoReliability.setByUser, root,
- new Consumer<List<SvnBranchItem>>() {
- public void consume(List<SvnBranchItem> svnBranchItems) {
- runnable.run();
- }
- }, true).run();
+ if (group != null) {
+ reloadBranches(root, group, InfoReliability.setByUser, true);
}
+ result.set(myMap.get(root).getValue().getWorkingBranch(svnurl));
}
catch (SVNException e) {
//
@@ -137,88 +153,6 @@ public class NewRootBunch implements SvnBranchConfigManager {
return result.get();
}
- public static class BranchesLoadRunnable implements Runnable {
- private final Project myProject;
- private final SvnBranchConfigManager myBunch;
- private final VirtualFile myRoot;
- @Nullable
- private final Consumer<List<SvnBranchItem>> myCallback;
- private final String myUrl;
- private final InfoReliability myInfoReliability;
- private boolean myPassive;
-
- public BranchesLoadRunnable(final Project project,
- final SvnBranchConfigManager bunch,
- final String url,
- final InfoReliability infoReliability,
- final VirtualFile root,
- @Nullable final Consumer<List<SvnBranchItem>> callback,
- boolean passive) {
- myProject = project;
- myBunch = bunch;
- myUrl = url;
- myInfoReliability = infoReliability;
- myRoot = root;
- myCallback = callback;
- myPassive = passive;
- }
-
- public void run() {
- boolean callbackCalled = false;
- try {
- final List<SvnBranchItem> items = BranchesLoader.loadBranches(myProject, myUrl, myPassive);
- myBunch.updateBranches(myRoot, myUrl, new InfoStorage<List<SvnBranchItem>>(items, myInfoReliability));
- if (myCallback != null) {
- myCallback.consume(items);
- callbackCalled = true;
- }
- }
- catch (VcsException e) {
- showError(e);
- }
- catch (SVNException e) {
- showError(e);
- }
- finally {
- // callback must be called by contract
- if (myCallback != null && (! callbackCalled)) {
- myCallback.consume(null);
- }
- }
- }
-
- private void showError(Exception e) {
- // already logged inside
- if (InfoReliability.setByUser.equals(myInfoReliability)) {
- VcsBalloonProblemNotifier.showOverChangesView(myProject, "Branches load error: " + e.getMessage(), MessageType.ERROR);
- }
- }
- }
-
- private static class DefaultBranchConfigInitializer implements Runnable {
- private final Project myProject;
- private final SvnBranchConfigManager myBunch;
- private final VirtualFile myRoot;
-
- private DefaultBranchConfigInitializer(final Project project, final SvnBranchConfigManager bunch, final VirtualFile root) {
- myProject = project;
- myRoot = root;
- myBunch = bunch;
- }
-
- public void run() {
- final SvnBranchConfigurationNew result = DefaultConfigLoader.loadDefaultConfiguration(myProject, myRoot);
- if (result != null) {
- final Application application = ApplicationManager.getApplication();
- for (String url : result.getBranchUrls()) {
- application.executeOnPooledThread(new BranchesLoadRunnable(myProject, myBunch, url, InfoReliability.defaultValues, myRoot, null,
- true));
- }
- myBunch.updateForRoot(myRoot, new InfoStorage<SvnBranchConfigurationNew>(result, InfoReliability.defaultValues), null);
- }
- }
- }
-
public Map<VirtualFile, SvnBranchConfigurationNew> getMapCopy() {
synchronized (myLock) {
final Map<VirtualFile, SvnBranchConfigurationNew> result = new HashMap<VirtualFile, SvnBranchConfigurationNew>();
@@ -228,4 +162,4 @@ public class NewRootBunch implements SvnBranchConfigManager {
return result;
}
}
-}
+} \ No newline at end of file
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SelectBranchPopup.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SelectBranchPopup.java
index 5e634f3b9b87..445ce4e9afe3 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/SelectBranchPopup.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SelectBranchPopup.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.jetbrains.idea.svn.actions;
+package org.jetbrains.idea.svn.branchConfig;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
@@ -30,13 +30,10 @@ import com.intellij.util.text.DateFormatUtil;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import org.jetbrains.idea.svn.*;
-import org.jetbrains.idea.svn.branchConfig.InfoReliability;
-import org.jetbrains.idea.svn.branchConfig.NewRootBunch;
-import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigManager;
-import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew;
-import org.jetbrains.idea.svn.dialogs.BranchConfigurationDialog;
-import org.jetbrains.idea.svn.integrate.SvnBranchItem;
+import org.jetbrains.idea.svn.RootUrlInfo;
+import org.jetbrains.idea.svn.SvnBundle;
+import org.jetbrains.idea.svn.SvnFileUrlMapping;
+import org.jetbrains.idea.svn.SvnVcs;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.internal.util.SVNPathUtil;
@@ -221,8 +218,9 @@ public class SelectBranchPopup {
@Override
protected void runImpl(@NotNull ProgressIndicator indicator) {
- final SvnBranchConfigManager manager = SvnBranchConfigurationManager.getInstance(myProject).getSvnBranchConfigManager();
- new NewRootBunch.BranchesLoadRunnable(myProject, manager, selectedBranchesHolder, InfoReliability.setByUser, myVcsRoot, null, false).run();
+ final NewRootBunch manager = SvnBranchConfigurationManager.getInstance(myProject).getSvnBranchConfigManager();
+
+ manager.reloadBranches(myVcsRoot, selectedBranchesHolder, InfoReliability.setByUser, false);
}
});
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchConfigManager.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchConfigManager.java
deleted file mode 100644
index 0a47a7771171..000000000000
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchConfigManager.java
+++ /dev/null
@@ -1,47 +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 org.jetbrains.idea.svn.branchConfig;
-
-import com.intellij.openapi.vcs.CalledInBackground;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.util.Consumer;
-import com.intellij.util.PairConsumer;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import org.jetbrains.idea.svn.integrate.SvnBranchItem;
-import org.tmatesoft.svn.core.SVNURL;
-
-import java.util.List;
-import java.util.Map;
-
-public interface SvnBranchConfigManager {
- void updateForRoot(@NotNull VirtualFile root, @NotNull InfoStorage<SvnBranchConfigurationNew> config,
- @Nullable final PairConsumer<SvnBranchConfigurationNew, SvnBranchConfigurationNew> callbackOnUpdate);
-
- void updateBranches(@NotNull VirtualFile root, @NotNull String branchesParent,
- @NotNull InfoStorage<List<SvnBranchItem>> items);
-
- @NotNull
- SvnBranchConfigurationNew getConfig(@NotNull VirtualFile root);
-
- void reloadBranches(@NotNull VirtualFile root, @NotNull String branchParentUrl,
- Consumer<List<SvnBranchItem>> callback);
- @Nullable
- @CalledInBackground
- SVNURL getWorkingBranchWithReload(final SVNURL svnurl, final VirtualFile root);
-
- Map<VirtualFile, SvnBranchConfigurationNew> getMapCopy();
-}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBranchConfiguration.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchConfiguration.java
index c167fd868531..0c6138fd08c2 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBranchConfiguration.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchConfiguration.java
@@ -14,24 +14,36 @@
* limitations under the License.
*/
-package org.jetbrains.idea.svn;
+package org.jetbrains.idea.svn.branchConfig;
+
+import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
+ * Default constructor and setters are necessary for serialization purposes.
+ *
* @author yole
*/
+@SuppressWarnings("UnusedDeclaration")
public class SvnBranchConfiguration {
private String myTrunkUrl;
- private List<String> myBranchUrls;
+ @NotNull private List<String> myBranchUrls;
private boolean myUserinfoInUrl;
public SvnBranchConfiguration() {
myBranchUrls = new ArrayList<String>();
}
+ public SvnBranchConfiguration(String trunkUrl, @NotNull List<String> branchUrls, boolean userinfoInUrl) {
+ myTrunkUrl = trunkUrl;
+ myBranchUrls = branchUrls;
+ Collections.sort(myBranchUrls);
+ myUserinfoInUrl = userinfoInUrl;
+ }
+
public boolean isUserinfoInUrl() {
return myUserinfoInUrl;
}
@@ -39,8 +51,8 @@ public class SvnBranchConfiguration {
public void setUserinfoInUrl(final boolean userinfoInUrl) {
myUserinfoInUrl = userinfoInUrl;
}
-
- public void setBranchUrls(final List<String> branchUrls) {
+
+ public void setBranchUrls(@NotNull List<String> branchUrls) {
myBranchUrls = branchUrls;
Collections.sort(myBranchUrls);
}
@@ -53,6 +65,7 @@ public class SvnBranchConfiguration {
return myTrunkUrl;
}
+ @NotNull
public List<String> getBranchUrls() {
return myBranchUrls;
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBranchConfigurationManager.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchConfigurationManager.java
index f13ed5a97a03..772e5edd2755 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBranchConfigurationManager.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchConfigurationManager.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.jetbrains.idea.svn;
+package org.jetbrains.idea.svn.branchConfig;
import com.intellij.lifecycle.PeriodicalTasksCloser;
import com.intellij.openapi.application.ApplicationManager;
@@ -27,7 +27,6 @@ import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressManagerQueue;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
-import com.intellij.openapi.util.Ref;
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.changes.committed.VcsConfigurationChangeListener;
@@ -35,14 +34,10 @@ import com.intellij.openapi.vcs.impl.ProjectLevelVcsManagerImpl;
import com.intellij.openapi.vcs.impl.VcsInitObject;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.util.PairConsumer;
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.messages.MessageBus;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import org.jetbrains.idea.svn.branchConfig.*;
-import org.jetbrains.idea.svn.integrate.SvnBranchItem;
-import org.tmatesoft.svn.core.SVNException;
-import org.tmatesoft.svn.core.SVNURL;
+import org.jetbrains.idea.svn.SvnVcs;
import java.io.File;
import java.util.*;
@@ -58,15 +53,16 @@ import java.util.*;
)}
)
public class SvnBranchConfigurationManager implements PersistentStateComponent<SvnBranchConfigurationManager.ConfigurationBean> {
- private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.SvnBranchConfigurationManager");
+ private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationManager");
private final Project myProject;
private final ProjectLevelVcsManager myVcsManager;
- private final SvnLoadedBrachesStorage myStorage;
+ private final SvnLoadedBranchesStorage myStorage;
private final ProgressManagerQueue myBranchesLoader;
+ private boolean myIsInitialized;
public SvnBranchConfigurationManager(final Project project,
final ProjectLevelVcsManager vcsManager,
- final SvnLoadedBrachesStorage storage) {
+ final SvnLoadedBranchesStorage storage) {
myProject = project;
myVcsManager = vcsManager;
myStorage = storage;
@@ -91,7 +87,13 @@ public class SvnBranchConfigurationManager implements PersistentStateComponent<S
}
public static SvnBranchConfigurationManager getInstance(final Project project) {
- return PeriodicalTasksCloser.getInstance().safeGetService(project, SvnBranchConfigurationManager.class);
+ SvnBranchConfigurationManager result = PeriodicalTasksCloser.getInstance().safeGetService(project, SvnBranchConfigurationManager.class);
+
+ if (result != null) {
+ result.initialize();
+ }
+
+ return result;
}
public static class ConfigurationBean {
@@ -108,19 +110,18 @@ public class SvnBranchConfigurationManager implements PersistentStateComponent<S
}
private ConfigurationBean myConfigurationBean = new ConfigurationBean();
- private final SvnBranchConfigManager myBunch;
+ private final NewRootBunch myBunch;
public SvnBranchConfigurationNew get(@NotNull final VirtualFile vcsRoot) throws VcsException {
return myBunch.getConfig(vcsRoot);
}
- public SvnBranchConfigManager getSvnBranchConfigManager() {
+ public NewRootBunch getSvnBranchConfigManager() {
return myBunch;
}
public void setConfiguration(final VirtualFile vcsRoot, final SvnBranchConfigurationNew configuration) {
- myBunch.updateForRoot(vcsRoot, new InfoStorage<SvnBranchConfigurationNew>(configuration, InfoReliability.setByUser),
- new BranchesPreloader(myProject, myBunch, vcsRoot, myBranchesLoader));
+ myBunch.updateForRoot(vcsRoot, new InfoStorage<SvnBranchConfigurationNew>(configuration, InfoReliability.setByUser), true);
SvnBranchMapperManager.getInstance().notifyBranchesChanged(myProject, vcsRoot, configuration);
@@ -136,71 +137,33 @@ public class SvnBranchConfigurationManager implements PersistentStateComponent<S
for (VirtualFile root : myBunch.getMapCopy().keySet()) {
final String key = root.getPath();
final SvnBranchConfigurationNew configOrig = myBunch.getConfig(root);
- final SvnBranchConfiguration configuration = new SvnBranchConfiguration();
- configuration.setTrunkUrl(configOrig.getTrunkUrl());
- configuration.setUserinfoInUrl(configOrig.isUserinfoInUrl());
- configuration.setBranchUrls(configOrig.getBranchUrls());
- final HashMap<String, List<SvnBranchItem>> map = new HashMap<String, List<SvnBranchItem>>();
- final Map<String, InfoStorage<List<SvnBranchItem>>> origMap = configOrig.getBranchMap();
- for (String origKey : origMap.keySet()) {
- map.put(origKey, origMap.get(origKey).getValue());
- }
+ final SvnBranchConfiguration configuration =
+ new SvnBranchConfiguration(configOrig.getTrunkUrl(), configOrig.getBranchUrls(), configOrig.isUserinfoInUrl());
+
result.myConfigurationMap.put(key, helper.prepareForSerialization(configuration));
}
result.mySupportsUserInfoFilter = true;
return result;
}
- private static class BranchesPreloader implements PairConsumer<SvnBranchConfigurationNew, SvnBranchConfigurationNew> {
- private final Project myProject;
- private final VirtualFile myRoot;
- private final ProgressManagerQueue myQueue;
- private final SvnBranchConfigManager myBunch;
- private boolean myAll;
+ public void loadState(ConfigurationBean object) {
+ myConfigurationBean = object;
+ }
- public BranchesPreloader(Project project, @NotNull final SvnBranchConfigManager bunch, VirtualFile root,
- final ProgressManagerQueue queue) {
- myBunch = bunch;
- myProject = project;
- myRoot = root;
- myQueue = queue;
- }
+ private synchronized void initialize() {
+ if (!myIsInitialized) {
+ myIsInitialized = true;
- public void consume(final SvnBranchConfigurationNew prev, final SvnBranchConfigurationNew next) {
- myQueue.run(new Runnable() {
- public void run() {
- loadImpl(prev, next);
- }
- });
- }
-
- protected void loadImpl(final SvnBranchConfigurationNew prev, final SvnBranchConfigurationNew next) {
- final Set<String> oldUrls = (prev == null) ? Collections.<String>emptySet() : new HashSet<String>(prev.getBranchUrls());
- final SvnVcs vcs = SvnVcs.getInstance(myProject);
- if (! vcs.isVcsBackgroundOperationsAllowed(myRoot)) return;
-
- for (String newBranchUrl : next.getBranchUrls()) {
- // check if cancel had been put
- if (! vcs.isVcsBackgroundOperationsAllowed(myRoot)) return;
- if (myAll || (! oldUrls.contains(newBranchUrl))) {
- new NewRootBunch.BranchesLoadRunnable(myProject, myBunch, newBranchUrl, InfoReliability.defaultValues, myRoot, null, true).run();
- }
- }
- }
-
- public void setAll(boolean all) {
- myAll = all;
+ preloadBranches(resolveAllBranchPoints());
}
}
- public void loadState(final ConfigurationBean object) {
- final UrlSerializationHelper helper = new UrlSerializationHelper(SvnVcs.getInstance(myProject));
- final Map<String, SvnBranchConfiguration> map = object.myConfigurationMap;
- final Map<String, SvnBranchConfiguration> newMap = new HashMap<String, SvnBranchConfiguration>(map.size(), 1);
+ @NotNull
+ private Set<Pair<VirtualFile, SvnBranchConfigurationNew>> resolveAllBranchPoints() {
final LocalFileSystem lfs = LocalFileSystem.getInstance();
-
- final Set<Pair<VirtualFile, SvnBranchConfigurationNew>> whatToInit = new HashSet<Pair<VirtualFile, SvnBranchConfigurationNew>>();
- for (Map.Entry<String, SvnBranchConfiguration> entry : map.entrySet()) {
+ final UrlSerializationHelper helper = new UrlSerializationHelper(SvnVcs.getInstance(myProject));
+ final Set<Pair<VirtualFile, SvnBranchConfigurationNew>> branchPointsToLoad = ContainerUtil.newHashSet();
+ for (Map.Entry<String, SvnBranchConfiguration> entry : myConfigurationBean.myConfigurationMap.entrySet()) {
final SvnBranchConfiguration configuration = entry.getValue();
final VirtualFile root = lfs.refreshAndFindFileByIoFile(new File(entry.getKey()));
if (root == null) {
@@ -222,22 +185,24 @@ public class SvnBranchConfigurationManager implements PersistentStateComponent<S
if (stored != null && ! stored.isEmpty()) {
newConfig.addBranches(branchUrl, new InfoStorage<List<SvnBranchItem>>(stored, InfoReliability.setByUser));
} else {
- whatToInit.add(Pair.create(root, newConfig));
+ branchPointsToLoad.add(Pair.create(root, newConfig));
newConfig.addBranches(branchUrl, new InfoStorage<List<SvnBranchItem>>(new ArrayList<SvnBranchItem>(), InfoReliability.empty));
}
}
- myBunch.updateForRoot(root, new InfoStorage<SvnBranchConfigurationNew>(newConfig, InfoReliability.setByUser), null);
+ myBunch.updateForRoot(root, new InfoStorage<SvnBranchConfigurationNew>(newConfig, InfoReliability.setByUser), false);
}
+ return branchPointsToLoad;
+ }
+
+ private void preloadBranches(@NotNull final Collection<Pair<VirtualFile, SvnBranchConfigurationNew>> branchPoints) {
((ProjectLevelVcsManagerImpl) myVcsManager).addInitializationRequest(VcsInitObject.BRANCHES, new Runnable() {
public void run() {
ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
public void run() {
try {
- for (Pair<VirtualFile, SvnBranchConfigurationNew> pair : whatToInit) {
- final BranchesPreloader branchesPreloader = new BranchesPreloader(myProject, myBunch, pair.getFirst(), myBranchesLoader);
- branchesPreloader.setAll(true);
- branchesPreloader.loadImpl(null, pair.getSecond());
+ for (Pair<VirtualFile, SvnBranchConfigurationNew> pair : branchPoints) {
+ myBunch.reloadBranches(pair.getFirst(), null, pair.getSecond());
}
}
catch (ProcessCanceledException e) {
@@ -247,9 +212,6 @@ public class SvnBranchConfigurationManager implements PersistentStateComponent<S
});
}
});
- object.myConfigurationMap.clear();
- object.myConfigurationMap.putAll(newMap);
- myConfigurationBean = object;
}
private List<SvnBranchItem> getStored(String branchUrl) {
@@ -259,93 +221,4 @@ public class SvnBranchConfigurationManager implements PersistentStateComponent<S
Collections.sort(items);
return items;
}
-
- private static class UrlSerializationHelper {
- private final SvnVcs myVcs;
-
- private UrlSerializationHelper(final SvnVcs vcs) {
- myVcs = vcs;
- }
-
- public SvnBranchConfiguration prepareForSerialization(final SvnBranchConfiguration configuration) {
- final Ref<Boolean> withUserInfo = new Ref<Boolean>();
- final String trunkUrl = serializeUrl(configuration.getTrunkUrl(), withUserInfo);
-
- if (Boolean.FALSE.equals(withUserInfo.get())) {
- return configuration;
- }
-
- final List<String> branches = configuration.getBranchUrls();
- final List<String> newBranchesList = new ArrayList<String>(branches.size());
- for (String s : branches) {
- newBranchesList.add(serializeUrl(s, withUserInfo));
- }
-
- final SvnBranchConfiguration result = new SvnBranchConfiguration();
- result.setTrunkUrl(trunkUrl);
- result.setBranchUrls(newBranchesList);
- result.setUserinfoInUrl(withUserInfo.isNull() ? false : withUserInfo.get());
- return result;
- }
-
- public SvnBranchConfiguration afterDeserialization(final String path, final SvnBranchConfiguration configuration) {
- if (! configuration.isUserinfoInUrl()) {
- return configuration;
- }
- final String userInfo = getUserInfo(path);
- if (userInfo == null) {
- return configuration;
- }
-
- final String newTrunkUrl = deserializeUrl(configuration.getTrunkUrl(), userInfo);
- final List<String> branches = configuration.getBranchUrls();
- final List<String> newBranchesList = new ArrayList<String>(branches.size());
- for (String s : branches) {
- newBranchesList.add(deserializeUrl(s, userInfo));
- }
-
- final SvnBranchConfiguration result = new SvnBranchConfiguration();
- result.setTrunkUrl(newTrunkUrl);
- result.setBranchUrls(newBranchesList);
- result.setUserinfoInUrl(userInfo != null && userInfo.length() > 0);
- return result;
- }
-
- private static String serializeUrl(final String url, final Ref<Boolean> withUserInfo) {
- if (Boolean.FALSE.equals(withUserInfo.get())) {
- return url;
- }
- try {
- final SVNURL svnurl = SVNURL.parseURIEncoded(url);
- if (withUserInfo.isNull()) {
- final String userInfo = svnurl.getUserInfo();
- withUserInfo.set((userInfo != null) && (userInfo.length() > 0));
- }
- if (withUserInfo.get()) {
- return SVNURL.create(svnurl.getProtocol(), null, svnurl.getHost(), SvnUtil.resolvePort(svnurl), svnurl.getURIEncodedPath(), true)
- .toString();
- }
- }
- catch (SVNException e) {
- //
- }
- return url;
- }
-
- @Nullable
- private String getUserInfo(final String path) {
- final SVNURL svnurl = myVcs.getSvnFileUrlMapping().getUrlForFile(new File(path));
- return svnurl != null ? svnurl.getUserInfo() : null;
- }
-
- private static String deserializeUrl(final String url, final String userInfo) {
- try {
- final SVNURL svnurl = SVNURL.parseURIEncoded(url);
- return SVNURL.create(svnurl.getProtocol(), userInfo, svnurl.getHost(), SvnUtil.resolvePort(svnurl), svnurl.getURIEncodedPath(),
- true).toString();
- } catch (SVNException e) {
- return url;
- }
- }
- }
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchConfigurationNew.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchConfigurationNew.java
index 4102210a657a..3ce3c986c8ae 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchConfigurationNew.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchConfigurationNew.java
@@ -24,7 +24,6 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.SvnUtil;
import org.jetbrains.idea.svn.SvnVcs;
import org.jetbrains.idea.svn.info.Info;
-import org.jetbrains.idea.svn.integrate.SvnBranchItem;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.internal.util.SVNPathUtil;
@@ -98,7 +97,7 @@ public class SvnBranchConfigurationNew {
LOG.info("Branches list not updated for : '" + branchParentName + "; since config has changed.");
return;
}
- current.accept(items, null);
+ current.accept(items);
}
public Map<String, InfoStorage<List<SvnBranchItem>>> getBranchMap() {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SvnBranchItem.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchItem.java
index f9e428d1becf..a0bd0868b6d2 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SvnBranchItem.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchItem.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.jetbrains.idea.svn.integrate;
+package org.jetbrains.idea.svn.branchConfig;
import java.util.Date;
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBranchMapperManager.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchMapperManager.java
index e82e363f598a..f9f99bea1e17 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBranchMapperManager.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnBranchMapperManager.java
@@ -13,17 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.jetbrains.idea.svn;
+package org.jetbrains.idea.svn.branchConfig;
-import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.*;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.util.messages.Topic;
-import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew;
import java.io.File;
-import java.util.*;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
/**
* Holds what working copies we have for URLs
@@ -56,7 +56,6 @@ public class SvnBranchMapperManager implements PersistentStateComponent<SvnBranc
public void put(final String url, final String value) {
myStateHolder.put(url, value);
- notifyWcRootsChanged(url, Collections.unmodifiableCollection(myStateHolder.get(url)));
}
public void remove(final String url, final File value) {
@@ -64,11 +63,6 @@ public class SvnBranchMapperManager implements PersistentStateComponent<SvnBranc
if (set != null) {
set.remove(value.getAbsolutePath());
}
- notifyWcRootsChanged(url, Collections.unmodifiableCollection(set));
- }
-
- private static void notifyWcRootsChanged(final String url, final Collection<String> roots) {
- ApplicationManager.getApplication().getMessageBus().syncPublisher(WC_ROOTS_CHANGED).rootsChanged(url, roots);
}
public void notifyBranchesChanged(final Project project, final VirtualFile vcsRoot, final SvnBranchConfigurationNew configuration) {
@@ -104,11 +98,4 @@ public class SvnBranchMapperManager implements PersistentStateComponent<SvnBranc
return myMapping.get(key);
}
}
-
- public static interface WcRootsChangeConsumer {
- void rootsChanged(final String url, final Collection<String> roots);
- }
-
- public static final Topic<WcRootsChangeConsumer> WC_ROOTS_CHANGED =
- new Topic<WcRootsChangeConsumer>("SVN_WC_ROOTS_CHANGED", WcRootsChangeConsumer.class);
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnLoadedBrachesStorage.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnLoadedBranchesStorage.java
index 8fe1fa52a938..041e33cc5ac7 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnLoadedBrachesStorage.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/SvnLoadedBranchesStorage.java
@@ -13,19 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.jetbrains.idea.svn;
+package org.jetbrains.idea.svn.branchConfig;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vcs.persistent.SmallMapSerializer;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.io.DataExternalizer;
import com.intellij.util.io.EnumeratorStringDescriptor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import org.jetbrains.idea.svn.branchConfig.InfoStorage;
-import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew;
-import org.jetbrains.idea.svn.integrate.SvnBranchItem;
import java.io.DataInput;
import java.io.DataOutput;
@@ -39,13 +37,13 @@ import java.util.*;
* Date: 8/24/11
* Time: 1:21 PM
*/
-public class SvnLoadedBrachesStorage {
+public class SvnLoadedBranchesStorage {
private final Object myLock;
private SmallMapSerializer<String, Map<String, Collection<SvnBranchItem>>> myState;
private final File myFile;
private final Project myProject;
- public SvnLoadedBrachesStorage(final Project project) {
+ public SvnLoadedBranchesStorage(final Project project) {
myProject = project;
final File vcsFile = new File(PathManager.getSystemPath(), "vcs");
File file = new File(vcsFile, "svn_branches");
@@ -63,18 +61,6 @@ public class SvnLoadedBrachesStorage {
}
}
- public void put(final String url, final Collection<SvnBranchItem> items) {
- synchronized (myLock) {
- if (myState == null) return;
- Map<String, Collection<SvnBranchItem>> map = myState.get("");
- if (map == null) {
- map = new HashMap<String, Collection<SvnBranchItem>>();
- myState.put("", map);
- }
- map.put(url, items);
- }
- }
-
public void activate() {
synchronized (myLock) {
myState = new SmallMapSerializer<String, Map<String, Collection<SvnBranchItem>>>(myFile, new EnumeratorStringDescriptor(), createExternalizer());
@@ -83,15 +69,19 @@ public class SvnLoadedBrachesStorage {
public void deactivate() {
+ Map<String, Collection<SvnBranchItem>> branchLocationToBranchItemsMap = ContainerUtil.newHashMap();
SvnBranchConfigurationManager manager = SvnBranchConfigurationManager.getInstance(myProject);
Map<VirtualFile,SvnBranchConfigurationNew> mapCopy = manager.getSvnBranchConfigManager().getMapCopy();
for (Map.Entry<VirtualFile, SvnBranchConfigurationNew> entry : mapCopy.entrySet()) {
Map<String,InfoStorage<List<SvnBranchItem>>> branchMap = entry.getValue().getBranchMap();
for (Map.Entry<String, InfoStorage<List<SvnBranchItem>>> storageEntry : branchMap.entrySet()) {
- put(storageEntry.getKey(), storageEntry.getValue().getValue());
+ branchLocationToBranchItemsMap.put(storageEntry.getKey(), storageEntry.getValue().getValue());
}
}
synchronized (myLock) {
+ // TODO: Possibly implement optimization - do not perform save if there are no changes in branch locations and branch items
+ // ensure myState.put() is called - so myState will treat itself as dirty and myState.force() will invoke real persisting
+ myState.put("", branchLocationToBranchItemsMap);
myState.force();
myState = null;
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/UrlSerializationHelper.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/UrlSerializationHelper.java
new file mode 100644
index 000000000000..36c16f33a0fc
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/UrlSerializationHelper.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.idea.svn.branchConfig;
+
+import com.intellij.openapi.util.Ref;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.svn.SvnUtil;
+import org.jetbrains.idea.svn.SvnVcs;
+import org.tmatesoft.svn.core.SVNException;
+import org.tmatesoft.svn.core.SVNURL;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+* @author Konstantin Kolosovsky.
+*/
+public class UrlSerializationHelper {
+ private final SvnVcs myVcs;
+
+ public UrlSerializationHelper(final SvnVcs vcs) {
+ myVcs = vcs;
+ }
+
+ public SvnBranchConfiguration prepareForSerialization(final SvnBranchConfiguration configuration) {
+ final Ref<Boolean> withUserInfo = new Ref<Boolean>();
+ final String trunkUrl = serializeUrl(configuration.getTrunkUrl(), withUserInfo);
+
+ if (Boolean.FALSE.equals(withUserInfo.get())) {
+ return configuration;
+ }
+
+ final List<String> branches = configuration.getBranchUrls();
+ final List<String> newBranchesList = new ArrayList<String>(branches.size());
+ for (String s : branches) {
+ newBranchesList.add(serializeUrl(s, withUserInfo));
+ }
+
+ return new SvnBranchConfiguration(trunkUrl, newBranchesList, withUserInfo.isNull() ? false : withUserInfo.get());
+ }
+
+ public SvnBranchConfiguration afterDeserialization(final String path, final SvnBranchConfiguration configuration) {
+ if (! configuration.isUserinfoInUrl()) {
+ return configuration;
+ }
+ final String userInfo = getUserInfo(path);
+ if (userInfo == null) {
+ return configuration;
+ }
+
+ final String newTrunkUrl = deserializeUrl(configuration.getTrunkUrl(), userInfo);
+ final List<String> branches = configuration.getBranchUrls();
+ final List<String> newBranchesList = new ArrayList<String>(branches.size());
+ for (String s : branches) {
+ newBranchesList.add(deserializeUrl(s, userInfo));
+ }
+
+ return new SvnBranchConfiguration(newTrunkUrl, newBranchesList, userInfo.length() > 0);
+ }
+
+ private static String serializeUrl(final String url, final Ref<Boolean> withUserInfo) {
+ if (Boolean.FALSE.equals(withUserInfo.get())) {
+ return url;
+ }
+ try {
+ final SVNURL svnurl = SVNURL.parseURIEncoded(url);
+ if (withUserInfo.isNull()) {
+ final String userInfo = svnurl.getUserInfo();
+ withUserInfo.set((userInfo != null) && (userInfo.length() > 0));
+ }
+ if (withUserInfo.get()) {
+ return SVNURL.create(svnurl.getProtocol(), null, svnurl.getHost(), SvnUtil.resolvePort(svnurl), svnurl.getURIEncodedPath(), true)
+ .toString();
+ }
+ }
+ catch (SVNException e) {
+ //
+ }
+ return url;
+ }
+
+ @Nullable
+ private String getUserInfo(final String path) {
+ final SVNURL svnurl = myVcs.getSvnFileUrlMapping().getUrlForFile(new File(path));
+ return svnurl != null ? svnurl.getUserInfo() : null;
+ }
+
+ private static String deserializeUrl(final String url, final String userInfo) {
+ try {
+ final SVNURL svnurl = SVNURL.parseURIEncoded(url);
+ return SVNURL.create(svnurl.getProtocol(), userInfo, svnurl.getHost(), SvnUtil.resolvePort(svnurl), svnurl.getURIEncodedPath(),
+ true).toString();
+ } catch (SVNException e) {
+ return url;
+ }
+ }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnCheckinEnvironment.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnCheckinEnvironment.java
index c9a843501253..3f43d7452b5e 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnCheckinEnvironment.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnCheckinEnvironment.java
@@ -124,7 +124,7 @@ public class SvnCheckinEnvironment implements CheckinEnvironment {
String comment,
List<VcsException> exception,
final Set<String> feedback,
- final WorkingCopyFormat format)
+ @NotNull WorkingCopyFormat format)
throws VcsException {
if (committables.isEmpty()) {
return;
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/UpdateOutputLineConverter.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/UpdateOutputLineConverter.java
index 602a6e8c460e..cfb4a935bc14 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/UpdateOutputLineConverter.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/UpdateOutputLineConverter.java
@@ -16,6 +16,9 @@
package org.jetbrains.idea.svn.commandLine;
import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.Stack;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.SvnUtil;
import org.jetbrains.idea.svn.api.EventAction;
@@ -43,17 +46,13 @@ public class UpdateOutputLineConverter {
private final static String RECORDING_MERGE_INFO = "--- Recording mergeinfo";
private final static String UPDATING = "Updating";
- private final static String AT_REVISION = "At revision (\\d+)\\.";
- private final static String UPDATED_TO_REVISION = "Updated to revision (\\d+)\\.";
private final static String SKIPPED = "Skipped";
private final static String RESTORED = "Restored";
private final static String FETCHING_EXTERNAL = "Fetching external";
- private final static String EXTERNAL = "External at (\\d+)\\.";
- private final static String UPDATED_EXTERNAL = "Updated external to revision (\\d+)\\.";
-
- private final static Pattern ourAtRevision = Pattern.compile(AT_REVISION);
- private final static Pattern ourUpdatedToRevision = Pattern.compile(UPDATED_TO_REVISION);
+
+ private final static Pattern ourAtRevision = Pattern.compile("At revision (\\d+)\\.");
+ private final static Pattern ourUpdatedToRevision = Pattern.compile("Updated to revision (\\d+)\\.");
private final static Pattern ourCheckedOutRevision = Pattern.compile("Checked out revision (\\d+)\\.");
// export from repository
@@ -61,8 +60,8 @@ public class UpdateOutputLineConverter {
// export from working copy
private final static Pattern ourExportComplete = Pattern.compile("Export complete\\.");
- private final static Pattern ourExternal = Pattern.compile(EXTERNAL);
- private final static Pattern ourUpdatedExternal = Pattern.compile(UPDATED_EXTERNAL);
+ private final static Pattern ourExternal = Pattern.compile("External at (\\d+)\\.");
+ private final static Pattern ourUpdatedExternal = Pattern.compile("Updated external to revision (\\d+)\\.");
private final static Pattern ourCheckedOutExternal = Pattern.compile("Checked out external at revision (\\d+)\\.");
private final static Pattern[] ourCompletePatterns =
@@ -70,15 +69,14 @@ public class UpdateOutputLineConverter {
ourCheckedOutExternal, ourExportComplete};
private final File myBase;
- private File myCurrentFile;
+ @NotNull private final Stack<File> myRootsUnderProcessing;
public UpdateOutputLineConverter(File base) {
myBase = base;
- // checkout output does not have special line like "Updating '.'" on start - so set current file directly
- // to correctly detect complete event
- myCurrentFile = base;
+ myRootsUnderProcessing = ContainerUtil.newStack();
}
+ @Nullable
public ProgressEvent convert(final String line) {
// TODO: Add direct processing of "Summary of conflicts" lines at the end of "svn update" output (if there are conflicts).
// TODO: Now it works ok because parseNormalLine could not determine necessary statuses from that and further lines
@@ -87,35 +85,45 @@ public class UpdateOutputLineConverter {
if (line.startsWith(MERGING) || line.startsWith(RECORDING_MERGE_INFO)) {
return null;
} else if (line.startsWith(UPDATING)) {
- myCurrentFile = parseForPath(line);
- return new ProgressEvent(myCurrentFile, -1, null, null, EventAction.UPDATE_NONE, null, null);
+ myRootsUnderProcessing.push(parseForPath(line));
+ return createEvent(myRootsUnderProcessing.peek(), EventAction.UPDATE_NONE);
} else if (line.startsWith(RESTORED)) {
- myCurrentFile = parseForPath(line);
- return new ProgressEvent(myCurrentFile, -1, null, null, EventAction.RESTORE, null, null);
+ return createEvent(parseForPath(line), EventAction.RESTORE);
} else if (line.startsWith(SKIPPED)) {
// called, for instance, when folder is not working copy
- myCurrentFile = parseForPath(line);
final String comment = parseComment(line);
- return new ProgressEvent(myCurrentFile, -1, null, null, EventAction.SKIP,
- comment == null ? null : SVNErrorMessage.create(SVNErrorCode.WC_OBSTRUCTED_UPDATE, comment), null);
+ return createEvent(parseForPath(line), -1, EventAction.SKIP,
+ comment == null ? null : SVNErrorMessage.create(SVNErrorCode.WC_OBSTRUCTED_UPDATE, comment));
} else if (line.startsWith(FETCHING_EXTERNAL)) {
- myCurrentFile = parseForPath(line);
- return new ProgressEvent(myCurrentFile, -1, null, null, EventAction.UPDATE_EXTERNAL, null, null);
+ myRootsUnderProcessing.push(parseForPath(line));
+ return createEvent(myRootsUnderProcessing.peek(), EventAction.UPDATE_EXTERNAL);
}
- for (int i = 0; i < ourCompletePatterns.length; i++) {
- final Pattern pattern = ourCompletePatterns[i];
+ for (final Pattern pattern : ourCompletePatterns) {
final long revision = matchAndGetRevision(pattern, line);
if (revision != -1) {
- // TODO: seems that myCurrentFile will not always be correct - complete update message could be right after complete externals update
- // TODO: check this and use Stack instead
- return new ProgressEvent(myCurrentFile, revision, null, null, EventAction.UPDATE_COMPLETED, null, null);
+ // checkout output does not have special line like "Updating '.'" on start - so stack could be empty and we should use myBase
+ File currentRoot = myRootsUnderProcessing.size() > 0 ? myRootsUnderProcessing.pop() : myBase;
+ return createEvent(currentRoot, revision, EventAction.UPDATE_COMPLETED, null);
}
}
return parseNormalString(line);
}
+ @NotNull
+ private static ProgressEvent createEvent(File file, @NotNull EventAction action) {
+ return createEvent(file, -1, action, null);
+ }
+
+ @NotNull
+ private static ProgressEvent createEvent(File file,
+ long revision,
+ @NotNull EventAction action,
+ @Nullable SVNErrorMessage error) {
+ return new ProgressEvent(file, revision, null, null, action, error, null);
+ }
+
private final static Set<Character> ourActions = new HashSet<Character>(Arrays.asList(new Character[] {'A', 'D', 'U', 'C', 'G', 'E', 'R'}));
@Nullable
@@ -134,7 +142,7 @@ public class UpdateOutputLineConverter {
final String path = line.substring(4).trim();
if (StringUtil.isEmptyOrSpaces(path)) return null;
- final File file = createFile(path);
+ final File file = SvnUtil.resolvePath(myBase, path);
if (StatusType.STATUS_OBSTRUCTED.equals(contentsStatus)) {
// obstructed
return new ProgressEvent(file, -1, contentsStatus, propertiesStatus, EventAction.UPDATE_SKIP_OBSTRUCTION, null, null);
@@ -157,12 +165,7 @@ public class UpdateOutputLineConverter {
return new ProgressEvent(file, -1, contentsStatus, propertiesStatus, action, null, null);
}
- private File createFile(String path) {
- return SvnUtil.resolvePath(myBase, path);
- }
-
- @Nullable
- private long matchAndGetRevision(final Pattern pattern, final String line) {
+ private static long matchAndGetRevision(final Pattern pattern, final String line) {
final Matcher matcher = pattern.matcher(line);
if (matcher.matches()) {
if (pattern == ourExportComplete) {
@@ -181,22 +184,26 @@ public class UpdateOutputLineConverter {
}
@Nullable
- private String parseComment(final String line) {
- final int idx = line.lastIndexOf("--");
- if (idx != -1 && idx < (line.length() - 2)) {
- return line.substring(idx + 2).trim();
- }
- return null;
+ private static String parseComment(final String line) {
+ int index = line.lastIndexOf("--");
+
+ return index != -1 && index < line.length() - 2 ? line.substring(index + 2).trim() : null;
}
@Nullable
- private File parseForPath(final String line) {
- final int idx1 = line.indexOf('\'');
- if (idx1 == -1) return null;
- final int idx2 = line.indexOf('\'', idx1 + 1);
- if (idx2 == -1) return null;
- final String substring = line.substring(idx1 + 1, idx2);
- if (".".equals(substring)) return myBase;
- return createFile(substring);
+ private File parseForPath(@NotNull String line) {
+ File result = null;
+ int start = line.indexOf('\'');
+
+ if (start != -1) {
+ int end = line.indexOf('\'', start + 1);
+
+ if (end != -1) {
+ String path = line.substring(start + 1, end);
+ result = SvnUtil.resolvePath(myBase, path);
+ }
+ }
+
+ return result;
}
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/CopiesPanel.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/CopiesPanel.java
index 9ca5b89d517a..1b48f9d70e5b 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/CopiesPanel.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/CopiesPanel.java
@@ -45,7 +45,8 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.*;
import org.jetbrains.idea.svn.actions.CleanupWorker;
-import org.jetbrains.idea.svn.actions.SelectBranchPopup;
+import org.jetbrains.idea.svn.branchConfig.BranchConfigurationDialog;
+import org.jetbrains.idea.svn.branchConfig.SelectBranchPopup;
import org.jetbrains.idea.svn.api.ClientFactory;
import org.jetbrains.idea.svn.api.Depth;
import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew;
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 cd504be56077..437e7f57e464 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/PropertiesComponent.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/PropertiesComponent.java
@@ -41,7 +41,6 @@ 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;
@@ -309,7 +308,7 @@ public class PropertiesComponent extends JPanel {
PropertyValue propValue = null;
try {
propValue = myVcs.getFactory(myFile).createPropertyClient()
- .getProperty(SvnTarget.fromFile(myFile), SVNProperty.KEYWORDS, false, SVNRevision.WORKING);
+ .getProperty(SvnTarget.fromFile(myFile), SvnPropertyKeys.SVN_KEYWORDS, false, SVNRevision.WORKING);
}
catch (VcsException e1) {
// show erorr message
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 163be4922224..f7e54a64f0ad 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserComponent.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserComponent.java
@@ -266,7 +266,7 @@ public class RepositoryBrowserComponent extends JPanel implements Disposable, Da
if (entry.getName().lastIndexOf('.') > 0 && !manager.getFileTypeByFileName(name).isBinary()) {
SVNURL url = node.getURL();
final SvnFileRevision revision = new SvnFileRevision(myVCS, SVNRevision.UNDEFINED, SVNRevision.HEAD, url.toString(),
- entry.getAuthor(), entry.getDate(), null, null, null);
+ entry.getAuthor(), entry.getDate(), null, null);
return new VcsVirtualFile(node.getSVNDirEntry().getName(), revision, VcsFileSystem.getInstance());
} else {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CompareWithBranchAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CompareWithBranchAction.java
index a8e0ca9e5e7a..278c7d0b5e1c 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CompareWithBranchAction.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CompareWithBranchAction.java
@@ -26,7 +26,7 @@ import com.intellij.openapi.vcs.FileStatusManager;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.svn.*;
-import org.jetbrains.idea.svn.actions.SelectBranchPopup;
+import org.jetbrains.idea.svn.branchConfig.SelectBranchPopup;
import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew;
/**
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/LoadedRevisionsCache.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/LoadedRevisionsCache.java
index 5da830f0ca87..7e1c9d155a0e 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/LoadedRevisionsCache.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/LoadedRevisionsCache.java
@@ -22,13 +22,13 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.vcs.RepositoryLocation;
-import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.changes.committed.ChangesBunch;
+import com.intellij.openapi.vcs.changes.committed.CommittedChangesAdapter;
import com.intellij.openapi.vcs.changes.committed.CommittedChangesCache;
-import com.intellij.openapi.vcs.changes.committed.CommittedChangesListener;
import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
import com.intellij.util.containers.SoftHashMap;
import com.intellij.util.messages.MessageBusConnection;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
@@ -51,7 +51,9 @@ public class LoadedRevisionsCache implements Disposable {
myMap = (ApplicationManager.getApplication().isUnitTestMode()) ? new HashMap<String, Bunch>() : new SoftHashMap<String, Bunch>();
myConnection = project.getMessageBus().connect();
- myConnection.subscribe(CommittedChangesCache.COMMITTED_TOPIC, new CommittedChangesListener() {
+ myConnection.subscribe(CommittedChangesCache.COMMITTED_TOPIC, new CommittedChangesAdapter() {
+
+ @Override
public void changesLoaded(final RepositoryLocation location, final List<CommittedChangeList> changes) {
ApplicationManager.getApplication().invokeLater(new Runnable() {
public void run() {
@@ -60,20 +62,6 @@ public class LoadedRevisionsCache implements Disposable {
}
});
}
-
- @Override
- public void changesCleared() {
- }
-
- @Override
- public void presentationChanged() {
- }
-
- public void incomingChangesUpdated(@Nullable final List<CommittedChangeList> receivedChanges) {
- }
-
- public void refreshErrorStatusChanged(@Nullable final VcsException lastError) {
- }
});
Disposer.register(myProject, this);
setRefreshTime(0);
@@ -90,18 +78,20 @@ public class LoadedRevisionsCache implements Disposable {
myRefreshTime = refreshTime;
}
}
-
- private void debugInfo(final List<CommittedChangeList> data, final boolean consistentWithPrevious, final Bunch bindTo) {
+
+ private static void debugInfo(@NotNull List<CommittedChangeList> data, final boolean consistentWithPrevious, final Bunch bindTo) {
LOG.debug(">>> cache internal >>> consistent: " + consistentWithPrevious + " bindTo: " + bindTo +
" oldest list: " + data.get(data.size() - 1).getNumber() + ", youngest list: " + data.get(0).getNumber());
}
public void dispose() {
+ // TODO: Seems that dispose could be removed as connection will be disposed anyway on project dispose and clearing map is not necessary
myConnection.disconnect();
myMap.clear();
}
- private List<List<CommittedChangeList>> split(final List<CommittedChangeList> list, final int size) {
+ @NotNull
+ private static List<List<CommittedChangeList>> split(final List<CommittedChangeList> list, final int size) {
final int listSize = list.size();
if (listSize < size) {
return Collections.singletonList(list);
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCommittedChangesProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCommittedChangesProvider.java
index 83642894711e..4712a080ad36 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCommittedChangesProvider.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCommittedChangesProvider.java
@@ -48,7 +48,7 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.SvnBundle;
import org.jetbrains.idea.svn.SvnUtil;
import org.jetbrains.idea.svn.SvnVcs;
-import org.jetbrains.idea.svn.actions.ConfigureBranchesAction;
+import org.jetbrains.idea.svn.branchConfig.ConfigureBranchesAction;
import org.jetbrains.idea.svn.api.Depth;
import org.jetbrains.idea.svn.commandLine.SvnBindException;
import org.jetbrains.idea.svn.status.Status;
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnFileRevision.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnFileRevision.java
index 007df92a403b..e636c9c0a8ef 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnFileRevision.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnFileRevision.java
@@ -22,10 +22,10 @@ import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.util.Throwable2Computable;
import com.intellij.openapi.vcs.RepositoryLocation;
import com.intellij.openapi.vcs.VcsException;
-import com.intellij.openapi.vcs.actions.VcsContextFactory;
import com.intellij.openapi.vcs.history.VcsFileRevision;
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
import com.intellij.openapi.vcs.impl.ContentRevisionCache;
+import com.intellij.vcsUtil.VcsUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.SvnBundle;
@@ -37,7 +37,6 @@ import org.tmatesoft.svn.core.wc.SVNRevision;
import org.tmatesoft.svn.core.wc2.SvnTarget;
import java.io.IOException;
-import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@@ -55,7 +54,6 @@ public class SvnFileRevision implements VcsFileRevision {
private final SVNRevision myRevision;
private final String myCopyFromPath;
private final List<SvnFileRevision> myMergeSources;
- private final Charset myCharset;
public SvnFileRevision(SvnVcs vcs,
SVNRevision pegRevision,
@@ -64,8 +62,7 @@ public class SvnFileRevision implements VcsFileRevision {
String author,
Date date,
String commitMessage,
- String copyFromPath, Charset charset) {
- myCharset = charset;
+ String copyFromPath) {
myRevisionNumber = new SvnRevisionNumber(revision);
myPegRevision = pegRevision;
myRevision = revision;
@@ -82,8 +79,7 @@ public class SvnFileRevision implements VcsFileRevision {
SVNRevision pegRevision,
LogEntry logEntry,
String url,
- String copyFromPath, Charset charset) {
- myCharset = charset;
+ String copyFromPath) {
final SVNRevision revision = SVNRevision.create(logEntry.getRevision());
myRevisionNumber = new SvnRevisionNumber(revision);
myPegRevision = pegRevision;
@@ -155,30 +151,37 @@ public class SvnFileRevision implements VcsFileRevision {
else {
loader.run();
}
- if (loader.getException() == null) {
+
+ VcsException exception = loader.getException();
+ if (exception == null) {
final byte[] contents = loader.getContents();
ContentRevisionCache.checkContentsSize(myURL, contents.length);
return contents;
}
else {
- final VcsException vcsException = loader.getException();
- LOG.info("Failed to load file '" + myURL + "' content at revision: " + myRevision + "\n" + vcsException.getMessage(), vcsException);
- throw vcsException;
+ LOG.info("Failed to load file '" + myURL + "' content at revision: " + myRevision + "\n" + exception.getMessage(), exception);
+ throw exception;
}
}
public byte[] getContent() throws IOException, VcsException {
- return ContentRevisionCache.getOrLoadAsBytes(myVCS.getProject(), VcsContextFactory.SERVICE.getInstance()
- .createFilePathOnNonLocal(myURL, false),
- getRevisionNumber(), myVCS.getKeyInstanceMethod(), ContentRevisionCache.UniqueType.REMOTE_CONTENT,
- new Throwable2Computable<byte[], VcsException, IOException>() {
- @Override
- public byte[] compute() throws VcsException, IOException {
- byte[] bytes = loadContent();
- return bytes;
- //return SvnUtil.decode(myCharset, bytes);
- }
- });
+ byte[] result;
+
+ if (SVNRevision.HEAD.equals(myRevision)) {
+ result = loadContent();
+ }
+ else {
+ result = ContentRevisionCache.getOrLoadAsBytes(myVCS.getProject(), VcsUtil.getFilePathOnNonLocal(myURL, false), getRevisionNumber(),
+ myVCS.getKeyInstanceMethod(), ContentRevisionCache.UniqueType.REMOTE_CONTENT,
+ new Throwable2Computable<byte[], VcsException, IOException>() {
+ @Override
+ public byte[] compute() throws VcsException, IOException {
+ return loadContent();
+ }
+ });
+ }
+
+ return result;
}
public String getCopyFromPath() {
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 b23b57772535..2ff19fcc56e6 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java
@@ -614,7 +614,7 @@ public class SvnHistoryProvider
final SVNURL url = myRepositoryRoot.appendPath(myLastPath, true);
// final SVNURL url = entryPath != null ? myRepositoryRoot.appendPath(entryPath.getPath(), true) :
// myRepositoryRoot.appendPath(myLastPathCorrector.getBefore(), false);
- return new SvnFileRevision(myVcs, myPegRevision, rev, url.toString(), author, date, message, copyPath, myCharset);
+ return new SvnFileRevision(myVcs, myPegRevision, rev, url.toString(), author, date, message, copyPath);
}
}
@@ -633,7 +633,7 @@ public class SvnHistoryProvider
throws SVNException {
final SVNURL url = entryPath == null ? myRepositoryRoot.appendPath(myLastPathCorrector.getBefore(), false) :
myRepositoryRoot.appendPath(entryPath.getPath(), true);
- return new SvnFileRevision(myVcs, SVNRevision.UNDEFINED, logEntry, url.toString(), copyPath, null);
+ return new SvnFileRevision(myVcs, SVNRevision.UNDEFINED, logEntry, url.toString(), copyPath);
}
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnMergeInfoRootPanelManual.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnMergeInfoRootPanelManual.java
index c6ed3c59a5c7..d4b48281f7ca 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnMergeInfoRootPanelManual.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnMergeInfoRootPanelManual.java
@@ -24,10 +24,10 @@ import com.intellij.util.NullableFunction;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import org.jetbrains.idea.svn.SvnBranchMapperManager;
+import org.jetbrains.idea.svn.branchConfig.SvnBranchMapperManager;
import org.jetbrains.idea.svn.SvnBundle;
import org.jetbrains.idea.svn.SvnUtil;
-import org.jetbrains.idea.svn.actions.SelectBranchPopup;
+import org.jetbrains.idea.svn.branchConfig.SelectBranchPopup;
import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew;
import org.jetbrains.idea.svn.dialogs.WCInfoWithBranches;
import org.jetbrains.idea.svn.integrate.IntegratedSelectedOptionsDialog;
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/WcInfoLoader.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/WcInfoLoader.java
index e0ab6ff02ae5..bbac377776b8 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/WcInfoLoader.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/WcInfoLoader.java
@@ -23,10 +23,11 @@ import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.*;
+import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationManager;
import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew;
import org.jetbrains.idea.svn.dialogs.WCInfo;
import org.jetbrains.idea.svn.dialogs.WCInfoWithBranches;
-import org.jetbrains.idea.svn.integrate.SvnBranchItem;
+import org.jetbrains.idea.svn.branchConfig.SvnBranchItem;
import org.tmatesoft.svn.core.internal.util.SVNPathUtil;
import java.io.File;
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/info/Info.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/info/Info.java
index 96dbdbbcbc99..71fb0a9ec51f 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/info/Info.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/info/Info.java
@@ -35,6 +35,8 @@ import java.util.Date;
*/
public class Info extends BaseNodeDescription {
+ public static final String SCHEDULE_ADD = "add";
+
private final File myFile;
private final String myPath;
private final SVNURL myURL;
@@ -49,10 +51,10 @@ public class Info extends BaseNodeDescription {
private final String mySchedule;
private final SVNURL myCopyFromURL;
private final SVNRevision myCopyFromRevision;
- private final File myConflictOldFile;
- private final File myConflictNewFile;
- private final File myConflictWrkFile;
- private final File myPropConflictFile;
+ @Nullable private final File myConflictOldFile;
+ @Nullable private final File myConflictNewFile;
+ @Nullable private final File myConflictWrkFile;
+ @Nullable private final File myPropConflictFile;
private final Depth myDepth;
@Nullable private final TreeConflictDescription myTreeConflict;
@@ -69,8 +71,8 @@ public class Info extends BaseNodeDescription {
result =
new Info(info.getFile(), info.getURL(), info.getRepositoryRootURL(), info.getRevision().getNumber(), NodeKind.from(info.getKind()),
info.getRepositoryUUID(), info.getCommittedRevision().getNumber(), toString(info.getCommittedDate()), info.getAuthor(),
- info.getSchedule(), info.getCopyFromURL(), info.getCopyFromRevision().getNumber(), getPath(info.getConflictOldFile()),
- getPath(info.getConflictNewFile()), getPath(info.getConflictWrkFile()), getPath(info.getPropConflictFile()),
+ info.getSchedule(), info.getCopyFromURL(), info.getCopyFromRevision().getNumber(), getName(info.getConflictOldFile()),
+ getName(info.getConflictNewFile()), getName(info.getConflictWrkFile()), getName(info.getPropConflictFile()),
Lock.create(info.getLock()), Depth.from(info.getDepth()), TreeConflictDescription.create(info.getTreeConflict()));
}
@@ -89,10 +91,10 @@ public class Info extends BaseNodeDescription {
String schedule,
SVNURL copyFromURL,
long copyFromRevision,
- String conflictOld,
- String conflictNew,
- String conflictWorking,
- String propRejectFile,
+ @Nullable String conflictOldFileName,
+ @Nullable String conflictNewFileName,
+ @Nullable String conflictWorkingFileName,
+ @Nullable String propRejectFileName,
@Nullable Lock lock,
Depth depth,
@Nullable TreeConflictDescription treeConflict) {
@@ -115,10 +117,10 @@ public class Info extends BaseNodeDescription {
myLock = lock;
myTreeConflict = treeConflict;
- myConflictOldFile = resolveConflictFile(file, conflictOld);
- myConflictNewFile = resolveConflictFile(file, conflictNew);
- myConflictWrkFile = resolveConflictFile(file, conflictWorking);
- myPropConflictFile = resolveConflictFile(file, propRejectFile);
+ myConflictOldFile = resolveConflictFile(file, conflictOldFileName);
+ myConflictNewFile = resolveConflictFile(file, conflictNewFileName);
+ myConflictWrkFile = resolveConflictFile(file, conflictWorkingFileName);
+ myPropConflictFile = resolveConflictFile(file, propRejectFileName);
myIsRemote = false;
myDepth = depth;
@@ -175,14 +177,17 @@ public class Info extends BaseNodeDescription {
return myCommittedRevision;
}
+ @Nullable
public File getConflictNewFile() {
return myConflictNewFile;
}
+ @Nullable
public File getConflictOldFile() {
return myConflictOldFile;
}
+ @Nullable
public File getConflictWrkFile() {
return myConflictWrkFile;
}
@@ -222,6 +227,7 @@ public class Info extends BaseNodeDescription {
return myPath;
}
+ @Nullable
public File getPropConflictFile() {
return myPropConflictFile;
}
@@ -256,8 +262,8 @@ public class Info extends BaseNodeDescription {
}
@Nullable
- private static String getPath(@Nullable File file) {
- return file != null ? file.getPath() : null;
+ private static String getName(@Nullable File file) {
+ return file != null ? file.getName() : null;
}
@Nullable
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/IntegratedSelectedOptionsDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/IntegratedSelectedOptionsDialog.java
index 3b2184c22484..7ff6e71ab75a 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/IntegratedSelectedOptionsDialog.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/IntegratedSelectedOptionsDialog.java
@@ -32,6 +32,7 @@ import com.intellij.util.PlatformIcons;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.*;
+import org.jetbrains.idea.svn.branchConfig.SvnBranchMapperManager;
import org.jetbrains.idea.svn.info.Info;
import org.tmatesoft.svn.core.SVNURL;
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SourceUrlCorrectionTask.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SourceUrlCorrectionTask.java
index 39d51de62943..99d4696ede3f 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SourceUrlCorrectionTask.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SourceUrlCorrectionTask.java
@@ -18,7 +18,7 @@ package org.jetbrains.idea.svn.integrate;
import com.intellij.util.continuation.ContinuationContext;
import com.intellij.util.continuation.Where;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.idea.svn.SvnBranchConfigurationManager;
+import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationManager;
import org.jetbrains.idea.svn.dialogs.MergeContext;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.internal.util.SVNPathUtil;
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SvnIntegrateChangesActionPerformer.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SvnIntegrateChangesActionPerformer.java
index e07fac011c9e..2ccd2242db10 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SvnIntegrateChangesActionPerformer.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SvnIntegrateChangesActionPerformer.java
@@ -23,7 +23,7 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.SvnBundle;
import org.jetbrains.idea.svn.SvnConfiguration;
import org.jetbrains.idea.svn.SvnVcs;
-import org.jetbrains.idea.svn.actions.SelectBranchPopup;
+import org.jetbrains.idea.svn.branchConfig.SelectBranchPopup;
import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNURL;
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SvnIntegrateChangesTask.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SvnIntegrateChangesTask.java
index 5dd6f24b10ba..0dd27d442ae5 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SvnIntegrateChangesTask.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SvnIntegrateChangesTask.java
@@ -19,7 +19,9 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
+import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.*;
import com.intellij.openapi.vcs.changes.Change;
@@ -28,6 +30,7 @@ import com.intellij.openapi.vcs.changes.InvokeAfterUpdateMode;
import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager;
import com.intellij.openapi.vcs.changes.ui.CommitChangeListDialog;
import com.intellij.openapi.vcs.ex.ProjectLevelVcsManagerEx;
+import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier;
import com.intellij.openapi.vcs.update.*;
import com.intellij.util.Consumer;
import org.jetbrains.annotations.NotNull;
@@ -330,18 +333,37 @@ public class SvnIntegrateChangesTask extends Task.Backgroundable {
});
}
- final SvnChangeProvider provider = new SvnChangeProvider(myVcs);
- final GatheringChangelistBuilder clb = new GatheringChangelistBuilder(myVcs, myAccomulatedFiles);
- try {
- provider.getChanges(dirtyScope, clb, ProgressManager.getInstance().getProgressIndicator(), null);
- } catch (VcsException e) {
- Messages.showErrorDialog(SvnBundle.message("action.Subversion.integrate.changes.error.unable.to.collect.changes.text",
- e.getMessage()), myTitle);
- return;
- }
+ new Task.Backgroundable(myVcs.getProject(),
+ SvnBundle.message("action.Subversion.integrate.changes.collecting.changes.to.commit.task.title")) {
- if (! clb.getChanges().isEmpty()) {
- CommitChangeListDialog.commitAlienChanges(myProject, clb.getChanges(), myVcs, myMerger.getComment(), myMerger.getComment());
- }
+ private final GatheringChangelistBuilder changesBuilder = new GatheringChangelistBuilder(myVcs, myAccomulatedFiles);
+ private final Ref<String> caughtError = new Ref<String>();
+
+ @Override
+ public void run(@NotNull ProgressIndicator indicator) {
+ indicator.setIndeterminate(true);
+ if (!myVcs.getProject().isDisposed()) {
+ final SvnChangeProvider provider = new SvnChangeProvider(myVcs);
+
+ try {
+ provider.getChanges(dirtyScope, changesBuilder, indicator, null);
+ }
+ catch (VcsException e) {
+ caughtError.set(SvnBundle.message("action.Subversion.integrate.changes.error.unable.to.collect.changes.text", e.getMessage()));
+ }
+ }
+ }
+
+ @Override
+ public void onSuccess() {
+ if (!caughtError.isNull()) {
+ VcsBalloonProblemNotifier.showOverVersionControlView(myVcs.getProject(), caughtError.get(), MessageType.ERROR);
+ }
+ else if (!changesBuilder.getChanges().isEmpty()) {
+ CommitChangeListDialog
+ .commitAlienChanges(myProject, changesBuilder.getChanges(), myVcs, myMerger.getComment(), myMerger.getComment());
+ }
+ }
+ }.queue();
}
}
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 701bb2575001..f69aac4a4133 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/BranchInfo.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/BranchInfo.java
@@ -19,11 +19,15 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.util.containers.MultiMap;
+import org.jetbrains.idea.svn.SvnPropertyKeys;
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.SVNException;
+import org.tmatesoft.svn.core.SVNMergeRange;
+import org.tmatesoft.svn.core.SVNMergeRangeList;
+import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.internal.util.SVNMergeInfoUtil;
import org.tmatesoft.svn.core.internal.util.SVNPathUtil;
import org.tmatesoft.svn.core.wc.SVNRevision;
@@ -209,7 +213,8 @@ public class BranchInfo {
SvnTarget target = SvnTarget.fromURL(branchUrl);
try {
- mergeinfoProperty = myVcs.getFactory(target).createPropertyClient().getProperty(target, SVNProperty.MERGE_INFO, false, SVNRevision.create(targetRevision));
+ mergeinfoProperty = myVcs.getFactory(target).createPropertyClient().getProperty(target, SvnPropertyKeys.MERGE_INFO, false,
+ SVNRevision.create(targetRevision));
}
catch (VcsException e) {
LOG.info(e);
@@ -283,13 +288,13 @@ public class BranchInfo {
// look in WC
SvnTarget target = SvnTarget.fromFile(pathFile, SVNRevision.WORKING);
mergeinfoProperty =
- myVcs.getFactory(target).createPropertyClient().getProperty(target, SVNProperty.MERGE_INFO, false, SVNRevision.WORKING);
+ myVcs.getFactory(target).createPropertyClient().getProperty(target, SvnPropertyKeys.MERGE_INFO, false, SVNRevision.WORKING);
} else {
// in repo
myMixedRevisionsFound = true;
SvnTarget target = SvnTarget.fromURL(svnInfo.getURL());
mergeinfoProperty = myVcs.getFactory(target).createPropertyClient()
- .getProperty(target, SVNProperty.MERGE_INFO, false, SVNRevision.create(targetRevisionCorrected));
+ .getProperty(target, SvnPropertyKeys.MERGE_INFO, false, SVNRevision.create(targetRevisionCorrected));
}
}
catch (VcsException 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 225bc6ad0396..b17d3317a801 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneRecursiveShotMergeInfoWorker.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneRecursiveShotMergeInfoWorker.java
@@ -21,12 +21,16 @@ import com.intellij.openapi.vcs.AreaMap;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.util.PairProcessor;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.idea.svn.SvnPropertyKeys;
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.SVNException;
+import org.tmatesoft.svn.core.SVNMergeRange;
+import org.tmatesoft.svn.core.SVNMergeRangeList;
+import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.internal.util.SVNMergeInfoUtil;
import org.tmatesoft.svn.core.internal.util.SVNPathUtil;
import org.tmatesoft.svn.core.wc.SVNRevision;
@@ -83,7 +87,7 @@ public class OneRecursiveShotMergeInfoWorker implements MergeInfoWorker {
File path = new File(myMergeContext.getWcInfo().getPath());
myMergeContext.getVcs().getFactory(path).createPropertyClient()
- .getProperty(SvnTarget.fromFile(path), SVNProperty.MERGE_INFO, SVNRevision.WORKING, depth, handler);
+ .getProperty(SvnTarget.fromFile(path), SvnPropertyKeys.MERGE_INFO, SVNRevision.WORKING, depth, handler);
}
public SvnMergeInfoCache.MergeCheckResult isMerged(final String relativeToRepoURLPath, final long revisionNumber) {
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 e053776d14ce..f00c4bd7341d 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/CmdPropertyClient.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/CmdPropertyClient.java
@@ -1,5 +1,7 @@
package org.jetbrains.idea.svn.properties;
+import com.intellij.openapi.diagnostic.Attachment;
+import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.vcs.VcsException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -30,6 +32,8 @@ import java.util.Map;
*/
public class CmdPropertyClient extends BaseSvnClient implements PropertyClient {
+ private static final Logger LOG = Logger.getInstance(CmdPropertyClient.class);
+
@Nullable
@Override
public PropertyValue getProperty(@NotNull SvnTarget target,
@@ -57,7 +61,7 @@ public class CmdPropertyClient extends BaseSvnClient implements PropertyClient {
parameters.add("--xml");
CommandExecutor command = execute(myVcs, target, SvnCommandName.propget, parameters, null);
- PropertyData data = parseSingleProperty(target, command.getOutput());
+ PropertyData data = parseSingleProperty(target, command);
return data != null ? data.getValue() : null;
}
@@ -74,7 +78,7 @@ public class CmdPropertyClient extends BaseSvnClient implements PropertyClient {
fillListParameters(target, revision, depth, parameters, false);
CommandExecutor command = execute(myVcs, target, SvnCommandName.propget, parameters, null);
- parseOutput(target, command.getOutput(), handler);
+ parseOutput(target, command, handler);
}
@Override
@@ -86,7 +90,7 @@ public class CmdPropertyClient extends BaseSvnClient implements PropertyClient {
fillListParameters(target, revision, depth, parameters, true);
CommandExecutor command = execute(myVcs, target, SvnCommandName.proplist, parameters, null);
- parseOutput(target, command.getOutput(), handler);
+ parseOutput(target, command, handler);
}
@Override
@@ -183,7 +187,7 @@ public class CmdPropertyClient extends BaseSvnClient implements PropertyClient {
}
@Nullable
- private PropertyData parseSingleProperty(SvnTarget target, String output) throws VcsException {
+ private PropertyData parseSingleProperty(SvnTarget target, @NotNull CommandExecutor command) throws VcsException {
final PropertyData[] data = new PropertyData[1];
PropertyConsumer handler = new PropertyConsumer() {
@Override
@@ -202,14 +206,14 @@ public class CmdPropertyClient extends BaseSvnClient implements PropertyClient {
}
};
- parseOutput(target, output, handler);
+ parseOutput(target, command, handler);
return data[0];
}
- private static void parseOutput(SvnTarget target, String output, PropertyConsumer handler) throws VcsException {
+ private static void parseOutput(SvnTarget target, @NotNull CommandExecutor command, PropertyConsumer handler) throws VcsException {
try {
- Properties properties = CommandUtil.parse(output, Properties.class);
+ Properties properties = CommandUtil.parse(command.getOutput(), Properties.class);
if (properties != null) {
for (Target childInfo : properties.targets) {
@@ -227,6 +231,8 @@ public class CmdPropertyClient extends BaseSvnClient implements PropertyClient {
}
}
catch (JAXBException e) {
+ LOG.error("Could not parse properties. Command: " + command.getCommandText() + ", Warning: " + command.getErrorOutput(),
+ new Attachment("output.xml", command.getOutput()));
throw new VcsException(e);
}
catch (SVNException e) {
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 7b09461b3766..16904b673b5f 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/rollback/SvnRollbackEnvironment.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/rollback/SvnRollbackEnvironment.java
@@ -37,8 +37,10 @@ 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.SVNErrorCode;
+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;
import java.io.File;
@@ -312,7 +314,7 @@ public class SvnRollbackEnvironment extends DefaultRollbackEnvironment {
if (info.isFile()) {
doRevert(file, false);
} else {
- if (SVNProperty.SCHEDULE_ADD.equals(info.getSchedule())) {
+ if (Info.SCHEDULE_ADD.equals(info.getSchedule())) {
doRevert(file, true);
} else {
boolean is17OrGreater = is17OrGreaterCopy(file, info);
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/status/CmdStatusClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/status/CmdStatusClient.java
index 4030c83005ea..8100d73da220 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/status/CmdStatusClient.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/status/CmdStatusClient.java
@@ -103,6 +103,7 @@ public class CmdStatusClient extends BaseSvnClient implements StatusClient {
// so it does not contain any <entry> element and current parsing logic returns null
PortableStatus status = new PortableStatus();
+ status.setFile(path);
status.setPath(path.getAbsolutePath());
status.setContentsStatus(StatusType.STATUS_NORMAL);
status.setInfoGetter(new Getter<Info>() {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/AbstractSvnUpdateIntegrateEnvironment.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/AbstractSvnUpdateIntegrateEnvironment.java
index b4e788c75260..ef3529aec092 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/AbstractSvnUpdateIntegrateEnvironment.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/AbstractSvnUpdateIntegrateEnvironment.java
@@ -46,7 +46,6 @@ public abstract class AbstractSvnUpdateIntegrateEnvironment implements UpdateEnv
protected final SvnVcs myVcs;
private final ProjectLevelVcsManager myVcsManager;
@NonNls public static final String REPLACED_ID = "replaced";
- @NonNls public static final String EXTERNAL_ID = "external";
protected AbstractSvnUpdateIntegrateEnvironment(final SvnVcs vcs) {
myVcs = vcs;
@@ -145,6 +144,7 @@ public abstract class AbstractSvnUpdateIntegrateEnvironment implements UpdateEnv
}
public void onRefreshFilesCompleted() {
+ // TODO: why do we need to mark all roots as dirty here???
dirtyRoots();
for (Runnable groupWorker : myGroupWorkers) {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateEnvironment.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateEnvironment.java
index 554b2c29bc48..41bfd61fded1 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateEnvironment.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateEnvironment.java
@@ -89,8 +89,6 @@ public class SvnUpdateEnvironment extends AbstractSvnUpdateIntegrateEnvironment
rev = updateClient.doUpdate(root, updateTo, configuration.getUpdateDepth(), configuration.isForceUpdate(), false);
}
- myPostUpdateFiles.setRevisions(root.getAbsolutePath(), myVcs, new SvnRevisionNumber(SVNRevision.create(rev)));
-
return rev;
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateRootOptionsPanel.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateRootOptionsPanel.java
index d232fdc3037f..9103c845ae75 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateRootOptionsPanel.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateRootOptionsPanel.java
@@ -22,7 +22,7 @@ import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.openapi.vcs.FilePath;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.*;
-import org.jetbrains.idea.svn.actions.SelectBranchPopup;
+import org.jetbrains.idea.svn.branchConfig.SelectBranchPopup;
import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew;
import org.jetbrains.idea.svn.dialogs.SelectLocationDialog;
import org.jetbrains.idea.svn.history.SvnChangeList;
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/UpdateEventHandler.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/UpdateEventHandler.java
index fc552dbd1655..aff94e123a31 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/UpdateEventHandler.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/UpdateEventHandler.java
@@ -16,10 +16,13 @@
package org.jetbrains.idea.svn.update;
import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vcs.VcsBundle;
import com.intellij.openapi.vcs.update.FileGroup;
import com.intellij.openapi.vcs.update.UpdatedFiles;
import com.intellij.openapi.wm.StatusBar;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.Stack;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.SvnBundle;
import org.jetbrains.idea.svn.SvnFileUrlMapping;
@@ -32,11 +35,12 @@ import org.jetbrains.idea.svn.status.StatusType;
import org.tmatesoft.svn.core.SVNCancelException;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.internal.wc.SVNErrorManager;
-import org.tmatesoft.svn.core.wc.*;
+import org.tmatesoft.svn.core.wc.SVNRevision;
import org.tmatesoft.svn.util.SVNLogType;
import java.io.File;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
/**
@@ -49,6 +53,10 @@ public class UpdateEventHandler implements ProgressTracker {
private final SvnVcs myVCS;
@Nullable private final SvnUpdateContext mySequentialUpdatesContext;
private final Map<File, SVNURL> myUrlToCheckForSwitch;
+ // pair.first - group id, pair.second - file path
+ // Stack is used to correctly handle cases when updates of externals occur during ordinary update, because these inner updates could have
+ // its own revisions.
+ private final Stack<List<Pair<String, String>>> myFilesWaitingForRevision;
protected String myText;
protected String myText2;
@@ -60,6 +68,11 @@ public class UpdateEventHandler implements ProgressTracker {
mySequentialUpdatesContext = sequentialUpdatesContext;
myExternalsCount = 1;
myUrlToCheckForSwitch = new HashMap<File, SVNURL>();
+ myFilesWaitingForRevision = ContainerUtil.newStack();
+ // It is more suitable to make this push while handling UPDATE_NONE event - for command line like "svn update <folder>" this event will
+ // be fired when update of <folder> is started. But it's not clear if this event won't be fired in other cases by SVNKit. So currently
+ // first push is made here. If further we want to support commands like "svn update <folder1> <folder2>" this logic should be revised.
+ myFilesWaitingForRevision.push(ContainerUtil.<Pair<String, String>>newArrayList());
}
public void addToSwitch(final File file, final SVNURL url) {
@@ -153,13 +166,8 @@ public class UpdateEventHandler implements ProgressTracker {
if (mySequentialUpdatesContext != null) {
mySequentialUpdatesContext.registerExternalRootBeingUpdated(event.getFile());
}
+ myFilesWaitingForRevision.push(ContainerUtil.<Pair<String, String>>newArrayList());
myExternalsCount++;
- if (myUpdatedFiles.getGroupById(AbstractSvnUpdateIntegrateEnvironment.EXTERNAL_ID) == null) {
- myUpdatedFiles.registerGroup(new FileGroup(SvnBundle.message("status.group.name.externals"),
- SvnBundle.message("status.group.name.externals"),
- false, AbstractSvnUpdateIntegrateEnvironment.EXTERNAL_ID, true));
- }
- addFileToGroup(AbstractSvnUpdateIntegrateEnvironment.EXTERNAL_ID, event);
myText = SvnBundle.message("progress.text.updating.external.location", event.getFile().getAbsolutePath());
}
else if (event.getAction() == EventAction.RESTORE) {
@@ -168,6 +176,7 @@ public class UpdateEventHandler implements ProgressTracker {
}
else if (event.getAction() == EventAction.UPDATE_COMPLETED && event.getRevision() >= 0) {
possiblySwitched(event);
+ setRevisionForWaitingFiles(event.getRevision());
myExternalsCount--;
myText2 = SvnBundle.message("progres.text2.updated.to.revision", event.getRevision());
if (myExternalsCount == 0) {
@@ -218,12 +227,22 @@ public class UpdateEventHandler implements ProgressTracker {
protected void addFileToGroup(final String id, final ProgressEvent event) {
final FileGroup fileGroup = myUpdatedFiles.getGroupById(id);
final String path = event.getFile().getAbsolutePath();
- fileGroup.add(path, SvnVcs.getKey(), new SvnRevisionNumber(SVNRevision.create(event.getRevision())));
+ myFilesWaitingForRevision.peek().add(Pair.create(id, path));
if (event.getErrorMessage() != null) {
fileGroup.addError(path, event.getErrorMessage().getMessage());
}
}
+ private void setRevisionForWaitingFiles(long revisionNumber) {
+ SvnRevisionNumber revision = new SvnRevisionNumber(SVNRevision.create(revisionNumber));
+
+ for (Pair<String, String> pair : myFilesWaitingForRevision.pop()) {
+ FileGroup fileGroup = myUpdatedFiles.getGroupById(pair.getFirst());
+
+ fileGroup.add(pair.getSecond(), SvnVcs.getKey(), revision);
+ }
+ }
+
public void checkCancelled() throws SVNCancelException {
if (myProgressIndicator != null) {
myProgressIndicator.checkCanceled();
diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/SvnTestCase.java b/plugins/svn4idea/testSource/org/jetbrains/idea/SvnTestCase.java
index 17ae6b5ce551..364906460fe6 100644
--- a/plugins/svn4idea/testSource/org/jetbrains/idea/SvnTestCase.java
+++ b/plugins/svn4idea/testSource/org/jetbrains/idea/SvnTestCase.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,10 +17,7 @@ package org.jetbrains.idea;
import com.intellij.execution.process.ProcessOutput;
import com.intellij.ide.startup.impl.StartupManagerImpl;
-import com.intellij.openapi.actionSystem.AnActionEvent;
-import com.intellij.openapi.actionSystem.CommonDataKeys;
-import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.actionSystem.Presentation;
+import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.application.PluginPathManager;
@@ -506,7 +503,7 @@ public abstract class SvnTestCase extends AbstractJunitVcsTestCase {
}
return null;
}
- }, "test", new Presentation(), null, 0));
+ }, "test", new Presentation(), ActionManager.getInstance(), 0));
final ChangeListManager clManager = ChangeListManager.getInstance(project);
clManager.ensureUpToDate(false);
diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnAnnotationIsClosedTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnAnnotationIsClosedTest.java
index f29b5d0bc45b..73000a14880e 100644
--- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnAnnotationIsClosedTest.java
+++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnAnnotationIsClosedTest.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,10 +15,7 @@
*/
package org.jetbrains.idea.svn;
-import com.intellij.openapi.actionSystem.AnActionEvent;
-import com.intellij.openapi.actionSystem.CommonDataKeys;
-import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.actionSystem.Presentation;
+import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
import com.intellij.openapi.vcs.VcsConfiguration;
import com.intellij.openapi.vcs.VcsException;
@@ -144,7 +141,7 @@ public class SvnAnnotationIsClosedTest extends Svn17TestCase {
}
return null;
}
- }, "test", new Presentation(), null, 0));
+ }, "test", new Presentation(), ActionManager.getInstance(), 0));
myChangeListManager.ensureUpToDate(false);
myChangeListManager.ensureUpToDate(false); // wait for after-events like annotations recalculation
@@ -191,7 +188,7 @@ public class SvnAnnotationIsClosedTest extends Svn17TestCase {
}
return null;
}
- }, "test", new Presentation(), null, 0));
+ }, "test", new Presentation(), ActionManager.getInstance(), 0));
myChangeListManager.ensureUpToDate(false);
myChangeListManager.ensureUpToDate(false); // wait for after-events like annotations recalculation
diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnQuickMergeTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnQuickMergeTest.java
index 6853141b8d45..a663e13d3b29 100644
--- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnQuickMergeTest.java
+++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnQuickMergeTest.java
@@ -36,9 +36,10 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.SvnTestCase;
import org.jetbrains.idea.svn.branchConfig.InfoReliability;
import org.jetbrains.idea.svn.branchConfig.InfoStorage;
+import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationManager;
import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew;
import org.jetbrains.idea.svn.dialogs.*;
-import org.jetbrains.idea.svn.integrate.SvnBranchItem;
+import org.jetbrains.idea.svn.branchConfig.SvnBranchItem;
import org.jetbrains.idea.svn.mergeinfo.MergeChecker;
import org.junit.Before;
import org.junit.Test;
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/pivotal/PivotalTrackerRepository.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/pivotal/PivotalTrackerRepository.java
index 559247356bcb..f327e0ad968a 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/pivotal/PivotalTrackerRepository.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/pivotal/PivotalTrackerRepository.java
@@ -386,6 +386,6 @@ public class PivotalTrackerRepository extends BaseRepositoryImpl {
@Override
protected int getFeatures() {
- return super.getFeatures() | BASIC_HTTP_AUTHORIZATION;
+ return super.getFeatures() | BASIC_HTTP_AUTHORIZATION | STATE_UPDATING;
}
}
diff --git a/plugins/terminal/src/org/jetbrains/plugins/terminal/AbstractTerminalRunner.java b/plugins/terminal/src/org/jetbrains/plugins/terminal/AbstractTerminalRunner.java
index d252c93bcb34..f671b1a19fc6 100644
--- a/plugins/terminal/src/org/jetbrains/plugins/terminal/AbstractTerminalRunner.java
+++ b/plugins/terminal/src/org/jetbrains/plugins/terminal/AbstractTerminalRunner.java
@@ -155,8 +155,7 @@ public abstract class AbstractTerminalRunner<T extends Process> {
return new CloseAction(defaultExecutor, myDescriptor, myProject);
}
-
- protected void showConsole(Executor defaultExecutor, RunContentDescriptor myDescriptor, final Component toFocus) {
+ protected void showConsole(Executor defaultExecutor, @NotNull RunContentDescriptor myDescriptor, final Component toFocus) {
// Show in run toolwindow
ExecutionManager.getInstance(myProject).getContentManager().showRunContent(defaultExecutor, myDescriptor);
diff --git a/plugins/terminal/src/org/jetbrains/plugins/terminal/TerminalToolWindowFactory.java b/plugins/terminal/src/org/jetbrains/plugins/terminal/TerminalToolWindowFactory.java
index 7a9a7a1e428a..6040e6c6c9ad 100644
--- a/plugins/terminal/src/org/jetbrains/plugins/terminal/TerminalToolWindowFactory.java
+++ b/plugins/terminal/src/org/jetbrains/plugins/terminal/TerminalToolWindowFactory.java
@@ -1,9 +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.plugins.terminal;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.wm.ToolWindow;
import com.intellij.openapi.wm.ToolWindowFactory;
+import org.jetbrains.annotations.NotNull;
/**
* @author traff
@@ -12,7 +28,7 @@ public class TerminalToolWindowFactory implements ToolWindowFactory, DumbAware {
public static final String TOOL_WINDOW_ID = "Terminal";
@Override
- public void createToolWindowContent(Project project, ToolWindow toolWindow) {
+ public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindow toolWindow) {
TerminalView terminalView = TerminalView.getInstance(project);
terminalView.initTerminal(toolWindow);
}
diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/actions/PreviewFormAction.java b/plugins/ui-designer/src/com/intellij/uiDesigner/actions/PreviewFormAction.java
index ce26a9b44264..49766b110bfa 100644
--- a/plugins/ui-designer/src/com/intellij/uiDesigner/actions/PreviewFormAction.java
+++ b/plugins/ui-designer/src/com/intellij/uiDesigner/actions/PreviewFormAction.java
@@ -25,6 +25,8 @@ import com.intellij.execution.executors.DefaultRunExecutor;
import com.intellij.execution.process.ProcessAdapter;
import com.intellij.execution.process.ProcessEvent;
import com.intellij.execution.runners.ExecutionEnvironment;
+import com.intellij.execution.runners.ExecutionEnvironmentBuilder;
+import com.intellij.execution.runners.ExecutionUtil;
import com.intellij.execution.runners.ProgramRunner;
import com.intellij.lang.properties.PropertiesFileType;
import com.intellij.lang.properties.PropertiesReferenceManager;
@@ -312,12 +314,9 @@ public final class PreviewFormAction extends AnAction{
}
try {
- final RunProfile profile = new MyRunProfile(module, parameters, tempPath,
- UIDesignerBundle.message("progress.preview.started", formFile.getPresentableUrl()));
- ProgramRunner defaultRunner = RunnerRegistry.getInstance().getRunner(DefaultRunExecutor.EXECUTOR_ID, profile);
- LOG.assertTrue(defaultRunner != null);
- Executor executor = DefaultRunExecutor.getRunExecutorInstance();
- defaultRunner.execute(new ExecutionEnvironment(profile, executor, module.getProject(), null));
+ RunProfile profile = new MyRunProfile(module, parameters, tempPath,
+ UIDesignerBundle.message("progress.preview.started", formFile.getPresentableUrl()));
+ ExecutionEnvironmentBuilder.create(module.getProject(), DefaultRunExecutor.getRunExecutorInstance(), profile).buildAndExecute();
}
catch (ExecutionException e) {
Messages.showErrorDialog(
diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/snapShooter/CreateSnapShotAction.java b/plugins/ui-designer/src/com/intellij/uiDesigner/snapShooter/CreateSnapShotAction.java
index 284ce42ec867..6ecb61920100 100644
--- a/plugins/ui-designer/src/com/intellij/uiDesigner/snapShooter/CreateSnapShotAction.java
+++ b/plugins/ui-designer/src/com/intellij/uiDesigner/snapShooter/CreateSnapShotAction.java
@@ -16,12 +16,14 @@
package com.intellij.uiDesigner.snapShooter;
-import com.intellij.execution.*;
+import com.intellij.execution.ExecutionException;
+import com.intellij.execution.RunManager;
+import com.intellij.execution.RunnerAndConfigurationSettings;
import com.intellij.execution.application.ApplicationConfiguration;
import com.intellij.execution.application.ApplicationConfigurationType;
import com.intellij.execution.executors.DefaultRunExecutor;
-import com.intellij.execution.runners.ExecutionEnvironment;
-import com.intellij.execution.runners.ProgramRunner;
+import com.intellij.execution.runners.ExecutionEnvironmentBuilder;
+import com.intellij.execution.runners.ExecutionUtil;
import com.intellij.execution.util.JreVersionDetector;
import com.intellij.icons.AllIcons;
import com.intellij.ide.IdeView;
@@ -168,13 +170,9 @@ public class CreateSnapShotAction extends AnAction {
});
}
});
-
+
try {
- final ProgramRunner runner = RunnerRegistry.getInstance().getRunner(DefaultRunExecutor.EXECUTOR_ID, appConfig);
- LOG.assertTrue(runner != null, "Runner MUST not be null!");
- Executor executor = DefaultRunExecutor.getRunExecutorInstance();
- runner.execute(
- new ExecutionEnvironment(executor, runner, snapshotConfiguration, project));
+ ExecutionEnvironmentBuilder.create(DefaultRunExecutor.getRunExecutorInstance(), snapshotConfiguration).buildAndExecute();
}
catch (ExecutionException ex) {
Messages.showMessageDialog(project, UIDesignerBundle.message("snapshot.run.error", ex.getMessage()),
diff --git a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltCommandLineState.java b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltCommandLineState.java
index 6406db9f23b8..50bd5c5720ed 100644
--- a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltCommandLineState.java
+++ b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltCommandLineState.java
@@ -65,12 +65,14 @@ public class XsltCommandLineState extends CommandLineState {
private UserDataHolder myExtensionData;
@SuppressWarnings({ "RawUseOfParameterizedType" })
- public XsltCommandLineState(XsltRunConfiguration xsltRunConfiguration, ExecutionEnvironment env) {
- super(env);
+ public XsltCommandLineState(XsltRunConfiguration xsltRunConfiguration, ExecutionEnvironment environment) {
+ super(environment);
+
myXsltRunConfiguration = xsltRunConfiguration;
- myIsDebugger = "Debug".equals(env.getRunnerId());
+ myIsDebugger = "Debug".equals(environment.getRunner().getRunnerId());
}
+ @Override
@NotNull
protected OSProcessHandler startProcess() throws ExecutionException {
final OSProcessHandler osProcessHandler = createJavaParameters().createOSProcessHandler();
@@ -204,12 +206,15 @@ public class XsltCommandLineState extends CommandLineState {
private class MyProcessAdapter extends ProcessAdapter {
+ @Override
public void processTerminated(final ProcessEvent event) {
if (myXsltRunConfiguration.isSaveToFile()) {
Runnable runnable = new Runnable() {
+ @Override
public void run() {
Runnable runnable = new Runnable() {
+ @Override
public void run() {
if (event.getExitCode() == 0) {
if (myXsltRunConfiguration.myOpenInBrowser) {
diff --git a/python/edu/build/build.xml b/python/edu/build/build.xml
deleted file mode 100644
index 913237c81f27..000000000000
--- a/python/edu/build/build.xml
+++ /dev/null
@@ -1,46 +0,0 @@
-<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/desktop.ini b/python/edu/build/desktop.ini
new file mode 100644
index 000000000000..f56d43c998bf
--- /dev/null
+++ b/python/edu/build/desktop.ini
@@ -0,0 +1,100 @@
+[Settings]
+NumFields=6
+
+[Field 1]
+Type=checkbox
+Left=5
+Right=100
+Top=10
+Bottom=20
+State=0
+
+[Field 2]
+Type=checkbox
+Left=120
+Right=-1
+Top=10
+Bottom=20
+State=0
+
+[Field 3]
+Type=GroupBox
+Left=1
+Right=-1
+Top=35
+Bottom=65
+Text=Choice Python version
+
+[Field 4]
+Type=RadioButton
+Left=5
+Right=45
+Top=50
+Bottom=60
+State=1
+Text=Python 2
+
+[Field 5]
+Type=RadioButton
+Left=95
+Right=135
+Top=50
+Bottom=60
+State=0
+Text=Python 3
+
+[Field 6]
+Type=GroupBox
+Left=1
+Right=-1
+Top=75
+Bottom=105
+Text=Create Associations
+
+[Field 7]
+Type=checkbox
+Left=5
+Right=45
+Top=90
+Bottom=100
+State=0
+
+[Field 8]
+Type=checkbox
+Left=50
+Right=90
+Top=90
+Bottom=100
+State=0
+
+[Field 9]
+Type=checkbox
+Left=95
+Right=135
+Top=90
+Bottom=100
+State=0
+
+[Field 10]
+Type=checkbox
+Left=140
+Right=180
+Top=90
+Bottom=100
+State=0
+
+[Field 11]
+Type=checkbox
+Left=185
+Right=225
+Top=90
+Bottom=100
+State=0
+
+[Field 12]
+Type=checkbox
+Left=230
+Right=270
+Top=90
+Bottom=100
+State=0
diff --git a/python/edu/build/idea.nsi b/python/edu/build/idea.nsi
new file mode 100644
index 000000000000..d9903c94de5e
--- /dev/null
+++ b/python/edu/build/idea.nsi
@@ -0,0 +1,1228 @@
+!verbose 2
+
+!include "paths.nsi"
+!include "strings.nsi"
+!include "Registry.nsi"
+!include "version.nsi"
+
+; Product with version (IntelliJ IDEA #xxxx).
+
+; Used in registry to put each build info into the separate subkey
+; Add&Remove programs doesn't understand subkeys in the Uninstall key,
+; thus ${PRODUCT_WITH_VER} is used for uninstall registry information
+!define PRODUCT_REG_VER "${MUI_PRODUCT}\${VER_BUILD}"
+
+!define INSTALL_OPTION_ELEMENTS 7
+Name "${MUI_PRODUCT}"
+SetCompressor lzma
+; http://nsis.sourceforge.net/Shortcuts_removal_fails_on_Windows_Vista
+RequestExecutionLevel user
+
+;------------------------------------------------------------------------------
+; include "Modern User Interface"
+;------------------------------------------------------------------------------
+!include "MUI2.nsh"
+!include "FileFunc.nsh"
+!include UAC.nsh
+!include "InstallOptions.nsh"
+!include StrFunc.nsh
+!include LogicLib.nsh
+
+${UnStrStr}
+${UnStrLoc}
+${UnStrRep}
+${StrRep}
+
+ReserveFile "desktop.ini"
+ReserveFile "DeleteSettings.ini"
+ReserveFile '${NSISDIR}\Plugins\InstallOptions.dll'
+!insertmacro MUI_RESERVEFILE_LANGDLL
+
+!define MUI_ICON "${IMAGES_LOCATION}\${PRODUCT_ICON_FILE}"
+!define MUI_UNICON "${IMAGES_LOCATION}\${PRODUCT_UNINST_ICON_FILE}"
+
+!define MUI_HEADERIMAGE
+!define MUI_HEADERIMAGE_BITMAP "${IMAGES_LOCATION}\${PRODUCT_HEADER_FILE}"
+!define MUI_WELCOMEFINISHPAGE_BITMAP "${IMAGES_LOCATION}\${PRODUCT_LOGO_FILE}"
+
+;------------------------------------------------------------------------------
+; on GUI initialization installer checks whether IDEA is already installed
+;------------------------------------------------------------------------------
+
+!define MUI_CUSTOMFUNCTION_GUIINIT GUIInit
+
+Var baseRegKey
+Var IS_UPGRADE_60
+
+!define MUI_LANGDLL_REGISTRY_ROOT "HKCU"
+!define MUI_LANGDLL_REGISTRY_KEY "Software\JetBrains\${MUI_PRODUCT}\${VER_BUILD}\"
+!define MUI_LANGDLL_REGISTRY_VALUENAME "Installer Language"
+
+;check if the window is win7 or newer
+!macro INST_UNINST_SWITCH un
+ Function ${un}winVersion
+ ;The platform is returned into $0, minor version into $1.
+ ;Windows 7 is equals values of 6 as platform and 1 as minor version.
+ ;Windows 8 is equals values of 6 as platform and 2 as minor version.
+ nsisos::osversion
+ ${If} $0 == "6"
+ ${AndIf} $1 >= "1"
+ StrCpy $0 "1"
+ ${else}
+ StrCpy $0 "0"
+ ${EndIf}
+ FunctionEnd
+
+ Function ${un}compareFileInstallationTime
+ StrCpy $9 ""
+ get_first_file:
+ Pop $7
+ IfFileExists "$7" get_next_file 0
+ StrCmp $7 "Complete" complete get_first_file
+ get_next_file:
+ Pop $8
+ StrCmp $8 "Complete" 0 +2
+ ; check if there is only one property file
+ StrCmp $9 "no changes" complete different
+ IfFileExists "$8" 0 get_next_file
+ ClearErrors
+ ${GetTime} "$7" "M" $0 $1 $2 $3 $4 $5 $6
+ ${GetTime} "$8" "M" $R0 $R1 $R2 $R3 $R4 $R5 $R6
+ StrCmp $0 $R0 0 different
+ StrCmp $1 $R1 0 different
+ StrCmp $2 $R2 0 different
+ StrCmp $4 $R4 0 different
+ StrCmp $5 $R5 0 different
+ StrCmp $6 $R6 0 different
+ StrCpy $9 "no changes"
+ Goto get_next_file
+ different:
+ StrCpy $9 "Modified"
+ complete:
+FunctionEnd
+
+Function ${un}SplitStr
+Exch $0 ; str
+Push $1 ; inQ
+Push $3 ; idx
+Push $4 ; tmp
+StrCpy $1 0
+StrCpy $3 0
+loop:
+ StrCpy $4 $0 1 $3
+ ${If} $4 == '"'
+ ${If} $1 <> 0
+ StrCpy $0 $0 "" 1
+ IntOp $3 $3 - 1
+ ${EndIf}
+ IntOp $1 $1 !
+ ${EndIf}
+ ${If} $4 == '' ; The end?
+ StrCpy $1 0
+ StrCpy $4 ','
+ ${EndIf}
+ ${If} $4 == ','
+ ${AndIf} $1 = 0
+ StrCpy $4 $0 $3
+ StrCpy $1 $4 "" -1
+ ${IfThen} $1 == '"' ${|} StrCpy $4 $4 -1 ${|}
+ killspace:
+ IntOp $3 $3 + 1
+ StrCpy $0 $0 "" $3
+ StrCpy $1 $0 1
+ StrCpy $3 0
+ StrCmp $1 ',' killspace
+ Push $0 ; Remaining
+ Exch 4
+ Pop $0
+ StrCmp $4 "" 0 moreleft
+ Pop $4
+ Pop $3
+ Pop $1
+ Return
+ moreleft:
+ Exch $4
+ Exch 2
+ Pop $1
+ Pop $3
+ Return
+ ${EndIf}
+ IntOp $3 $3 + 1
+ Goto loop
+FunctionEnd
+
+!macroend
+!insertmacro INST_UNINST_SWITCH ""
+!insertmacro INST_UNINST_SWITCH "un."
+
+Function InstDirState
+ !define InstDirState `!insertmacro InstDirStateCall`
+
+ !macro InstDirStateCall _PATH _RESULT
+ Push `${_PATH}`
+ Call InstDirState
+ Pop ${_RESULT}
+ !macroend
+
+ Exch $0
+ Push $1
+ ClearErrors
+
+ FindFirst $1 $0 '$0\*.*'
+ IfErrors 0 +3
+ StrCpy $0 -1
+ goto end
+ StrCmp $0 '.' 0 +4
+ FindNext $1 $0
+ StrCmp $0 '..' 0 +2
+ FindNext $1 $0
+ FindClose $1
+ IfErrors 0 +3
+ StrCpy $0 0
+ goto end
+ StrCpy $0 1
+
+ end:
+ Pop $1
+ Exch $0
+FunctionEnd
+
+Function SplitFirstStrPart
+ Exch $R0
+ Exch
+ Exch $R1
+ Push $R2
+ Push $R3
+ StrCpy $R3 $R1
+ StrLen $R1 $R0
+ IntOp $R1 $R1 + 1
+ loop:
+ IntOp $R1 $R1 - 1
+ StrCpy $R2 $R0 1 -$R1
+ StrCmp $R1 0 exit0
+ StrCmp $R2 $R3 exit1 loop
+ exit0:
+ StrCpy $R1 ""
+ Goto exit2
+ exit1:
+ IntOp $R1 $R1 - 1
+ StrCmp $R1 0 0 +3
+ StrCpy $R2 ""
+ Goto +2
+ StrCpy $R2 $R0 "" -$R1
+ IntOp $R1 $R1 + 1
+ StrCpy $R0 $R0 -$R1
+ StrCpy $R1 $R2
+ exit2:
+ Pop $R3
+ Pop $R2
+ Exch $R1 ;rest
+ Exch
+ Exch $R0 ;first
+FunctionEnd
+
+Function VersionSplit
+ !define VersionSplit `!insertmacro VersionSplitCall`
+
+ !macro VersionSplitCall _FULL _PRODUCT _BRANCH _BUILD
+ Push `${_FULL}`
+ Call VersionSplit
+ Pop ${_PRODUCT}
+ Pop ${_BRANCH}
+ Pop ${_BUILD}
+ !macroend
+
+ Pop $R0
+ Push "-"
+ Push $R0
+ Call SplitFirstStrPart
+ Pop $R0
+ Pop $R1
+ Push "."
+ Push $R1
+ Call SplitFirstStrPart
+ Push $R0
+FunctionEnd
+
+Function OnDirectoryPageLeave
+ StrCpy $IS_UPGRADE_60 "0"
+ ${InstDirState} "$INSTDIR" $R0
+ IntCmp $R0 1 check_build skip_abort skip_abort
+check_build:
+ FileOpen $R1 "$INSTDIR\build.txt" "r"
+ IfErrors do_abort
+ FileRead $R1 $R2
+ FileClose $R1
+ IfErrors do_abort
+ ${VersionSplit} ${MIN_UPGRADE_BUILD} $R3 $R4 $R5
+ ${VersionSplit} ${MAX_UPGRADE_BUILD} $R6 $R7 $R8
+ ${VersionSplit} $R2 $R9 $R2 $R0
+ StrCmp $R9 $R3 0 do_abort
+ IntCmp $R2 $R4 0 do_abort
+ IntCmp $R0 $R5 do_accept do_abort
+
+ StrCmp $R9 $R6 0 do_abort
+ IntCmp $R2 $R7 0 0 do_abort
+ IntCmp $R0 $R8 do_abort do_accept do_abort
+
+do_accept:
+ StrCpy $IS_UPGRADE_60 "1"
+ FileClose $R1
+ Goto skip_abort
+
+do_abort:
+ ;check
+ ; - if there are no files into $INSTDIR (recursively) just excepted property files
+ ; - if property files have the same installation time.
+ StrCpy $9 "$INSTDIR"
+ Call instDirEmpty
+ StrCmp $9 "not empty" abort 0
+ Push "Complete"
+ Push "$INSTDIR\bin\${PRODUCT_EXE_FILE}.vmoptions"
+ Push "$INSTDIR\bin\idea.properties"
+ ${StrRep} $0 ${PRODUCT_EXE_FILE} ".exe" "64.exe.vmoptions"
+ Push "$INSTDIR\bin\$0"
+ Call compareFileInstallationTime
+ StrCmp $9 "Modified" abort skip_abort
+abort:
+ MessageBox MB_OK|MB_ICONEXCLAMATION "$(empty_or_upgrade_folder)"
+ Abort
+skip_abort:
+FunctionEnd
+
+
+;check if there are no files into $INSTDIR recursively just except property files.
+Function instDirEmpty
+ Push $0
+ Push $1
+ Push $2
+ ClearErrors
+ FindFirst $1 $2 "$9\*.*"
+nextElemement:
+ ;is the element a folder?
+ StrCmp $2 "." getNextElement
+ StrCmp $2 ".." getNextElement
+ IfFileExists "$9\$2\*.*" 0 nextFile
+ Push $9
+ StrCpy "$9" "$9\$2"
+ Call instDirEmpty
+ StrCmp $9 "not empty" done 0
+ Pop $9
+ Goto getNextElement
+nextFile:
+ ;is it the file property?
+ ${If} $2 != "idea.properties"
+ ${AndIf} $2 != "${PRODUCT_EXE_FILE}.vmoptions"
+ ${StrRep} $0 ${PRODUCT_EXE_FILE} ".exe" "64.exe.vmoptions"
+ ${AndIf} $2 != $0
+ StrCpy $9 "not empty"
+ Goto done
+ ${EndIf}
+getNextElement:
+ FindNext $1 $2
+ IfErrors 0 nextElemement
+done:
+ FindClose $1
+ Pop $2
+ Pop $1
+ Pop $0
+FunctionEnd
+
+
+;------------------------------------------------------------------------------
+; Variables
+;------------------------------------------------------------------------------
+ Var STARTMENU_FOLDER
+ Var config_path
+ Var system_path
+
+;------------------------------------------------------------------------------
+; configuration
+;------------------------------------------------------------------------------
+
+!insertmacro MUI_PAGE_WELCOME
+
+Page custom uninstallOldVersionDialog
+
+Var control_fields
+Var max_fields
+
+!ifdef LICENSE_FILE
+!insertmacro MUI_PAGE_LICENSE "$(myLicenseData)"
+!endif
+
+!define MUI_PAGE_CUSTOMFUNCTION_LEAVE OnDirectoryPageLeave
+!insertmacro MUI_PAGE_DIRECTORY
+
+Page custom ConfirmDesktopShortcut
+ !define MUI_STARTMENUPAGE_NODISABLE
+ !define MUI_STARTMENUPAGE_DEFAULTFOLDER "JetBrains"
+
+!insertmacro MUI_PAGE_STARTMENU Application $STARTMENU_FOLDER
+!define MUI_ABORTWARNING
+!insertmacro MUI_PAGE_INSTFILES
+!define MUI_FINISHPAGE_RUN_NOTCHECKED
+!define MUI_FINISHPAGE_RUN
+!define MUI_FINISHPAGE_RUN_FUNCTION PageFinishRun
+!insertmacro MUI_PAGE_FINISH
+
+!define MUI_UNINSTALLER
+;!insertmacro MUI_UNPAGE_CONFIRM
+UninstPage custom un.ConfirmDeleteSettings
+!insertmacro MUI_UNPAGE_INSTFILES
+
+OutFile "${OUT_DIR}\${OUT_FILE}.exe"
+
+InstallDir "$PROGRAMFILES\${MANUFACTURER}\${PRODUCT_WITH_VER}"
+!define MUI_BRANDINGTEXT " "
+BrandingText " "
+
+Function PageFinishRun
+!insertmacro UAC_AsUser_ExecShell "" "$INSTDIR\bin\${PRODUCT_EXE_FILE}" "" "" ""
+FunctionEnd
+
+;------------------------------------------------------------------------------
+; languages
+;------------------------------------------------------------------------------
+!insertmacro MUI_LANGUAGE "English"
+;!insertmacro MUI_LANGUAGE "Japanese"
+!include "idea_en.nsi"
+;!include "idea_jp.nsi"
+
+!ifdef LICENSE_FILE
+LicenseLangString myLicenseData ${LANG_ENGLISH} "${LICENSE_FILE}.txt"
+LicenseLangString myLicenseData ${LANG_JAPANESE} "${LICENSE_FILE}.txt"
+!endif
+
+Function .onInit
+ StrCpy $baseRegKey "HKCU"
+ IfSilent UAC_Done
+UAC_Elevate:
+ !insertmacro UAC_RunElevated
+ StrCmp 1223 $0 UAC_ElevationAborted ; UAC dialog aborted by user? - continue install under user
+ StrCmp 0 $0 0 UAC_Err ; Error?
+ StrCmp 1 $1 0 UAC_Success ;Are we the real deal or just the wrapper?
+ Quit
+UAC_Err:
+ Abort
+UAC_ElevationAborted:
+ StrCpy $INSTDIR "$APPDATA\${MANUFACTURER}\${PRODUCT_WITH_VER}"
+ goto UAC_Done
+UAC_Success:
+ StrCmp 1 $3 UAC_Admin ;Admin?
+ StrCmp 3 $1 0 UAC_ElevationAborted ;Try again?
+ goto UAC_Elevate
+UAC_Admin:
+ StrCpy $INSTDIR "$PROGRAMFILES\${MANUFACTURER}\${PRODUCT_WITH_VER}"
+ SetShellVarContext all
+ StrCpy $baseRegKey "HKLM"
+UAC_Done:
+; !insertmacro MUI_LANGDLL_DISPLAY
+FunctionEnd
+
+Function checkVersion
+ StrCpy $2 ""
+ StrCpy $1 "Software\${MANUFACTURER}\${PRODUCT_REG_VER}"
+; ${If} $0 == "HKLM"
+; StrCpy $1 "Software\${MANUFACTURER}\${PRODUCT_REG_VER}"
+; Push $0
+; call winVersion
+; ${If} $0 == "1"
+; StrCpy $1 "Software\Wow6432Node\${MANUFACTURER}\${PRODUCT_REG_VER}"
+; ${Else}
+; StrCpy $1 "Software\${MANUFACTURER}\${PRODUCT_REG_VER}"
+; ${EndIf}
+; Pop $0
+; ${EndIf}
+ Call OMReadRegStr
+ IfFileExists $3\bin\${PRODUCT_EXE_FILE} check_version
+ Goto Done
+check_version:
+ StrCpy $2 "Build"
+ Call OMReadRegStr
+ StrCmp $3 "" Done
+ IntCmpU $3 ${VER_BUILD} ask_Install_Over Done ask_Install_Over
+ask_Install_Over:
+ MessageBox MB_YESNO|MB_ICONQUESTION "$(current_version_already_installed)" IDYES continue IDNO exit_installer
+exit_installer:
+ Abort
+continue:
+ StrCpy $0 "complete"
+Done:
+FunctionEnd
+
+
+Function searchCurrentVersion
+ ; search current version of IDEA
+ StrCpy $0 "HKCU"
+ Call checkVersion
+ StrCmp $0 "complete" Done
+ StrCpy $0 "HKLM"
+ Call checkVersion
+Done:
+FunctionEnd
+
+
+Function uninstallOldVersion
+ ;check if the uninstalled application is running
+remove_previous_installation:
+ ;prepare a copy of launcher
+ CopyFiles "$3\bin\${PRODUCT_EXE_FILE}" "$3\bin\${PRODUCT_EXE_FILE}_copy"
+ ClearErrors
+ ;copy launcher to itself
+ CopyFiles "$3\bin\${PRODUCT_EXE_FILE}_copy" "$3\bin\${PRODUCT_EXE_FILE}"
+ Delete "$3\bin\${PRODUCT_EXE_FILE}_copy"
+ IfErrors 0 +3
+ 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 2" "State"
+ ${If} $9 == "1"
+ ExecWait '"$3\bin\Uninstall.exe" /S'
+ ${else}
+ ExecWait '"$3\bin\Uninstall.exe" _?=$3\bin'
+ ${EndIf}
+ IfFileExists $3\bin\${PRODUCT_EXE_FILE} 0 uninstall
+ goto complete
+uninstall:
+ ;previous installation has been removed
+ ;customer decided to keep properties?
+ IfFileExists $3\bin\idea.properties saveProperties fullRemove
+saveProperties:
+ Delete "$3\bin\Uninstall.exe"
+ Goto complete
+fullRemove:
+ RmDir /r "$3"
+complete:
+FunctionEnd
+
+
+Function checkProductVersion
+;$8 - count of already added fields to the dialog
+;$3 - an old version which will be checked if the one should be added too
+StrCpy $7 $control_fields
+StrCpy $6 ""
+loop:
+ IntOp $7 $7 + 1
+ ${If} $8 >= $7
+ !insertmacro INSTALLOPTIONS_READ $6 "UninstallOldVersions.ini" "Field $7" "Text"
+ ${If} $6 == $3
+ ;found the same value in list of installations
+ StrCpy $6 "duplicated"
+ Goto finish
+ ${EndIf}
+ Goto loop
+ ${EndIf}
+finish:
+FunctionEnd
+
+
+Function uninstallOldVersionDialog
+ StrCpy $control_fields 2
+ StrCpy $max_fields 13
+ StrCpy $0 "HKLM"
+ StrCpy $4 0
+ ReserveFile "UninstallOldVersions.ini"
+ !insertmacro INSTALLOPTIONS_EXTRACT "UninstallOldVersions.ini"
+ StrCpy $8 $control_fields
+
+get_installation_info:
+ StrCpy $1 "Software\${MANUFACTURER}\${MUI_PRODUCT}"
+ StrCpy $5 "\bin\${PRODUCT_EXE_FILE}"
+ StrCpy $2 ""
+ Call getInstallationPath
+ StrCmp $3 "complete" next_registry_root
+ ;check if the old installation could be uninstalled
+ IfFileExists $3\bin\Uninstall.exe uninstall_dialog get_next_key
+uninstall_dialog:
+ Call checkProductVersion
+ ${If} $6 != "duplicated"
+ IntOp $8 $8 + 1
+ !insertmacro INSTALLOPTIONS_WRITE "UninstallOldVersions.ini" "Field $8" "Text" "$3"
+ StrCmp $8 $max_fields complete
+ ${EndIf}
+get_next_key:
+ IntOp $4 $4 + 1 ;to check next record from registry
+ goto get_installation_info
+
+next_registry_root:
+${If} $0 == "HKLM"
+ StrCpy $0 "HKCU"
+ StrCpy $4 0
+ Goto get_installation_info
+${EndIf}
+complete:
+!insertmacro INSTALLOPTIONS_WRITE "UninstallOldVersions.ini" "Settings" "NumFields" "$8"
+${If} $8 > $control_fields
+ ;$2 used in prompt text
+ StrCpy $2 "s"
+ StrCpy $7 $control_fields
+ IntOp $7 $7 + 1
+ StrCmp $8 $7 0 +2
+ 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)
+
+ ;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"
+ ${If} $0 == "1"
+ Call uninstallOldVersion
+ ${EndIf}
+ IntOp $8 $8 - 1
+ StrCmp $8 $control_fields finish loop
+ ${EndIf}
+finish:
+FunctionEnd
+
+
+Function getInstallationPath
+ Push $1
+ Push $2
+ Push $5
+loop:
+ Call OMEnumRegKey
+ StrCmp $3 "" 0 getPath
+ StrCpy $3 "complete"
+ goto done
+getPath:
+ Push $1
+ StrCpy $1 "$1\$3"
+ Call OMReadRegStr
+ Pop $1
+ IfFileExists $3$5 done 0
+ IntOp $4 $4 + 1
+ goto loop
+done:
+ Pop $5
+ Pop $2
+ Pop $1
+FunctionEnd
+
+
+Function GUIInit
+ Push $0
+ Push $1
+ Push $2
+ Push $3
+ Push $4
+ Push $5
+
+; is the current version of IDEA installed?
+ Call searchCurrentVersion
+
+; search old versions of IDEA
+ StrCpy $4 0
+ StrCpy $0 "HKCU"
+ StrCpy $1 "Software\${MANUFACTURER}\${MUI_PRODUCT}"
+ StrCpy $5 "\bin\${PRODUCT_EXE_FILE}"
+ StrCpy $2 ""
+ Call getInstallationPath
+ StrCmp $3 "complete" all_users
+ IfFileExists $3\bin\${PRODUCT_EXE_FILE} old_version_located all_users
+all_users:
+ StrCpy $4 0
+ StrCpy $0 "HKLM"
+ Call getInstallationPath
+ StrCmp $3 "complete" success
+ IfFileExists $3\bin\${PRODUCT_EXE_FILE} 0 success
+old_version_located:
+; MessageBox MB_YESNO|MB_ICONQUESTION "$(previous_installations)" IDYES uninstall IDNO success
+;uninstall:
+; Call uninstallOldVersions
+
+success:
+ IntCmp ${SHOULD_SET_DEFAULT_INSTDIR} 0 end_enum_versions_hklm
+ StrCpy $3 "0" # latest build number
+ StrCpy $0 "0" # registry key index
+
+enum_versions_hkcu:
+ EnumRegKey $1 "HKCU" "Software\${MANUFACTURER}\${MUI_PRODUCT}" $0
+ StrCmp $1 "" end_enum_versions_hkcu
+ IntCmp $1 $3 continue_enum_versions_hkcu continue_enum_versions_hkcu
+ StrCpy $3 $1
+ ReadRegStr $INSTDIR "HKCU" "Software\${MANUFACTURER}\${MUI_PRODUCT}\$3" ""
+
+continue_enum_versions_hkcu:
+ IntOp $0 $0 + 1
+ Goto enum_versions_hkcu
+
+end_enum_versions_hkcu:
+
+ StrCpy $0 "0" # registry key index
+
+enum_versions_hklm:
+ EnumRegKey $1 "HKLM" "Software\${MANUFACTURER}\${MUI_PRODUCT}" $0
+ StrCmp $1 "" end_enum_versions_hklm
+ IntCmp $1 $3 continue_enum_versions_hklm continue_enum_versions_hklm
+ StrCpy $3 $1
+ ReadRegStr $INSTDIR "HKLM" "Software\${MANUFACTURER}\${MUI_PRODUCT}\$3" ""
+
+continue_enum_versions_hklm:
+ IntOp $0 $0 + 1
+ Goto enum_versions_hklm
+
+end_enum_versions_hklm:
+
+ StrCmp $INSTDIR "" 0 skip_default_instdir
+ StrCpy $INSTDIR "$PROGRAMFILES\${MANUFACTURER}\${MUI_PRODUCT} ${MUI_VERSION_MAJOR}.${MUI_VERSION_MINOR}"
+skip_default_instdir:
+
+ Pop $5
+ Pop $4
+ Pop $3
+ Pop $2
+ Pop $1
+ Pop $0
+ !insertmacro INSTALLOPTIONS_EXTRACT "Desktop.ini"
+
+FunctionEnd
+
+Function DoAssociation
+ ; back up old value of an association
+ ReadRegStr $1 HKCR $R4 ""
+ StrCmp $1 "" skip_backup
+ StrCmp $1 ${PRODUCT_PATHS_SELECTOR} skip_backup
+ WriteRegStr HKCR $R4 "backup_val" $1
+skip_backup:
+ WriteRegStr HKCR $R4 "" "${PRODUCT_PATHS_SELECTOR}"
+ ReadRegStr $0 HKCR ${PRODUCT_PATHS_SELECTOR} ""
+ StrCmp $0 "" 0 command_exists
+ WriteRegStr HKCR ${PRODUCT_PATHS_SELECTOR} "" "${PRODUCT_FULL_NAME}"
+ WriteRegStr HKCR "${PRODUCT_PATHS_SELECTOR}\shell" "" "open"
+ WriteRegStr HKCR "${PRODUCT_PATHS_SELECTOR}\DefaultIcon" "" "$INSTDIR\bin\${PRODUCT_EXE_FILE},0"
+command_exists:
+ WriteRegStr HKCR "${PRODUCT_PATHS_SELECTOR}\shell\open\command" "" \
+ '$INSTDIR\bin\${PRODUCT_EXE_FILE} "%1"'
+FunctionEnd
+
+;------------------------------------------------------------------------------
+; Installer sections
+;------------------------------------------------------------------------------
+Section "IDEA Files" CopyIdeaFiles
+; StrCpy $baseRegKey "HKCU"
+; !insertmacro INSTALLOPTIONS_READ $R2 "Desktop.ini" "Field 3" "State"
+; StrCmp $R2 1 continue_for_current_user
+; SetShellVarContext all
+; StrCpy $baseRegKey "HKLM"
+; continue_for_current_user:
+
+; create shortcuts
+
+ !insertmacro INSTALLOPTIONS_READ $R2 "Desktop.ini" "Field 4" "State"
+ StrCmp $R2 1 "" python3
+ StrCpy $R2 "2.7"
+ goto check_python
+python3:
+ StrCpy $R2 "3.4"
+check_python:
+ ReadRegStr $1 "HKCU" "Software\Python\PythonCore\$R2\InstallPath" $0
+ StrCmp $1 "" installation_for_all_users
+ goto verefy_python_launcher
+installation_for_all_users:
+ ReadRegStr $1 "HKLM" "Software\Python\PythonCore\$R2\InstallPath" $0
+ StrCmp $1 "" get_python
+verefy_python_launcher:
+ IfFileExists $1\python.exe python_exists get_python
+
+get_python:
+ CreateDirectory "$INSTDIR\python"
+ StrCmp $R2 "2.7" get_python2
+ inetc::get "https://www.python.org/ftp/python/3.4.1/python-3.4.1.amd64.msi" "$INSTDIR\python\python_$R2.msi"
+ goto validate_download
+get_python2:
+ inetc::get "http://www.python.org/ftp/python/2.7.8/python-2.7.8.msi" "$INSTDIR\python\python_$R2.msi"
+validate_download:
+ Pop $0
+ ${If} $0 == "OK"
+ ExecCmd::exec 'msiexec /i "$INSTDIR\python\python_$R2.msi" /quiet /qn /norestart /log "$INSTDIR\python\python_$R2_silent.log"'
+ ${EndIf}
+
+python_exists:
+ !insertmacro INSTALLOPTIONS_READ $R2 "Desktop.ini" "Field 1" "State"
+ StrCmp $R2 1 "" skip_desktop_shortcut
+ CreateShortCut "$DESKTOP\${PRODUCT_FULL_NAME_WITH_VER}.lnk" \
+ "$INSTDIR\bin\${PRODUCT_EXE_FILE}" "" "" "" SW_SHOWNORMAL
+
+skip_desktop_shortcut:
+ ; OS is not win7
+ Call winVersion
+ ${If} $0 == "0"
+ !insertmacro INSTALLOPTIONS_READ $R2 "Desktop.ini" "Field 2" "State"
+ StrCmp $R2 1 "" skip_quicklaunch_shortcut
+ CreateShortCut "$QUICKLAUNCH\${PRODUCT_FULL_NAME_WITH_VER}.lnk" \
+ "$INSTDIR\bin\${PRODUCT_EXE_FILE}" "" "" "" SW_SHOWNORMAL
+ ${EndIf}
+skip_quicklaunch_shortcut:
+
+ !insertmacro INSTALLOPTIONS_READ $R1 "Desktop.ini" "Settings" "NumFields"
+ IntCmp $R1 ${INSTALL_OPTION_ELEMENTS} do_association done do_association
+do_association:
+ StrCpy $R2 ${INSTALL_OPTION_ELEMENTS}
+get_user_choice:
+ !insertmacro INSTALLOPTIONS_READ $R3 "Desktop.ini" "Field $R2" "State"
+ StrCmp $R3 1 "" next_association
+ !insertmacro INSTALLOPTIONS_READ $R4 "Desktop.ini" "Field $R2" "Text"
+ call DoAssociation
+next_association:
+ IntOp $R2 $R2 + 1
+ IntCmp $R1 $R2 get_user_choice done get_user_choice
+
+done:
+!insertmacro MUI_STARTMENU_WRITE_BEGIN Application
+; $STARTMENU_FOLDER stores name of IDEA folder in Start Menu,
+; save it name in the "MenuFolder" RegValue
+ CreateDirectory "$SMPROGRAMS\$STARTMENU_FOLDER"
+
+ CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\${PRODUCT_FULL_NAME_WITH_VER}.lnk" \
+ "$INSTDIR\bin\${PRODUCT_EXE_FILE}" "" "" "" SW_SHOWNORMAL
+; CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\Uninstall ${PRODUCT_FULL_NAME_WITH_VER}.lnk" \
+; "$INSTDIR\bin\Uninstall.exe"
+ StrCpy $0 $baseRegKey
+ StrCpy $1 "Software\${MANUFACTURER}\${PRODUCT_REG_VER}"
+ StrCpy $2 "MenuFolder"
+ StrCpy $3 "$STARTMENU_FOLDER"
+ Call OMWriteRegStr
+!insertmacro MUI_STARTMENU_WRITE_END
+
+ StrCmp ${IPR} "false" skip_ipr
+
+ ; back up old value of .ipr
+!define Index "Line${__LINE__}"
+ ReadRegStr $1 HKCR ".ipr" ""
+ StrCmp $1 "" "${Index}-NoBackup"
+ StrCmp $1 "IntelliJIdeaProjectFile" "${Index}-NoBackup"
+ WriteRegStr HKCR ".ipr" "backup_val" $1
+"${Index}-NoBackup:"
+ WriteRegStr HKCR ".ipr" "" "IntelliJIdeaProjectFile"
+ ReadRegStr $0 HKCR "IntelliJIdeaProjectFile" ""
+ StrCmp $0 "" 0 "${Index}-Skip"
+ WriteRegStr HKCR "IntelliJIdeaProjectFile" "" "IntelliJ IDEA Project File"
+ WriteRegStr HKCR "IntelliJIdeaProjectFile\shell" "" "open"
+ WriteRegStr HKCR "IntelliJIdeaProjectFile\DefaultIcon" "" "$INSTDIR\bin\idea.exe,0"
+"${Index}-Skip:"
+ WriteRegStr HKCR "IntelliJIdeaProjectFile\shell\open\command" "" \
+ '$INSTDIR\bin\${PRODUCT_EXE_FILE} "%1"'
+!undef Index
+
+skip_ipr:
+
+; readonly section
+ SectionIn RO
+!include "idea_win.nsh"
+
+ IntCmp $IS_UPGRADE_60 1 skip_properties
+ SetOutPath $INSTDIR\bin
+ File "${PRODUCT_PROPERTIES_FILE}"
+ File "${PRODUCT_VM_OPTIONS_FILE}"
+skip_properties:
+
+ StrCpy $0 $baseRegKey
+ StrCpy $1 "Software\${MANUFACTURER}\${PRODUCT_REG_VER}"
+ StrCpy $2 ""
+ StrCpy $3 "$INSTDIR"
+ Call OMWriteRegStr
+ StrCpy $2 "Build"
+ StrCpy $3 ${VER_BUILD}
+ Call OMWriteRegStr
+
+; write uninstaller & add it to add/remove programs in control panel
+ WriteUninstaller "$INSTDIR\bin\Uninstall.exe"
+ WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_WITH_VER}" \
+ "DisplayName" "${PRODUCT_FULL_NAME_WITH_VER}"
+ WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_WITH_VER}" \
+ "UninstallString" "$INSTDIR\bin\Uninstall.exe"
+ WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_WITH_VER}" \
+ "InstallLocation" "$INSTDIR"
+ WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_WITH_VER}" \
+ "DisplayIcon" "$INSTDIR\bin\${PRODUCT_EXE_FILE}"
+ WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_WITH_VER}" \
+ "DisplayVersion" "${VER_BUILD}"
+ WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_WITH_VER}" \
+ "Publisher" "JetBrains s.r.o."
+ WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_WITH_VER}" \
+ "URLInfoAbout" "http://www.jetbrains.com/products"
+ WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_WITH_VER}" \
+ "InstallType" "$baseRegKey"
+ WriteRegDWORD SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_WITH_VER}" \
+ "NoModify" 1
+ WriteRegDWORD SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_WITH_VER}" \
+ "NoRepair" 1
+
+ ExecWait "$INSTDIR\jre\jre\bin\javaw.exe -Xshare:dump"
+ SetOutPath $INSTDIR\bin
+ ; set the current time for installation files under $INSTDIR\bin
+ ExecCmd::exec 'copy "$INSTDIR\bin\*.*s" +,,'
+ call winVersion
+ ${If} $0 == "1"
+ ;ExecCmd::exec 'icacls "$INSTDIR" /grant %username%:F /T >"$INSTDIR"\installation_log.txt 2>"$INSTDIR"\installation_error.txt'
+ AccessControl::GrantOnFile \
+ "$INSTDIR" "(S-1-5-32-545)" "GenericRead + GenericExecute"
+ ${EndIf}
+SectionEnd
+
+;------------------------------------------------------------------------------
+; Descriptions of sections
+;------------------------------------------------------------------------------
+; LangString DESC_CopyRuntime ${LANG_ENGLISH} "${MUI_PRODUCT} files"
+
+;------------------------------------------------------------------------------
+; custom install pages
+;------------------------------------------------------------------------------
+
+Function ConfirmDesktopShortcut
+ !insertmacro MUI_HEADER_TEXT "$(installation_options)" "$(installation_options_prompt)"
+ !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field 1" "Text" "$(create_desktop_shortcut)"
+ call winVersion
+ !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field 2" "Text" "$(create_quick_launch_shortcut)"
+ ${If} $0 == "1"
+ !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field 2" "Flags" "DISABLED"
+ ${EndIf}
+ StrCmp "${ASSOCIATION}" "NoAssociation" skip_association
+ StrCpy $R0 6
+ push "${ASSOCIATION}"
+loop:
+ call SplitStr
+ Pop $0
+ StrCmp $0 "" done
+ IntOp $R0 $R0 + 1
+ !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Field $R0" "Text" "$0"
+ goto loop
+skip_association:
+ StrCpy $R0 2
+ call winVersion
+ ${If} $0 == "1"
+ IntOp $R0 $R0 - 1
+ ${EndIf}
+done:
+ !insertmacro INSTALLOPTIONS_WRITE "Desktop.ini" "Settings" "NumFields" "$R0"
+ !insertmacro INSTALLOPTIONS_DISPLAY "Desktop.ini"
+FunctionEnd
+
+
+;------------------------------------------------------------------------------
+; custom uninstall functions
+;------------------------------------------------------------------------------
+
+Function un.onInit
+ ;admin perm. is required to uninstall?
+ ${UnStrStr} $R0 $INSTDIR $PROGRAMFILES
+ StrCmp $R0 $INSTDIR requred_admin_perm UAC_Done
+
+requred_admin_perm:
+ ;the user has admin rights?
+ UserInfo::GetAccountType
+ Pop $R2
+ StrCmp $R2 "Admin" UAC_Admin uninstall_location
+
+uninstall_location:
+ ;check if the uninstallation is running from the product location
+ IfFileExists $APPDATA\${PRODUCT_PATHS_SELECTOR}_${VER_BUILD}_Uninstall.exe UAC_Elevate copy_uninstall
+
+copy_uninstall:
+ ;do copy for unistall.exe
+ CopyFiles "$OUTDIR\Uninstall.exe" "$APPDATA\${PRODUCT_PATHS_SELECTOR}_${VER_BUILD}_Uninstall.exe"
+ ExecWait '"$APPDATA\${PRODUCT_PATHS_SELECTOR}_${VER_BUILD}_Uninstall.exe" _?=$INSTDIR'
+ Delete "$APPDATA\${PRODUCT_PATHS_SELECTOR}_${VER_BUILD}_Uninstall.exe"
+ Quit
+
+UAC_Elevate:
+ !insertmacro UAC_RunElevated
+ StrCmp 1223 $0 UAC_ElevationAborted ; UAC dialog aborted by user? - continue install under user
+ StrCmp 0 $0 0 UAC_Err ; Error?
+ StrCmp 1 $1 0 UAC_Success ;Are we the real deal or just the wrapper?
+ Quit
+UAC_ElevationAborted:
+UAC_Err:
+ Abort
+UAC_Success:
+ StrCmp 1 $3 UAC_Admin ;Admin?
+ StrCmp 3 $1 0 UAC_ElevationAborted ;Try again?
+ goto UAC_Elevate
+UAC_Admin:
+ SetShellVarContext all
+ StrCpy $baseRegKey "HKLM"
+UAC_Done:
+ !insertmacro MUI_UNGETLANGUAGE
+ !insertmacro INSTALLOPTIONS_EXTRACT "DeleteSettings.ini"
+FunctionEnd
+
+Function OMEnumRegKey
+ StrCmp $0 "HKCU" hkcu
+ EnumRegKey $3 HKLM $1 $4
+ goto done
+hkcu:
+ EnumRegKey $3 HKCU $1 $4
+done:
+FunctionEnd
+
+Function un.OMReadRegStr
+ StrCmp $0 "HKCU" hkcu
+ ReadRegStr $3 HKLM $1 $2
+ goto done
+hkcu:
+ ReadRegStr $3 HKCU $1 $2
+done:
+FunctionEnd
+
+Function un.OMDeleteRegValue
+ StrCmp $0 "HKCU" hkcu
+ DeleteRegValue HKLM $1 $2
+ goto done
+hkcu:
+ DeleteRegValue HKCU $1 $2
+done:
+FunctionEnd
+
+Function un.ReturnBackupRegValue
+ ;replace Default str with the backup value (if there is the one) and then delete backup
+ ; $1 - key (for example ".java")
+ ; $2 - name (for example "backup_val")
+ Push $0
+ ReadRegStr $0 HKCR $1 $2
+ StrCmp $0 "" "noBackup"
+ WriteRegStr HKCR $1 "" $0
+ DeleteRegValue HKCR $1 $2
+noBackup:
+ Pop $0
+FunctionEnd
+
+Function un.OMDeleteRegKeyIfEmpty
+ StrCmp $0 "HKCU" hkcu
+ DeleteRegKey /ifempty HKLM $1
+ goto done
+hkcu:
+ DeleteRegKey /ifempty HKCU $1
+done:
+FunctionEnd
+
+Function un.OMDeleteRegKey
+ StrCmp $0 "HKCU" hkcu
+ DeleteRegKey /ifempty HKLM $1
+ goto done
+hkcu:
+ DeleteRegKey /ifempty HKCU $1
+done:
+FunctionEnd
+
+Function un.OMWriteRegStr
+ StrCmp $0 "HKCU" hkcu
+ WriteRegStr HKLM $1 $2 $3
+ goto done
+hkcu:
+ WriteRegStr HKCU $1 $2 $3
+done:
+FunctionEnd
+
+
+;------------------------------------------------------------------------------
+; custom uninstall pages
+;------------------------------------------------------------------------------
+
+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" $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
+
+
+Function un.PrepareCustomPath
+ ;Input:
+ ;$0 - name of variable
+ ;$1 - value of the variable
+ ;$2 - line from the property file
+ push $3
+ push $5
+ ${UnStrLoc} $3 $2 $0 ">"
+ StrCmp $3 "" not_found
+ StrLen $5 $0
+ IntOp $3 $3 + $5
+ StrCpy $2 $2 "" $3
+ IfFileExists "$1$2\\*.*" not_found
+ StrCpy $2 $1$2
+ goto complete
+not_found:
+ StrCpy $0 ""
+complete:
+ pop $5
+ pop $3
+FunctionEnd
+
+
+Function un.getCustomPath
+ push $0
+ push $1
+ StrCpy $0 "${user.home}/"
+ StrCpy $1 "$PROFILE/"
+ Call un.PrepareCustomPath
+ StrCmp $0 "" check_idea_var
+ goto complete
+check_idea_var:
+ StrCpy $0 "${idea.home}/"
+ StrCpy $1 "$INSTDIR/"
+ Call un.PrepareCustomPath
+ StrCmp $2 "" +1 +2
+ StrCpy $2 ""
+complete:
+ pop $1
+ pop $0
+FunctionEnd
+
+
+Function un.getPath
+; The function read lines from idea.properties and search the substring and prepare the path to settings or caches.
+ ClearErrors
+ FileOpen $3 $INSTDIR\bin\idea.properties r
+ IfErrors complete ;file can not be open. not sure if a message should be displayed in this case.
+ StrLen $5 $1
+read_line:
+ FileRead $3 $4
+ StrCmp $4 "" complete
+ ${UnStrLoc} $6 $4 $1 ">"
+ StrCmp $6 "" read_line ; there is no substring in a string from the file. go for next one.
+ IntOp $6 $6 + $5
+ ${unStrStr} $7 $4 "#" ;check if the property has been customized
+ StrCmp $7 "" custom
+ StrCpy $2 "$PROFILE/${PRODUCT_SETTINGS_DIR}/$0" ;no. use the default value.
+ goto complete
+custom:
+ StrCpy $2 $4 "" $6
+ Call un.getCustomPath
+complete:
+ FileClose $3
+ ${UnStrRep} $2 $2 "/" "\"
+FunctionEnd
+
+
+Section "Uninstall"
+ StrCpy $baseRegKey "HKCU"
+ ; Uninstaller is in the \bin directory, we need upper level dir
+ StrCpy $INSTDIR $INSTDIR\..
+
+ !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
+ StrCpy $0 "system"
+ StrCpy $1 "idea.system.path="
+ Call un.getPath
+ StrCmp $2 "" skip_delete_caches
+ StrCpy $system_path $2
+ RmDir /r "$system_path"
+ RmDir "$system_path\\.." ; remove parent of system dir if the dir is empty
+; RmDir /r $DOCUMENTS\..\${PRODUCT_SETTINGS_DIR}\system
+skip_delete_caches:
+
+ !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"
+ StrCpy $1 "idea.config.path="
+ Call un.getPath
+ StrCmp $2 "" skip_delete_settings
+ StrCpy $config_path $2
+ RmDir /r "$config_path"
+; RmDir /r $DOCUMENTS\..\${PRODUCT_SETTINGS_DIR}\config
+ Delete "$INSTDIR\bin\${PRODUCT_VM_OPTIONS_NAME}"
+ Delete "$INSTDIR\bin\idea.properties"
+ StrCmp $R2 1 "" skip_delete_settings
+ RmDir "$config_path\\.." ; remove parent of config dir if the dir is empty
+; RmDir $DOCUMENTS\..\${PRODUCT_SETTINGS_DIR}
+skip_delete_settings:
+
+; Delete uninstaller itself
+ Delete "$INSTDIR\bin\Uninstall.exe"
+ Delete "$INSTDIR\jre\jre\bin\client\classes.jsa"
+
+ Push "Complete"
+ Push "$INSTDIR\bin\${PRODUCT_EXE_FILE}.vmoptions"
+ Push "$INSTDIR\bin\idea.properties"
+ ${UnStrRep} $0 ${PRODUCT_EXE_FILE} ".exe" "64.exe.vmoptions"
+ Push "$INSTDIR\bin\$0"
+ Call un.compareFileInstallationTime
+ ${If} $9 != "Modified"
+ RMDir /r "$INSTDIR"
+ ${Else}
+ !include "unidea_win.nsh"
+ RMDir "$INSTDIR"
+ ${EndIf}
+
+ ReadRegStr $R9 HKCU "Software\${MANUFACTURER}\${PRODUCT_REG_VER}" "MenuFolder"
+ StrCmp $R9 "" "" clear_shortcuts
+ ReadRegStr $R9 HKLM "Software\${MANUFACTURER}\${PRODUCT_REG_VER}" "MenuFolder"
+ StrCmp $R9 "" clear_Registry
+ StrCpy $baseRegKey "HKLM"
+ StrCpy $5 "Software\${MANUFACTURER}"
+; call un.winVersion
+; ${If} $0 == "1"
+; StrCpy $5 "Software\Wow6432Node\${MANUFACTURER}"
+; ${EndIf}
+clear_shortcuts:
+ ;the user has the admin rights
+; UserInfo::GetAccountType
+; Pop $R2
+ IfFileExists "$DESKTOP\${PRODUCT_FULL_NAME_WITH_VER}.lnk" keep_current_user
+ SetShellVarContext all
+keep_current_user:
+ DetailPrint "Start Menu: $SMPROGRAMS\$R9\${PRODUCT_FULL_NAME_WITH_VER}"
+
+ Delete "$SMPROGRAMS\$R9\${PRODUCT_FULL_NAME_WITH_VER}.lnk"
+; Delete "$SMPROGRAMS\$R9\Uninstall ${PRODUCT_FULL_NAME_WITH_VER}.lnk"
+; Delete only if empty (last IDEA version is uninstalled)
+ RMDir "$SMPROGRAMS\$R9"
+
+ Delete "$DESKTOP\${PRODUCT_FULL_NAME_WITH_VER}.lnk"
+ Delete "$QUICKLAUNCH\${PRODUCT_FULL_NAME_WITH_VER}.lnk"
+
+clear_Registry:
+ StrCpy $5 "Software\${MANUFACTURER}"
+; call un.winVersion
+; ${If} $0 == "1"
+; StrCpy $5 "Software\Wow6432Node\${MANUFACTURER}"
+; ${EndIf}
+
+ StrCpy $0 $baseRegKey
+ StrCpy $1 "$5\${PRODUCT_REG_VER}"
+ StrCpy $2 "MenuFolder"
+ Call un.OMDeleteRegValue
+
+ StrCmp "${ASSOCIATION}" "NoAssociation" finish_uninstall
+ push "${ASSOCIATION}"
+loop:
+ call un.SplitStr
+ Pop $0
+ StrCmp $0 "" finish_uninstall
+ StrCpy $1 $0
+ StrCpy $2 "backup_val"
+ Call un.ReturnBackupRegValue
+ goto loop
+finish_uninstall:
+ StrCpy $1 "$5\${PRODUCT_REG_VER}"
+ StrCpy $2 "Build"
+ Call un.OMDeleteRegValue
+ StrCpy $2 ""
+ Call un.OMDeleteRegValue
+
+ StrCpy $1 "$5\${PRODUCT_REG_VER}"
+ Call un.OMDeleteRegKeyIfEmpty
+
+ StrCpy $1 "$5\${MUI_PRODUCT}"
+ Call un.OMDeleteRegKeyIfEmpty
+
+ StrCpy $1 "$5"
+ Call un.OMDeleteRegKeyIfEmpty
+
+ DeleteRegKey SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_WITH_VER}"
+
+; UNCOMMENT THIS IN RELEASE BUILD
+; ExecShell "" "http://www.jetbrains.com/idea/uninstall/"
+
+SectionEnd
diff --git a/python/edu/build/plugin-list.txt b/python/edu/build/plugin-list.txt
index ceaa60895918..bc4b94c9e7f4 100644
--- a/python/edu/build/plugin-list.txt
+++ b/python/edu/build/plugin-list.txt
@@ -2,10 +2,6 @@ svn4idea
git4idea
remote-servers-git
github
-terminal
IntelliLang
-IntelliLang-xml
-IntelliLang-js
IntelliLang-python
-rest
-python-rest
+learn-python \ No newline at end of file
diff --git a/python/edu/build/pycharm_edu_build.gant b/python/edu/build/pycharm_edu_build.gant
index 8c857c159874..2ef0bed607a7 100644
--- a/python/edu/build/pycharm_edu_build.gant
+++ b/python/edu/build/pycharm_edu_build.gant
@@ -13,26 +13,22 @@
* 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))
+import org.jetbrains.jps.LayoutInfo
-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")
+setProperty("home", getHome())
+includeTargets << new File("$home/community/build/scripts/utils.gant")
+includeTargets << new File("$home/community/build/scripts/libLicenses.gant")
+includeTargets << new File("$home/build/scripts/ultimate_utils.gant")
requireProperty("buildNumber", requireProperty("build.number", snapshot))
-
-setProperty("ch", "$home")
+setProperty("buildName", "PE-$buildNumber")
+setProperty("ch", "$home/community")
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())
@@ -40,6 +36,12 @@ setProperty("jdk16", guessJdk())
//modules to compile
setProperty("pluginFilter", new File("$pythonEduHome/build/plugin-list.txt").readLines())
+private String getHome(){
+ // current file is supposed to be at build/scripts/*.gant path
+ String uri = this["gant.file"]
+ return new File(new URI(uri).getSchemeSpecificPart()).getParentFile().getParentFile().getParentFile().getParentFile().getParentFile()
+}
+
private List<String> pycharmPlatformApiModules() {
return [platformApiModules, "dom-openapi"].flatten()
}
@@ -93,6 +95,10 @@ target('default': "Build artifacts") {
loadProject()
+ List resourcePaths = ["$ch/community-resources/src",
+ "$ch/platform/icons/src",
+ "$pythonEduHome/resources"]
+
projectBuilder.stage("Cleaning up sandbox folder")
projectBuilder.targetFolder = "${paths.sandbox}/classes"
@@ -126,6 +132,8 @@ target('default': "Build artifacts") {
exclude(name: "intentionDescriptions")
exclude(name: "tips/**/*")
exclude(name: "tips")
+ exclude(name: "courses")
+ exclude(name: "courses/*")
}
zipSources(home, paths.artifacts)
@@ -135,13 +143,9 @@ target('default': "Build artifacts") {
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)
+ def extraArgs = ["build.code": "pycharm${buildName}", "build.number": "PE-$buildNumber", "artifacts.path": "${paths.artifacts}"]
+ signMacZip("pycharm", extraArgs + ["sitFileName": "pycharm${buildName}-jdk-bundled", "jdk_archive_name": "jdk_mac_redist_for_${buildNumber}.tar"])
+ buildDmg("pycharm", "${pythonEduHome}/build/DMG_background.png", extraArgs + ["sitFileName": "pycharm${buildName}-jdk-bundled", "jdk_archive_name": "jdk_mac_redist_for_${buildNumber}.tar"])
}
@@ -152,7 +156,7 @@ public layoutEducational(String classesPath, Set usedJars) {
usedJars = collectUsedJars(modules(), approvedJars(), ["/ant/"], null)
}
- def appInfo = appInfoFile(classesPath)
+ def appInfo = appInfoFile()
def paths = new Paths(home)
buildSearchableOptions("${projectBuilder.moduleOutput(findModule("platform-resources"))}/search", [], {
projectBuilder.moduleRuntimeClasspath(findModule("main_pycharm_edu"), false).each {
@@ -181,30 +185,42 @@ public layoutEducational(String classesPath, Set usedJars) {
def launcher = "${paths.distWin}/bin/pycharm.exe"
List resourcePaths = ["$ch/community-resources/src",
"$ch/platform/icons/src",
+ "$pythonCommunityHome/resources",
"$pythonEduHome/resources"]
- buildWinLauncher("$ch", "$ch/bin/WinLauncher/WinLauncher.exe", launcher,
+ buildWinLauncher(ch, "$ch/bin/WinLauncher/WinLauncher.exe", launcher,
appInfo, "$pythonEduHome/build/pycharm_edu_launcher.properties", system_selector, resourcePaths)
+ //signExe(launcher)
+ executeExternalAnt(["dirName": "${paths.distWin}/bin", "fileName": "pycharm.exe"], "$home/build/signBuild.xml")
- buildWinZip("${paths.artifacts}/pycharmPE-${buildNumber}.zip", [paths.distAll, paths.distWin])
+ buildWinZip("${paths.artifacts}/pycharm${buildName}.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])
+ buildNSIS([paths.distAll, paths.distWin],
+ "$pythonEduHome/build/strings.nsi", "$pythonEduHome/build/paths.nsi",
+ "pycharmPE-", false, true, ".py", system_selector)
- 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)
+ String tarRoot = isEap() ? "pycharm-pe-$buildNumber" : "pycharm-pe-${p("component.version.major")}.${p("component.version.minor")}"
+ buildTarGz(tarRoot, "$paths.artifacts/pycharm${buildName}.tar", [paths.distAll, paths.distUnix])
+
+ String macAppRoot = isEap() ? "PyCharm PE ${p("component.version.major")}.${p("component.version.minor")} EAP.app/Contents" : "PyCharm PE.app/Contents"
+ buildMacZip(macAppRoot, "${paths.artifacts}/pycharm${buildName}.sit", [paths.distAll], paths.distMac)
+ ant.copy(file: "${paths.artifacts}/pycharm${buildName}.sit", tofile: "${paths.artifacts}/pycharm${buildName}-jdk-bundled.sit")
+ ant.delete(file: "${paths.artifacts}/pycharm${buildName}.sit")
}
private layoutPlugins(layouts) {
dir("plugins") {
- layouts.layoutPlugin("rest")
- layouts.layoutPlugin("python-rest")
+ layouts.layoutPlugin("learn-python") {
+ dir("courses") {
+ fileset(dir: "$pythonEduHome/learn-python/resources/courses")
+ }
+ }
}
layouts.layoutCommunityPlugins(ch)
}
-private String appInfoFile(String classesPath) {
- return "$classesPath/python-educational/idea/PyCharmEduApplicationInfo.xml"
+private String appInfoFile() {
+ return "$pythonEduHome/resources/idea/PyCharmEduApplicationInfo.xml"
}
private layoutFull(Map args, String target, Set usedJars) {
diff --git a/python/edu/build/resources/logo.bmp b/python/edu/build/resources/logo.bmp
deleted file mode 100644
index 0f0f82da7b1e..000000000000
--- a/python/edu/build/resources/logo.bmp
+++ /dev/null
Binary files differ
diff --git a/python/edu/build/resources/logo.png b/python/edu/build/resources/logo.png
new file mode 100644
index 000000000000..1ccbc0773837
--- /dev/null
+++ b/python/edu/build/resources/logo.png
Binary files differ
diff --git a/python/edu/learn-python/gen/icons/StudyIcons.java b/python/edu/learn-python/gen/icons/StudyIcons.java
new file mode 100644
index 000000000000..28409103ea00
--- /dev/null
+++ b/python/edu/learn-python/gen/icons/StudyIcons.java
@@ -0,0 +1,29 @@
+package icons;
+
+import com.intellij.openapi.util.IconLoader;
+
+import javax.swing.*;
+
+/**
+ * NOTE THIS FILE IS AUTO-GENERATED
+ * DO NOT EDIT IT BY HAND, run build/scripts/icons.gant instead
+ */
+public class StudyIcons {
+ private static Icon load(String path) {
+ return IconLoader.getIcon(path, StudyIcons.class);
+ }
+
+ public static final Icon Add = load("/icons/com/jetbrains/python/edu/add.png"); // 16x16
+ public static final Icon Checked = load("/icons/com/jetbrains/python/edu/checked.png"); // 32x32
+ public static final Icon Failed = load("/icons/com/jetbrains/python/edu/failed.png"); // 32x32
+ public static final Icon Next = load("/icons/com/jetbrains/python/edu/next.png"); // 24x24
+ public static final Icon Playground = load("/icons/com/jetbrains/python/edu/playground.png"); // 32x28
+ public static final Icon Prev = load("/icons/com/jetbrains/python/edu/prev.png"); // 24x24
+ public static final Icon Refresh = load("/icons/com/jetbrains/python/edu/refresh.png"); // 16x16
+ public static final Icon Refresh24 = load("/icons/com/jetbrains/python/edu/refresh24.png"); // 24x24
+ public static final Icon Resolve = load("/icons/com/jetbrains/python/edu/resolve.png"); // 24x24
+ public static final Icon Run = load("/icons/com/jetbrains/python/edu/Run.png"); // 24x24
+ public static final Icon ShowHint = load("/icons/com/jetbrains/python/edu/showHint.png"); // 24x24
+ public static final Icon Unchecked = load("/icons/com/jetbrains/python/edu/unchecked.png"); // 32x32
+ public static final Icon WatchInput = load("/icons/com/jetbrains/python/edu/WatchInput.png"); // 24x24
+}
diff --git a/python/edu/learn-python/learn-python.iml b/python/edu/learn-python/learn-python.iml
new file mode 100644
index 000000000000..bd539d1e2147
--- /dev/null
+++ b/python/edu/learn-python/learn-python.iml
@@ -0,0 +1,20 @@
+<?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$/tests" isTestSource="true" />
+ <sourceFolder url="file://$MODULE_DIR$/gen" isTestSource="false" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/resources" type="java-resource" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="module" module-name="platform-impl" />
+ <orderEntry type="module" module-name="python-community" />
+ <orderEntry type="module" module-name="lang-impl" />
+ <orderEntry type="library" name="gson" level="project" />
+ <orderEntry type="library" name="JUnit4" level="project" />
+ </component>
+</module>
+
diff --git a/python/edu/learn-python/resources/META-INF/plugin.xml b/python/edu/learn-python/resources/META-INF/plugin.xml
new file mode 100644
index 000000000000..ec828eb44d59
--- /dev/null
+++ b/python/edu/learn-python/resources/META-INF/plugin.xml
@@ -0,0 +1,73 @@
+<!--suppress XmlUnboundNsPrefix -->
+<idea-plugin version="2">
+ <id>com.jetbrains.python.edu.learn-python</id>
+ <name>Educational plugin for PyCharm</name>
+ <version>1.0</version>
+ <vendor email="support@yourcompany.com" url="http://www.yourcompany.com">YourCompany</vendor>
+
+ <description><![CDATA[
+
+ ]]></description>
+
+ <change-notes><![CDATA[
+
+ ]]>
+ </change-notes>
+
+ <!--depends>com.intellij.modules.python</depends-->
+
+ <!-- please see http://confluence.jetbrains.net/display/IDEADEV/Plugin+Compatibility+with+IntelliJ+Platform+Products
+ on how to target different products -->
+
+ <depends>com.intellij.modules.lang</depends>
+ <depends>com.intellij.modules.python</depends>
+ <application-components>
+ </application-components>
+
+ <project-components>
+ <component>
+ <implementation-class>com.jetbrains.python.edu.StudyTaskManager</implementation-class>
+ <interface-class>com.jetbrains.python.edu.StudyTaskManager</interface-class>
+ </component>
+ </project-components>
+
+ <application-components>
+ <component>
+ <implementation-class>com.jetbrains.python.edu.StudyInitialConfigurator</implementation-class>
+ <headless-implementation-class/>
+ </component>
+ </application-components>
+
+ <actions>
+ <action id="CheckAction" class="com.jetbrains.python.edu.actions.StudyCheckAction" text="check"
+ description="Runs tests for current tasks" icon="/icons/icon.jpg">
+ </action>
+ <action id="PrevWindowAction" class="com.jetbrains.python.edu.actions.StudyPrevWindowAction" text="PrevWindowAction" description="prev">
+ </action>
+
+ <action id="NextWindow" class="com.jetbrains.python.edu.actions.StudyNextWindowAction" text="NextWindowAction" description="next">
+ </action>
+ <action id="NextTaskAction" class="com.jetbrains.python.edu.actions.StudyNextStudyTaskAction" text="NextTaskAction" description="Next Task"/>
+ <action id="PreviousTaskAction" class="com.jetbrains.python.edu.actions.StudyPreviousStudyTaskAction" text="PreviousTaskAction"
+ description="Previous Task"/>
+ <action id="RefreshTaskAction" class="com.jetbrains.python.edu.actions.StudyRefreshTaskAction" text="RefreshTaskAction"
+ description="Refresh current task"/>
+ <action id="WatchInputAction" class="com.jetbrains.python.edu.actions.StudyEditInputAction" text="WatchInputAction"
+ description="watch input"/>
+ <action id="StudyRunAction" class="com.jetbrains.python.edu.actions.StudyRunAction" text="StudyRunAction" description="run your code"/>
+ <action id="ShowHintAction" class="com.jetbrains.python.edu.actions.StudyShowHintAction" text="Show hint"
+ description="show hint">
+ <add-to-group group-id="MainToolBar" anchor="last"/>
+ </action>
+ </actions>
+
+ <extensions defaultExtensionNs="com.intellij">
+ <toolWindow id="Course Description" anchor="right" factoryClass="com.jetbrains.python.edu.ui.StudyToolWindowFactory" conditionClass="com.jetbrains.python.edu.ui.StudyCondition"/>
+ <fileEditorProvider implementation="com.jetbrains.python.edu.editor.StudyFileEditorProvider"/>
+ <directoryProjectGenerator implementation="com.jetbrains.python.edu.StudyDirectoryProjectGenerator"/>
+ <treeStructureProvider implementation="com.jetbrains.python.edu.projectView.StudyTreeStructureProvider"/>
+ <highlightErrorFilter implementation="com.jetbrains.python.edu.StudyHighlightErrorFilter"/>
+ <applicationService serviceInterface="com.intellij.openapi.fileEditor.impl.EditorEmptyTextPainter"
+ serviceImplementation="com.jetbrains.python.edu.StudyInstructionPainter" overrides="true"/>
+ </extensions>
+</idea-plugin> \ No newline at end of file
diff --git a/python/edu/learn-python/resources/com/jetbrains/python/edu/user_tester.py b/python/edu/learn-python/resources/com/jetbrains/python/edu/user_tester.py
new file mode 100644
index 000000000000..c17e6cdd7479
--- /dev/null
+++ b/python/edu/learn-python/resources/com/jetbrains/python/edu/user_tester.py
@@ -0,0 +1,58 @@
+import sys
+import imp
+import os
+import subprocess
+
+USER_TESTS = "userTests"
+
+TEST_FAILED = "FAILED"
+
+TEST_PASSED = "PASSED"
+
+INPUT = "input"
+OUTPUT = "output"
+
+
+def get_index(logical_name, full_name):
+ logical_name_len = len(logical_name)
+ if full_name[:logical_name_len] == logical_name:
+ return int(full_name[logical_name_len])
+ return -1
+
+
+def process_user_tests(file_path):
+ user_tests = []
+ imp.load_source('user_file', file_path)
+ user_tests_dir_path = os.path.abspath(os.path.join(file_path, os.pardir, USER_TESTS))
+ user_test_files = os.listdir(user_tests_dir_path)
+ for user_file in user_test_files:
+ index = get_index(INPUT, user_file)
+ if index == -1:
+ continue
+ output = OUTPUT + str(index)
+ if output in user_test_files:
+ input_path = os.path.abspath(os.path.join(user_tests_dir_path, user_file))
+ output_path = os.path.abspath(os.path.join(user_tests_dir_path, output))
+ user_tests.append((input_path, output_path, index))
+ return sorted(user_tests, key=(lambda x: x[2]))
+
+
+def run_user_test(python, executable_path):
+ user_tests = process_user_tests(executable_path)
+ for test in user_tests:
+ input, output, index = test
+ test_output = subprocess.check_output([python, executable_path, input])
+ expected_output = open(output).read()
+ test_status = TEST_PASSED if test_output == expected_output else TEST_FAILED
+ print "TEST" + str(index) + " " + test_status
+ print "OUTPUT:"
+ print test_output + "\n"
+ if test_status == TEST_FAILED:
+ print "EXPECTED OUTPUT:"
+ print expected_output + "\n"
+
+
+if __name__ == "__main__":
+ python = sys.argv[1]
+ executable_path = sys.argv[2]
+ run_user_test(python , executable_path) \ No newline at end of file
diff --git a/python/edu/learn-python/resources/courses/introduction_course.zip b/python/edu/learn-python/resources/courses/introduction_course.zip
new file mode 100644
index 000000000000..f3b24f24b1e2
--- /dev/null
+++ b/python/edu/learn-python/resources/courses/introduction_course.zip
Binary files differ
diff --git a/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/Run.png b/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/Run.png
new file mode 100644
index 000000000000..27a6e362cded
--- /dev/null
+++ b/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/Run.png
Binary files differ
diff --git a/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/WatchInput.png b/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/WatchInput.png
new file mode 100644
index 000000000000..4992191eb9e7
--- /dev/null
+++ b/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/WatchInput.png
Binary files differ
diff --git a/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/add.png b/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/add.png
new file mode 100644
index 000000000000..9494f2d0c72e
--- /dev/null
+++ b/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/add.png
Binary files differ
diff --git a/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/checked.png b/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/checked.png
new file mode 100644
index 000000000000..4105a01f1353
--- /dev/null
+++ b/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/checked.png
Binary files differ
diff --git a/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/failed.png b/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/failed.png
new file mode 100644
index 000000000000..e2aaa556056e
--- /dev/null
+++ b/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/failed.png
Binary files differ
diff --git a/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/icon.jpg b/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/icon.jpg
new file mode 100644
index 000000000000..3a9716e4e1fb
--- /dev/null
+++ b/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/icon.jpg
Binary files differ
diff --git a/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/next.png b/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/next.png
new file mode 100644
index 000000000000..dd1a5d9aebf3
--- /dev/null
+++ b/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/next.png
Binary files differ
diff --git a/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/playground.png b/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/playground.png
new file mode 100644
index 000000000000..d12a751c0c40
--- /dev/null
+++ b/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/playground.png
Binary files differ
diff --git a/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/prev.png b/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/prev.png
new file mode 100644
index 000000000000..0656f81eee83
--- /dev/null
+++ b/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/prev.png
Binary files differ
diff --git a/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/refresh.png b/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/refresh.png
new file mode 100644
index 000000000000..d595f6b42f56
--- /dev/null
+++ b/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/refresh.png
Binary files differ
diff --git a/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/refresh24.png b/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/refresh24.png
new file mode 100644
index 000000000000..218f075d0c18
--- /dev/null
+++ b/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/refresh24.png
Binary files differ
diff --git a/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/resolve.png b/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/resolve.png
new file mode 100644
index 000000000000..7ef960bcf244
--- /dev/null
+++ b/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/resolve.png
Binary files differ
diff --git a/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/resolve_dark.png b/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/resolve_dark.png
new file mode 100644
index 000000000000..99aaa1d20a32
--- /dev/null
+++ b/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/resolve_dark.png
Binary files differ
diff --git a/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/showHint.png b/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/showHint.png
new file mode 100644
index 000000000000..f10fd560464a
--- /dev/null
+++ b/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/showHint.png
Binary files differ
diff --git a/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/unchecked.png b/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/unchecked.png
new file mode 100644
index 000000000000..2145982cf2be
--- /dev/null
+++ b/python/edu/learn-python/resources/icons/com/jetbrains/python/edu/unchecked.png
Binary files differ
diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/StudyDirectoryProjectGenerator.java b/python/edu/learn-python/src/com/jetbrains/python/edu/StudyDirectoryProjectGenerator.java
new file mode 100644
index 000000000000..d4831d93e367
--- /dev/null
+++ b/python/edu/learn-python/src/com/jetbrains/python/edu/StudyDirectoryProjectGenerator.java
@@ -0,0 +1,393 @@
+package com.jetbrains.python.edu;
+
+import com.google.gson.*;
+import com.google.gson.stream.JsonReader;
+import com.intellij.facet.ui.FacetEditorValidator;
+import com.intellij.facet.ui.FacetValidatorsManager;
+import com.intellij.facet.ui.ValidationResult;
+import com.intellij.lang.javascript.boilerplate.GithubDownloadUtil;
+import com.intellij.openapi.application.PathManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.progress.ProcessCanceledException;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.vfs.VirtualFileManager;
+import com.intellij.platform.DirectoryProjectGenerator;
+import com.intellij.platform.templates.github.GeneratorException;
+import com.intellij.platform.templates.github.ZipUtil;
+import com.jetbrains.python.edu.course.Course;
+import com.jetbrains.python.edu.course.CourseInfo;
+import com.jetbrains.python.edu.ui.StudyNewProjectPanel;
+import com.jetbrains.python.newProject.PythonProjectGenerator;
+import icons.StudyIcons;
+import org.jetbrains.annotations.Nls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.io.*;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+
+public class StudyDirectoryProjectGenerator extends PythonProjectGenerator implements DirectoryProjectGenerator {
+ private static final Logger LOG = Logger.getInstance(StudyDirectoryProjectGenerator.class.getName());
+ private static final String REPO_URL = "https://github.com/JetBrains/pycharm-courses/archive/master.zip";
+ private static final String USER_NAME = "PyCharm";
+ private static final String COURSE_META_FILE = "course.json";
+ private static final String COURSE_NAME_ATTRIBUTE = "name";
+ private static final Pattern CACHE_PATTERN = Pattern.compile("(name=(.*)) (path=(.*course.json)) (author=(.*)) (description=(.*))");
+ private static final String REPOSITORY_NAME = "pycharm-courses";
+ public static final String AUTHOR_ATTRIBUTE = "author";
+ private final File myCoursesDir = new File(PathManager.getConfigPath(), "courses");
+ private static final String CACHE_NAME = "courseNames.txt";
+ private Map<CourseInfo, File> myCourses = new HashMap<CourseInfo, File>();
+ private File mySelectedCourseFile;
+ private Project myProject;
+ public ValidationResult myValidationResult = new ValidationResult("selected course is not valid");
+
+ @Nls
+ @NotNull
+ @Override
+ public String getName() {
+ return "Study project";
+ }
+
+
+ public void setCourses(Map<CourseInfo, File> courses) {
+ myCourses = courses;
+ }
+
+ /**
+ * Finds selected course in courses by name.
+ *
+ * @param courseName name of selected course
+ */
+ public void setSelectedCourse(@NotNull CourseInfo courseName) {
+ File courseFile = myCourses.get(courseName);
+ if (courseFile == null) {
+ LOG.error("invalid course in list");
+ }
+ mySelectedCourseFile = courseFile;
+ }
+
+ /**
+ * Adds course to courses specified in params
+ *
+ * @param courseDir must be directory containing course file
+ * @return added course name or null if course is invalid
+ */
+ @Nullable
+ private static CourseInfo addCourse(Map<CourseInfo, File> courses, File courseDir) {
+ if (courseDir.isDirectory()) {
+ File[] courseFiles = courseDir.listFiles(new FilenameFilter() {
+ @Override
+ public boolean accept(File dir, String name) {
+ return name.equals(COURSE_META_FILE);
+ }
+ });
+ if (courseFiles.length != 1) {
+ LOG.info("User tried to add course with more than one or without course files");
+ return null;
+ }
+ File courseFile = courseFiles[0];
+ CourseInfo courseInfo = getCourseInfo(courseFile);
+ if (courseInfo != null) {
+ courses.put(courseInfo, courseFile);
+ }
+ return courseInfo;
+ }
+ return null;
+ }
+
+
+ /**
+ * Adds course from zip archive to courses
+ *
+ * @return added course name or null if course is invalid
+ */
+ @Nullable
+ public CourseInfo addLocalCourse(String zipFilePath) {
+ File file = new File(zipFilePath);
+ try {
+ String fileName = file.getName();
+ String unzippedName = fileName.substring(0, fileName.indexOf("."));
+ File courseDir = new File(myCoursesDir, unzippedName);
+ ZipUtil.unzip(null, courseDir, file, null, null, true);
+ CourseInfo courseName = addCourse(myCourses, courseDir);
+ flushCache();
+ return courseName;
+ }
+ catch (IOException e) {
+ LOG.error("Failed to unzip course archive");
+ LOG.error(e);
+ }
+ return null;
+ }
+
+ @Nullable
+ @Override
+ public Object showGenerationSettings(VirtualFile baseDir) throws ProcessCanceledException {
+ return null;
+ }
+
+ @Nullable
+ @Override
+ public Icon getLogo() {
+ return StudyIcons.Playground;
+ }
+
+
+ @Override
+ public void generateProject(@NotNull final Project project, @NotNull final VirtualFile baseDir,
+ @Nullable Object settings, @NotNull Module module) {
+
+ myProject = project;
+ Reader reader = null;
+ try {
+ reader = new InputStreamReader(new FileInputStream(mySelectedCourseFile));
+ Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create();
+ Course course = gson.fromJson(reader, Course.class);
+ course.init(false);
+ course.create(baseDir, new File(mySelectedCourseFile.getParent()));
+ course.setResourcePath(mySelectedCourseFile.getAbsolutePath());
+ VirtualFileManager.getInstance().refreshWithoutFileWatcher(true);
+ StudyTaskManager.getInstance(project).setCourse(course);
+ }
+ catch (FileNotFoundException e) {
+ LOG.error(e);
+ }
+ finally {
+ StudyUtils.closeSilently(reader);
+ }
+ }
+
+ /**
+ * Downloads courses from {@link com.jetbrains.python.edu.StudyDirectoryProjectGenerator#REPO_URL}
+ * and unzips them into {@link com.jetbrains.python.edu.StudyDirectoryProjectGenerator#myCoursesDir}
+ */
+
+ public void downloadAndUnzip(boolean needProgressBar) {
+ File outputFile = new File(PathManager.getConfigPath(), "courses.zip");
+ try {
+ if (!needProgressBar) {
+ GithubDownloadUtil.downloadAtomically(null, REPO_URL,
+ outputFile, USER_NAME, REPOSITORY_NAME);
+ }
+ else {
+ GithubDownloadUtil.downloadContentToFileWithProgressSynchronously(myProject, REPO_URL, "downloading courses", outputFile, USER_NAME,
+ REPOSITORY_NAME, false);
+ }
+ if (outputFile.exists()) {
+ ZipUtil.unzip(null, myCoursesDir, outputFile, null, null, true);
+ if (!outputFile.delete()) {
+ LOG.error("Failed to delete", outputFile.getName());
+ }
+ File[] files = myCoursesDir.listFiles();
+ if (files != null) {
+ for (File file : files) {
+ String fileName = file.getName();
+ if (StudyUtils.isZip(fileName)) {
+ ZipUtil.unzip(null, new File(myCoursesDir, fileName.substring(0, fileName.indexOf("."))), file, null, null, true);
+ if (!file.delete()) {
+ LOG.error("Failed to delete", fileName);
+ }
+ }
+ }
+ }
+ } else {
+ LOG.debug("failed to download course");
+ }
+ }
+ catch (IOException e) {
+ LOG.error(e);
+ }
+ catch (GeneratorException e) {
+ LOG.error(e);
+ }
+ }
+
+ public Map<CourseInfo, File> getLoadedCourses() {
+ return myCourses;
+ }
+
+ /**
+ * Parses courses located in {@link com.jetbrains.python.edu.StudyDirectoryProjectGenerator#myCoursesDir}
+ * to {@link com.jetbrains.python.edu.StudyDirectoryProjectGenerator#myCourses}
+ *
+ * @return map with course names and course files location
+ */
+ public Map<CourseInfo, File> loadCourses() {
+ Map<CourseInfo, File> courses = new HashMap<CourseInfo, File>();
+ if (myCoursesDir.exists()) {
+ File[] courseDirs = myCoursesDir.listFiles(new FileFilter() {
+ @Override
+ public boolean accept(File pathname) {
+ return pathname.isDirectory();
+ }
+ });
+ for (File courseDir : courseDirs) {
+ addCourse(courses, courseDir);
+ }
+ }
+ return courses;
+ }
+
+ /**
+ * Parses course json meta file and finds course name
+ *
+ * @return information about course or null if course file is invalid
+ */
+ @Nullable
+ private static CourseInfo getCourseInfo(File courseFile) {
+ CourseInfo courseInfo = null;
+ BufferedReader reader = null;
+ try {
+ if (courseFile.getName().equals(COURSE_META_FILE)) {
+ reader = new BufferedReader(new InputStreamReader(new FileInputStream(courseFile)));
+ JsonReader r = new JsonReader(reader);
+ JsonParser parser = new JsonParser();
+ JsonElement el = parser.parse(r);
+ String courseName = el.getAsJsonObject().get(COURSE_NAME_ATTRIBUTE).getAsString();
+ String courseAuthor = el.getAsJsonObject().get(AUTHOR_ATTRIBUTE).getAsString();
+ String courseDescription = el.getAsJsonObject().get("description").getAsString();
+ courseInfo = new CourseInfo(courseName, courseAuthor, courseDescription);
+ }
+ }
+ catch (Exception e) {
+ //error will be shown in UI
+ }
+ finally {
+ StudyUtils.closeSilently(reader);
+ }
+ return courseInfo;
+ }
+
+ @NotNull
+ @Override
+ public ValidationResult validate(@NotNull String s) {
+ return myValidationResult;
+ }
+
+ public void setValidationResult(ValidationResult validationResult) {
+ myValidationResult = validationResult;
+ }
+
+ /**
+ * @return courses from memory or from cash file or parses course directory
+ */
+ public Map<CourseInfo, File> getCourses() {
+ if (!myCourses.isEmpty()) {
+ return myCourses;
+ }
+ if (myCoursesDir.exists()) {
+ File cacheFile = new File(myCoursesDir, CACHE_NAME);
+ if (cacheFile.exists()) {
+ myCourses = getCoursesFromCache(cacheFile);
+ if (!myCourses.isEmpty()) {
+ return myCourses;
+ }
+ }
+ myCourses = loadCourses();
+ if (!myCourses.isEmpty()) {
+ return myCourses;
+ }
+ }
+ downloadAndUnzip(false);
+ myCourses = loadCourses();
+ flushCache();
+ return myCourses;
+ }
+
+ /**
+ * Writes courses to cash file {@link com.jetbrains.python.edu.StudyDirectoryProjectGenerator#CACHE_NAME}
+ */
+ @SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
+ public void flushCache() {
+ File cashFile = new File(myCoursesDir, CACHE_NAME);
+ PrintWriter writer = null;
+ try {
+ if (!cashFile.exists()) {
+ final boolean created = cashFile.createNewFile();
+ if (!created) {
+ LOG.error("Cannot flush courses cache. Can't create " + CACHE_NAME + " file");
+ return;
+ }
+ }
+ writer = new PrintWriter(cashFile);
+ for (Map.Entry<CourseInfo, File> course : myCourses.entrySet()) {
+ CourseInfo courseInfo = course.getKey();
+ String line = String
+ .format("name=%s path=%s author=%s description=%s", courseInfo.getName(), course.getValue(), courseInfo.getAuthor(),
+ courseInfo.getDescription());
+ writer.println(line);
+ }
+ }
+ catch (FileNotFoundException e) {
+ LOG.error(e);
+ }
+ catch (IOException e) {
+ LOG.error(e);
+ }
+ finally {
+ StudyUtils.closeSilently(writer);
+ }
+ }
+
+ /**
+ * Loads courses from {@link com.jetbrains.python.edu.StudyDirectoryProjectGenerator#CACHE_NAME} file
+ *
+ * @return map of course names and course files
+ */
+ @SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
+ private static Map<CourseInfo, File> getCoursesFromCache(File cashFile) {
+ Map<CourseInfo, File> coursesFromCash = new HashMap<CourseInfo, File>();
+ BufferedReader reader = null;
+ try {
+ reader = new BufferedReader(new InputStreamReader(new FileInputStream(cashFile)));
+ String line;
+
+ while ((line = reader.readLine()) != null) {
+ Matcher matcher = CACHE_PATTERN.matcher(line);
+ if (matcher.matches()) {
+ String courseName = matcher.group(2);
+ File file = new File(matcher.group(4));
+ String author = matcher.group(6);
+ String description = matcher.group(8);
+ CourseInfo courseInfo = new CourseInfo(courseName, author, description);
+ if (file.exists()) {
+ coursesFromCash.put(courseInfo, file);
+ }
+ }
+ }
+ }
+ catch (FileNotFoundException e) {
+ LOG.error(e);
+ }
+ catch (IOException e) {
+ LOG.error(e);
+ }
+ finally {
+ StudyUtils.closeSilently(reader);
+ }
+ return coursesFromCash;
+ }
+
+ @Nullable
+ @Override
+ public JPanel extendBasePanel() throws ProcessCanceledException {
+ StudyNewProjectPanel settingsPanel = new StudyNewProjectPanel(this);
+ settingsPanel.registerValidators(new FacetValidatorsManager() {
+ public void registerValidator(FacetEditorValidator validator, JComponent... componentsToWatch) {
+ throw new UnsupportedOperationException();
+ }
+ public void validate() {
+ fireStateChanged();
+ }
+ });
+ return settingsPanel.getContentPanel();
+ }
+}
diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/StudyDocumentListener.java b/python/edu/learn-python/src/com/jetbrains/python/edu/StudyDocumentListener.java
new file mode 100644
index 000000000000..9fdcf704a29b
--- /dev/null
+++ b/python/edu/learn-python/src/com/jetbrains/python/edu/StudyDocumentListener.java
@@ -0,0 +1,65 @@
+package com.jetbrains.python.edu;
+
+
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.LogicalPosition;
+import com.intellij.openapi.editor.event.DocumentAdapter;
+import com.intellij.openapi.editor.event.DocumentEvent;
+import com.intellij.openapi.editor.impl.event.DocumentEventImpl;
+import com.jetbrains.python.edu.course.TaskFile;
+import com.jetbrains.python.edu.course.TaskWindow;
+
+/**
+ * author: liana
+ * data: 7/16/14.
+ * Listens changes in study files and updates
+ * coordinates of all the windows in current task file
+ */
+public class StudyDocumentListener extends DocumentAdapter {
+ private final TaskFile myTaskFile;
+ private int oldLine;
+ private int oldLineStartOffset;
+ private TaskWindow myTaskWindow;
+
+ public StudyDocumentListener(TaskFile taskFile) {
+ myTaskFile = taskFile;
+ }
+
+
+ //remembering old end before document change because of problems
+ // with fragments containing "\n"
+ @Override
+ public void beforeDocumentChange(DocumentEvent e) {
+ int offset = e.getOffset();
+ int oldEnd = offset + e.getOldLength();
+ Document document = e.getDocument();
+ oldLine = document.getLineNumber(oldEnd);
+ oldLineStartOffset = document.getLineStartOffset(oldLine);
+ int line = document.getLineNumber(offset);
+ int offsetInLine = offset - document.getLineStartOffset(line);
+ LogicalPosition pos = new LogicalPosition(line, offsetInLine);
+ myTaskWindow = myTaskFile.getTaskWindow(document, pos);
+
+ }
+
+ @Override
+ public void documentChanged(DocumentEvent e) {
+ if (e instanceof DocumentEventImpl) {
+ DocumentEventImpl event = (DocumentEventImpl)e;
+ Document document = e.getDocument();
+ int offset = e.getOffset();
+ int change = event.getNewLength() - event.getOldLength();
+ if (myTaskWindow != null) {
+ int newLength = myTaskWindow.getLength() + change;
+ myTaskWindow.setLength(newLength <= 0 ? 0 : newLength);
+ }
+ int newEnd = offset + event.getNewLength();
+ int newLine = document.getLineNumber(newEnd);
+ int lineChange = newLine - oldLine;
+ myTaskFile.incrementLines(oldLine + 1, lineChange);
+ int newEndOffsetInLine = offset + e.getNewLength() - document.getLineStartOffset(newLine);
+ int oldEndOffsetInLine = offset + e.getOldLength() - oldLineStartOffset;
+ myTaskFile.updateLine(lineChange, oldLine, newEndOffsetInLine, oldEndOffsetInLine);
+ }
+ }
+}
diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/StudyEditorFactoryListener.java b/python/edu/learn-python/src/com/jetbrains/python/edu/StudyEditorFactoryListener.java
new file mode 100644
index 000000000000..7565d76b3acf
--- /dev/null
+++ b/python/edu/learn-python/src/com/jetbrains/python/edu/StudyEditorFactoryListener.java
@@ -0,0 +1,100 @@
+package com.jetbrains.python.edu;
+
+
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.LogicalPosition;
+import com.intellij.openapi.editor.event.EditorFactoryEvent;
+import com.intellij.openapi.editor.event.EditorFactoryListener;
+import com.intellij.openapi.editor.event.EditorMouseAdapter;
+import com.intellij.openapi.editor.event.EditorMouseEvent;
+import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.jetbrains.python.edu.course.StudyStatus;
+import com.jetbrains.python.edu.course.TaskFile;
+import com.jetbrains.python.edu.course.TaskWindow;
+import com.jetbrains.python.edu.editor.StudyEditor;
+import org.jetbrains.annotations.NotNull;
+
+import java.awt.*;
+
+
+class StudyEditorFactoryListener implements EditorFactoryListener {
+
+ /**
+ * draws selected task window if there is one located in mouse position
+ */
+ private static class WindowSelectionListener extends EditorMouseAdapter {
+ private final TaskFile myTaskFile;
+
+ WindowSelectionListener(TaskFile taskFile) {
+ myTaskFile = taskFile;
+ }
+
+ @Override
+ public void mouseClicked(EditorMouseEvent e) {
+ Editor editor = e.getEditor();
+ Point point = e.getMouseEvent().getPoint();
+ LogicalPosition pos = editor.xyToLogicalPosition(point);
+ TaskWindow taskWindow = myTaskFile.getTaskWindow(editor.getDocument(), pos);
+ if (taskWindow != null) {
+ myTaskFile.setSelectedTaskWindow(taskWindow);
+ taskWindow.draw(editor, taskWindow.getStatus() != StudyStatus.Solved, true);
+ }
+ else {
+ myTaskFile.drawAllWindows(editor);
+ }
+ }
+ }
+
+ @Override
+ public void editorCreated(@NotNull final EditorFactoryEvent event) {
+ final Editor editor = event.getEditor();
+
+ final Project project = editor.getProject();
+ if (project == null) {
+ return;
+ }
+ ApplicationManager.getApplication().invokeLater(
+ new Runnable() {
+ @Override
+ public void run() {
+ ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ @Override
+ public void run() {
+ Document document = editor.getDocument();
+ VirtualFile openedFile = FileDocumentManager.getInstance().getFile(document);
+ if (openedFile != null) {
+ StudyTaskManager taskManager = StudyTaskManager.getInstance(project);
+ TaskFile taskFile = taskManager.getTaskFile(openedFile);
+ if (taskFile != null) {
+ taskFile.navigateToFirstTaskWindow(editor);
+ editor.addEditorMouseListener(new WindowSelectionListener(taskFile));
+ StudyDocumentListener listener = new StudyDocumentListener(taskFile);
+ StudyEditor.addDocumentListener(document, listener);
+ document.addDocumentListener(listener);
+ taskFile.drawAllWindows(editor);
+ }
+ }
+ }
+ });
+ }
+ }
+ );
+ }
+
+ @Override
+ public void editorReleased(@NotNull EditorFactoryEvent event) {
+ Editor editor = event.getEditor();
+ Document document = editor.getDocument();
+ StudyDocumentListener listener = StudyEditor.getListener(document);
+ if (listener != null) {
+ document.removeDocumentListener(listener);
+ StudyEditor.removeListener(document);
+ }
+ editor.getMarkupModel().removeAllHighlighters();
+ editor.getSelectionModel().removeSelection();
+ }
+}
diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/StudyHighlightErrorFilter.java b/python/edu/learn-python/src/com/jetbrains/python/edu/StudyHighlightErrorFilter.java
new file mode 100644
index 000000000000..1377128ed417
--- /dev/null
+++ b/python/edu/learn-python/src/com/jetbrains/python/edu/StudyHighlightErrorFilter.java
@@ -0,0 +1,23 @@
+package com.jetbrains.python.edu;
+
+import com.intellij.codeInsight.highlighting.HighlightErrorFilter;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiErrorElement;
+import org.jetbrains.annotations.NotNull;
+import com.jetbrains.python.edu.course.TaskFile;
+
+/**
+ * author: liana
+ * data: 7/23/14.
+ */
+public class StudyHighlightErrorFilter extends HighlightErrorFilter {
+ @Override
+ public boolean shouldHighlightErrorElement(@NotNull final PsiErrorElement element) {
+ VirtualFile file = element.getContainingFile().getVirtualFile();
+ Project project = element.getProject();
+ StudyTaskManager taskManager = StudyTaskManager.getInstance(project);
+ TaskFile taskFile = taskManager.getTaskFile(file);
+ return taskFile == null;
+ }
+}
diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/StudyInitialConfigurator.java b/python/edu/learn-python/src/com/jetbrains/python/edu/StudyInitialConfigurator.java
new file mode 100644
index 000000000000..34776f3fabd2
--- /dev/null
+++ b/python/edu/learn-python/src/com/jetbrains/python/edu/StudyInitialConfigurator.java
@@ -0,0 +1,67 @@
+package com.jetbrains.python.edu;
+
+import com.intellij.codeInsight.CodeInsightSettings;
+import com.intellij.ide.RecentProjectsManagerBase;
+import com.intellij.ide.ui.UISettings;
+import com.intellij.ide.util.PropertiesComponent;
+import com.intellij.openapi.application.PathManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.fileTypes.FileTypeManager;
+import com.intellij.openapi.project.ex.ProjectManagerEx;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.platform.templates.github.ZipUtil;
+import com.intellij.util.PathUtil;
+import com.intellij.util.messages.MessageBus;
+import org.jetbrains.annotations.NonNls;
+
+import java.io.File;
+import java.io.IOException;
+
+@SuppressWarnings({"UtilityClassWithoutPrivateConstructor", "UtilityClassWithPublicConstructor"})
+public class StudyInitialConfigurator {
+ private static final Logger LOG = Logger.getInstance(StudyInitialConfigurator.class.getName()
+ );
+ @NonNls private static final String CONFIGURED = "StudyPyCharm.InitialConfiguration";
+
+
+ /**
+ * @noinspection UnusedParameters
+ */
+ public StudyInitialConfigurator(MessageBus bus,
+ UISettings uiSettings,
+ CodeInsightSettings codeInsightSettings,
+ final PropertiesComponent propertiesComponent,
+ FileTypeManager fileTypeManager,
+ final ProjectManagerEx projectManager,
+ RecentProjectsManagerBase recentProjectsManager) {
+ if (!propertiesComponent.getBoolean(CONFIGURED, false)) {
+ final File file = new File(getCoursesRoot(), "introduction_course.zip");
+ final File newCourses = new File(PathManager.getConfigPath(), "courses");
+ try {
+ FileUtil.createDirectory(newCourses);
+ String fileName = file.getName();
+ String unzippedName = fileName.substring(0, fileName.indexOf("."));
+ File courseDir = new File(newCourses, unzippedName);
+ ZipUtil.unzip(null, courseDir, file, null, null, true);
+
+ }
+ catch (IOException e) {
+ LOG.warn("Couldn't copy bundled courses " + e);
+ }
+ }
+ }
+
+ public static File getCoursesRoot() {
+ @NonNls String jarPath = PathUtil.getJarPathForClass(StudyInitialConfigurator.class);
+ if (jarPath.endsWith(".jar")) {
+ final File jarFile = new File(jarPath);
+
+
+ File pluginBaseDir = jarFile.getParentFile();
+ return new File(pluginBaseDir, "courses");
+ }
+
+ return new File(jarPath , "courses");
+ }
+
+}
diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/StudyInstructionPainter.java b/python/edu/learn-python/src/com/jetbrains/python/edu/StudyInstructionPainter.java
new file mode 100644
index 000000000000..4f34bfb92fab
--- /dev/null
+++ b/python/edu/learn-python/src/com/jetbrains/python/edu/StudyInstructionPainter.java
@@ -0,0 +1,47 @@
+package com.jetbrains.python.edu;
+
+import com.intellij.openapi.fileEditor.impl.EditorEmptyTextPainter;
+import com.intellij.openapi.fileEditor.impl.EditorsSplitters;
+import com.intellij.openapi.util.Couple;
+import com.intellij.ui.Gray;
+import com.intellij.ui.JBColor;
+import com.intellij.util.PairFunction;
+import com.intellij.util.ui.GraphicsUtil;
+import com.intellij.util.ui.UIUtil;
+import com.jetbrains.python.edu.ui.StudyCondition;
+
+import java.awt.*;
+
+/**
+ * author: liana
+ * data: 7/29/14.
+ */
+public class StudyInstructionPainter extends EditorEmptyTextPainter {
+ @Override
+ public void paintEmptyText(final EditorsSplitters splitters, Graphics g) {
+ if (!StudyCondition.VALUE) {
+ super.paintEmptyText(splitters, g);
+ return;
+ }
+ boolean isDarkBackground = UIUtil.isUnderDarcula();
+ UIUtil.applyRenderingHints(g);
+ GraphicsUtil.setupAntialiasing(g, true, false);
+ g.setColor(new JBColor(isDarkBackground ? Gray._230 : Gray._80, Gray._160));
+ g.setFont(UIUtil.getLabelFont().deriveFont(isDarkBackground ? 24f : 20f));
+
+ UIUtil.TextPainter painter = new UIUtil.TextPainter().withLineSpacing(1.5f);
+
+ painter.appendLine("PyCharm Educational Edition").underlined(new JBColor(Gray._150, Gray._180));
+ painter.appendLine("Navigate to the next task window with Ctrl + Enter").smaller().withBullet();
+ painter.appendLine("Navigate between task windows with Ctrl + < and Ctrl + >").smaller().withBullet();
+ painter.appendLine("Get hint for the task window using Ctrl + 7").smaller().withBullet();
+ painter.appendLine("To see your progress open the 'Course Description' panel").smaller().withBullet();
+ painter.draw(g, new PairFunction<Integer, Integer, Couple<Integer>>() {
+ @Override
+ public Couple<Integer> fun(Integer width, Integer height) {
+ Dimension s = splitters.getSize();
+ return Couple.of((s.width - width) / 2, (s.height - height) / 2);
+ }
+ });
+ }
+}
diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/StudyResourceManger.java b/python/edu/learn-python/src/com/jetbrains/python/edu/StudyResourceManger.java
new file mode 100644
index 000000000000..38f1c2ff2cde
--- /dev/null
+++ b/python/edu/learn-python/src/com/jetbrains/python/edu/StudyResourceManger.java
@@ -0,0 +1,5 @@
+package com.jetbrains.python.edu;
+
+public interface StudyResourceManger {
+ String USER_TESTER = "user_tester.py";
+}
diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/StudyTaskManager.java b/python/edu/learn-python/src/com/jetbrains/python/edu/StudyTaskManager.java
new file mode 100644
index 000000000000..213c1f7601f0
--- /dev/null
+++ b/python/edu/learn-python/src/com/jetbrains/python/edu/StudyTaskManager.java
@@ -0,0 +1,296 @@
+package com.jetbrains.python.edu;
+
+import com.intellij.ide.ui.UISettings;
+import com.intellij.openapi.actionSystem.*;
+import com.intellij.openapi.actionSystem.ex.AnActionListener;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.components.*;
+import com.intellij.openapi.editor.EditorFactory;
+import com.intellij.openapi.fileEditor.FileEditor;
+import com.intellij.openapi.fileEditor.FileEditorManager;
+import com.intellij.openapi.keymap.Keymap;
+import com.intellij.openapi.keymap.KeymapManager;
+import com.intellij.openapi.project.DumbAware;
+import com.intellij.openapi.project.DumbAwareRunnable;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.startup.StartupManager;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.vfs.VirtualFileAdapter;
+import com.intellij.openapi.vfs.VirtualFileEvent;
+import com.intellij.openapi.vfs.VirtualFileManager;
+import com.intellij.openapi.wm.*;
+import com.intellij.util.xmlb.XmlSerializer;
+import com.jetbrains.python.edu.actions.StudyNextWindowAction;
+import com.jetbrains.python.edu.actions.StudyPrevWindowAction;
+import com.jetbrains.python.edu.actions.StudyShowHintAction;
+import com.jetbrains.python.edu.course.Course;
+import com.jetbrains.python.edu.course.Lesson;
+import com.jetbrains.python.edu.course.Task;
+import com.jetbrains.python.edu.course.TaskFile;
+import com.jetbrains.python.edu.ui.StudyCondition;
+import com.jetbrains.python.edu.ui.StudyToolWindowFactory;
+import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Implementation of class which contains all the information
+ * about study in context of current project
+ */
+
+@State(
+ name = "StudySettings",
+ storages = {
+ @Storage(
+ id = "others",
+ file = "$PROJECT_CONFIG_DIR$/study_project.xml",
+ scheme = StorageScheme.DIRECTORY_BASED
+ )}
+)
+public class StudyTaskManager implements ProjectComponent, PersistentStateComponent<Element>, DumbAware {
+ public static final String COURSE_ELEMENT = "courseElement";
+ private static Map<String, StudyTaskManager> myTaskManagers = new HashMap<String, StudyTaskManager>();
+ private static Map<String, String> myDeletedShortcuts = new HashMap<String, String>();
+ private final Project myProject;
+ private Course myCourse;
+ private FileCreatedListener myListener;
+
+
+ public void setCourse(Course course) {
+ myCourse = course;
+ }
+
+ private StudyTaskManager(@NotNull final Project project) {
+ myTaskManagers.put(project.getBasePath(), this);
+ myProject = project;
+ }
+
+
+ @Nullable
+ public Course getCourse() {
+ return myCourse;
+ }
+
+ @Nullable
+ @Override
+ public Element getState() {
+ Element el = new Element("taskManager");
+ if (myCourse != null) {
+ Element courseElement = new Element(COURSE_ELEMENT);
+ XmlSerializer.serializeInto(myCourse, courseElement);
+ el.addContent(courseElement);
+ }
+ return el;
+ }
+
+ @Override
+ public void loadState(Element el) {
+ myCourse = XmlSerializer.deserialize(el.getChild(COURSE_ELEMENT), Course.class);
+ if (myCourse != null) {
+ myCourse.init(true);
+ }
+ }
+
+ @Override
+ public void projectOpened() {
+ ApplicationManager.getApplication().invokeLater(new DumbAwareRunnable() {
+ @Override
+ public void run() {
+ ApplicationManager.getApplication().runWriteAction(new DumbAwareRunnable() {
+ @Override
+ public void run() {
+ if (myCourse != null) {
+ StartupManager.getInstance(myProject).runWhenProjectIsInitialized(new Runnable() {
+ @Override
+ public void run() {
+ ToolWindowManager.getInstance(myProject).getToolWindow(ToolWindowId.PROJECT_VIEW).show(null);
+ FileEditor[] editors = FileEditorManager.getInstance(myProject).getSelectedEditors();
+ if (editors.length > 0) {
+ JComponent focusedComponent = editors[0].getPreferredFocusedComponent();
+ if (focusedComponent != null) {
+ IdeFocusManager.getInstance(myProject).requestFocus(focusedComponent, true);
+ }
+ }
+ }
+ });
+ UISettings.getInstance().HIDE_TOOL_STRIPES = false;
+ UISettings.getInstance().fireUISettingsChanged();
+ ToolWindowManager toolWindowManager = ToolWindowManager.getInstance(myProject);
+ String toolWindowId = StudyToolWindowFactory.STUDY_TOOL_WINDOW;
+ //TODO:decide smth with tool window position
+ try {
+ Method method = toolWindowManager.getClass().getDeclaredMethod("registerToolWindow", String.class,
+ JComponent.class,
+ ToolWindowAnchor.class,
+ boolean.class, boolean.class, boolean.class);
+ method.setAccessible(true);
+ method.invoke(toolWindowManager, toolWindowId, null, ToolWindowAnchor.LEFT, true, true, true);
+ }
+ catch (Exception e) {
+ final ToolWindow toolWindow = toolWindowManager.getToolWindow(toolWindowId);
+ if (toolWindow == null)
+ toolWindowManager.registerToolWindow(toolWindowId, true, ToolWindowAnchor.RIGHT, myProject, true);
+ }
+
+ final ToolWindow studyToolWindow = toolWindowManager.getToolWindow(toolWindowId);
+ if (studyToolWindow != null) {
+ StudyUtils.updateStudyToolWindow(myProject);
+ studyToolWindow.show(null);
+ }
+ addShortcut(StudyNextWindowAction.SHORTCUT, StudyNextWindowAction.ACTION_ID);
+ addShortcut(StudyPrevWindowAction.SHORTCUT, StudyPrevWindowAction.ACTION_ID);
+ addShortcut(StudyShowHintAction.SHORTCUT, StudyShowHintAction.ACTION_ID);
+ addShortcut(StudyNextWindowAction.SHORTCUT2, StudyNextWindowAction.ACTION_ID);
+ }
+ }
+ });
+ }
+ });
+ }
+
+
+ private static void addShortcut(@NotNull final String shortcutString, @NotNull final String actionIdString) {
+ Keymap keymap = KeymapManager.getInstance().getActiveKeymap();
+ Shortcut studyActionShortcut = new KeyboardShortcut(KeyStroke.getKeyStroke(shortcutString), null);
+ String[] actionsIds = keymap.getActionIds(studyActionShortcut);
+ for (String actionId : actionsIds) {
+ myDeletedShortcuts.put(actionId, shortcutString);
+ keymap.removeShortcut(actionId, studyActionShortcut);
+ }
+ keymap.addShortcut(actionIdString, studyActionShortcut);
+ }
+
+ @Override
+ public void projectClosed() {
+ StudyCondition.VALUE = false;
+ if (myCourse != null) {
+ ToolWindowManager.getInstance(myProject).getToolWindow(StudyToolWindowFactory.STUDY_TOOL_WINDOW).getContentManager()
+ .removeAllContents(false);
+ if (!myDeletedShortcuts.isEmpty()) {
+ for (Map.Entry<String, String> shortcut : myDeletedShortcuts.entrySet()) {
+ Keymap keymap = KeymapManager.getInstance().getActiveKeymap();
+ Shortcut actionShortcut = new KeyboardShortcut(KeyStroke.getKeyStroke(shortcut.getValue()), null);
+ keymap.addShortcut(shortcut.getKey(), actionShortcut);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void initComponent() {
+ EditorFactory.getInstance().addEditorFactoryListener(new StudyEditorFactoryListener(), myProject);
+ ActionManager.getInstance().addAnActionListener(new AnActionListener() {
+ @Override
+ public void beforeActionPerformed(AnAction action, DataContext dataContext, AnActionEvent event) {
+ AnAction[] newGroupActions = ((ActionGroup)ActionManager.getInstance().getAction("NewGroup")).getChildren(null);
+ for (AnAction newAction : newGroupActions) {
+ if (newAction == action) {
+ myListener = new FileCreatedListener();
+ VirtualFileManager.getInstance().addVirtualFileListener(myListener);
+ break;
+ }
+ }
+ }
+
+ @Override
+ public void afterActionPerformed(AnAction action, DataContext dataContext, AnActionEvent event) {
+ AnAction[] newGroupActions = ((ActionGroup)ActionManager.getInstance().getAction("NewGroup")).getChildren(null);
+ for (AnAction newAction : newGroupActions) {
+ if (newAction == action) {
+ VirtualFileManager.getInstance().removeVirtualFileListener(myListener);
+ }
+ }
+ }
+
+ @Override
+ public void beforeEditorTyping(char c, DataContext dataContext) {
+
+ }
+ });
+ }
+
+ @Override
+ public void disposeComponent() {
+ }
+
+ @NotNull
+ @Override
+ public String getComponentName() {
+ return "StudyTaskManager";
+ }
+
+ public static StudyTaskManager getInstance(@NotNull final Project project) {
+ StudyTaskManager item = myTaskManagers.get(project.getBasePath());
+ return item != null ? item : new StudyTaskManager(project);
+ }
+
+
+ @Nullable
+ public TaskFile getTaskFile(@NotNull final VirtualFile file) {
+ if (myCourse == null) {
+ return null;
+ }
+ VirtualFile taskDir = file.getParent();
+ if (taskDir != null) {
+ String taskDirName = taskDir.getName();
+ if (taskDirName.contains(Task.TASK_DIR)) {
+ VirtualFile lessonDir = taskDir.getParent();
+ if (lessonDir != null) {
+ String lessonDirName = lessonDir.getName();
+ int lessonIndex = StudyUtils.getIndex(lessonDirName, Lesson.LESSON_DIR);
+ List<Lesson> lessons = myCourse.getLessons();
+ if (!StudyUtils.indexIsValid(lessonIndex, lessons)) {
+ return null;
+ }
+ Lesson lesson = lessons.get(lessonIndex);
+ int taskIndex = StudyUtils.getIndex(taskDirName, Task.TASK_DIR);
+ List<Task> tasks = lesson.getTaskList();
+ if (!StudyUtils.indexIsValid(taskIndex, tasks)) {
+ return null;
+ }
+ Task task = tasks.get(taskIndex);
+ return task.getFile(file.getName());
+ }
+ }
+ }
+ return null;
+ }
+
+ class FileCreatedListener extends VirtualFileAdapter {
+ @Override
+ public void fileCreated(@NotNull VirtualFileEvent event) {
+ VirtualFile createdFile = event.getFile();
+ VirtualFile taskDir = createdFile.getParent();
+ String taskLogicalName = Task.TASK_DIR;
+ if (taskDir != null && taskDir.getName().contains(taskLogicalName)) {
+ int taskIndex = StudyUtils.getIndex(taskDir.getName(), taskLogicalName);
+ VirtualFile lessonDir = taskDir.getParent();
+ String lessonLogicalName = Lesson.LESSON_DIR;
+ if (lessonDir != null && lessonDir.getName().contains(lessonLogicalName)) {
+ int lessonIndex = StudyUtils.getIndex(lessonDir.getName(), lessonLogicalName);
+ if (myCourse != null) {
+ List<Lesson> lessons = myCourse.getLessons();
+ if (StudyUtils.indexIsValid(lessonIndex, lessons)) {
+ Lesson lesson = lessons.get(lessonIndex);
+ List<Task> tasks = lesson.getTaskList();
+ if (StudyUtils.indexIsValid(taskIndex, tasks)) {
+ Task task = tasks.get(taskIndex);
+ TaskFile taskFile = new TaskFile();
+ taskFile.init(task, false);
+ taskFile.setUserCreated(true);
+ task.getTaskFiles().put(createdFile.getName(), taskFile);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+}
diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/StudyUtils.java b/python/edu/learn-python/src/com/jetbrains/python/edu/StudyUtils.java
new file mode 100644
index 000000000000..d3ac1dadf98e
--- /dev/null
+++ b/python/edu/learn-python/src/com/jetbrains/python/edu/StudyUtils.java
@@ -0,0 +1,151 @@
+package com.jetbrains.python.edu;
+
+import com.intellij.ide.SaveAndSyncHandlerImpl;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.actionSystem.Presentation;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.fileEditor.FileEditor;
+import com.intellij.openapi.fileEditor.FileEditorManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.vfs.VirtualFileManager;
+import com.intellij.openapi.wm.ToolWindowManager;
+import com.intellij.util.ui.UIUtil;
+import com.jetbrains.python.edu.course.TaskFile;
+import com.jetbrains.python.edu.course.TaskWindow;
+import com.jetbrains.python.edu.editor.StudyEditor;
+import com.jetbrains.python.edu.ui.StudyToolWindowFactory;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.*;
+import java.util.Collection;
+
+public class StudyUtils {
+ private static final Logger LOG = Logger.getInstance(StudyUtils.class.getName());
+ public static void closeSilently(Closeable stream) {
+ if (stream != null) {
+ try {
+ stream.close();
+ }
+ catch (IOException e) {
+ // close silently
+ }
+ }
+ }
+
+ public static boolean isZip(String fileName) {
+ return fileName.contains(".zip");
+ }
+
+ public static <T> T getFirst(Iterable<T> container) {
+ return container.iterator().next();
+ }
+
+ public static boolean indexIsValid(int index, Collection collection) {
+ int size = collection.size();
+ return index >= 0 && index < size;
+ }
+
+ @SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
+ @Nullable
+ public static String getFileText(String parentDir, String fileName, boolean wrapHTML) {
+
+ File inputFile = parentDir !=null ? new File(parentDir, fileName) : new File(fileName);
+ if (!inputFile.exists()) return null;
+ StringBuilder taskText = new StringBuilder();
+ BufferedReader reader = null;
+ try {
+ reader = new BufferedReader(new InputStreamReader(new FileInputStream(inputFile)));
+ String line;
+ while ((line = reader.readLine()) != null) {
+ taskText.append(line).append("\n");
+ if (wrapHTML) {
+ taskText.append("<br>");
+ }
+ }
+ return wrapHTML ? UIUtil.toHtml(taskText.toString()) : taskText.toString();
+ }
+ catch (IOException e) {
+ LOG.error("Failed to get file text from file " + fileName, e);
+ }
+ finally {
+ closeSilently(reader);
+ }
+ return null;
+ }
+
+ public static void updateAction(AnActionEvent e) {
+ Presentation presentation = e.getPresentation();
+ presentation.setEnabled(false);
+ Project project = e.getProject();
+ if (project != null) {
+ FileEditor[] editors = FileEditorManager.getInstance(project).getAllEditors();
+ for (FileEditor editor : editors) {
+ if (editor instanceof StudyEditor) {
+ presentation.setEnabled(true);
+ }
+ }
+ }
+ }
+
+ public static void updateStudyToolWindow(Project project) {
+ ToolWindowManager.getInstance(project).getToolWindow(StudyToolWindowFactory.STUDY_TOOL_WINDOW).getContentManager().removeAllContents(false);
+ StudyToolWindowFactory factory = new StudyToolWindowFactory();
+ factory.createToolWindowContent(project, ToolWindowManager.getInstance(project).getToolWindow(StudyToolWindowFactory.STUDY_TOOL_WINDOW));
+ }
+
+ public static void synchronize() {
+ FileDocumentManager.getInstance().saveAllDocuments();
+ SaveAndSyncHandlerImpl.refreshOpenFiles();
+ VirtualFileManager.getInstance().refreshWithoutFileWatcher(true);
+ }
+
+ /**
+ * Gets number index in directory names like "task1", "lesson2"
+ *
+ * @param fullName full name of directory
+ * @param logicalName part of name without index
+ * @return index of object
+ */
+ public static int getIndex(@NotNull final String fullName, @NotNull final String logicalName) {
+ if (!fullName.contains(logicalName)) {
+ throw new IllegalArgumentException();
+ }
+ return Integer.parseInt(fullName.substring(logicalName.length())) - 1;
+ }
+
+ @SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
+ public static VirtualFile flushWindows(Document document, TaskFile taskFile, VirtualFile file) {
+ VirtualFile taskDir = file.getParent();
+ VirtualFile fileWindows = null;
+ if (taskDir != null) {
+ String name = file.getNameWithoutExtension() + "_windows";
+ PrintWriter printWriter = null;
+ try {
+
+ fileWindows = taskDir.createChildData(taskFile, name);
+ printWriter = new PrintWriter(new FileOutputStream(fileWindows.getPath()));
+ for (TaskWindow taskWindow : taskFile.getTaskWindows()) {
+ if (!taskWindow.isValid(document)) {
+ continue;
+ }
+ int start = taskWindow.getRealStartOffset(document);
+ String windowDescription = document.getText(new TextRange(start, start + taskWindow.getLength()));
+ printWriter.println("#study_plugin_window = " + windowDescription);
+ }
+ }
+ catch (IOException e) {
+ LOG.error(e);
+ }
+ finally {
+ closeSilently(printWriter);
+ synchronize();
+ }
+ }
+ return fileWindows;
+ }
+}
diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyCheckAction.java b/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyCheckAction.java
new file mode 100644
index 000000000000..f8e10c9c4521
--- /dev/null
+++ b/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyCheckAction.java
@@ -0,0 +1,340 @@
+package com.jetbrains.python.edu.actions;
+
+import com.intellij.execution.ExecutionException;
+import com.intellij.execution.configurations.GeneralCommandLine;
+import com.intellij.ide.projectView.ProjectView;
+import com.intellij.openapi.actionSystem.ActionManager;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.CommandProcessor;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.fileEditor.FileEditor;
+import com.intellij.openapi.fileEditor.FileEditorManager;
+import com.intellij.openapi.module.ModuleManager;
+import com.intellij.openapi.project.DumbAwareAction;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.projectRoots.Sdk;
+import com.intellij.openapi.ui.popup.Balloon;
+import com.intellij.openapi.ui.popup.BalloonBuilder;
+import com.intellij.openapi.ui.popup.JBPopupFactory;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.ui.JBColor;
+import com.jetbrains.python.edu.StudyDocumentListener;
+import com.jetbrains.python.edu.StudyTaskManager;
+import com.jetbrains.python.edu.StudyUtils;
+import com.jetbrains.python.edu.course.*;
+import com.jetbrains.python.edu.editor.StudyEditor;
+import com.jetbrains.python.sdk.PythonSdkType;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import java.awt.*;
+import java.io.*;
+import java.util.*;
+import java.util.List;
+
+public class StudyCheckAction extends DumbAwareAction {
+
+ private static final Logger LOG = Logger.getInstance(StudyCheckAction.class.getName());
+ public static final String PYTHONPATH = "PYTHONPATH";
+
+ static class StudyTestRunner {
+ public static final String TEST_OK = "#study_plugin test OK";
+ private static final String TEST_FAILED = "#study_plugin FAILED + ";
+ private final Task myTask;
+ private final VirtualFile myTaskDir;
+
+ StudyTestRunner(Task task, VirtualFile taskDir) {
+ myTask = task;
+ myTaskDir = taskDir;
+ }
+
+ Process launchTests(Project project, String executablePath) throws ExecutionException {
+ Sdk sdk = PythonSdkType.findPythonSdk(ModuleManager.getInstance(project).getModules()[0]);
+ File testRunner = new File(myTaskDir.getPath(), myTask.getTestFile());
+ GeneralCommandLine commandLine = new GeneralCommandLine();
+ commandLine.setWorkDirectory(myTaskDir.getPath());
+ final Map<String, String> env = commandLine.getEnvironment();
+ final VirtualFile courseDir = project.getBaseDir();
+ if (courseDir != null)
+ env.put(PYTHONPATH, courseDir.getPath());
+ if (sdk != null) {
+ String pythonPath = sdk.getHomePath();
+ if (pythonPath != null) {
+ commandLine.setExePath(pythonPath);
+ commandLine.addParameter(testRunner.getPath());
+ final Course course = StudyTaskManager.getInstance(project).getCourse();
+ assert course != null;
+ commandLine.addParameter(new File(course.getResourcePath()).getParent());
+ commandLine.addParameter(FileUtil.toSystemDependentName(executablePath));
+ return commandLine.createProcess();
+ }
+ }
+ return null;
+ }
+
+
+ String getPassedTests(Process p) {
+ InputStream testOutput = p.getInputStream();
+ BufferedReader testOutputReader = new BufferedReader(new InputStreamReader(testOutput));
+ String line;
+ try {
+ while ((line = testOutputReader.readLine()) != null) {
+ if (line.contains(TEST_FAILED)) {
+ return line.substring(TEST_FAILED.length(), line.length());
+ }
+ }
+ }
+ catch (IOException e) {
+ LOG.error(e);
+ }
+ finally {
+ StudyUtils.closeSilently(testOutputReader);
+ }
+ return TEST_OK;
+ }
+ }
+
+ public void check(@NotNull final Project project) {
+ ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ @Override
+ public void run() {
+ CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() {
+ @Override
+ public void run() {
+ final Editor selectedEditor = StudyEditor.getSelectedEditor(project);
+ if (selectedEditor != null) {
+ final FileDocumentManager fileDocumentManager = FileDocumentManager.getInstance();
+ final VirtualFile openedFile = fileDocumentManager.getFile(selectedEditor.getDocument());
+ if (openedFile != null) {
+ StudyTaskManager taskManager = StudyTaskManager.getInstance(project);
+ final TaskFile selectedTaskFile = taskManager.getTaskFile(openedFile);
+ List<VirtualFile> filesToDelete = new ArrayList<VirtualFile>();
+ if (selectedTaskFile != null) {
+ final VirtualFile taskDir = openedFile.getParent();
+ Task currentTask = selectedTaskFile.getTask();
+ StudyStatus oldStatus = currentTask.getStatus();
+ Map<String, TaskFile> taskFiles = selectedTaskFile.getTask().getTaskFiles();
+ for (Map.Entry<String, TaskFile> entry : taskFiles.entrySet()) {
+ String name = entry.getKey();
+ TaskFile taskFile = entry.getValue();
+ VirtualFile virtualFile = taskDir.findChild(name);
+ if (virtualFile == null) {
+ continue;
+ }
+ VirtualFile windowFile = StudyUtils.flushWindows(FileDocumentManager.getInstance().getDocument(virtualFile), taskFile, virtualFile);
+ filesToDelete.add(windowFile);
+ FileDocumentManager.getInstance().saveAllDocuments();
+ }
+
+ StudyRunAction runAction = (StudyRunAction)ActionManager.getInstance().getAction(StudyRunAction.ACTION_ID);
+ if (runAction != null && currentTask.getTaskFiles().size() == 1) {
+ runAction.run(project);
+ }
+ final StudyTestRunner testRunner = new StudyTestRunner(currentTask, taskDir);
+ Process testProcess = null;
+ try {
+ testProcess = testRunner.launchTests(project, openedFile.getPath());
+ }
+ catch (ExecutionException e) {
+ LOG.error(e);
+ }
+ if (testProcess != null) {
+ String failedMessage = testRunner.getPassedTests(testProcess);
+ if (failedMessage.equals(StudyTestRunner.TEST_OK)) {
+ currentTask.setStatus(StudyStatus.Solved, oldStatus);
+ StudyUtils.updateStudyToolWindow(project);
+ selectedTaskFile.drawAllWindows(selectedEditor);
+ ProjectView.getInstance(project).refresh();
+ for (VirtualFile file:filesToDelete) {
+ try {
+ file.delete(this);
+ }
+ catch (IOException e) {
+ LOG.error(e);
+ }
+ }
+ createTestResultPopUp("Congratulations!", JBColor.GREEN, project);
+ return;
+ }
+ for (Map.Entry<String, TaskFile> entry : taskFiles.entrySet()) {
+ String name = entry.getKey();
+ TaskFile taskFile = entry.getValue();
+ TaskFile answerTaskFile = new TaskFile();
+ VirtualFile virtualFile = taskDir.findChild(name);
+ if (virtualFile == null) {
+ continue;
+ }
+ VirtualFile answerFile = getCopyWithAnswers(taskDir, virtualFile, taskFile, answerTaskFile);
+ for (TaskWindow taskWindow : answerTaskFile.getTaskWindows()) {
+ Document document = FileDocumentManager.getInstance().getDocument(virtualFile);
+ if (document == null) {
+ continue;
+ }
+ if (!taskWindow.isValid(document)) {
+ continue;
+ }
+ check(project, taskWindow, answerFile, answerTaskFile, taskFile, document, testRunner, virtualFile);
+ }
+ FileEditor fileEditor = FileEditorManager.getInstance(project).getSelectedEditor(virtualFile);
+ Editor editor = null;
+ if (fileEditor instanceof StudyEditor) {
+ StudyEditor studyEditor = (StudyEditor) fileEditor;
+ editor = studyEditor.getEditor();
+ }
+
+ if (editor != null) {
+ taskFile.drawAllWindows(editor);
+ StudyUtils.synchronize();
+ }
+ try {
+ answerFile.delete(this);
+ }
+ catch (IOException e) {
+ LOG.error(e);
+ }
+ }
+ for (VirtualFile file:filesToDelete) {
+ try {
+ file.delete(this);
+ }
+ catch (IOException e) {
+ LOG.error(e);
+ }
+ }
+ currentTask.setStatus(StudyStatus.Failed, oldStatus);
+ StudyUtils.updateStudyToolWindow(project);
+ createTestResultPopUp(failedMessage, JBColor.RED, project);
+ }
+ }
+ }
+ }
+
+ }
+ });
+ }
+ });
+ }
+
+ private void check(Project project,
+ TaskWindow taskWindow,
+ VirtualFile answerFile,
+ TaskFile answerTaskFile,
+ TaskFile usersTaskFile,
+ Document usersDocument,
+ StudyTestRunner testRunner,
+ VirtualFile openedFile) {
+
+ try {
+ VirtualFile windowCopy = answerFile.copy(this, answerFile.getParent(), answerFile.getNameWithoutExtension() + "_window" + taskWindow.getIndex() + ".py");
+ final FileDocumentManager documentManager = FileDocumentManager.getInstance();
+ final Document windowDocument = documentManager.getDocument(windowCopy);
+ if (windowDocument != null) {
+ StudyTaskManager taskManager = StudyTaskManager.getInstance(project);
+ Course course = taskManager.getCourse();
+ Task task = usersTaskFile.getTask();
+ int taskNum = task.getIndex() + 1;
+ int lessonNum = task.getLesson().getIndex() + 1;
+ assert course != null;
+ String pathToResource = FileUtil.join(new File(course.getResourcePath()).getParent(), Lesson.LESSON_DIR + lessonNum, Task.TASK_DIR + taskNum);
+ File resourceFile = new File(pathToResource, windowCopy.getName());
+ FileUtil.copy(new File(pathToResource, openedFile.getName()), resourceFile);
+ TaskFile windowTaskFile = new TaskFile();
+ TaskFile.copy(answerTaskFile, windowTaskFile);
+ StudyDocumentListener listener = new StudyDocumentListener(windowTaskFile);
+ windowDocument.addDocumentListener(listener);
+ int start = taskWindow.getRealStartOffset(windowDocument);
+ int end = start + taskWindow.getLength();
+ TaskWindow userTaskWindow = usersTaskFile.getTaskWindows().get(taskWindow.getIndex());
+ int userStart = userTaskWindow.getRealStartOffset(usersDocument);
+ int userEnd = userStart + userTaskWindow.getLength();
+ String text = usersDocument.getText(new TextRange(userStart, userEnd));
+ windowDocument.replaceString(start, end, text);
+ ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ @Override
+ public void run() {
+ documentManager.saveDocument(windowDocument);
+ }
+ });
+ VirtualFile fileWindows = StudyUtils.flushWindows(windowDocument, windowTaskFile, windowCopy);
+ Process smartTestProcess = testRunner.launchTests(project, windowCopy.getPath());
+ boolean res = testRunner.getPassedTests(smartTestProcess).equals(StudyTestRunner.TEST_OK);
+ userTaskWindow.setStatus(res ? StudyStatus.Solved : StudyStatus.Failed, StudyStatus.Unchecked);
+ windowCopy.delete(this);
+ fileWindows.delete(this);
+ if (!resourceFile.delete()) {
+ LOG.error("failed to delete", resourceFile.getPath());
+ }
+ }
+ }
+ catch (IOException e) {
+ LOG.error(e);
+ }
+ catch (ExecutionException e) {
+ LOG.error(e);
+ }
+ }
+
+
+ private VirtualFile getCopyWithAnswers(final VirtualFile taskDir,
+ final VirtualFile file,
+ final TaskFile source,
+ TaskFile target) {
+ VirtualFile copy = null;
+ try {
+
+ copy = file.copy(this, taskDir, file.getNameWithoutExtension() +"_answers.py");
+ final FileDocumentManager documentManager = FileDocumentManager.getInstance();
+ final Document document = documentManager.getDocument(copy);
+ if (document != null) {
+ TaskFile.copy(source, target);
+ StudyDocumentListener listener = new StudyDocumentListener(target);
+ document.addDocumentListener(listener);
+ for (TaskWindow taskWindow : target.getTaskWindows()) {
+ if (!taskWindow.isValid(document)) {
+ continue;
+ }
+ final int start = taskWindow.getRealStartOffset(document);
+ final int end = start + taskWindow.getLength();
+ final String text = taskWindow.getPossibleAnswer();
+ document.replaceString(start, end, text);
+ }
+ ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ @Override
+ public void run() {
+ documentManager.saveDocument(document);
+ }
+ });
+ }
+ }
+ catch (IOException e) {
+ LOG.error(e);
+ }
+
+
+ return copy;
+ }
+
+ private static void createTestResultPopUp(final String text, Color color, @NotNull final Project project) {
+ BalloonBuilder balloonBuilder =
+ JBPopupFactory.getInstance().createHtmlTextBalloonBuilder(text, null, color, null);
+ Balloon balloon = balloonBuilder.createBalloon();
+ StudyEditor studyEditor = StudyEditor.getSelectedStudyEditor(project);
+ assert studyEditor != null;
+ JButton checkButton = studyEditor.getCheckButton();
+ balloon.showInCenterOf(checkButton);
+ }
+
+ @Override
+ public void actionPerformed(AnActionEvent e) {
+ Project project = e.getProject();
+ if (project != null) {
+ check(project);
+ }
+ }
+}
diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyEditInputAction.java b/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyEditInputAction.java
new file mode 100644
index 000000000000..5b9a6fef23ac
--- /dev/null
+++ b/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyEditInputAction.java
@@ -0,0 +1,213 @@
+package com.jetbrains.python.edu.actions;
+
+import com.intellij.icons.AllIcons;
+import com.intellij.ide.ui.UISettings;
+import com.intellij.openapi.actionSystem.*;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.project.DumbAware;
+import com.intellij.openapi.project.DumbAwareAction;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.popup.JBPopup;
+import com.intellij.openapi.ui.popup.JBPopupAdapter;
+import com.intellij.openapi.ui.popup.JBPopupFactory;
+import com.intellij.openapi.ui.popup.LightweightWindowEvent;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.wm.IdeFocusManager;
+import com.intellij.ui.tabs.TabInfo;
+import com.intellij.ui.tabs.TabsListener;
+import com.intellij.ui.tabs.impl.JBEditorTabs;
+import com.jetbrains.python.edu.StudyTaskManager;
+import com.jetbrains.python.edu.StudyUtils;
+import com.jetbrains.python.edu.course.Task;
+import com.jetbrains.python.edu.course.TaskFile;
+import com.jetbrains.python.edu.course.UserTest;
+import com.jetbrains.python.edu.editor.StudyEditor;
+import com.jetbrains.python.edu.ui.StudyTestContentPanel;
+import icons.StudyIcons;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.PrintWriter;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class StudyEditInputAction extends DumbAwareAction {
+
+ public static final String TEST_TAB_NAME = "test";
+ public static final String USER_TEST_INPUT = "input";
+ public static final String USER_TEST_OUTPUT = "output";
+ private static final Logger LOG = Logger.getInstance(StudyEditInputAction.class.getName());
+ private JBEditorTabs tabbedPane;
+ private Map<TabInfo, UserTest> myEditableTabs = new HashMap<TabInfo, UserTest>();
+
+ public void showInput(final Project project) {
+ final Editor selectedEditor = StudyEditor.getSelectedEditor(project);
+ if (selectedEditor != null) {
+ FileDocumentManager fileDocumentManager = FileDocumentManager.getInstance();
+ final VirtualFile openedFile = fileDocumentManager.getFile(selectedEditor.getDocument());
+ StudyTaskManager studyTaskManager = StudyTaskManager.getInstance(project);
+ assert openedFile != null;
+ TaskFile taskFile = studyTaskManager.getTaskFile(openedFile);
+ assert taskFile != null;
+ final Task currentTask = taskFile.getTask();
+ tabbedPane = new JBEditorTabs(project, ActionManager.getInstance(), IdeFocusManager.findInstance(), project);
+ tabbedPane.addListener(new TabsListener.Adapter() {
+ @Override
+ public void selectionChanged(TabInfo oldSelection, TabInfo newSelection) {
+ if (newSelection.getIcon() != null) {
+ int tabCount = tabbedPane.getTabCount();
+ VirtualFile taskDir = openedFile.getParent();
+ VirtualFile testsDir = taskDir.findChild(Task.USER_TESTS);
+ assert testsDir != null;
+ UserTest userTest = createUserTest(testsDir, currentTask);
+ userTest.setEditable(true);
+ StudyTestContentPanel testContentPanel = new StudyTestContentPanel(userTest);
+ TabInfo testTab = addTestTab(tabbedPane.getTabCount(), testContentPanel, currentTask, true);
+ myEditableTabs.put(testTab, userTest);
+ tabbedPane.addTabSilently(testTab, tabCount - 1);
+ tabbedPane.select(testTab, true);
+ }
+ }
+ });
+ List<UserTest> userTests = currentTask.getUserTests();
+ int i = 1;
+ for (UserTest userTest : userTests) {
+ String inputFileText = StudyUtils.getFileText(null, userTest.getInput(), false);
+ String outputFileText = StudyUtils.getFileText(null, userTest.getOutput(), false);
+ StudyTestContentPanel myContentPanel = new StudyTestContentPanel(userTest);
+ myContentPanel.addInputContent(inputFileText);
+ myContentPanel.addOutputContent(outputFileText);
+ TabInfo testTab = addTestTab(i, myContentPanel, currentTask, userTest.isEditable());
+ tabbedPane.addTabSilently(testTab, i - 1);
+ if (userTest.isEditable()) {
+ myEditableTabs.put(testTab, userTest);
+ }
+ i++;
+ }
+ TabInfo plusTab = new TabInfo(new JPanel());
+ plusTab.setIcon(StudyIcons.Add);
+ tabbedPane.addTabSilently(plusTab, tabbedPane.getTabCount());
+ final JBPopup hint =
+ JBPopupFactory.getInstance().createComponentPopupBuilder(tabbedPane.getComponent(), tabbedPane.getComponent())
+ .setResizable(true)
+ .setMovable(true)
+ .setRequestFocus(true)
+ .createPopup();
+ StudyEditor selectedStudyEditor = StudyEditor.getSelectedStudyEditor(project);
+ assert selectedStudyEditor != null;
+ hint.showInCenterOf(selectedStudyEditor.getComponent());
+ hint.addListener(new HintClosedListener(currentTask));
+ }
+ }
+
+
+ private static void flushBuffer(@NotNull final StringBuilder buffer, @NotNull final File file) {
+ PrintWriter printWriter = null;
+ try {
+ printWriter = new PrintWriter(new FileOutputStream(file));
+ printWriter.print(buffer.toString());
+ }
+ catch (FileNotFoundException e) {
+ LOG.error(e);
+ }
+ finally {
+ StudyUtils.closeSilently(printWriter);
+ }
+ StudyUtils.synchronize();
+ }
+
+ private static UserTest createUserTest(@NotNull final VirtualFile testsDir, @NotNull final Task currentTask) {
+ UserTest userTest = new UserTest();
+ List<UserTest> userTests = currentTask.getUserTests();
+ int testNum = userTests.size() + 1;
+ String inputName = USER_TEST_INPUT + testNum;
+ File inputFile = new File(testsDir.getPath(), inputName);
+ String outputName = USER_TEST_OUTPUT + testNum;
+ File outputFile = new File(testsDir.getPath(), outputName);
+ userTest.setInput(inputFile.getPath());
+ userTest.setOutput(outputFile.getPath());
+ userTests.add(userTest);
+ return userTest;
+ }
+
+ private TabInfo addTestTab(int nameIndex, final StudyTestContentPanel contentPanel, @NotNull final Task currentTask, boolean toBeClosable) {
+ TabInfo testTab = toBeClosable ? createClosableTab(contentPanel, currentTask) : new TabInfo(contentPanel);
+ return testTab.setText(TEST_TAB_NAME + String.valueOf(nameIndex));
+ }
+
+ private TabInfo createClosableTab(StudyTestContentPanel contentPanel, Task currentTask) {
+ TabInfo closableTab = new TabInfo(contentPanel);
+ final DefaultActionGroup tabActions = new DefaultActionGroup();
+ tabActions.add(new CloseTab(closableTab, currentTask));
+ closableTab.setTabLabelActions(tabActions, ActionPlaces.EDITOR_TAB);
+ return closableTab;
+ }
+
+ public void actionPerformed(AnActionEvent e) {
+ showInput(e.getProject());
+ }
+
+ private class HintClosedListener extends JBPopupAdapter {
+ private final Task myTask;
+ private HintClosedListener(@NotNull final Task task) {
+ myTask = task;
+ }
+
+ @Override
+ public void onClosed(LightweightWindowEvent event) {
+ for (final UserTest userTest : myTask.getUserTests()) {
+ ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ @Override
+ public void run() {
+ if (userTest.isEditable()) {
+ File inputFile = new File(userTest.getInput());
+ File outputFile = new File(userTest.getOutput());
+ flushBuffer(userTest.getInputBuffer(), inputFile);
+ flushBuffer(userTest.getOutputBuffer(), outputFile);
+ }
+ }
+ });
+ }
+ }
+ }
+
+ private class CloseTab extends AnAction implements DumbAware {
+
+ private final TabInfo myTabInfo;
+ private final Task myTask;
+
+ public CloseTab(final TabInfo info, @NotNull final Task task) {
+ myTabInfo = info;
+ myTask = task;
+ }
+
+ @Override
+ public void update(final AnActionEvent e) {
+ e.getPresentation().setIcon(tabbedPane.isEditorTabs() ? AllIcons.Actions.CloseNew : AllIcons.Actions.Close);
+ e.getPresentation().setHoveredIcon(tabbedPane.isEditorTabs() ? AllIcons.Actions.CloseNewHovered : AllIcons.Actions.CloseHovered);
+ e.getPresentation().setVisible(UISettings.getInstance().SHOW_CLOSE_BUTTON);
+ e.getPresentation().setText("Delete test");
+ }
+
+ @Override
+ public void actionPerformed(final AnActionEvent e) {
+ tabbedPane.removeTab(myTabInfo);
+ UserTest userTest = myEditableTabs.get(myTabInfo);
+ File testInputFile = new File(userTest.getInput());
+ File testOutputFile = new File(userTest.getOutput());
+ if (testInputFile.delete() && testOutputFile.delete()) {
+ StudyUtils.synchronize();
+ } else {
+ LOG.error("failed to delete user tests");
+ }
+ myTask.getUserTests().remove(userTest);
+ }
+ }
+}
diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyNextStudyTaskAction.java b/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyNextStudyTaskAction.java
new file mode 100644
index 000000000000..81818a95c044
--- /dev/null
+++ b/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyNextStudyTaskAction.java
@@ -0,0 +1,24 @@
+package com.jetbrains.python.edu.actions;
+
+import com.jetbrains.python.edu.editor.StudyEditor;
+import com.jetbrains.python.edu.course.Task;
+
+import javax.swing.*;
+
+public class StudyNextStudyTaskAction extends StudyTaskNavigationAction {
+
+ @Override
+ protected JButton getButton(StudyEditor selectedStudyEditor) {
+ return selectedStudyEditor.getNextTaskButton();
+ }
+
+ @Override
+ protected String getNavigationFinishedMessage() {
+ return "It's the last task";
+ }
+
+ @Override
+ protected Task getTargetTask(Task sourceTask) {
+ return sourceTask.next();
+ }
+} \ No newline at end of file
diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyNextWindowAction.java b/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyNextWindowAction.java
new file mode 100644
index 000000000000..595aeeff42e3
--- /dev/null
+++ b/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyNextWindowAction.java
@@ -0,0 +1,32 @@
+package com.jetbrains.python.edu.actions;
+
+import com.jetbrains.python.edu.StudyUtils;
+import com.jetbrains.python.edu.course.TaskWindow;
+import icons.StudyIcons;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+/**
+ * move caret to next task window
+ */
+public class StudyNextWindowAction extends StudyWindowNavigationAction {
+ public static final String ACTION_ID = "NextWindow";
+ public static final String SHORTCUT = "ctrl pressed PERIOD";
+ public static final String SHORTCUT2 = "ctrl pressed ENTER";
+
+ public StudyNextWindowAction() {
+ super("NextWindowAction", "Select next window", StudyIcons.Next);
+ }
+
+ @Override
+ protected TaskWindow getNextTaskWindow(@NotNull final TaskWindow window) {
+ int index = window.getIndex();
+ List<TaskWindow> windows = window.getTaskFile().getTaskWindows();
+ if (StudyUtils.indexIsValid(index, windows)) {
+ int newIndex = index + 1;
+ return newIndex == windows.size() ? windows.get(0) : windows.get(newIndex);
+ }
+ return null;
+ }
+}
diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyPrevWindowAction.java b/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyPrevWindowAction.java
new file mode 100644
index 000000000000..347456189a00
--- /dev/null
+++ b/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyPrevWindowAction.java
@@ -0,0 +1,34 @@
+package com.jetbrains.python.edu.actions;
+
+import com.jetbrains.python.edu.StudyUtils;
+import com.jetbrains.python.edu.course.TaskWindow;
+import icons.StudyIcons;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+/**
+ * author: liana
+ * data: 6/30/14.
+ */
+public class StudyPrevWindowAction extends StudyWindowNavigationAction {
+ public static final String ACTION_ID = "PrevWindowAction";
+ public static final String SHORTCUT = "ctrl pressed COMMA";
+
+ public StudyPrevWindowAction() {
+ super("PrevWindowAction", "Select previous window", StudyIcons.Prev);
+ }
+
+
+ @Nullable
+ @Override
+ protected TaskWindow getNextTaskWindow(@NotNull final TaskWindow window) {
+ int prevIndex = window.getIndex() - 1;
+ List<TaskWindow> windows = window.getTaskFile().getTaskWindows();
+ if (StudyUtils.indexIsValid(prevIndex, windows)) {
+ return windows.get(prevIndex);
+ }
+ return null;
+ }
+}
diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyPreviousStudyTaskAction.java b/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyPreviousStudyTaskAction.java
new file mode 100644
index 000000000000..bc26c28cfabd
--- /dev/null
+++ b/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyPreviousStudyTaskAction.java
@@ -0,0 +1,25 @@
+package com.jetbrains.python.edu.actions;
+
+
+import com.jetbrains.python.edu.editor.StudyEditor;
+import com.jetbrains.python.edu.course.Task;
+
+import javax.swing.*;
+
+public class StudyPreviousStudyTaskAction extends StudyTaskNavigationAction {
+
+ @Override
+ protected JButton getButton(StudyEditor selectedStudyEditor) {
+ return selectedStudyEditor.getPrevTaskButton();
+ }
+
+ @Override
+ protected String getNavigationFinishedMessage() {
+ return "It's already the first task";
+ }
+
+ @Override
+ protected Task getTargetTask(Task sourceTask) {
+ return sourceTask.prev();
+ }
+} \ No newline at end of file
diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyRefreshTaskAction.java b/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyRefreshTaskAction.java
new file mode 100644
index 000000000000..f8abb0b63365
--- /dev/null
+++ b/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyRefreshTaskAction.java
@@ -0,0 +1,122 @@
+package com.jetbrains.python.edu.actions;
+
+import com.intellij.ide.projectView.ProjectView;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.CommandProcessor;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.project.DumbAwareAction;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.MessageType;
+import com.intellij.openapi.ui.popup.Balloon;
+import com.intellij.openapi.ui.popup.BalloonBuilder;
+import com.intellij.openapi.ui.popup.JBPopupFactory;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.wm.IdeFocusManager;
+import com.jetbrains.python.edu.StudyDocumentListener;
+import com.jetbrains.python.edu.StudyTaskManager;
+import com.jetbrains.python.edu.StudyUtils;
+import com.jetbrains.python.edu.course.*;
+import com.jetbrains.python.edu.editor.StudyEditor;
+
+import java.io.*;
+
+public class StudyRefreshTaskAction extends DumbAwareAction {
+ private static final Logger LOG = Logger.getInstance(StudyRefreshTaskAction.class.getName());
+
+ public void refresh(final Project project) {
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ @SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
+ @Override
+ public void run() {
+ final Editor editor = StudyEditor.getSelectedEditor(project);
+ assert editor != null;
+ final Document document = editor.getDocument();
+ StudyDocumentListener listener = StudyEditor.getListener(document);
+ if (listener != null) {
+ document.removeDocumentListener(listener);
+ }
+ final int lineCount = document.getLineCount();
+ if (lineCount != 0) {
+ CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() {
+ @Override
+ public void run() {
+ document.deleteString(0, document.getLineEndOffset(lineCount - 1));
+ }
+ });
+ }
+ StudyTaskManager taskManager = StudyTaskManager.getInstance(project);
+ Course course = taskManager.getCourse();
+ assert course != null;
+ File resourceFile = new File(course.getResourcePath());
+ File resourceRoot = resourceFile.getParentFile();
+ FileDocumentManager fileDocumentManager = FileDocumentManager.getInstance();
+ VirtualFile openedFile = fileDocumentManager.getFile(document);
+ assert openedFile != null;
+ final TaskFile selectedTaskFile = taskManager.getTaskFile(openedFile);
+ assert selectedTaskFile != null;
+ Task currentTask = selectedTaskFile.getTask();
+ String lessonDir = Lesson.LESSON_DIR + String.valueOf(currentTask.getLesson().getIndex() + 1);
+ String taskDir = Task.TASK_DIR + String.valueOf(currentTask.getIndex() + 1);
+ File pattern = new File(new File(new File(resourceRoot, lessonDir), taskDir), openedFile.getName());
+ BufferedReader reader = null;
+ try {
+ reader = new BufferedReader(new InputStreamReader(new FileInputStream(pattern)));
+ String line;
+ StringBuilder patternText = new StringBuilder();
+ while ((line = reader.readLine()) != null) {
+ patternText.append(line);
+ patternText.append("\n");
+ }
+ int patternLength = patternText.length();
+ if (patternText.charAt(patternLength - 1) == '\n') {
+ patternText.delete(patternLength - 1, patternLength);
+ }
+ document.setText(patternText);
+ StudyStatus oldStatus = currentTask.getStatus();
+ LessonInfo lessonInfo = currentTask.getLesson().getLessonInfo();
+ lessonInfo.update(oldStatus, -1);
+ lessonInfo.update(StudyStatus.Unchecked, +1);
+ StudyUtils.updateStudyToolWindow(project);
+ for (TaskWindow taskWindow : selectedTaskFile.getTaskWindows()) {
+ taskWindow.reset();
+ }
+ ProjectView.getInstance(project).refresh();
+ if (listener != null) {
+ document.addDocumentListener(listener);
+ }
+ selectedTaskFile.drawAllWindows(editor);
+ IdeFocusManager.getInstance(project).requestFocus(editor.getContentComponent(), true);
+ selectedTaskFile.navigateToFirstTaskWindow(editor);
+ BalloonBuilder balloonBuilder =
+ JBPopupFactory.getInstance().createHtmlTextBalloonBuilder("You can now start again", MessageType.INFO, null);
+ Balloon balloon = balloonBuilder.createBalloon();
+ StudyEditor selectedStudyEditor = StudyEditor.getSelectedStudyEditor(project);
+ assert selectedStudyEditor != null;
+ balloon.showInCenterOf(selectedStudyEditor.getRefreshButton());
+ }
+ catch (FileNotFoundException e1) {
+ LOG.error(e1);
+ }
+ catch (IOException e1) {
+ LOG.error(e1);
+ }
+ finally {
+ StudyUtils.closeSilently(reader);
+ }
+ }
+ });
+ }
+ });
+ }
+
+ public void actionPerformed(AnActionEvent e) {
+ refresh(e.getProject());
+ }
+}
diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyRunAction.java b/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyRunAction.java
new file mode 100644
index 000000000000..71e95defdedc
--- /dev/null
+++ b/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyRunAction.java
@@ -0,0 +1,89 @@
+package com.jetbrains.python.edu.actions;
+
+import com.intellij.execution.ExecutionException;
+import com.intellij.execution.RunContentExecutor;
+import com.intellij.execution.configurations.GeneralCommandLine;
+import com.intellij.execution.process.OSProcessHandler;
+import com.intellij.execution.process.ProcessHandler;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.module.ModuleManager;
+import com.intellij.openapi.project.DumbAwareAction;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.projectRoots.Sdk;
+import com.intellij.openapi.util.Disposer;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.jetbrains.python.sdk.PythonSdkType;
+import com.jetbrains.python.edu.StudyResourceManger;
+import com.jetbrains.python.edu.StudyTaskManager;
+import com.jetbrains.python.edu.course.Task;
+import com.jetbrains.python.edu.course.TaskFile;
+import com.jetbrains.python.edu.editor.StudyEditor;
+
+import java.io.File;
+
+public class StudyRunAction extends DumbAwareAction {
+ private static final Logger LOG = Logger.getInstance(StudyRunAction.class.getName());
+ public static final String ACTION_ID = "StudyRunAction";
+
+ public void run(Project project) {
+ Editor selectedEditor = StudyEditor.getSelectedEditor(project);
+ FileDocumentManager fileDocumentManager = FileDocumentManager.getInstance();
+ assert selectedEditor != null;
+ VirtualFile openedFile = fileDocumentManager.getFile(selectedEditor.getDocument());
+ StudyTaskManager taskManager = StudyTaskManager.getInstance(project);
+ if (openedFile != null && openedFile.getCanonicalPath() != null) {
+ String filePath = openedFile.getCanonicalPath();
+ GeneralCommandLine cmd = new GeneralCommandLine();
+ cmd.setWorkDirectory(openedFile.getParent().getCanonicalPath());
+ Sdk sdk = PythonSdkType.findPythonSdk(ModuleManager.getInstance(project).getModules()[0]);
+ if (sdk != null) {
+ String pythonPath = sdk.getHomePath();
+ if (pythonPath != null) {
+ cmd.setExePath(pythonPath);
+ TaskFile selectedTaskFile = taskManager.getTaskFile(openedFile);
+ assert selectedTaskFile != null;
+ Task currentTask = selectedTaskFile.getTask();
+ if (!currentTask.getUserTests().isEmpty()) {
+ cmd.addParameter(new File(project.getBaseDir().getPath(), StudyResourceManger.USER_TESTER).getPath());
+ cmd.addParameter(pythonPath);
+ cmd.addParameter(filePath);
+ Process p;
+ try {
+ p = cmd.createProcess();
+ }
+ catch (ExecutionException e) {
+ LOG.error(e);
+ return;
+ }
+ ProcessHandler handler = new OSProcessHandler(p);
+
+ RunContentExecutor executor = new RunContentExecutor(project, handler);
+ Disposer.register(project, executor);
+ executor.run();
+ return;
+ }
+ try {
+ cmd.addParameter(filePath);
+ Process p = cmd.createProcess();
+ ProcessHandler handler = new OSProcessHandler(p);
+
+ RunContentExecutor executor = new RunContentExecutor(project, handler);
+ Disposer.register(project, executor);
+ executor.run();
+ }
+
+ catch (ExecutionException e) {
+ LOG.error(e);
+ }
+ }
+ }
+ }
+ }
+
+ public void actionPerformed(AnActionEvent e) {
+ run(e.getProject());
+ }
+}
diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyShowHintAction.java b/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyShowHintAction.java
new file mode 100644
index 000000000000..1efa90889449
--- /dev/null
+++ b/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyShowHintAction.java
@@ -0,0 +1,95 @@
+package com.jetbrains.python.edu.actions;
+
+import com.intellij.codeInsight.documentation.DocumentationComponent;
+import com.intellij.codeInsight.documentation.DocumentationManager;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.LogicalPosition;
+import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.project.DumbAwareAction;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.popup.JBPopup;
+import com.intellij.openapi.ui.popup.JBPopupFactory;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiManager;
+import com.jetbrains.python.edu.StudyTaskManager;
+import com.jetbrains.python.edu.StudyUtils;
+import com.jetbrains.python.edu.course.Course;
+import com.jetbrains.python.edu.course.TaskFile;
+import com.jetbrains.python.edu.course.TaskWindow;
+import com.jetbrains.python.edu.editor.StudyEditor;
+import icons.StudyIcons;
+
+import java.io.File;
+
+public class StudyShowHintAction extends DumbAwareAction {
+ public static final String ACTION_ID = "ShowHintAction";
+ public static final String SHORTCUT = "ctrl pressed 7";
+
+ public StudyShowHintAction() {
+ super("Show hint", "Show hint", StudyIcons.ShowHint);
+ }
+
+ public void actionPerformed(AnActionEvent e) {
+ Project project = e.getProject();
+ if (project != null) {
+ DocumentationManager documentationManager = DocumentationManager.getInstance(project);
+ DocumentationComponent component = new DocumentationComponent(documentationManager);
+ Editor selectedEditor = StudyEditor.getSelectedEditor(project);
+ FileDocumentManager fileDocumentManager = FileDocumentManager.getInstance();
+ assert selectedEditor != null;
+ VirtualFile openedFile = fileDocumentManager.getFile(selectedEditor.getDocument());
+ if (openedFile != null) {
+ StudyTaskManager taskManager = StudyTaskManager.getInstance(e.getProject());
+ TaskFile taskFile = taskManager.getTaskFile(openedFile);
+ if (taskFile != null) {
+ PsiFile file = PsiManager.getInstance(project).findFile(openedFile);
+ if (file != null) {
+ LogicalPosition pos = selectedEditor.getCaretModel().getLogicalPosition();
+ TaskWindow taskWindow = taskFile.getTaskWindow(selectedEditor.getDocument(), pos);
+ if (taskWindow != null) {
+ String hint = taskWindow.getHint();
+ if (hint == null) {
+ return;
+ }
+ Course course = taskManager.getCourse();
+ if (course != null) {
+ File resourceFile = new File(course.getResourcePath());
+ File resourceRoot = resourceFile.getParentFile();
+ if (resourceRoot != null && resourceRoot.exists()) {
+ File hintsDir = new File(resourceRoot, Course.HINTS_DIR);
+ if (hintsDir.exists()) {
+ String hintText = StudyUtils.getFileText(hintsDir.getAbsolutePath(), hint, true);
+ if (hintText != null) {
+ int offset = selectedEditor.getDocument().getLineStartOffset(pos.line) + pos.column;
+ PsiElement element = file.findElementAt(offset);
+ if (element != null) {
+ component.setData(element, hintText, true, null);
+ final JBPopup popup =
+ JBPopupFactory.getInstance().createComponentPopupBuilder(component, component)
+ .setDimensionServiceKey(project, DocumentationManager.JAVADOC_LOCATION_AND_SIZE, false)
+ .setResizable(true)
+ .setMovable(true)
+ .setRequestFocus(true)
+ .createPopup();
+ component.setHint(popup);
+ popup.showInBestPositionFor(selectedEditor);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public void update(AnActionEvent e) {
+ StudyUtils.updateAction(e);
+ }
+}
diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyTaskNavigationAction.java b/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyTaskNavigationAction.java
new file mode 100644
index 000000000000..b781e7da8849
--- /dev/null
+++ b/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyTaskNavigationAction.java
@@ -0,0 +1,97 @@
+package com.jetbrains.python.edu.actions;
+
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.fileEditor.FileEditorManager;
+import com.intellij.openapi.project.DumbAwareAction;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.MessageType;
+import com.intellij.openapi.ui.popup.Balloon;
+import com.intellij.openapi.ui.popup.BalloonBuilder;
+import com.intellij.openapi.ui.popup.JBPopupFactory;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.jetbrains.python.edu.StudyTaskManager;
+import com.jetbrains.python.edu.course.Lesson;
+import com.jetbrains.python.edu.course.Task;
+import com.jetbrains.python.edu.course.TaskFile;
+import com.jetbrains.python.edu.editor.StudyEditor;
+
+import javax.swing.*;
+import java.util.Map;
+
+/**
+ * author: liana
+ * data: 7/21/14.
+ */
+abstract public class StudyTaskNavigationAction extends DumbAwareAction {
+ public void navigateTask(Project project) {
+ Editor selectedEditor = StudyEditor.getSelectedEditor(project);
+ FileDocumentManager fileDocumentManager = FileDocumentManager.getInstance();
+ assert selectedEditor != null;
+ VirtualFile openedFile = fileDocumentManager.getFile(selectedEditor.getDocument());
+ StudyTaskManager taskManager = StudyTaskManager.getInstance(project);
+ assert openedFile != null;
+ TaskFile selectedTaskFile = taskManager.getTaskFile(openedFile);
+ assert selectedTaskFile != null;
+ Task currentTask = selectedTaskFile.getTask();
+ Task nextTask = getTargetTask(currentTask);
+ if (nextTask == null) {
+ BalloonBuilder balloonBuilder =
+ JBPopupFactory.getInstance().createHtmlTextBalloonBuilder(getNavigationFinishedMessage(), MessageType.INFO, null);
+ Balloon balloon = balloonBuilder.createBalloon();
+ StudyEditor selectedStudyEditor = StudyEditor.getSelectedStudyEditor(project);
+ balloon.showInCenterOf(getButton(selectedStudyEditor));
+ return;
+ }
+ for (VirtualFile file : FileEditorManager.getInstance(project).getOpenFiles()) {
+ FileEditorManager.getInstance(project).closeFile(file);
+ }
+ int nextTaskIndex = nextTask.getIndex();
+ int lessonIndex = nextTask.getLesson().getIndex();
+ Map<String, TaskFile> nextTaskFiles = nextTask.getTaskFiles();
+ if (nextTaskFiles.isEmpty()) {
+ return;
+ }
+ VirtualFile projectDir = project.getBaseDir();
+ String lessonDirName = Lesson.LESSON_DIR + String.valueOf(lessonIndex + 1);
+ if (projectDir == null) {
+ return;
+ }
+ VirtualFile lessonDir = projectDir.findChild(lessonDirName);
+ if (lessonDir == null) {
+ return;
+ }
+ String taskDirName = Task.TASK_DIR + String.valueOf(nextTaskIndex + 1);
+ VirtualFile taskDir = lessonDir.findChild(taskDirName);
+ if (taskDir == null) {
+ return;
+ }
+ VirtualFile shouldBeActive = null;
+ for (Map.Entry<String, TaskFile> entry : nextTaskFiles.entrySet()) {
+ String name = entry.getKey();
+ TaskFile taskFile = entry.getValue();
+ VirtualFile vf = taskDir.findChild(name);
+ if (vf != null) {
+ FileEditorManager.getInstance(project).openFile(vf, true);
+ if (!taskFile.getTaskWindows().isEmpty()) {
+ shouldBeActive = vf;
+ }
+ }
+ }
+ if (shouldBeActive != null) {
+ FileEditorManager.getInstance(project).openFile(shouldBeActive, true);
+ }
+ }
+
+ protected abstract JButton getButton(StudyEditor selectedStudyEditor);
+
+ @Override
+ public void actionPerformed(AnActionEvent e) {
+ navigateTask(e.getProject());
+ }
+
+ protected abstract String getNavigationFinishedMessage();
+
+ protected abstract Task getTargetTask(Task sourceTask);
+}
diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyWindowNavigationAction.java b/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyWindowNavigationAction.java
new file mode 100644
index 000000000000..8c6b90221555
--- /dev/null
+++ b/python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyWindowNavigationAction.java
@@ -0,0 +1,65 @@
+package com.jetbrains.python.edu.actions;
+
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.project.DumbAwareAction;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.jetbrains.python.edu.StudyTaskManager;
+import com.jetbrains.python.edu.StudyUtils;
+import com.jetbrains.python.edu.course.TaskFile;
+import com.jetbrains.python.edu.course.TaskWindow;
+import com.jetbrains.python.edu.editor.StudyEditor;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+
+abstract public class StudyWindowNavigationAction extends DumbAwareAction {
+
+ public StudyWindowNavigationAction(String actionId, String description, Icon icon) {
+ super(actionId, description, icon);
+ }
+
+ public void navigateWindow(@NotNull final Project project) {
+ Editor selectedEditor = StudyEditor.getSelectedEditor(project);
+ if (selectedEditor != null) {
+ FileDocumentManager fileDocumentManager = FileDocumentManager.getInstance();
+ VirtualFile openedFile = fileDocumentManager.getFile(selectedEditor.getDocument());
+ if (openedFile != null) {
+ StudyTaskManager taskManager = StudyTaskManager.getInstance(project);
+ TaskFile selectedTaskFile = taskManager.getTaskFile(openedFile);
+ if (selectedTaskFile != null) {
+ TaskWindow selectedTaskWindow = selectedTaskFile.getSelectedTaskWindow();
+ if (selectedTaskWindow == null) {
+ return;
+ }
+ TaskWindow nextTaskWindow = getNextTaskWindow(selectedTaskWindow);
+ if (nextTaskWindow == null) {
+ return;
+ }
+ nextTaskWindow.draw(selectedEditor, true, true);
+ selectedTaskFile.setSelectedTaskWindow(nextTaskWindow);
+ }
+ }
+ }
+ }
+
+ @Nullable
+ protected abstract TaskWindow getNextTaskWindow(@NotNull final TaskWindow window);
+
+ @Override
+ public void actionPerformed(AnActionEvent e) {
+ Project project = e.getProject();
+ if (project == null) {
+ return;
+ }
+ navigateWindow(project);
+ }
+
+ @Override
+ public void update(AnActionEvent e) {
+ StudyUtils.updateAction(e);
+ }
+}
diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/course/Course.java b/python/edu/learn-python/src/com/jetbrains/python/edu/course/Course.java
new file mode 100644
index 000000000000..89613ac7918f
--- /dev/null
+++ b/python/edu/learn-python/src/com/jetbrains/python/edu/course/Course.java
@@ -0,0 +1,104 @@
+package com.jetbrains.python.edu.course;
+
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+public class Course {
+
+ private static final Logger LOG = Logger.getInstance(Course.class.getName());
+ public static final String PLAYGROUND_DIR = "Playground";
+ public List<Lesson> lessons = new ArrayList<Lesson>();
+ public String description;
+ public String name;
+ public String myResourcePath = "";
+ public String author;
+ public static final String COURSE_DIR = "course";
+ public static final String HINTS_DIR = "hints";
+
+
+ public List<Lesson> getLessons() {
+ return lessons;
+ }
+
+ /**
+ * Initializes state of course
+ */
+ public void init(boolean isRestarted) {
+ for (Lesson lesson : lessons) {
+ lesson.init(this, isRestarted);
+ }
+ }
+
+ public String getAuthor() {
+ return author;
+ }
+
+ /**
+ * Creates course directory in project user created
+ *
+ * @param baseDir project directory
+ * @param resourceRoot directory where original course is stored
+ */
+ public void create(@NotNull final VirtualFile baseDir, @NotNull final File resourceRoot) {
+ ApplicationManager.getApplication().invokeLater(
+ new Runnable() {
+ @Override
+ public void run() {
+ ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ for (int i = 0; i < lessons.size(); i++) {
+ Lesson lesson = lessons.get(i);
+ lesson.setIndex(i);
+ lesson.create(baseDir, resourceRoot);
+ }
+ baseDir.createChildDirectory(this, PLAYGROUND_DIR);
+ File[] files = resourceRoot.listFiles(new FilenameFilter() {
+ @Override
+ public boolean accept(File dir, String name) {
+ return !name.contains(Lesson.LESSON_DIR) && !name.equals("course.json") && !name.equals("hints");
+ }
+ });
+ for (File file: files) {
+ FileUtil.copy(file, new File(baseDir.getPath(), file.getName()));
+ }
+ }
+ catch (IOException e) {
+ LOG.error(e);
+ }
+ }
+ });
+ }
+ });
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setResourcePath(@NotNull final String resourcePath) {
+ myResourcePath = resourcePath;
+ }
+
+ public String getResourcePath() {
+ return myResourcePath;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+}
diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/course/CourseInfo.java b/python/edu/learn-python/src/com/jetbrains/python/edu/course/CourseInfo.java
new file mode 100644
index 000000000000..9f820c12c572
--- /dev/null
+++ b/python/edu/learn-python/src/com/jetbrains/python/edu/course/CourseInfo.java
@@ -0,0 +1,52 @@
+package com.jetbrains.python.edu.course;
+
+/**
+ * Implementation of class which contains information to be shawn in course description in tool window
+ * and when project is being created
+ */
+public class CourseInfo {
+ private String myName;
+ private String myAuthor;
+ private String myDescription;
+ public static CourseInfo INVALID_COURSE = new CourseInfo("", "", "");
+
+ public CourseInfo(String name, String author, String description) {
+ myName = name;
+ myAuthor = author;
+ myDescription = description;
+ }
+
+ public String getName() {
+ return myName;
+ }
+
+ public String getAuthor() {
+ return myAuthor;
+ }
+
+ public String getDescription() {
+ return myDescription;
+ }
+
+ @Override
+ public String toString() {
+ return myName;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ CourseInfo that = (CourseInfo)o;
+ return that.getName().equals(myName) && that.getAuthor().equals(myAuthor)
+ && that.getDescription().equals(myDescription);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = myName != null ? myName.hashCode() : 0;
+ result = 31 * result + (myAuthor != null ? myAuthor.hashCode() : 0);
+ result = 31 * result + (myDescription != null ? myDescription.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/course/Lesson.java b/python/edu/learn-python/src/com/jetbrains/python/edu/course/Lesson.java
new file mode 100644
index 000000000000..3879d519957e
--- /dev/null
+++ b/python/edu/learn-python/src/com/jetbrains/python/edu/course/Lesson.java
@@ -0,0 +1,109 @@
+package com.jetbrains.python.edu.course;
+
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.xmlb.annotations.Transient;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+public class Lesson implements Stateful{
+ public String name;
+ public List<Task> taskList = new ArrayList<Task>();
+ private Course myCourse = null;
+ public int myIndex = -1;
+ public static final String LESSON_DIR = "lesson";
+ public LessonInfo myLessonInfo = new LessonInfo();
+
+ public LessonInfo getLessonInfo() {
+ return myLessonInfo;
+ }
+
+ @Transient
+ public StudyStatus getStatus() {
+ for (Task task : taskList) {
+ StudyStatus taskStatus = task.getStatus();
+ if (taskStatus == StudyStatus.Unchecked || taskStatus == StudyStatus.Failed) {
+ return StudyStatus.Unchecked;
+ }
+ }
+ return StudyStatus.Solved;
+ }
+
+ @Override
+ public void setStatus(StudyStatus status, StudyStatus oldStatus) {
+ for (Task task : taskList) {
+ task.setStatus(status, oldStatus);
+ }
+ }
+
+ public List<Task> getTaskList() {
+ return taskList;
+ }
+
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Creates lesson directory in its course folder in project user created
+ *
+ * @param courseDir project directory of course
+ * @param resourceRoot directory where original lesson stored
+ * @throws java.io.IOException
+ */
+ public void create(@NotNull final VirtualFile courseDir, @NotNull final File resourceRoot) throws IOException {
+ String lessonDirName = LESSON_DIR + Integer.toString(myIndex + 1);
+ VirtualFile lessonDir = courseDir.createChildDirectory(this, lessonDirName);
+ for (int i = 0; i < taskList.size(); i++) {
+ Task task = taskList.get(i);
+ task.setIndex(i);
+ task.create(lessonDir, new File(resourceRoot, lessonDir.getName()));
+ }
+ }
+
+
+ /**
+ * Initializes state of lesson
+ *
+ * @param course course which lesson belongs to
+ */
+ public void init(final Course course, boolean isRestarted) {
+ myCourse = course;
+ myLessonInfo.setTaskNum(taskList.size());
+ myLessonInfo.setTaskUnchecked(taskList.size());
+ for (Task task : taskList) {
+ task.init(this, isRestarted);
+ }
+ }
+
+ public Lesson next() {
+ List<Lesson> lessons = myCourse.getLessons();
+ if (myIndex + 1 >= lessons.size()) {
+ return null;
+ }
+ return lessons.get(myIndex + 1);
+ }
+
+ public void setIndex(int index) {
+ myIndex = index;
+ }
+
+ public int getIndex() {
+ return myIndex;
+ }
+
+ public Lesson prev() {
+ if (myIndex - 1 < 0) {
+ return null;
+ }
+ return myCourse.getLessons().get(myIndex - 1);
+ }
+}
diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/course/LessonInfo.java b/python/edu/learn-python/src/com/jetbrains/python/edu/course/LessonInfo.java
new file mode 100644
index 000000000000..85e2eb8be1a9
--- /dev/null
+++ b/python/edu/learn-python/src/com/jetbrains/python/edu/course/LessonInfo.java
@@ -0,0 +1,60 @@
+package com.jetbrains.python.edu.course;
+
+/**
+ * Implementation of class which contains information about student progress in current lesson
+ */
+public class LessonInfo {
+ private int myTaskNum;
+ private int myTaskFailed;
+ private int myTaskSolved;
+ private int myTaskUnchecked;
+
+ public int getTaskNum() {
+ return myTaskNum;
+ }
+
+ public void setTaskNum(int taskNum) {
+ myTaskNum = taskNum;
+ }
+
+ public int getTaskFailed() {
+ return myTaskFailed;
+ }
+
+ public void setTaskFailed(int taskFailed) {
+ myTaskFailed = taskFailed;
+ }
+
+ public int getTaskSolved() {
+ return myTaskSolved;
+ }
+
+ public void setTaskSolved(int taskSolved) {
+ myTaskSolved = taskSolved;
+ }
+
+ public int getTaskUnchecked() {
+ return myTaskUnchecked;
+ }
+
+ public void setTaskUnchecked(int taskUnchecked) {
+ myTaskUnchecked = taskUnchecked;
+ }
+
+ public void update(StudyStatus status, int delta) {
+ switch (status) {
+ case Solved: {
+ myTaskSolved += delta;
+ break;
+ }
+ case Failed: {
+ myTaskFailed += delta;
+ break;
+ }
+ case Unchecked: {
+ myTaskUnchecked += delta;
+ break;
+ }
+ }
+ }
+}
diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/course/Stateful.java b/python/edu/learn-python/src/com/jetbrains/python/edu/course/Stateful.java
new file mode 100644
index 000000000000..3a163622f56d
--- /dev/null
+++ b/python/edu/learn-python/src/com/jetbrains/python/edu/course/Stateful.java
@@ -0,0 +1,6 @@
+package com.jetbrains.python.edu.course;
+
+public interface Stateful {
+ StudyStatus getStatus();
+ void setStatus(StudyStatus status, StudyStatus oldStatus);
+}
diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/course/StudyStatus.java b/python/edu/learn-python/src/com/jetbrains/python/edu/course/StudyStatus.java
new file mode 100644
index 000000000000..d95b42b73866
--- /dev/null
+++ b/python/edu/learn-python/src/com/jetbrains/python/edu/course/StudyStatus.java
@@ -0,0 +1,8 @@
+package com.jetbrains.python.edu.course;
+
+/**
+ * @see {@link TaskWindow#myStatus}
+ */
+public enum StudyStatus {
+ Unchecked, Solved, Failed
+}
diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/course/Task.java b/python/edu/learn-python/src/com/jetbrains/python/edu/course/Task.java
new file mode 100644
index 000000000000..2323412f4374
--- /dev/null
+++ b/python/edu/learn-python/src/com/jetbrains/python/edu/course/Task.java
@@ -0,0 +1,201 @@
+package com.jetbrains.python.edu.course;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.xmlb.annotations.Transient;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import com.jetbrains.python.edu.StudyUtils;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Implementation of task which contains task files, tests, input file for tests
+ */
+public class Task implements Stateful{
+ public static final String TASK_DIR = "task";
+ private static final String ourTestFile = "tests.py";
+ public String name;
+ private static final String ourTextFile = "task.html";
+ public Map<String, TaskFile> taskFiles = new HashMap<String, TaskFile>();
+ private Lesson myLesson;
+ public int myIndex;
+ public List<UserTest> userTests = new ArrayList<UserTest>();
+ public static final String USER_TESTS = "userTests";
+
+ public Map<String, TaskFile> getTaskFiles() {
+ return taskFiles;
+ }
+
+ @Transient
+ public StudyStatus getStatus() {
+ for (TaskFile taskFile : taskFiles.values()) {
+ StudyStatus taskFileStatus = taskFile.getStatus();
+ if (taskFileStatus == StudyStatus.Unchecked) {
+ return StudyStatus.Unchecked;
+ }
+ if (taskFileStatus == StudyStatus.Failed) {
+ return StudyStatus.Failed;
+ }
+ }
+ return StudyStatus.Solved;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public void setStatus(@NotNull final StudyStatus status, @NotNull final StudyStatus oldStatus) {
+ LessonInfo lessonInfo = myLesson.getLessonInfo();
+ if (status != oldStatus) {
+ lessonInfo.update(oldStatus, -1);
+ lessonInfo.update(status, +1);
+ }
+ for (TaskFile taskFile : taskFiles.values()) {
+ taskFile.setStatus(status, oldStatus);
+ }
+ }
+
+ public List<UserTest> getUserTests() {
+ return userTests;
+ }
+
+ public String getTestFile() {
+ return ourTestFile;
+ }
+
+ public String getText() {
+ return ourTextFile;
+ }
+
+ /**
+ * Creates task directory in its lesson folder in project user created
+ *
+ * @param lessonDir project directory of lesson which task belongs to
+ * @param resourceRoot directory where original task file stored
+ * @throws java.io.IOException
+ */
+ public void create(@NotNull final VirtualFile lessonDir, @NotNull final File resourceRoot) throws IOException {
+ VirtualFile taskDir = lessonDir.createChildDirectory(this, TASK_DIR + Integer.toString(myIndex + 1));
+ File newResourceRoot = new File(resourceRoot, taskDir.getName());
+ int i = 0;
+ for (Map.Entry<String, TaskFile> taskFile : taskFiles.entrySet()) {
+ TaskFile taskFileContent = taskFile.getValue();
+ taskFileContent.setIndex(i);
+ i++;
+ taskFileContent.create(taskDir, newResourceRoot, taskFile.getKey());
+ }
+ File[] filesInTask = newResourceRoot.listFiles();
+ if (filesInTask != null) {
+ for (File file : filesInTask) {
+ String fileName = file.getName();
+ if (!isTaskFile(fileName)) {
+ File resourceFile = new File(newResourceRoot, fileName);
+ File fileInProject = new File(taskDir.getCanonicalPath(), fileName);
+ FileUtil.copy(resourceFile, fileInProject);
+ }
+ }
+ }
+ }
+
+ private boolean isTaskFile(@NotNull final String fileName) {
+ return taskFiles.get(fileName) != null;
+ }
+
+ @Nullable
+ public TaskFile getFile(@NotNull final String fileName) {
+ return taskFiles.get(fileName);
+ }
+
+ /**
+ * Initializes state of task file
+ *
+ * @param lesson lesson which task belongs to
+ */
+ public void init(final Lesson lesson, boolean isRestarted) {
+ myLesson = lesson;
+ for (TaskFile taskFile : taskFiles.values()) {
+ taskFile.init(this, isRestarted);
+ }
+ }
+
+ public Task next() {
+ Lesson currentLesson = this.myLesson;
+ List<Task> taskList = myLesson.getTaskList();
+ if (myIndex + 1 < taskList.size()) {
+ return taskList.get(myIndex + 1);
+ }
+ Lesson nextLesson = currentLesson.next();
+ if (nextLesson == null) {
+ return null;
+ }
+ return StudyUtils.getFirst(nextLesson.getTaskList());
+ }
+
+ public Task prev() {
+ Lesson currentLesson = this.myLesson;
+ if (myIndex - 1 >= 0) {
+ return myLesson.getTaskList().get(myIndex - 1);
+ }
+ Lesson prevLesson = currentLesson.prev();
+ if (prevLesson == null) {
+ return null;
+ }
+ //getting last task in previous lesson
+ return prevLesson.getTaskList().get(prevLesson.getTaskList().size() - 1);
+ }
+
+ public void setIndex(int index) {
+ myIndex = index;
+ }
+
+ public int getIndex() {
+ return myIndex;
+ }
+
+ public Lesson getLesson() {
+ return myLesson;
+ }
+
+
+ @Nullable
+ public VirtualFile getTaskDir(Project project) {
+ String lessonDirName = Lesson.LESSON_DIR + String.valueOf(myLesson.getIndex() + 1);
+ String taskDirName = TASK_DIR + String.valueOf(myIndex + 1);
+ VirtualFile courseDir = project.getBaseDir();
+ if (courseDir != null) {
+ VirtualFile lessonDir = courseDir.findChild(lessonDirName);
+ if (lessonDir != null) {
+ return lessonDir.findChild(taskDirName);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Gets text of resource file such as test input file or task text in needed format
+ *
+ * @param fileName name of resource file which should exist in task directory
+ * @param wrapHTML if it's necessary to wrap text with html tags
+ * @return text of resource file wrapped with html tags if necessary
+ */
+ @Nullable
+ public String getResourceText(@NotNull final Project project, @NotNull final String fileName, boolean wrapHTML) {
+ VirtualFile taskDir = getTaskDir(project);
+ if (taskDir != null) {
+ return StudyUtils.getFileText(taskDir.getCanonicalPath(), fileName, wrapHTML);
+ }
+ return null;
+ }
+
+}
diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/course/TaskFile.java b/python/edu/learn-python/src/com/jetbrains/python/edu/course/TaskFile.java
new file mode 100644
index 000000000000..4f17fc0d27f3
--- /dev/null
+++ b/python/edu/learn-python/src/com/jetbrains/python/edu/course/TaskFile.java
@@ -0,0 +1,228 @@
+package com.jetbrains.python.edu.course;
+
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.LogicalPosition;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.xmlb.annotations.Transient;
+import com.jetbrains.python.edu.StudyUtils;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Implementation of task file which contains task windows for student to type in and
+ * which is visible to student in project view
+ */
+
+public class TaskFile implements Stateful{
+ public List<TaskWindow> taskWindows = new ArrayList<TaskWindow>();
+ private Task myTask;
+ @Transient
+ private TaskWindow mySelectedTaskWindow = null;
+ public int myIndex = -1;
+ private boolean myUserCreated = false;
+
+ /**
+ * @return if all the windows in task file are marked as resolved
+ */
+ @Transient
+ public StudyStatus getStatus() {
+ for (TaskWindow taskWindow : taskWindows) {
+ StudyStatus windowStatus = taskWindow.getStatus();
+ if (windowStatus == StudyStatus.Failed) {
+ return StudyStatus.Failed;
+ }
+ if (windowStatus == StudyStatus.Unchecked) {
+ return StudyStatus.Unchecked;
+ }
+ }
+ return StudyStatus.Solved;
+ }
+
+ public Task getTask() {
+ return myTask;
+ }
+
+ @Nullable
+ @Transient
+ public TaskWindow getSelectedTaskWindow() {
+ return mySelectedTaskWindow;
+ }
+
+ /**
+ * @param selectedTaskWindow window from this task file to be set as selected
+ */
+ public void setSelectedTaskWindow(@NotNull final TaskWindow selectedTaskWindow) {
+ if (selectedTaskWindow.getTaskFile() == this) {
+ mySelectedTaskWindow = selectedTaskWindow;
+ }
+ else {
+ throw new IllegalArgumentException("Window may be set as selected only in task file which it belongs to");
+ }
+ }
+
+ public List<TaskWindow> getTaskWindows() {
+ return taskWindows;
+ }
+
+ /**
+ * Creates task files in its task folder in project user created
+ *
+ * @param taskDir project directory of task which task file belongs to
+ * @param resourceRoot directory where original task file stored
+ * @throws java.io.IOException
+ */
+ public void create(@NotNull final VirtualFile taskDir, @NotNull final File resourceRoot,
+ @NotNull final String name) throws IOException {
+ String systemIndependentName = FileUtil.toSystemIndependentName(name);
+ final int index = systemIndependentName.lastIndexOf("/");
+ if (index > 0) {
+ systemIndependentName = systemIndependentName.substring(index + 1);
+ }
+ File resourceFile = new File(resourceRoot, name);
+ File fileInProject = new File(taskDir.getPath(), systemIndependentName);
+ FileUtil.copy(resourceFile, fileInProject);
+ }
+
+ public void drawAllWindows(Editor editor) {
+ for (TaskWindow taskWindow : taskWindows) {
+ taskWindow.draw(editor, false, false);
+ }
+ }
+
+
+ /**
+ * @param pos position in editor
+ * @return task window located in specified position or null if there is no task window in this position
+ */
+ @Nullable
+ public TaskWindow getTaskWindow(@NotNull final Document document, @NotNull final LogicalPosition pos) {
+ int line = pos.line;
+ if (line >= document.getLineCount()) {
+ return null;
+ }
+ int column = pos.column;
+ int offset = document.getLineStartOffset(line) + column;
+ for (TaskWindow tw : taskWindows) {
+ if (tw.getLine() <= line) {
+ int twStartOffset = tw.getRealStartOffset(document);
+ final int length = tw.getLength() > 0 ? tw.getLength() : 0;
+ int twEndOffset = twStartOffset + length;
+ if (twStartOffset <= offset && offset <= twEndOffset) {
+ return tw;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Updates task window lines
+ *
+ * @param startLine lines greater than this line and including this line will be updated
+ * @param change change to be added to line numbers
+ */
+ public void incrementLines(int startLine, int change) {
+ for (TaskWindow taskTaskWindow : taskWindows) {
+ if (taskTaskWindow.getLine() >= startLine) {
+ taskTaskWindow.setLine(taskTaskWindow.getLine() + change);
+ }
+ }
+ }
+
+ /**
+ * Initializes state of task file
+ *
+ * @param task task which task file belongs to
+ */
+
+ public void init(final Task task, boolean isRestarted) {
+ myTask = task;
+ for (TaskWindow taskWindow : taskWindows) {
+ taskWindow.init(this, isRestarted);
+ }
+ Collections.sort(taskWindows);
+ for (int i = 0; i < taskWindows.size(); i++) {
+ taskWindows.get(i).setIndex(i);
+ }
+ }
+
+ /**
+ * @param index index of task file in list of task files of its task
+ */
+ public void setIndex(int index) {
+ myIndex = index;
+ }
+
+ /**
+ * Updates windows in specific line
+ *
+ * @param lineChange change in line number
+ * @param line line to be updated
+ * @param newEndOffsetInLine distance from line start to end of inserted fragment
+ * @param oldEndOffsetInLine distance from line start to end of changed fragment
+ */
+ public void updateLine(int lineChange, int line, int newEndOffsetInLine, int oldEndOffsetInLine) {
+ for (TaskWindow w : taskWindows) {
+ if ((w.getLine() == line) && (w.getStart() >= oldEndOffsetInLine)) {
+ int distance = w.getStart() - oldEndOffsetInLine;
+ if (lineChange != 0 || newEndOffsetInLine <= w.getStart()) {
+ w.setStart(distance + newEndOffsetInLine);
+ w.setLine(line + lineChange);
+ }
+ }
+ }
+ }
+
+ public static void copy(@NotNull final TaskFile source, @NotNull final TaskFile target) {
+ List<TaskWindow> sourceTaskWindows = source.getTaskWindows();
+ List<TaskWindow> windowsCopy = new ArrayList<TaskWindow>(sourceTaskWindows.size());
+ for (TaskWindow taskWindow : sourceTaskWindows) {
+ TaskWindow taskWindowCopy = new TaskWindow();
+ taskWindowCopy.setLine(taskWindow.getLine());
+ taskWindowCopy.setStart(taskWindow.getStart());
+ taskWindowCopy.setLength(taskWindow.getLength());
+ taskWindowCopy.setPossibleAnswer(taskWindow.getPossibleAnswer());
+ taskWindowCopy.setIndex(taskWindow.getIndex());
+ windowsCopy.add(taskWindowCopy);
+ }
+ target.setTaskWindows(windowsCopy);
+ }
+
+ public void setTaskWindows(List<TaskWindow> taskWindows) {
+ this.taskWindows = taskWindows;
+ }
+
+ public void setStatus(@NotNull final StudyStatus status, @NotNull final StudyStatus oldStatus) {
+ for (TaskWindow taskWindow : taskWindows) {
+ taskWindow.setStatus(status, oldStatus);
+ }
+ }
+
+ public void setUserCreated(boolean userCreated) {
+ myUserCreated = userCreated;
+ }
+
+ public boolean isUserCreated() {
+ return myUserCreated;
+ }
+
+ public void navigateToFirstTaskWindow(@NotNull final Editor editor) {
+ if (!taskWindows.isEmpty()) {
+ TaskWindow firstTaskWindow = StudyUtils.getFirst(taskWindows);
+ mySelectedTaskWindow = firstTaskWindow;
+ LogicalPosition taskWindowStart = new LogicalPosition(firstTaskWindow.getLine(), firstTaskWindow.getStart());
+ editor.getCaretModel().moveToLogicalPosition(taskWindowStart);
+ int startOffset = firstTaskWindow.getRealStartOffset(editor.getDocument());
+ int endOffset = startOffset + firstTaskWindow.getLength();
+ editor.getSelectionModel().setSelection(startOffset, endOffset);
+ }
+ }
+}
diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/course/TaskWindow.java b/python/edu/learn-python/src/com/jetbrains/python/edu/course/TaskWindow.java
new file mode 100644
index 000000000000..4fb112cc1f9b
--- /dev/null
+++ b/python/edu/learn-python/src/com/jetbrains/python/edu/course/TaskWindow.java
@@ -0,0 +1,177 @@
+package com.jetbrains.python.edu.course;
+
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.colors.EditorColors;
+import com.intellij.openapi.editor.colors.EditorColorsManager;
+import com.intellij.openapi.editor.markup.HighlighterLayer;
+import com.intellij.openapi.editor.markup.HighlighterTargetArea;
+import com.intellij.openapi.editor.markup.RangeHighlighter;
+import com.intellij.openapi.editor.markup.TextAttributes;
+import com.intellij.ui.JBColor;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Implementation of windows which user should type in
+ */
+
+
+public class TaskWindow implements Comparable, Stateful {
+
+ public int line = 0;
+ public int start = 0;
+ public String hint = "";
+ public String possibleAnswer = "";
+ public int length = 0;
+ private TaskFile myTaskFile;
+ public int myIndex = -1;
+ public int myInitialLine = -1;
+ public int myInitialStart = -1;
+ public int myInitialLength = -1;
+ public StudyStatus myStatus = StudyStatus.Unchecked;
+
+ public StudyStatus getStatus() {
+ return myStatus;
+ }
+
+ public void setStatus(StudyStatus status, StudyStatus oldStatus) {
+ myStatus = status;
+ }
+
+ public void setIndex(int index) {
+ myIndex = index;
+ }
+
+ public int getLength() {
+ return length;
+ }
+
+ public void setLength(int length) {
+ this.length = length;
+ }
+
+ public int getStart() {
+ return start;
+ }
+
+ public void setStart(int start) {
+ this.start = start;
+ }
+
+ public void setLine(int line) {
+ this.line = line;
+ }
+
+ public int getLine() {
+ return line;
+ }
+
+
+ /**
+ * Draw task window with color according to its status
+ */
+ public void draw(@NotNull final Editor editor, boolean drawSelection, boolean moveCaret) {
+ Document document = editor.getDocument();
+ if (!isValid(document)) {
+ return;
+ }
+ TextAttributes defaultTestAttributes =
+ EditorColorsManager.getInstance().getGlobalScheme().getAttributes(EditorColors.LIVE_TEMPLATE_ATTRIBUTES);
+ JBColor color = getColor();
+ int startOffset = document.getLineStartOffset(line) + start;
+ RangeHighlighter
+ rh = editor.getMarkupModel().addRangeHighlighter(startOffset, startOffset + length, HighlighterLayer.LAST + 1,
+ new TextAttributes(defaultTestAttributes.getForegroundColor(),
+ defaultTestAttributes.getBackgroundColor(), color,
+ defaultTestAttributes.getEffectType(),
+ defaultTestAttributes.getFontType()),
+ HighlighterTargetArea.EXACT_RANGE);
+ if (drawSelection) {
+ editor.getSelectionModel().setSelection(startOffset, startOffset + length);
+ }
+ if (moveCaret) {
+ editor.getCaretModel().moveToOffset(startOffset);
+ }
+ rh.setGreedyToLeft(true);
+ rh.setGreedyToRight(true);
+ }
+
+ public boolean isValid(@NotNull final Document document) {
+ boolean isLineValid = line < document.getLineCount() && line >= 0;
+ if (!isLineValid) return false;
+ boolean isStartValid = start >= 0 && start < document.getLineEndOffset(line);
+ boolean isLengthValid = (getRealStartOffset(document) + length) <= document.getTextLength();
+ return isLengthValid && isStartValid;
+ }
+
+ private JBColor getColor() {
+ if (myStatus == StudyStatus.Solved) {
+ return JBColor.GREEN;
+ }
+ if (myStatus == StudyStatus.Failed) {
+ return JBColor.RED;
+ }
+ return JBColor.BLUE;
+ }
+
+ public int getRealStartOffset(@NotNull final Document document) {
+ return document.getLineStartOffset(line) + start;
+ }
+
+ /**
+ * Initializes window
+ *
+ * @param file task file which window belongs to
+ */
+ public void init(final TaskFile file, boolean isRestarted) {
+ if (!isRestarted) {
+ myInitialLine = line;
+ myInitialLength = length;
+ myInitialStart = start;
+ }
+ myTaskFile = file;
+ }
+
+ public TaskFile getTaskFile() {
+ return myTaskFile;
+ }
+
+ @Override
+ public int compareTo(@NotNull Object o) {
+ TaskWindow taskWindow = (TaskWindow)o;
+ if (taskWindow.getTaskFile() != myTaskFile) {
+ throw new ClassCastException();
+ }
+ int lineDiff = line - taskWindow.line;
+ if (lineDiff == 0) {
+ return start - taskWindow.start;
+ }
+ return lineDiff;
+ }
+
+ /**
+ * Returns window to its initial state
+ */
+ public void reset() {
+ myStatus = StudyStatus.Unchecked;
+ line = myInitialLine;
+ start = myInitialStart;
+ length = myInitialLength;
+ }
+
+ public String getHint() {
+ return hint;
+ }
+
+ public String getPossibleAnswer() {
+ return possibleAnswer;
+ }
+
+ public void setPossibleAnswer(String possibleAnswer) {
+ this.possibleAnswer = possibleAnswer;
+ }
+
+ public int getIndex() {
+ return myIndex;
+ }
+} \ No newline at end of file
diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/course/UserTest.java b/python/edu/learn-python/src/com/jetbrains/python/edu/course/UserTest.java
new file mode 100644
index 000000000000..8133e9102a14
--- /dev/null
+++ b/python/edu/learn-python/src/com/jetbrains/python/edu/course/UserTest.java
@@ -0,0 +1,41 @@
+package com.jetbrains.python.edu.course;
+
+public class UserTest {
+ private String input;
+ private String output;
+ private StringBuilder myInputBuffer = new StringBuilder();
+ private StringBuilder myOutputBuffer = new StringBuilder();
+ private boolean myEditable = false;
+
+ public String getInput() {
+ return input;
+ }
+
+ public void setInput(String input) {
+ this.input = input;
+ }
+
+ public String getOutput() {
+ return output;
+ }
+
+ public void setOutput(String output) {
+ this.output = output;
+ }
+
+ public StringBuilder getInputBuffer() {
+ return myInputBuffer;
+ }
+
+ public StringBuilder getOutputBuffer() {
+ return myOutputBuffer;
+ }
+
+ public boolean isEditable() {
+ return myEditable;
+ }
+
+ public void setEditable(boolean editable) {
+ myEditable = editable;
+ }
+}
diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/editor/StudyEditor.java b/python/edu/learn-python/src/com/jetbrains/python/edu/editor/StudyEditor.java
new file mode 100644
index 000000000000..69c5acc5f127
--- /dev/null
+++ b/python/edu/learn-python/src/com/jetbrains/python/edu/editor/StudyEditor.java
@@ -0,0 +1,347 @@
+package com.jetbrains.python.edu.editor;
+
+import com.intellij.codeHighlighting.BackgroundEditorHighlighter;
+import com.intellij.ide.structureView.StructureViewBuilder;
+import com.intellij.openapi.actionSystem.ActionManager;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.EditorFactory;
+import com.intellij.openapi.editor.colors.EditorColorsManager;
+import com.intellij.openapi.editor.colors.EditorColorsScheme;
+import com.intellij.openapi.editor.impl.DocumentImpl;
+import com.intellij.openapi.fileEditor.*;
+import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx;
+import com.intellij.openapi.fileEditor.impl.text.PsiAwareTextEditorImpl;
+import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Disposer;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.pom.Navigatable;
+import com.intellij.ui.HideableTitledPanel;
+import com.intellij.ui.JBColor;
+import com.intellij.util.ui.UIUtil;
+import com.jetbrains.python.edu.StudyDocumentListener;
+import com.jetbrains.python.edu.StudyTaskManager;
+import com.jetbrains.python.edu.actions.*;
+import com.jetbrains.python.edu.course.Task;
+import com.jetbrains.python.edu.course.TaskFile;
+import icons.StudyIcons;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import javax.swing.border.EmptyBorder;
+import javax.swing.text.MutableAttributeSet;
+import javax.swing.text.StyleConstants;
+import javax.swing.text.StyledDocument;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.beans.PropertyChangeListener;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Implementation of StudyEditor which has panel with special buttons and task text
+ * also @see {@link com.jetbrains.python.edu.editor.StudyFileEditorProvider}
+ */
+public class StudyEditor implements TextEditor {
+ private static final String TASK_TEXT_HEADER = "Task Text";
+ private final FileEditor myDefaultEditor;
+ private final JComponent myComponent;
+ private JButton myCheckButton;
+ private JButton myNextTaskButton;
+ private JButton myPrevTaskButton;
+ private JButton myRefreshButton;
+ private static final Map<Document, StudyDocumentListener> myDocumentListeners = new HashMap<Document, StudyDocumentListener>();
+ private Project myProject;
+
+ public JButton getCheckButton() {
+ return myCheckButton;
+ }
+
+ public JButton getPrevTaskButton() {
+ return myPrevTaskButton;
+ }
+
+ private static JButton addButton(@NotNull final JComponent parentComponent, String toolTipText, Icon icon) {
+ JButton newButton = new JButton();
+ newButton.setToolTipText(toolTipText);
+ newButton.setIcon(icon);
+ newButton.setSize(new Dimension(icon.getIconWidth(), icon.getIconHeight()));
+ parentComponent.add(newButton);
+ return newButton;
+ }
+
+ public static void addDocumentListener(@NotNull final Document document, @NotNull final StudyDocumentListener listener) {
+ myDocumentListeners.put(document, listener);
+ }
+
+ @Nullable
+ public static StudyDocumentListener getListener(@NotNull final Document document) {
+ return myDocumentListeners.get(document);
+ }
+
+ public StudyEditor(@NotNull final Project project, @NotNull final VirtualFile file) {
+ myProject = project;
+ myDefaultEditor = TextEditorProvider.getInstance().createEditor(myProject, file);
+ myComponent = myDefaultEditor.getComponent();
+ JPanel studyPanel = new JPanel();
+ studyPanel.setLayout(new BoxLayout(studyPanel, BoxLayout.Y_AXIS));
+ TaskFile taskFile = StudyTaskManager.getInstance(myProject).getTaskFile(file);
+ if (taskFile != null) {
+ Task currentTask = taskFile.getTask();
+ String taskText = currentTask.getResourceText(project, currentTask.getText(), false);
+ initializeTaskText(studyPanel, taskText);
+ JPanel studyButtonPanel = new JPanel(new GridLayout(1, 2));
+ JPanel taskActionsPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
+ studyButtonPanel.add(taskActionsPanel);
+ studyButtonPanel.add(new JPanel());
+ initializeButtons(taskActionsPanel, taskFile);
+ studyPanel.add(studyButtonPanel);
+ myComponent.add(studyPanel, BorderLayout.NORTH);
+ }
+ }
+
+ private static void initializeTaskText(JPanel studyPanel, @Nullable String taskText) {
+ JTextPane taskTextPane = new JTextPane();
+ taskTextPane.setContentType("text/html");
+ taskTextPane.setEditable(false);
+ taskTextPane.setText(taskText);
+ EditorColorsScheme editorColorsScheme = EditorColorsManager.getInstance().getGlobalScheme();
+ int fontSize = editorColorsScheme.getEditorFontSize();
+ String fontName = editorColorsScheme.getEditorFontName();
+ setJTextPaneFont(taskTextPane, new Font(fontName, Font.PLAIN, fontSize), JBColor.BLACK);
+ taskTextPane.setBackground(UIUtil.getPanelBackground());
+ taskTextPane.setBorder(new EmptyBorder(15, 20, 0, 100));
+ HideableTitledPanel taskTextPanel = new HideableTitledPanel(TASK_TEXT_HEADER, taskTextPane, true);
+ taskTextPanel.setBorder(new EmptyBorder(10, 10, 10, 10));
+ studyPanel.add(taskTextPanel);
+ }
+
+ private static void setJTextPaneFont(JTextPane jtp, Font font, Color c) {
+ MutableAttributeSet attrs = jtp.getInputAttributes();
+ StyleConstants.setFontFamily(attrs, font.getFamily());
+ StyleConstants.setFontSize(attrs, font.getSize());
+ StyleConstants.setItalic(attrs, (font.getStyle() & Font.ITALIC) != 0);
+ StyleConstants.setBold(attrs, (font.getStyle() & Font.BOLD) != 0);
+ StyleConstants.setForeground(attrs, c);
+ StyledDocument doc = jtp.getStyledDocument();
+ doc.setCharacterAttributes(0, doc.getLength() + 1, attrs, false);
+ }
+
+ private void initializeButtons(@NotNull final JPanel taskActionsPanel, @NotNull final TaskFile taskFile) {
+ myCheckButton = addButton(taskActionsPanel, "Check task", StudyIcons.Resolve);
+ myPrevTaskButton = addButton(taskActionsPanel, "Prev Task", StudyIcons.Prev);
+ myNextTaskButton = addButton(taskActionsPanel, "Next Task", StudyIcons.Next);
+ myRefreshButton = addButton(taskActionsPanel, "Start task again", StudyIcons.Refresh24);
+ if (!taskFile.getTask().getUserTests().isEmpty()) {
+ JButton runButton = addButton(taskActionsPanel, "Run", StudyIcons.Run);
+ runButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ StudyRunAction studyRunAction = (StudyRunAction)ActionManager.getInstance().getAction("StudyRunAction");
+ studyRunAction.run(myProject);
+ }
+ });
+ JButton watchInputButton = addButton(taskActionsPanel, "Watch test input", StudyIcons.WatchInput);
+ watchInputButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ StudyEditInputAction studyEditInputAction = (StudyEditInputAction)ActionManager.getInstance().getAction("WatchInputAction");
+ studyEditInputAction.showInput(myProject);
+ }
+ });
+ }
+ myCheckButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ StudyCheckAction studyCheckAction = (StudyCheckAction)ActionManager.getInstance().getAction("CheckAction");
+ studyCheckAction.check(myProject);
+ }
+ });
+
+ myNextTaskButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ StudyNextStudyTaskAction studyNextTaskAction = (StudyNextStudyTaskAction)ActionManager.getInstance().getAction("NextTaskAction");
+ studyNextTaskAction.navigateTask(myProject);
+ }
+ });
+ myPrevTaskButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ StudyPreviousStudyTaskAction
+ prevTaskAction = (StudyPreviousStudyTaskAction)ActionManager.getInstance().getAction("PreviousTaskAction");
+ prevTaskAction.navigateTask(myProject);
+ }
+ });
+ myRefreshButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ StudyRefreshTaskAction studyRefreshTaskAction = (StudyRefreshTaskAction)ActionManager.getInstance().getAction("RefreshTaskAction");
+ studyRefreshTaskAction.refresh(myProject);
+ }
+ });
+ }
+
+ public JButton getNextTaskButton() {
+ return myNextTaskButton;
+ }
+
+ public JButton getRefreshButton() {
+ return myRefreshButton;
+ }
+
+ FileEditor getDefaultEditor() {
+ return myDefaultEditor;
+ }
+
+ @NotNull
+ @Override
+ public JComponent getComponent() {
+ return myComponent;
+ }
+
+ @Nullable
+ @Override
+ public JComponent getPreferredFocusedComponent() {
+ return myDefaultEditor.getPreferredFocusedComponent();
+ }
+
+ @NotNull
+ @Override
+ public String getName() {
+ return "Study Editor";
+ }
+
+ @NotNull
+ @Override
+ public FileEditorState getState(@NotNull FileEditorStateLevel level) {
+ return myDefaultEditor.getState(level);
+ }
+
+ @Override
+ public void setState(@NotNull FileEditorState state) {
+ myDefaultEditor.setState(state);
+ }
+
+ @Override
+ public boolean isModified() {
+ return myDefaultEditor.isModified();
+ }
+
+ @Override
+ public boolean isValid() {
+ return myDefaultEditor.isValid();
+ }
+
+ @Override
+ public void selectNotify() {
+ myDefaultEditor.selectNotify();
+ }
+
+ @Override
+ public void deselectNotify() {
+ myDefaultEditor.deselectNotify();
+ }
+
+ @Override
+ public void addPropertyChangeListener(@NotNull PropertyChangeListener listener) {
+ myDefaultEditor.addPropertyChangeListener(listener);
+ }
+
+ @Override
+ public void removePropertyChangeListener(@NotNull PropertyChangeListener listener) {
+ myDefaultEditor.removePropertyChangeListener(listener);
+ }
+
+ @Nullable
+ @Override
+ public BackgroundEditorHighlighter getBackgroundHighlighter() {
+ return myDefaultEditor.getBackgroundHighlighter();
+ }
+
+ @Nullable
+ @Override
+ public FileEditorLocation getCurrentLocation() {
+ return myDefaultEditor.getCurrentLocation();
+ }
+
+ @Nullable
+ @Override
+ public StructureViewBuilder getStructureViewBuilder() {
+ return myDefaultEditor.getStructureViewBuilder();
+ }
+
+ @Override
+ public void dispose() {
+ Disposer.dispose(myDefaultEditor);
+ }
+
+ @Nullable
+ @Override
+ public <T> T getUserData(@NotNull Key<T> key) {
+ return myDefaultEditor.getUserData(key);
+ }
+
+ @Override
+ public <T> void putUserData(@NotNull Key<T> key, @Nullable T value) {
+ myDefaultEditor.putUserData(key, value);
+ }
+
+
+ @Nullable
+ public static StudyEditor getSelectedStudyEditor(@NotNull final Project project) {
+ try {
+ FileEditor fileEditor = FileEditorManagerEx.getInstanceEx(project).getSplitters().getCurrentWindow().
+ getSelectedEditor().getSelectedEditorWithProvider().getFirst();
+ if (fileEditor instanceof StudyEditor) {
+ return (StudyEditor)fileEditor;
+ }
+ } catch (Exception e) {
+ return null;
+ }
+ return null;
+ }
+
+ @Nullable
+ public static Editor getSelectedEditor(@NotNull final Project project) {
+ StudyEditor studyEditor = getSelectedStudyEditor(project);
+ if (studyEditor != null) {
+ FileEditor defaultEditor = studyEditor.getDefaultEditor();
+ if (defaultEditor instanceof PsiAwareTextEditorImpl) {
+ return ((PsiAwareTextEditorImpl)defaultEditor).getEditor();
+ }
+ }
+ return null;
+ }
+
+ public static void removeListener(Document document) {
+ myDocumentListeners.remove(document);
+ }
+
+ @NotNull
+ @Override
+ public Editor getEditor() {
+ if (myDefaultEditor instanceof TextEditor)
+ return ((TextEditor)myDefaultEditor).getEditor();
+ return EditorFactory.getInstance().createViewer(new DocumentImpl(""), myProject);
+ }
+
+ @Override
+ public boolean canNavigateTo(@NotNull Navigatable navigatable) {
+ if (myDefaultEditor instanceof TextEditor) {
+ ((TextEditor)myDefaultEditor).canNavigateTo(navigatable);
+ }
+ return false;
+ }
+
+ @Override
+ public void navigateTo(@NotNull Navigatable navigatable) {
+ if (myDefaultEditor instanceof TextEditor) {
+ ((TextEditor)myDefaultEditor).navigateTo(navigatable);
+ }
+ }
+}
diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/editor/StudyFileEditorProvider.java b/python/edu/learn-python/src/com/jetbrains/python/edu/editor/StudyFileEditorProvider.java
new file mode 100644
index 000000000000..631b5a9eaf4c
--- /dev/null
+++ b/python/edu/learn-python/src/com/jetbrains/python/edu/editor/StudyFileEditorProvider.java
@@ -0,0 +1,64 @@
+package com.jetbrains.python.edu.editor;
+
+import com.intellij.openapi.fileEditor.FileEditor;
+import com.intellij.openapi.fileEditor.FileEditorPolicy;
+import com.intellij.openapi.fileEditor.FileEditorProvider;
+import com.intellij.openapi.fileEditor.FileEditorState;
+import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider;
+import com.intellij.openapi.project.DumbAware;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
+import com.jetbrains.python.edu.StudyTaskManager;
+import com.jetbrains.python.edu.course.TaskFile;
+
+/**
+ * User: lia
+ * Date: 10.05.14
+ * Time: 12:45
+ */
+class StudyFileEditorProvider implements FileEditorProvider, DumbAware {
+ static final private String EDITOR_TYPE_ID = "StudyEditor";
+ final private FileEditorProvider defaultTextEditorProvider = TextEditorProvider.getInstance();
+
+ @Override
+ public boolean accept(@NotNull Project project, @NotNull VirtualFile file) {
+ TaskFile taskFile = StudyTaskManager.getInstance(project).getTaskFile(file);
+ return taskFile != null && !taskFile.isUserCreated();
+ }
+
+ @NotNull
+ @Override
+ public FileEditor createEditor(@NotNull Project project, @NotNull VirtualFile file) {
+ return new StudyEditor(project, file);
+ }
+
+ @Override
+ public void disposeEditor(@NotNull FileEditor editor) {
+ defaultTextEditorProvider.disposeEditor(editor);
+ }
+
+ @NotNull
+ @Override
+ public FileEditorState readState(@NotNull Element sourceElement, @NotNull Project project, @NotNull VirtualFile file) {
+ return defaultTextEditorProvider.readState(sourceElement, project, file);
+ }
+
+ @Override
+ public void writeState(@NotNull FileEditorState state, @NotNull Project project, @NotNull Element targetElement) {
+ defaultTextEditorProvider.writeState(state, project, targetElement);
+ }
+
+ @NotNull
+ @Override
+ public String getEditorTypeId() {
+ return EDITOR_TYPE_ID;
+ }
+
+ @NotNull
+ @Override
+ public FileEditorPolicy getPolicy() {
+ return FileEditorPolicy.HIDE_DEFAULT_EDITOR;
+ }
+}
diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/projectView/StudyDirectoryNode.java b/python/edu/learn-python/src/com/jetbrains/python/edu/projectView/StudyDirectoryNode.java
new file mode 100644
index 000000000000..abf648c5c82a
--- /dev/null
+++ b/python/edu/learn-python/src/com/jetbrains/python/edu/projectView/StudyDirectoryNode.java
@@ -0,0 +1,112 @@
+package com.jetbrains.python.edu.projectView;
+
+import com.intellij.ide.projectView.PresentationData;
+import com.intellij.ide.projectView.ViewSettings;
+import com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiDirectory;
+import com.intellij.psi.PsiElement;
+import com.intellij.ui.JBColor;
+import com.intellij.ui.SimpleTextAttributes;
+import com.jetbrains.python.edu.StudyTaskManager;
+import com.jetbrains.python.edu.StudyUtils;
+import com.jetbrains.python.edu.course.*;
+import icons.StudyIcons;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import java.awt.*;
+
+public class StudyDirectoryNode extends PsiDirectoryNode {
+ private final PsiDirectory myValue;
+ private final Project myProject;
+
+ public StudyDirectoryNode(@NotNull final Project project,
+ PsiDirectory value,
+ ViewSettings viewSettings) {
+ super(project, value, viewSettings);
+ myValue = value;
+ myProject = project;
+ }
+
+ @Override
+ protected void updateImpl(PresentationData data) {
+ data.setIcon(StudyIcons.Unchecked);
+ String valueName = myValue.getName();
+ StudyTaskManager studyTaskManager = StudyTaskManager.getInstance(myProject);
+ Course course = studyTaskManager.getCourse();
+ if (course == null) {
+ return;
+ }
+ if (valueName.equals(myProject.getName())) {
+ data.clearText();
+ data.addText(course.getName(), new SimpleTextAttributes(SimpleTextAttributes.STYLE_BOLD, JBColor.BLUE));
+ data.addText(" (" + valueName + ")", SimpleTextAttributes.GRAYED_ATTRIBUTES);
+ return;
+ }
+ if (valueName.contains(Task.TASK_DIR)) {
+ TaskFile file = null;
+ for (PsiElement child : myValue.getChildren()) {
+ VirtualFile virtualFile = child.getContainingFile().getVirtualFile();
+ file = studyTaskManager.getTaskFile(virtualFile);
+ if (file != null) {
+ break;
+ }
+ }
+ if (file != null) {
+ Task task = file.getTask();
+ setStudyAttributes(task, data, task.getName());
+ }
+ }
+ if (valueName.contains(Lesson.LESSON_DIR)) {
+ int lessonIndex = Integer.parseInt(valueName.substring(Lesson.LESSON_DIR.length())) - 1;
+ Lesson lesson = course.getLessons().get(lessonIndex);
+ setStudyAttributes(lesson, data, lesson.getName());
+ }
+
+ if (valueName.contains(Course.PLAYGROUND_DIR)) {
+ if (myValue.getParent() != null) {
+ if (!myValue.getParent().getName().contains(Course.PLAYGROUND_DIR)) {
+ data.setPresentableText(Course.PLAYGROUND_DIR);
+ data.setIcon(StudyIcons.Playground);
+ return;
+ }
+ }
+ }
+ data.setPresentableText(valueName);
+ }
+
+ @Override
+ public int getTypeSortWeight(boolean sortByType) {
+ String name = myValue.getName();
+ if (name.contains(Lesson.LESSON_DIR) || name.contains(Task.TASK_DIR)) {
+ String logicalName = name.contains(Lesson.LESSON_DIR) ? Lesson.LESSON_DIR : Task.TASK_DIR;
+ return StudyUtils.getIndex(name, logicalName) + 1;
+ }
+ return name.contains(Course.PLAYGROUND_DIR) ? 0 : 3;
+ }
+
+ private static void setStudyAttributes(Stateful stateful, PresentationData data, String additionalName) {
+ StudyStatus taskStatus = stateful.getStatus();
+ switch (taskStatus) {
+ case Unchecked: {
+ updatePresentation(data, additionalName, JBColor.blue, StudyIcons.Unchecked);
+ break;
+ }
+ case Solved: {
+ updatePresentation(data, additionalName, new JBColor(new Color(0, 134, 0), new Color(98, 150, 85)), StudyIcons.Checked);
+ break;
+ }
+ case Failed: {
+ updatePresentation(data, additionalName, JBColor.RED, StudyIcons.Failed);
+ }
+ }
+ }
+
+ private static void updatePresentation(PresentationData data, String additionalName, JBColor color, Icon icon) {
+ data.clearText();
+ data.addText(additionalName, new SimpleTextAttributes(Font.PLAIN, color));
+ data.setIcon(icon);
+ }
+}
diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/projectView/StudyTreeStructureProvider.java b/python/edu/learn-python/src/com/jetbrains/python/edu/projectView/StudyTreeStructureProvider.java
new file mode 100644
index 000000000000..e301bc3e626b
--- /dev/null
+++ b/python/edu/learn-python/src/com/jetbrains/python/edu/projectView/StudyTreeStructureProvider.java
@@ -0,0 +1,83 @@
+package com.jetbrains.python.edu.projectView;
+
+import com.intellij.ide.projectView.TreeStructureProvider;
+import com.intellij.ide.projectView.ViewSettings;
+import com.intellij.ide.projectView.impl.nodes.PsiFileNode;
+import com.intellij.ide.util.treeView.AbstractTreeNode;
+import com.intellij.openapi.project.DumbAware;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiDirectory;
+import com.jetbrains.python.edu.StudyTaskManager;
+import com.jetbrains.python.edu.course.Course;
+import com.jetbrains.python.edu.course.Task;
+import com.jetbrains.python.edu.course.TaskFile;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+public class StudyTreeStructureProvider implements TreeStructureProvider, DumbAware {
+ @NotNull
+ @Override
+ public Collection<AbstractTreeNode> modify(@NotNull AbstractTreeNode parent,
+ @NotNull Collection<AbstractTreeNode> children,
+ ViewSettings settings) {
+ if (!needModify(parent)) {
+ return children;
+ }
+ Collection<AbstractTreeNode> nodes = new ArrayList<AbstractTreeNode>();
+ for (AbstractTreeNode node : children) {
+ Project project = node.getProject();
+ if (project != null) {
+ if (node.getValue() instanceof PsiDirectory) {
+ PsiDirectory nodeValue = (PsiDirectory)node.getValue();
+ if (!nodeValue.getName().contains(Task.USER_TESTS)) {
+ StudyDirectoryNode newNode = new StudyDirectoryNode(project, nodeValue, settings);
+ nodes.add(newNode);
+ }
+ }
+ else {
+ if (parent instanceof StudyDirectoryNode) {
+ if (node instanceof PsiFileNode) {
+ PsiFileNode psiFileNode = (PsiFileNode)node;
+ VirtualFile virtualFile = psiFileNode.getVirtualFile();
+ if (virtualFile == null) {
+ return nodes;
+ }
+ TaskFile taskFile = StudyTaskManager.getInstance(project).getTaskFile(virtualFile);
+ if (taskFile != null) {
+ nodes.add(node);
+ }
+ String parentName = parent.getName();
+ if (parentName != null) {
+ if (parentName.equals(Course.PLAYGROUND_DIR)) {
+ nodes.add(node);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return nodes;
+ }
+
+ private static boolean needModify(AbstractTreeNode parent) {
+ Project project = parent.getProject();
+ if (project != null) {
+ StudyTaskManager studyTaskManager = StudyTaskManager.getInstance(project);
+ if (studyTaskManager.getCourse() == null) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Nullable
+ @Override
+ public Object getData(Collection<AbstractTreeNode> selected, String dataName) {
+ return null;
+ }
+}
diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/ui/StudyCondition.java b/python/edu/learn-python/src/com/jetbrains/python/edu/ui/StudyCondition.java
new file mode 100644
index 000000000000..5add6c934ecd
--- /dev/null
+++ b/python/edu/learn-python/src/com/jetbrains/python/edu/ui/StudyCondition.java
@@ -0,0 +1,25 @@
+package com.jetbrains.python.edu.ui;
+
+import com.intellij.openapi.project.DumbAware;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Condition;
+import com.jetbrains.python.edu.StudyTaskManager;
+
+/**
+ * author: liana
+ * data: 7/29/14.
+ */
+public class StudyCondition implements Condition, DumbAware {
+ public static boolean VALUE = false;
+ @Override
+ public boolean value(Object o) {
+ if (o instanceof Project) {
+ Project project = (Project) o;
+ StudyTaskManager taskManager = StudyTaskManager.getInstance(project);
+ if (taskManager.getCourse() != null) {
+ VALUE = true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/ui/StudyNewProjectPanel.form b/python/edu/learn-python/src/com/jetbrains/python/edu/ui/StudyNewProjectPanel.form
new file mode 100644
index 000000000000..133c38d4e8f8
--- /dev/null
+++ b/python/edu/learn-python/src/com/jetbrains/python/edu/ui/StudyNewProjectPanel.form
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.jetbrains.python.edu.ui.StudyNewProjectPanel">
+ <grid id="27dc6" binding="myContentPanel" layout-manager="GridLayoutManager" row-count="2" column-count="4" 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>
+ <grid id="54488" 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="1" row-span="1" col-span="3" vsize-policy="2" hsize-policy="4" anchor="0" fill="3" indent="0" use-parent-layout="false">
+ <minimum-size width="-1" height="60"/>
+ <preferred-size width="-1" height="60"/>
+ </grid>
+ </constraints>
+ <properties/>
+ <border type="line">
+ <color color="-6709600"/>
+ </border>
+ <children>
+ <component id="213f6" class="javax.swing.JLabel" binding="myAuthorLabel">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <text value=""/>
+ </properties>
+ </component>
+ <component id="d754d" class="javax.swing.JLabel" binding="myDescriptionLabel">
+ <constraints>
+ <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <text value=""/>
+ </properties>
+ </component>
+ </children>
+ </grid>
+ <component id="6c40c" class="javax.swing.JLabel">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="1" indent="0" use-parent-layout="false">
+ <preferred-size width="81" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <font/>
+ <horizontalTextPosition value="0"/>
+ <text value="Courses:"/>
+ </properties>
+ </component>
+ <component id="21ac6" class="javax.swing.JComboBox" binding="myCoursesComboBox">
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="7" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ </component>
+ <component id="5c614" class="com.intellij.openapi.ui.FixedSizeButton" binding="myBrowseButton">
+ <constraints>
+ <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="1" indent="0" use-parent-layout="false">
+ <minimum-size width="30" height="25"/>
+ </grid>
+ </constraints>
+ <properties/>
+ </component>
+ <component id="f1e10" class="javax.swing.JButton" binding="myRefreshButton">
+ <constraints>
+ <grid row="0" column="3" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="1" indent="0" use-parent-layout="false">
+ <minimum-size width="30" height="23"/>
+ </grid>
+ </constraints>
+ <properties>
+ <hideActionText value="false"/>
+ <text value=""/>
+ <toolTipText value="Refresh course list"/>
+ <verticalAlignment value="1"/>
+ <verticalTextPosition value="1"/>
+ </properties>
+ </component>
+ </children>
+ </grid>
+</form>
diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/ui/StudyNewProjectPanel.java b/python/edu/learn-python/src/com/jetbrains/python/edu/ui/StudyNewProjectPanel.java
new file mode 100644
index 000000000000..0f1ec08a8856
--- /dev/null
+++ b/python/edu/learn-python/src/com/jetbrains/python/edu/ui/StudyNewProjectPanel.java
@@ -0,0 +1,196 @@
+package com.jetbrains.python.edu.ui;
+
+import com.intellij.facet.ui.FacetValidatorsManager;
+import com.intellij.facet.ui.ValidationResult;
+import com.intellij.openapi.fileChooser.FileChooser;
+import com.intellij.openapi.fileChooser.FileChooserDescriptor;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.Consumer;
+import com.jetbrains.python.edu.StudyDirectoryProjectGenerator;
+import com.jetbrains.python.edu.StudyUtils;
+import com.jetbrains.python.edu.course.CourseInfo;
+import icons.StudyIcons;
+
+import javax.swing.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * author: liana
+ * data: 7/31/14.
+ */
+public class StudyNewProjectPanel{
+ private Set<CourseInfo> myAvailableCourses = new HashSet<CourseInfo>();
+ private JComboBox myCoursesComboBox;
+ private JButton myBrowseButton;
+ private JButton myRefreshButton;
+ private JPanel myContentPanel;
+ private JLabel myAuthorLabel;
+ private JLabel myDescriptionLabel;
+ private final StudyDirectoryProjectGenerator myGenerator;
+ private static final String CONNECTION_ERROR = "<html>Failed to download courses.<br>Check your Internet connection.</html>";
+ private static final String INVALID_COURSE = "Selected course is invalid";
+ private FacetValidatorsManager myValidationManager;
+
+ public StudyNewProjectPanel(StudyDirectoryProjectGenerator generator) {
+ myGenerator = generator;
+ Map<CourseInfo, File> courses = myGenerator.getCourses();
+ if (courses.isEmpty()) {
+ setError(CONNECTION_ERROR);
+ }
+ else {
+ myAvailableCourses = courses.keySet();
+ for (CourseInfo courseInfo : myAvailableCourses) {
+ myCoursesComboBox.addItem(courseInfo);
+ }
+ myAuthorLabel.setText("Author: " + StudyUtils.getFirst(myAvailableCourses).getAuthor());
+ myDescriptionLabel.setText(StudyUtils.getFirst(myAvailableCourses).getDescription());
+ //setting the first course in list as selected
+ myGenerator.setSelectedCourse(StudyUtils.getFirst(myAvailableCourses));
+ setOK();
+ }
+ initListeners();
+ myRefreshButton.setVisible(true);
+ myRefreshButton.setIcon(StudyIcons.Refresh);
+ }
+
+ private void initListeners() {
+
+ final FileChooserDescriptor fileChooser = new FileChooserDescriptor(true, false, false, true, false, false) {
+ @Override
+ public boolean isFileVisible(VirtualFile file, boolean showHiddenFiles) {
+ return file.isDirectory() || StudyUtils.isZip(file.getName());
+ }
+
+ @Override
+ public boolean isFileSelectable(VirtualFile file) {
+ return StudyUtils.isZip(file.getName());
+ }
+ };
+ myBrowseButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ FileChooser.chooseFile(fileChooser, null, null,
+ new Consumer<VirtualFile>() {
+ @Override
+ public void consume(VirtualFile file) {
+ String fileName = file.getPath();
+ int oldSize = myAvailableCourses.size();
+ CourseInfo courseInfo = myGenerator.addLocalCourse(fileName);
+ if (courseInfo != null) {
+ if (oldSize != myAvailableCourses.size()) {
+ myCoursesComboBox.addItem(courseInfo);
+ }
+ myCoursesComboBox.setSelectedItem(courseInfo);
+ setOK();
+ }
+ else {
+ setError(INVALID_COURSE);
+ myCoursesComboBox.removeAllItems();
+ myCoursesComboBox.addItem(CourseInfo.INVALID_COURSE);
+ for (CourseInfo course : myAvailableCourses) {
+ myCoursesComboBox.addItem(course);
+ }
+ myCoursesComboBox.setSelectedItem(CourseInfo.INVALID_COURSE);
+ }
+ }
+ });
+ }
+ });
+ myRefreshButton.addActionListener(new RefreshActionListener());
+ myCoursesComboBox.addActionListener(new CourseSelectedListener());
+ }
+
+ private void setError(String errorMessage) {
+ myGenerator.setValidationResult(new ValidationResult(errorMessage));
+ if (myValidationManager != null) {
+ myValidationManager.validate();
+ }
+ }
+
+ private void setOK() {
+ myGenerator.setValidationResult(ValidationResult.OK);
+ if (myValidationManager != null) {
+ myValidationManager.validate();
+ }
+ }
+
+ public JPanel getContentPanel() {
+ return myContentPanel;
+ }
+
+ public void registerValidators(final FacetValidatorsManager manager) {
+ myValidationManager = manager;
+ }
+
+
+ /**
+ * Handles refreshing courses
+ * Old courses added to new courses only if their
+ * meta file still exists in local file system
+ */
+ private class RefreshActionListener implements ActionListener {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ myGenerator.downloadAndUnzip(true);
+ Map<CourseInfo, File> downloadedCourses = myGenerator.loadCourses();
+ if (downloadedCourses.isEmpty()) {
+ setError(CONNECTION_ERROR);
+ return;
+ }
+ Map<CourseInfo, File> oldCourses = myGenerator.getLoadedCourses();
+ Map<CourseInfo, File> newCourses = new HashMap<CourseInfo, File>();
+ for (Map.Entry<CourseInfo, File> course : oldCourses.entrySet()) {
+ File courseFile = course.getValue();
+ if (courseFile.exists()) {
+ newCourses.put(course.getKey(), courseFile);
+ }
+ }
+ for (Map.Entry<CourseInfo, File> course : downloadedCourses.entrySet()) {
+ CourseInfo courseName = course.getKey();
+ if (newCourses.get(courseName) == null) {
+ newCourses.put(courseName, course.getValue());
+ }
+ }
+ myCoursesComboBox.removeAllItems();
+
+ for (CourseInfo courseInfo : newCourses.keySet()) {
+ myCoursesComboBox.addItem(courseInfo);
+ }
+ myGenerator.setSelectedCourse(StudyUtils.getFirst(newCourses.keySet()));
+
+ myGenerator.setCourses(newCourses);
+ myAvailableCourses = newCourses.keySet();
+ myGenerator.flushCache();
+ }
+ }
+
+
+ /**
+ * Handles selecting course in combo box
+ * Sets selected course in combo box as selected in
+ * {@link StudyNewProjectPanel#myGenerator}
+ */
+ private class CourseSelectedListener implements ActionListener {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ JComboBox cb = (JComboBox)e.getSource();
+ CourseInfo selectedCourse = (CourseInfo)cb.getSelectedItem();
+ if (selectedCourse == null || selectedCourse.equals(CourseInfo.INVALID_COURSE)) {
+ myAuthorLabel.setText("");
+ myDescriptionLabel.setText("");
+ return;
+ }
+ myAuthorLabel.setText("Author: " + selectedCourse.getAuthor());
+ myCoursesComboBox.removeItem(CourseInfo.INVALID_COURSE);
+ myDescriptionLabel.setText(selectedCourse.getDescription());
+ myGenerator.setSelectedCourse(selectedCourse);
+ setOK();
+ }
+ }
+}
diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/ui/StudyProgressBar.java b/python/edu/learn-python/src/com/jetbrains/python/edu/ui/StudyProgressBar.java
new file mode 100644
index 000000000000..97fa00d0f70d
--- /dev/null
+++ b/python/edu/learn-python/src/com/jetbrains/python/edu/ui/StudyProgressBar.java
@@ -0,0 +1,92 @@
+package com.jetbrains.python.edu.ui;
+
+import com.intellij.openapi.project.DumbAware;
+import com.intellij.openapi.ui.GraphicsConfig;
+import com.intellij.ui.ColorUtil;
+import com.intellij.ui.Gray;
+import com.intellij.ui.JBColor;
+import com.intellij.util.ui.GraphicsUtil;
+import com.intellij.util.ui.UIUtil;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.geom.Rectangle2D;
+
+public class StudyProgressBar extends JComponent implements DumbAware {
+ public static final Color BLUE = JBColor.BLUE;
+ private static final Color SHADOW1 = new JBColor(Gray._190, JBColor.border());
+ private static final Color SHADOW2 = Gray._105;
+ private static final int BRICK_WIDTH = 10;
+ private static final int BRICK_SPACE = 2;
+ private final int myHeight;
+ private final int myIndent;
+ private double myFraction = 0.0;
+ private Color myColor = BLUE;
+
+ public StudyProgressBar(double fraction, Color color, int height, int indent) {
+ myFraction = fraction;
+ myColor = color;
+ myHeight = height;
+ myIndent = indent;
+ }
+
+ private int getBricksToDraw(double fraction) {
+ int bricksTotal = (getWidth() - 8) / (BRICK_WIDTH + BRICK_SPACE);
+ return (int)(bricksTotal * fraction) + 1;
+ }
+
+ protected void paintComponent(Graphics g) {
+ final GraphicsConfig config = GraphicsUtil.setupAAPainting(g);
+ Graphics2D g2 = (Graphics2D)g;
+ if (myFraction > 1) {
+ myFraction = 1;
+ }
+
+ Dimension size = getSize();
+ double width = size.getWidth() - 2*myIndent;
+ g2.setPaint(UIUtil.getListBackground());
+ Rectangle2D rect = new Rectangle2D.Double(myIndent, 0, width, myHeight);
+ g2.fill(rect);
+
+ g2.setPaint(new JBColor(SHADOW1, JBColor.border()));
+ rect.setRect(myIndent, 0, width, myHeight);
+ int arcWidth = 5;
+ int arcHeight = 5;
+ g2.drawRoundRect(myIndent, 0, (int)width, myHeight, arcWidth, arcHeight);
+ g2.setPaint(SHADOW2);
+ g2.drawRoundRect(myIndent, 0, (int)width, myHeight, arcWidth, arcHeight);
+
+ int y_center = myHeight / 2;
+ int y_steps = myHeight / 2 - 3;
+ int alpha_step = y_steps > 0 ? (255 - 70) / y_steps : 255 - 70;
+ int x_offset = 4;
+
+ g.setClip(4 + myIndent, 3, (int)width - 6, myHeight - 4);
+
+ int bricksToDraw = myFraction == 0 ? 0 : getBricksToDraw(myFraction);
+ for (int i = 0; i < bricksToDraw; i++) {
+ g2.setPaint(myColor);
+ UIUtil.drawLine(g2, x_offset, y_center, x_offset + BRICK_WIDTH - 1, y_center);
+ for (int j = 0; j < y_steps; j++) {
+ Color color = ColorUtil.toAlpha(myColor, 255 - alpha_step * (j + 1));
+ g2.setPaint(color);
+ UIUtil.drawLine(g2, x_offset, y_center - 1 - j, x_offset + BRICK_WIDTH - 1, y_center - 1 - j);
+ if (!(y_center % 2 != 0 && j == y_steps - 1)) {
+ UIUtil.drawLine(g2, x_offset, y_center + 1 + j, x_offset + BRICK_WIDTH - 1, y_center + 1 + j);
+ }
+ }
+ g2.setColor(
+ ColorUtil.toAlpha(myColor, 255 - alpha_step * (y_steps / 2 + 1)));
+ g2.drawRect(x_offset, y_center - y_steps, BRICK_WIDTH - 1, myHeight - 7);
+ x_offset += BRICK_WIDTH + BRICK_SPACE;
+ }
+ config.restore();
+ }
+
+ @Override
+ public Dimension getMaximumSize() {
+ Dimension dimension = super.getMaximumSize();
+ dimension.height = myHeight + 10;
+ return dimension;
+ }
+}
diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/ui/StudyTestContentPanel.java b/python/edu/learn-python/src/com/jetbrains/python/edu/ui/StudyTestContentPanel.java
new file mode 100644
index 000000000000..dee4fbaf9d01
--- /dev/null
+++ b/python/edu/learn-python/src/com/jetbrains/python/edu/ui/StudyTestContentPanel.java
@@ -0,0 +1,67 @@
+package com.jetbrains.python.edu.ui;
+
+import com.intellij.ui.DocumentAdapter;
+import com.intellij.ui.components.JBScrollPane;
+import org.jetbrains.annotations.NotNull;
+import com.jetbrains.python.edu.course.UserTest;
+
+import javax.swing.*;
+import javax.swing.event.DocumentEvent;
+import javax.swing.text.BadLocationException;
+import java.awt.*;
+
+public class StudyTestContentPanel extends JPanel {
+ public static final Dimension PREFERRED_SIZE = new Dimension(300, 200);
+ private static final Font HEADER_FONT = new Font("Arial", Font.BOLD, 16);
+ private final JTextArea myInputArea = new JTextArea();
+ private final JTextArea myOutputArea = new JTextArea();
+ public StudyTestContentPanel(UserTest userTest) {
+ this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
+ initContentLabel("input", myInputArea);
+ myInputArea.getDocument().addDocumentListener(new BufferUpdater(userTest.getInputBuffer()));
+ myOutputArea.getDocument().addDocumentListener(new BufferUpdater(userTest.getOutputBuffer()));
+ initContentLabel("output", myOutputArea);
+ setEditable(userTest.isEditable());
+ }
+
+ private void initContentLabel(final String headerText, @NotNull final JTextArea contentArea) {
+ JLabel headerLabel = new JLabel(headerText);
+ headerLabel.setFont(HEADER_FONT);
+ this.add(headerLabel);
+ this.add(new JSeparator(SwingConstants.HORIZONTAL));
+ JScrollPane scroll = new JBScrollPane(contentArea);
+ scroll.setPreferredSize(PREFERRED_SIZE);
+ this.add(scroll);
+ }
+
+ private void setEditable(boolean isEditable) {
+ myInputArea.setEditable(isEditable);
+ myOutputArea.setEditable(isEditable);
+ }
+ public void addInputContent(final String content) {
+ myInputArea.setText(content);
+ }
+
+ public void addOutputContent(final String content) {
+ myOutputArea.setText(content);
+ }
+
+ private class BufferUpdater extends DocumentAdapter {
+ private final StringBuilder myBuffer;
+
+ private BufferUpdater(StringBuilder buffer) {
+ myBuffer = buffer;
+ }
+
+ @Override
+ protected void textChanged(DocumentEvent e) {
+ myBuffer.delete(0, myBuffer.length());
+ try {
+ myBuffer.append(e.getDocument().getText(0, e.getDocument().getLength()));
+ }
+ catch (BadLocationException e1) {
+ e1.printStackTrace();
+ }
+ }
+ }
+}
diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/ui/StudyToolWindowFactory.java b/python/edu/learn-python/src/com/jetbrains/python/edu/ui/StudyToolWindowFactory.java
new file mode 100644
index 000000000000..a553978c416a
--- /dev/null
+++ b/python/edu/learn-python/src/com/jetbrains/python/edu/ui/StudyToolWindowFactory.java
@@ -0,0 +1,81 @@
+package com.jetbrains.python.edu.ui;
+
+import com.intellij.openapi.project.DumbAware;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.wm.ToolWindow;
+import com.intellij.openapi.wm.ToolWindowFactory;
+import com.intellij.ui.JBColor;
+import com.intellij.ui.content.Content;
+import com.intellij.ui.content.ContentFactory;
+import com.intellij.util.ui.UIUtil;
+import com.jetbrains.python.edu.StudyTaskManager;
+import com.jetbrains.python.edu.course.Course;
+import com.jetbrains.python.edu.course.Lesson;
+import com.jetbrains.python.edu.course.LessonInfo;
+import com.jetbrains.python.edu.course.StudyStatus;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import java.awt.*;
+import java.util.List;
+
+public class StudyToolWindowFactory implements ToolWindowFactory, DumbAware {
+ public static final String STUDY_TOOL_WINDOW = "Course Description";
+ JPanel contentPanel = new JPanel();
+
+ @Override
+ public void createToolWindowContent(@NotNull final Project project, @NotNull final ToolWindow toolWindow) {
+ if (StudyTaskManager.getInstance(project).getCourse() != null) {
+ contentPanel.setLayout(new BoxLayout(contentPanel, BoxLayout.PAGE_AXIS));
+ contentPanel.add(Box.createRigidArea(new Dimension(10, 0)));
+ StudyTaskManager taskManager = StudyTaskManager.getInstance(project);
+ Course course = taskManager.getCourse();
+ if (course == null) {
+ return;
+ }
+ String courseName = UIUtil.toHtml("<h1>" + course.getName() + "</h1>", 10);
+ String description = UIUtil.toHtml(course.getDescription(), 5);
+ String author = taskManager.getCourse().getAuthor();
+ String authorLabel = UIUtil.toHtml("<b>Author: </b>" + author, 5);
+ contentPanel.add(new JLabel(courseName));
+ contentPanel.add(new JLabel(authorLabel));
+ contentPanel.add(Box.createRigidArea(new Dimension(0, 10)));
+ contentPanel.add(new JLabel(description));
+
+ int taskNum = 0;
+ int taskSolved = 0;
+ int lessonsCompleted = 0;
+ List<Lesson> lessons = course.getLessons();
+ for (Lesson lesson : lessons) {
+ if (lesson.getStatus() == StudyStatus.Solved) {
+ lessonsCompleted++;
+ }
+ LessonInfo lessonInfo = lesson.getLessonInfo();
+ taskNum += lessonInfo.getTaskNum();
+ taskSolved += lessonInfo.getTaskSolved();
+ }
+ String completedLessons = String.format("%d of %d lessons completed", lessonsCompleted, course.getLessons().size());
+ String completedTasks = String.format("%d of %d tasks completed", taskSolved, taskNum);
+ String tasksLeft = String.format("%d of %d tasks left", taskNum - taskSolved, taskNum);
+ contentPanel.add(Box.createVerticalStrut(10));
+ addStatistics(completedLessons);
+ addStatistics(completedTasks);
+
+ double percent = (taskSolved * 100.0) / taskNum;
+ contentPanel.add(Box.createRigidArea(new Dimension(0, 10)));
+ StudyProgressBar studyProgressBar = new StudyProgressBar(percent / 100, JBColor.GREEN, 40, 10);
+ contentPanel.add(studyProgressBar);
+ addStatistics(tasksLeft);
+ ContentFactory contentFactory = ContentFactory.SERVICE.getInstance();
+ Content content = contentFactory.createContent(contentPanel, "", true);
+ toolWindow.getContentManager().addContent(content);
+ }
+ }
+
+ private void addStatistics(String statistics) {
+ String labelText = UIUtil.toHtml(statistics, 5);
+ contentPanel.add(Box.createRigidArea(new Dimension(0, 10)));
+ JLabel statisticLabel = new JLabel(labelText);
+ contentPanel.add(statisticLabel);
+ }
+}
diff --git a/python/edu/learn-python/testData/course.json b/python/edu/learn-python/testData/course.json
new file mode 100644
index 000000000000..bff570afd29a
--- /dev/null
+++ b/python/edu/learn-python/testData/course.json
@@ -0,0 +1,130 @@
+{
+ "name": "Python для начинающих",
+ "description": "Начальный курс по языку Python",
+ "lessons": [
+ {
+ "name": "Первые программа",
+ "task_list": [
+ {
+ "name": "Задание 1",
+ "text": "hello-text.html",
+ "test_file": "hello-tests.py",
+ "test_num": 1,
+ "task_files": {
+ "helloworld.py": {
+ "task_windows": [
+ {
+ "line": 0,
+ "start": 0,
+ "text": "type operator",
+ "hint": "hello-text.html",
+ "possible_answer": "print"
+ },
+ {
+ "line": 0,
+ "start": 33,
+ "text": "type your name",
+ "hint": "empty_study.docs",
+ "possible_answer": "Liana"
+ }
+ ]
+ }
+ }
+ },
+ {
+ "name": "Задание 2",
+ "text": "matchends-text.html",
+ "test_file": "matchends-test.py",
+ "test_num": 3,
+ "task_files": {
+ "match_ends.py": {
+ "task_windows": [
+ {
+ "line": 1,
+ "start": 43,
+ "text": "condition",
+ "hint": "empty_study.docs",
+ "possible_answer": ">="
+ },
+ {
+ "line": 1,
+ "start": 61,
+ "text": "index",
+ "hint": "empty_study.docs",
+ "possible_answer": "0"
+ },
+ {
+ "line": 1,
+ "start": 73,
+ "text": "index",
+ "hint": "empty_study.docs",
+ "possible_answer": "-1"
+ },
+ {
+ "line": 2,
+ "start": 11,
+ "text": "function",
+ "hint": "list.docs",
+ "possible_answer": "len"
+ }
+ ]
+ }
+ }
+ }
+ ]
+ },
+ {
+ "name": "Простые задачи",
+ "task_list": [
+ {
+ "name": "Задание 1",
+ "text": "sum-text.html",
+ "test_file": "sum_tests.py",
+ "test_num": 3,
+ "user_tests": [
+ {
+ "input": "sum-input.txt",
+ "output": "sum-output"
+ }
+ ],
+ "task_files": {
+ "sum.py": {
+ "task_windows": [
+ {
+ "line": 4,
+ "start": 15,
+ "text": "получите из консоли имя файла",
+ "hint": "argv.docs",
+ "possible_answer": "sys.argv[1]"
+ },
+ {
+ "line": 5,
+ "start": 8,
+ "text": "откройте файл на запись",
+ "hint": "empty_study.docs",
+ "possible_answer": "open(filename, 'r')"
+ },
+ {
+ "line": 10,
+ "start": 4,
+ "text": "закройте файл",
+ "hint": "empty_study.docs",
+ "possible_answer": "f.close()"
+ },
+ {
+ "line": 11,
+ "start": 14,
+ "text": "правильно проинициализируйте значение",
+ "hint": "empty_study.docs",
+ "possible_answer": "-sys.maxint"
+ }
+ ]
+ }
+ }
+ }
+
+ ]
+
+ }
+ ]
+} \ No newline at end of file
diff --git a/python/edu/learn-python/tests/JsonParserTest.java b/python/edu/learn-python/tests/JsonParserTest.java
new file mode 100644
index 000000000000..903f0a539acf
--- /dev/null
+++ b/python/edu/learn-python/tests/JsonParserTest.java
@@ -0,0 +1,37 @@
+import com.google.gson.FieldNamingPolicy;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import org.junit.Before;
+import org.junit.Test;
+import com.jetbrains.python.edu.StudyUtils;
+import com.jetbrains.python.edu.course.Course;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * author: liana
+ * data: 7/4/14.
+ */
+public class JsonParserTest {
+ private Course myCourse = null;
+ @Before
+ public void setUp() throws FileNotFoundException {
+ Reader reader = new InputStreamReader(new FileInputStream("EDIDE/testData/course.json"));
+ Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create();
+ myCourse = gson.fromJson(reader, Course.class);
+ }
+
+ @Test
+ public void testCourseLevel() {
+ assertEquals(myCourse.getName(), "Python для начинающих");
+ assertEquals(StudyUtils.getFirst(myCourse.getLessons().get(1).getTaskList().get(0).getUserTests()).getInput(), "sum-input.txt");
+ assertEquals(myCourse.getLessons().size(), 2);
+ assertEquals(myCourse.getLessons().get(0).getTaskList().size(), 2);
+ assertEquals(myCourse.getLessons().get(1).getTaskList().size(), 1);
+ }
+}
diff --git a/python/edu/main_pycharm_edu.iml b/python/edu/main_pycharm_edu.iml
index 2acdd8733873..12efe9b350d1 100644
--- a/python/edu/main_pycharm_edu.iml
+++ b/python/edu/main_pycharm_edu.iml
@@ -11,11 +11,11 @@
<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" />
+ <orderEntry type="module" module-name="learn-python" />
</component>
</module>
diff --git a/python/edu/resources/idea/PyCharmEduApplicationInfo.xml b/python/edu/resources/idea/PyCharmEduApplicationInfo.xml
index 46695ef29ed4..0fdf0d48fd08 100644
--- a/python/edu/resources/idea/PyCharmEduApplicationInfo.xml
+++ b/python/edu/resources/idea/PyCharmEduApplicationInfo.xml
@@ -1,9 +1,9 @@
<component>
<company name="JetBrains s.r.o." url="http://www.jetbrains.com/?fromIDE"/>
- <version major="3" minor="0" eap="true"/>
+ <version major="1" 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"/>
+ <logo url="/pycharm_edu_logo.png" textcolor="5a8179" progressColor="ffaa16" progressY="230" progressTailIcon="/community_progress_tail.png"/>
+ <about url="/pycharm_edu_about.png" logoX="300" logoY="265" logoW="75" logoH="30" foreground="5a8179" 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"/>
diff --git a/python/edu/resources/pycharm_edu_about.png b/python/edu/resources/pycharm_edu_about.png
new file mode 100644
index 000000000000..f3312ac6b3c8
--- /dev/null
+++ b/python/edu/resources/pycharm_edu_about.png
Binary files differ
diff --git a/python/edu/resources/pycharm_edu_about@2x.png b/python/edu/resources/pycharm_edu_about@2x.png
new file mode 100644
index 000000000000..2803e04cec09
--- /dev/null
+++ b/python/edu/resources/pycharm_edu_about@2x.png
Binary files differ
diff --git a/python/edu/resources/pycharm_edu_logo.png b/python/edu/resources/pycharm_edu_logo.png
new file mode 100644
index 000000000000..c8b69b39b18d
--- /dev/null
+++ b/python/edu/resources/pycharm_edu_logo.png
Binary files differ
diff --git a/python/edu/resources/pycharm_edu_logo@2x.png b/python/edu/resources/pycharm_edu_logo@2x.png
new file mode 100644
index 000000000000..6c186ad89e6d
--- /dev/null
+++ b/python/edu/resources/pycharm_edu_logo@2x.png
Binary files differ
diff --git a/python/edu/src/META-INF/PyCharmEduPlugin.xml b/python/edu/src/META-INF/PyCharmEduPlugin.xml
index 9adf03dfd9c8..d5b2fdfe8c28 100644
--- a/python/edu/src/META-INF/PyCharmEduPlugin.xml
+++ b/python/edu/src/META-INF/PyCharmEduPlugin.xml
@@ -8,10 +8,16 @@
</component>
</application-components>
- <xi:include href="/META-INF/pycharm-core.xml" xpointer="xpointer(/idea-plugin/*)"/>
+ <xi:include href="/META-INF/pycharm-community.xml" xpointer="xpointer(/idea-plugin/*)"/>
<xi:include href="/META-INF/python-core.xml" xpointer="xpointer(/idea-plugin/*)"/>
+ <application-components>
+ <component>
+ <implementation-class>com.jetbrains.python.edu.PyCharmEduInitialConfigurator</implementation-class>
+ <headless-implementation-class/>
+ </component>
+ </application-components>
<actions>
<group overrides="true" class="com.intellij.openapi.actionSystem.EmptyActionGroup" id="ToolsMenu"/>
diff --git a/python/edu/src/com/jetbrains/python/edu/PyCharmEduInitialConfigurator.java b/python/edu/src/com/jetbrains/python/edu/PyCharmEduInitialConfigurator.java
index 451c5193645e..ecf3d79a6424 100644
--- a/python/edu/src/com/jetbrains/python/edu/PyCharmEduInitialConfigurator.java
+++ b/python/edu/src/com/jetbrains/python/edu/PyCharmEduInitialConfigurator.java
@@ -25,10 +25,8 @@ 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;
@@ -41,8 +39,6 @@ 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;
@@ -51,7 +47,6 @@ 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;
@@ -91,13 +86,15 @@ public class PyCharmEduInitialConfigurator {
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;
+ uiSettings.SHOW_MAIN_TOOLBAR = false;
codeInsightSettings.REFORMAT_ON_PASTE = CodeInsightSettings.NO_REFORMAT;
+ GeneralSettings.getInstance().setShowTipsOnStartup(false);
+
EditorSettingsExternalizable.getInstance().setVirtualSpace(false);
final CodeStyleSettings settings = CodeStyleSettingsManager.getInstance().getCurrentSettings();
settings.ALIGN_MULTILINE_PARAMETERS_IN_CALLS = true;
@@ -116,23 +113,31 @@ public class PyCharmEduInitialConfigurator {
});
}
});
- PyCodeInsightSettings.getInstance().SHOW_IMPORT_POPUP = false;
+ PyCodeInsightSettings.getInstance().SHOW_IMPORT_POPUP = true;
}
- 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");
+
+ if (!propertiesComponent.isValueSet(DISPLAYED_PROPERTY)) {
+
+ bus.connect().subscribe(AppLifecycleListener.TOPIC, new AppLifecycleListener.Adapter() {
+ @Override
+ public void welcomeScreenDisplayed() {
+
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ if (!propertiesComponent.isValueSet(DISPLAYED_PROPERTY)) {
+ GeneralSettings.getInstance().setShowTipsOnStartup(false);
+ propertiesComponent.setValue(DISPLAYED_PROPERTY, "true");
+ showInitialConfigurationDialog();
+
+ patchKeymap();
+ }
+ }
+ });
}
- }
+ });
+ }
- @Override
- public void appStarting(Project projectFromCommandLine) {
- patchKeymap();
- }
- });
bus.connect().subscribe(ProjectManager.TOPIC, new ProjectManagerAdapter() {
@Override
public void projectOpened(final Project project) {
@@ -142,58 +147,16 @@ public class PyCharmEduInitialConfigurator {
}
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)) {
+ if (ToolWindowId.FAVORITES_VIEW.equals(ep.id) || ToolWindowId.TODO_VIEW.equals(ep.id) || EventLog.LOG_TOOL_WINDOW_ID.equals(ep.id)
+ || "Structure".equals(ep.id)) {
rootArea.getExtensionPoint(ToolWindowEP.EP_NAME).unregisterExtension(ep);
}
}
diff --git a/python/gen/icons/PythonIcons.java b/python/gen/icons/PythonIcons.java
index b4c59bdb3b30..f98387fedc29 100644
--- a/python/gen/icons/PythonIcons.java
+++ b/python/gen/icons/PythonIcons.java
@@ -49,6 +49,8 @@ public class PythonIcons {
public static final Icon Python = load("/icons/com/jetbrains/python/python.png"); // 16x16
public static final Icon Python_24 = load("/icons/com/jetbrains/python/python_24.png"); // 24x24
public static final Icon PythonClosed = load("/icons/com/jetbrains/python/pythonClosed.png"); // 16x16
+ public static final Icon PythonConsole = load("/icons/com/jetbrains/python/pythonConsole.png"); // 16x16
+ public static final Icon PythonConsoleToolWindow = load("/icons/com/jetbrains/python/pythonConsoleToolWindow.png"); // 13x13
public static final Icon PythonTests = load("/icons/com/jetbrains/python/pythonTests.png"); // 16x16
public static final Icon TemplateRoot = load("/icons/com/jetbrains/python/templateRoot.png"); // 16x16
public static final Icon Virtualenv = load("/icons/com/jetbrains/python/virtualenv.png"); // 16x16
diff --git a/python/helpers/pycharm/_bdd_utils.py b/python/helpers/pycharm/_bdd_utils.py
index 0c92532b516c..300feb286051 100644
--- a/python/helpers/pycharm/_bdd_utils.py
+++ b/python/helpers/pycharm/_bdd_utils.py
@@ -27,7 +27,7 @@ def get_path_by_args(arguments):
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
+ base_dir = os.path.dirname(what_to_run) # User may point to the file directly
return base_dir, what_to_run
@@ -62,8 +62,11 @@ class BddRunner(object):
""""
Runs runner. To be called right after constructor.
"""
- self.tc_messages.testCount(self._get_number_of_tests())
+ number_of_tests = self._get_number_of_tests()
+ self.tc_messages.testCount(number_of_tests)
self.tc_messages.testMatrixEntered()
+ if number_of_tests == 0: # Nothing to run, so no need to report even feature/scenario start. (See PY-13623)
+ return
self._run_tests()
def __gen_location(self, location):
@@ -175,9 +178,9 @@ class BddRunner(object):
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)
+ num_of_steps += len(list(feature.background.steps)) * len(list(feature.scenarios))
for scenario in feature.scenarios:
- num_of_steps += len(scenario.steps)
+ num_of_steps += len(list(scenario.steps))
return num_of_steps
@abc.abstractmethod
diff --git a/python/helpers/pycharm/behave_runner.py b/python/helpers/pycharm/behave_runner.py
index 4a1b2f6557c5..0ad83137adb6 100644
--- a/python/helpers/pycharm/behave_runner.py
+++ b/python/helpers/pycharm/behave_runner.py
@@ -136,20 +136,23 @@ class _BehaveRunner(_bdd_utils.BddRunner):
element.location.file = element.location.filename # To preserve _bdd_utils contract
if isinstance(element, Step):
# Process step
+ step_name = "{} {}".format(element.keyword, element.name)
if is_started:
- self._test_started(element.name, element.location)
+ self._test_started(step_name, element.location)
elif element.status == 'passed':
- self._test_passed(element.name, element.duration)
+ self._test_passed(step_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)
+ if trace in str(element.error_message):
+ trace = None # No reason to duplicate output (see PY-13647)
+ self._test_failed(step_name, element.error_message, trace)
elif element.status == 'undefined':
- self._test_undefined(element.name, element.location)
+ self._test_undefined(step_name, element.location)
else:
- self._test_skipped(element.name, element.status, element.location)
+ self._test_skipped(step_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:
diff --git a/python/helpers/pycharm/docrunner.py b/python/helpers/pycharm/docrunner.py
index ad619be0428f..ed9a6f186186 100644
--- a/python/helpers/pycharm/docrunner.py
+++ b/python/helpers/pycharm/docrunner.py
@@ -69,6 +69,12 @@ class TeamcityDocTestResult(TeamcityTestResult):
self.messages.testError(self.getTestName(test),
message='Error', details=err)
+ 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))
+
class DocTestRunner(doctest.DocTestRunner):
"""
Special runner for doctests,
diff --git a/python/helpers/pycharm_generator_utils/module_redeclarator.py b/python/helpers/pycharm_generator_utils/module_redeclarator.py
index 0dbdbb58ac6b..bdffe3ec8e97 100644
--- a/python/helpers/pycharm_generator_utils/module_redeclarator.py
+++ b/python/helpers/pycharm_generator_utils/module_redeclarator.py
@@ -1009,6 +1009,8 @@ class ModuleRedeclarator(object):
self.classes_buf.out(0, txt)
txt = create_function()
self.classes_buf.out(0, txt)
+ txt = create_method()
+ self.classes_buf.out(0, txt)
# Fake <type 'namedtuple'>
if version[0] >= 3 or (version[0] == 2 and version[1] >= 6):
diff --git a/python/helpers/pycharm_generator_utils/util_methods.py b/python/helpers/pycharm_generator_utils/util_methods.py
index b6805c4a5942..273b0a20b715 100644
--- a/python/helpers/pycharm_generator_utils/util_methods.py
+++ b/python/helpers/pycharm_generator_utils/util_methods.py
@@ -115,6 +115,25 @@ class __function(object):
"""
return txt
+def create_method():
+ txt = """
+class __method(object):
+ '''A mock class representing method type.'''
+
+ def __init__(self):
+"""
+ if version[0] == 2:
+ txt += """
+ self.im_class = None
+ self.im_self = None
+ self.im_func = None
+"""
+ if version[0] >= 3 or (version[0] == 2 and version[1] >= 6):
+ txt += """
+ self.__func__ = None
+ self.__self__ = None
+"""
+ return txt
def _searchbases(cls, accum):
# logic copied from inspect.py
diff --git a/python/helpers/pydev/LICENSE b/python/helpers/pydev/LICENSE
new file mode 100644
index 000000000000..503284377532
--- /dev/null
+++ b/python/helpers/pydev/LICENSE
@@ -0,0 +1,203 @@
+Eclipse Public License - v 1.0
+
+THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC
+LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM
+CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
+
+1. DEFINITIONS
+
+"Contribution" means:
+
+a) in the case of the initial Contributor, the initial code and documentation
+ distributed under this Agreement, and
+b) in the case of each subsequent Contributor:
+ i) changes to the Program, and
+ ii) additions to the Program;
+
+ where such changes and/or additions to the Program originate from and are
+ distributed by that particular Contributor. A Contribution 'originates'
+ from a Contributor if it was added to the Program by such Contributor
+ itself or anyone acting on such Contributor's behalf. Contributions do not
+ include additions to the Program which: (i) are separate modules of
+ software distributed in conjunction with the Program under their own
+ license agreement, and (ii) are not derivative works of the Program.
+
+"Contributor" means any person or entity that distributes the Program.
+
+"Licensed Patents" mean patent claims licensable by a Contributor which are
+necessarily infringed by the use or sale of its Contribution alone or when
+combined with the Program.
+
+"Program" means the Contributions distributed in accordance with this
+Agreement.
+
+"Recipient" means anyone who receives the Program under this Agreement,
+including all Contributors.
+
+2. GRANT OF RIGHTS
+ a) Subject to the terms of this Agreement, each Contributor hereby grants
+ Recipient a non-exclusive, worldwide, royalty-free copyright license to
+ reproduce, prepare derivative works of, publicly display, publicly
+ perform, distribute and sublicense the Contribution of such Contributor,
+ if any, and such derivative works, in source code and object code form.
+ b) Subject to the terms of this Agreement, each Contributor hereby grants
+ Recipient a non-exclusive, worldwide, royalty-free patent license under
+ Licensed Patents to make, use, sell, offer to sell, import and otherwise
+ transfer the Contribution of such Contributor, if any, in source code and
+ object code form. This patent license shall apply to the combination of
+ the Contribution and the Program if, at the time the Contribution is
+ added by the Contributor, such addition of the Contribution causes such
+ combination to be covered by the Licensed Patents. The patent license
+ shall not apply to any other combinations which include the Contribution.
+ No hardware per se is licensed hereunder.
+ c) Recipient understands that although each Contributor grants the licenses
+ to its Contributions set forth herein, no assurances are provided by any
+ Contributor that the Program does not infringe the patent or other
+ intellectual property rights of any other entity. Each Contributor
+ disclaims any liability to Recipient for claims brought by any other
+ entity based on infringement of intellectual property rights or
+ otherwise. As a condition to exercising the rights and licenses granted
+ hereunder, each Recipient hereby assumes sole responsibility to secure
+ any other intellectual property rights needed, if any. For example, if a
+ third party patent license is required to allow Recipient to distribute
+ the Program, it is Recipient's responsibility to acquire that license
+ before distributing the Program.
+ d) Each Contributor represents that to its knowledge it has sufficient
+ copyright rights in its Contribution, if any, to grant the copyright
+ license set forth in this Agreement.
+
+3. REQUIREMENTS
+
+A Contributor may choose to distribute the Program in object code form under
+its own license agreement, provided that:
+
+ a) it complies with the terms and conditions of this Agreement; and
+ b) its license agreement:
+ i) effectively disclaims on behalf of all Contributors all warranties
+ and conditions, express and implied, including warranties or
+ conditions of title and non-infringement, and implied warranties or
+ conditions of merchantability and fitness for a particular purpose;
+ ii) effectively excludes on behalf of all Contributors all liability for
+ damages, including direct, indirect, special, incidental and
+ consequential damages, such as lost profits;
+ iii) states that any provisions which differ from this Agreement are
+ offered by that Contributor alone and not by any other party; and
+ iv) states that source code for the Program is available from such
+ Contributor, and informs licensees how to obtain it in a reasonable
+ manner on or through a medium customarily used for software exchange.
+
+When the Program is made available in source code form:
+
+ a) it must be made available under this Agreement; and
+ b) a copy of this Agreement must be included with each copy of the Program.
+ Contributors may not remove or alter any copyright notices contained
+ within the Program.
+
+Each Contributor must identify itself as the originator of its Contribution,
+if
+any, in a manner that reasonably allows subsequent Recipients to identify the
+originator of the Contribution.
+
+4. COMMERCIAL DISTRIBUTION
+
+Commercial distributors of software may accept certain responsibilities with
+respect to end users, business partners and the like. While this license is
+intended to facilitate the commercial use of the Program, the Contributor who
+includes the Program in a commercial product offering should do so in a manner
+which does not create potential liability for other Contributors. Therefore,
+if a Contributor includes the Program in a commercial product offering, such
+Contributor ("Commercial Contributor") hereby agrees to defend and indemnify
+every other Contributor ("Indemnified Contributor") against any losses,
+damages and costs (collectively "Losses") arising from claims, lawsuits and
+other legal actions brought by a third party against the Indemnified
+Contributor to the extent caused by the acts or omissions of such Commercial
+Contributor in connection with its distribution of the Program in a commercial
+product offering. The obligations in this section do not apply to any claims
+or Losses relating to any actual or alleged intellectual property
+infringement. In order to qualify, an Indemnified Contributor must:
+a) promptly notify the Commercial Contributor in writing of such claim, and
+b) allow the Commercial Contributor to control, and cooperate with the
+Commercial Contributor in, the defense and any related settlement
+negotiations. The Indemnified Contributor may participate in any such claim at
+its own expense.
+
+For example, a Contributor might include the Program in a commercial product
+offering, Product X. That Contributor is then a Commercial Contributor. If
+that Commercial Contributor then makes performance claims, or offers
+warranties related to Product X, those performance claims and warranties are
+such Commercial Contributor's responsibility alone. Under this section, the
+Commercial Contributor would have to defend claims against the other
+Contributors related to those performance claims and warranties, and if a
+court requires any other Contributor to pay any damages as a result, the
+Commercial Contributor must pay those damages.
+
+5. NO WARRANTY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR
+IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each
+Recipient is solely responsible for determining the appropriateness of using
+and distributing the Program and assumes all risks associated with its
+exercise of rights under this Agreement , including but not limited to the
+risks and costs of program errors, compliance with applicable laws, damage to
+or loss of data, programs or equipment, and unavailability or interruption of
+operations.
+
+6. DISCLAIMER OF LIABILITY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY
+CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION
+LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE
+EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY
+OF SUCH DAMAGES.
+
+7. GENERAL
+
+If any provision of this Agreement is invalid or unenforceable under
+applicable law, it shall not affect the validity or enforceability of the
+remainder of the terms of this Agreement, and without further action by the
+parties hereto, such provision shall be reformed to the minimum extent
+necessary to make such provision valid and enforceable.
+
+If Recipient institutes patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Program itself
+(excluding combinations of the Program with other software or hardware)
+infringes such Recipient's patent(s), then such Recipient's rights granted
+under Section 2(b) shall terminate as of the date such litigation is filed.
+
+All Recipient's rights under this Agreement shall terminate if it fails to
+comply with any of the material terms or conditions of this Agreement and does
+not cure such failure in a reasonable period of time after becoming aware of
+such noncompliance. If all Recipient's rights under this Agreement terminate,
+Recipient agrees to cease use and distribution of the Program as soon as
+reasonably practicable. However, Recipient's obligations under this Agreement
+and any licenses granted by Recipient relating to the Program shall continue
+and survive.
+
+Everyone is permitted to copy and distribute copies of this Agreement, but in
+order to avoid inconsistency the Agreement is copyrighted and may only be
+modified in the following manner. The Agreement Steward reserves the right to
+publish new versions (including revisions) of this Agreement from time to
+time. No one other than the Agreement Steward has the right to modify this
+Agreement. The Eclipse Foundation is the initial Agreement Steward. The
+Eclipse Foundation may assign the responsibility to serve as the Agreement
+Steward to a suitable separate entity. Each new version of the Agreement will
+be given a distinguishing version number. The Program (including
+Contributions) may always be distributed subject to the version of the
+Agreement under which it was received. In addition, after a new version of the
+Agreement is published, Contributor may elect to distribute the Program
+(including its Contributions) under the new version. Except as expressly
+stated in Sections 2(a) and 2(b) above, Recipient receives no rights or
+licenses to the intellectual property of any Contributor under this Agreement,
+whether expressly, by implication, estoppel or otherwise. All rights in the
+Program not expressly granted under this Agreement are reserved.
+
+This Agreement is governed by the laws of the State of New York and the
+intellectual property laws of the United States of America. No party to this
+Agreement will bring a legal action under this Agreement more than one year
+after the cause of action arose. Each party waives its rights to a jury trial in
+any resulting litigation. \ No newline at end of file
diff --git a/python/helpers/pydev/README.md b/python/helpers/pydev/README.md
new file mode 100644
index 000000000000..7b221164e66f
--- /dev/null
+++ b/python/helpers/pydev/README.md
@@ -0,0 +1,2 @@
+PyDev.Debugger
+==============
diff --git a/python/helpers/pydev/_pydev_execfile.py b/python/helpers/pydev/_pydev_execfile.py
deleted file mode 100644
index d60d7ed94bb0..000000000000
--- a/python/helpers/pydev/_pydev_execfile.py
+++ /dev/null
@@ -1,38 +0,0 @@
-#We must redefine it in Py3k if it's not already there
-def execfile(file, glob=None, loc=None):
- if glob is None:
- import sys
- glob = sys._getframe().f_back.f_globals
- if loc is None:
- loc = glob
- stream = open(file, 'rb')
- try:
- encoding = None
- #Get encoding!
- for _i in range(2):
- line = stream.readline() #Should not raise an exception even if there are no more contents
- #Must be a comment line
- if line.strip().startswith(b'#'):
- #Don't import re if there's no chance that there's an encoding in the line
- if b'coding' in line:
- import re
- p = re.search(br"coding[:=]\s*([-\w.]+)", line)
- if p:
- try:
- encoding = p.group(1).decode('ascii')
- break
- except:
- encoding = None
- finally:
- stream.close()
-
- if encoding:
- stream = open(file, encoding=encoding)
- else:
- stream = open(file)
- try:
- contents = stream.read()
- finally:
- stream.close()
-
- exec(compile(contents+"\n", file, 'exec'), glob, loc) #execute the script \ No newline at end of file
diff --git a/python/helpers/pydev/_pydev_getopt.py b/python/helpers/pydev/_pydev_getopt.py
new file mode 100644
index 000000000000..5548651e35e9
--- /dev/null
+++ b/python/helpers/pydev/_pydev_getopt.py
@@ -0,0 +1,130 @@
+
+#=======================================================================================================================
+# getopt code copied since gnu_getopt is not available on jython 2.1
+#=======================================================================================================================
+class GetoptError(Exception):
+ opt = ''
+ msg = ''
+ def __init__(self, msg, opt=''):
+ self.msg = msg
+ self.opt = opt
+ Exception.__init__(self, msg, opt)
+
+ def __str__(self):
+ return self.msg
+
+
+def gnu_getopt(args, shortopts, longopts=[]):
+ """getopt(args, options[, long_options]) -> opts, args
+
+ This function works like getopt(), except that GNU style scanning
+ mode is used by default. This means that option and non-option
+ arguments may be intermixed. The getopt() function stops
+ processing options as soon as a non-option argument is
+ encountered.
+
+ If the first character of the option string is `+', or if the
+ environment variable POSIXLY_CORRECT is set, then option
+ processing stops as soon as a non-option argument is encountered.
+ """
+
+ opts = []
+ prog_args = []
+ if type('') == type(longopts):
+ longopts = [longopts]
+ else:
+ longopts = list(longopts)
+
+ # Allow options after non-option arguments?
+ all_options_first = False
+ if shortopts.startswith('+'):
+ shortopts = shortopts[1:]
+ all_options_first = True
+
+ while args:
+ if args[0] == '--':
+ prog_args += args[1:]
+ break
+
+ if args[0][:2] == '--':
+ opts, args = do_longs(opts, args[0][2:], longopts, args[1:])
+ elif args[0][:1] == '-':
+ opts, args = do_shorts(opts, args[0][1:], shortopts, args[1:])
+ else:
+ if all_options_first:
+ prog_args += args
+ break
+ else:
+ prog_args.append(args[0])
+ args = args[1:]
+
+ return opts, prog_args
+
+def do_longs(opts, opt, longopts, args):
+ try:
+ i = opt.index('=')
+ except ValueError:
+ optarg = None
+ else:
+ opt, optarg = opt[:i], opt[i + 1:]
+
+ has_arg, opt = long_has_args(opt, longopts)
+ if has_arg:
+ if optarg is None:
+ if not args:
+ raise GetoptError('option --%s requires argument' % opt, opt)
+ optarg, args = args[0], args[1:]
+ elif optarg:
+ raise GetoptError('option --%s must not have an argument' % opt, opt)
+ opts.append(('--' + opt, optarg or ''))
+ return opts, args
+
+# Return:
+# has_arg?
+# full option name
+def long_has_args(opt, longopts):
+ possibilities = [o for o in longopts if o.startswith(opt)]
+ if not possibilities:
+ raise GetoptError('option --%s not recognized' % opt, opt)
+ # Is there an exact match?
+ if opt in possibilities:
+ return False, opt
+ elif opt + '=' in possibilities:
+ return True, opt
+ # No exact match, so better be unique.
+ if len(possibilities) > 1:
+ # XXX since possibilities contains all valid continuations, might be
+ # nice to work them into the error msg
+ raise GetoptError('option --%s not a unique prefix' % opt, opt)
+ assert len(possibilities) == 1
+ unique_match = possibilities[0]
+ has_arg = unique_match.endswith('=')
+ if has_arg:
+ unique_match = unique_match[:-1]
+ return has_arg, unique_match
+
+def do_shorts(opts, optstring, shortopts, args):
+ while optstring != '':
+ opt, optstring = optstring[0], optstring[1:]
+ if short_has_arg(opt, shortopts):
+ if optstring == '':
+ if not args:
+ raise GetoptError('option -%s requires argument' % opt,
+ opt)
+ optstring, args = args[0], args[1:]
+ optarg, optstring = optstring, ''
+ else:
+ optarg = ''
+ opts.append(('-' + opt, optarg))
+ return opts, args
+
+def short_has_arg(opt, shortopts):
+ for i in range(len(shortopts)):
+ if opt == shortopts[i] != ':':
+ return shortopts.startswith(':', i + 1)
+ raise GetoptError('option -%s not recognized' % opt, opt)
+
+
+#=======================================================================================================================
+# End getopt code
+#=======================================================================================================================
diff --git a/python/helpers/pydev/_pydev_imports_tipper.py b/python/helpers/pydev/_pydev_imports_tipper.py
index e4b3b863f210..76cf2cdc473f 100644
--- a/python/helpers/pydev/_pydev_imports_tipper.py
+++ b/python/helpers/pydev/_pydev_imports_tipper.py
@@ -4,6 +4,10 @@ import sys
from _pydev_tipper_common import DoFind
+try:
+ xrange
+except:
+ xrange = range
#completion types.
TYPE_IMPORT = '0'
@@ -19,20 +23,20 @@ def _imp(name, log=None):
except:
if '.' in name:
sub = name[0:name.rfind('.')]
-
+
if log is not None:
log.AddContent('Unable to import', name, 'trying with', sub)
log.AddException()
-
+
return _imp(sub, log)
else:
s = 'Unable to import module: %s - sys.path: %s' % (str(name), sys.path)
if log is not None:
log.AddContent(s)
log.AddException()
-
+
raise ImportError(s)
-
+
IS_IPY = False
if sys.platform == 'cli':
@@ -53,9 +57,9 @@ if sys.platform == 'cli':
clr.AddReference(name)
except:
pass #That's OK (not dot net module).
-
+
return _old_imp(initial_name, log)
-
+
def GetFile(mod):
@@ -69,19 +73,19 @@ def GetFile(mod):
filename = f[:-4] + '.py'
if os.path.exists(filename):
f = filename
-
+
return f
def Find(name, log=None):
f = None
-
+
mod = _imp(name, log)
parent = mod
foundAs = ''
-
+
if inspect.ismodule(mod):
f = GetFile(mod)
-
+
components = name.split('.')
old_comp = None
@@ -94,22 +98,22 @@ def Find(name, log=None):
except AttributeError:
if old_comp != comp:
raise
-
+
if inspect.ismodule(mod):
f = GetFile(mod)
else:
if len(foundAs) > 0:
foundAs = foundAs + '.'
foundAs = foundAs + comp
-
+
old_comp = comp
-
+
return f, mod, parent, foundAs
def Search(data):
'''@return file, line, col
'''
-
+
data = data.replace('\n', '')
if data.endswith('.'):
data = data.rstrip('.')
@@ -118,19 +122,19 @@ def Search(data):
return DoFind(f, mod), foundAs
except:
return DoFind(f, parent), foundAs
-
-
+
+
def GenerateTip(data, log=None):
data = data.replace('\n', '')
if data.endswith('.'):
data = data.rstrip('.')
-
+
f, mod, parent, foundAs = Find(data, log)
#print_ >> open('temp.txt', 'w'), f
tips = GenerateImportsTipForModule(mod)
return f, tips
-
-
+
+
def CheckChar(c):
if c == '-' or c == '.':
return '_'
@@ -146,7 +150,7 @@ def GenerateImportsTipForModule(obj_to_complete, dirComps=None, getattr=getattr,
name, doc, args, type (from the TYPE_* constants)
'''
ret = []
-
+
if dirComps is None:
dirComps = dir(obj_to_complete)
if hasattr(obj_to_complete, '__dict__'):
@@ -155,22 +159,22 @@ def GenerateImportsTipForModule(obj_to_complete, dirComps=None, getattr=getattr,
dirComps.append('__class__')
getCompleteInfo = True
-
+
if len(dirComps) > 1000:
- #ok, we don't want to let our users wait forever...
+ #ok, we don't want to let our users wait forever...
#no complete info for you...
-
+
getCompleteInfo = False
-
+
dontGetDocsOn = (float, int, str, tuple, list)
for d in dirComps:
-
+
if d is None:
continue
-
+
if not filter(d):
continue
-
+
args = ''
try:
@@ -182,18 +186,18 @@ def GenerateImportsTipForModule(obj_to_complete, dirComps=None, getattr=getattr,
if getCompleteInfo:
try:
retType = TYPE_BUILTIN
-
+
#check if we have to get docs
getDoc = True
for class_ in dontGetDocsOn:
-
+
if isinstance(obj, class_):
getDoc = False
break
-
+
doc = ''
if getDoc:
- #no need to get this info... too many constants are defined and
+ #no need to get this info... too many constants are defined and
#makes things much slower (passing all that through sockets takes quite some time)
try:
doc = inspect.getdoc(obj)
@@ -201,12 +205,12 @@ def GenerateImportsTipForModule(obj_to_complete, dirComps=None, getattr=getattr,
doc = ''
except: #may happen on jython when checking java classes (so, just ignore it)
doc = ''
-
-
+
+
if inspect.ismethod(obj) or inspect.isbuiltin(obj) or inspect.isfunction(obj) or inspect.isroutine(obj):
try:
args, vargs, kwargs, defaults = inspect.getargspec(obj)
-
+
r = ''
for a in (args):
if len(r) > 0:
@@ -250,7 +254,7 @@ def GenerateImportsTipForModule(obj_to_complete, dirComps=None, getattr=getattr,
if major:
args = major[major.index('('):]
found = True
-
+
if not found:
i = doc.find('->')
@@ -260,12 +264,12 @@ def GenerateImportsTipForModule(obj_to_complete, dirComps=None, getattr=getattr,
i = doc.find('\n')
if i < 0:
i = doc.find('\r')
-
-
+
+
if i > 0:
s = doc[0:i]
s = s.strip()
-
+
#let's see if we have a docstring in the first line
if s[-1] == ')':
start = s.find('(')
@@ -275,21 +279,21 @@ def GenerateImportsTipForModule(obj_to_complete, dirComps=None, getattr=getattr,
end = s.find(')')
if end <= 0:
end = len(s)
-
+
args = s[start:end]
if not args[-1] == ')':
args = args + ')'
-
-
+
+
#now, get rid of unwanted chars
l = len(args) - 1
r = []
- for i in range(len(args)):
+ for i in xrange(len(args)):
if i == 0 or i == l:
r.append(args[i])
else:
r.append(CheckChar(args[i]))
-
+
args = ''.join(r)
if IS_IPY:
@@ -305,43 +309,43 @@ def GenerateImportsTipForModule(obj_to_complete, dirComps=None, getattr=getattr,
except:
pass
-
+
retType = TYPE_FUNCTION
-
+
elif inspect.isclass(obj):
retType = TYPE_CLASS
-
+
elif inspect.ismodule(obj):
retType = TYPE_IMPORT
-
+
else:
retType = TYPE_ATTR
-
-
+
+
#add token and doc to return - assure only strings.
ret.append((d, doc, args, retType))
-
+
except: #just ignore and get it without aditional info
ret.append((d, '', args, TYPE_BUILTIN))
-
+
else: #getCompleteInfo == False
if inspect.ismethod(obj) or inspect.isbuiltin(obj) or inspect.isfunction(obj) or inspect.isroutine(obj):
retType = TYPE_FUNCTION
-
+
elif inspect.isclass(obj):
retType = TYPE_CLASS
-
+
elif inspect.ismodule(obj):
retType = TYPE_IMPORT
-
+
else:
retType = TYPE_ATTR
#ok, no complete info, let's try to do this as fast and clean as possible
#so, no docs for this kind of information, only the signatures
ret.append((d, '', str(args), retType))
-
+
return ret
-
-
+
+
diff --git a/python/helpers/pydev/_pydev_imps/__init__.py b/python/helpers/pydev/_pydev_imps/__init__.py
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/python/helpers/pydev/_pydev_imps/__init__.py
diff --git a/python/helpers/pydev/_pydev_imps/_pydev_BaseHTTPServer.py b/python/helpers/pydev/_pydev_imps/_pydev_BaseHTTPServer.py
new file mode 100644
index 000000000000..5f9dbfd63f4f
--- /dev/null
+++ b/python/helpers/pydev/_pydev_imps/_pydev_BaseHTTPServer.py
@@ -0,0 +1,604 @@
+"""HTTP server base class.
+
+Note: the class in this module doesn't implement any HTTP request; see
+SimpleHTTPServer for simple implementations of GET, HEAD and POST
+(including CGI scripts). It does, however, optionally implement HTTP/1.1
+persistent connections, as of version 0.3.
+
+Contents:
+
+- BaseHTTPRequestHandler: HTTP request handler base class
+- test: test function
+
+XXX To do:
+
+- log requests even later (to capture byte count)
+- log user-agent header and other interesting goodies
+- send error log to separate file
+"""
+
+
+# See also:
+#
+# HTTP Working Group T. Berners-Lee
+# INTERNET-DRAFT R. T. Fielding
+# <draft-ietf-http-v10-spec-00.txt> H. Frystyk Nielsen
+# Expires September 8, 1995 March 8, 1995
+#
+# URL: http://www.ics.uci.edu/pub/ietf/http/draft-ietf-http-v10-spec-00.txt
+#
+# and
+#
+# Network Working Group R. Fielding
+# Request for Comments: 2616 et al
+# Obsoletes: 2068 June 1999
+# Category: Standards Track
+#
+# URL: http://www.faqs.org/rfcs/rfc2616.html
+
+# Log files
+# ---------
+#
+# Here's a quote from the NCSA httpd docs about log file format.
+#
+# | The logfile format is as follows. Each line consists of:
+# |
+# | host rfc931 authuser [DD/Mon/YYYY:hh:mm:ss] "request" ddd bbbb
+# |
+# | host: Either the DNS name or the IP number of the remote client
+# | rfc931: Any information returned by identd for this person,
+# | - otherwise.
+# | authuser: If user sent a userid for authentication, the user name,
+# | - otherwise.
+# | DD: Day
+# | Mon: Month (calendar name)
+# | YYYY: Year
+# | hh: hour (24-hour format, the machine's timezone)
+# | mm: minutes
+# | ss: seconds
+# | request: The first line of the HTTP request as sent by the client.
+# | ddd: the status code returned by the server, - if not available.
+# | bbbb: the total number of bytes sent,
+# | *not including the HTTP/1.0 header*, - if not available
+# |
+# | You can determine the name of the file accessed through request.
+#
+# (Actually, the latter is only true if you know the server configuration
+# at the time the request was made!)
+
+__version__ = "0.3"
+
+__all__ = ["HTTPServer", "BaseHTTPRequestHandler"]
+
+import sys
+from _pydev_imps import _pydev_time as time
+from _pydev_imps import _pydev_socket as socket
+from warnings import filterwarnings, catch_warnings
+with catch_warnings():
+ if sys.py3kwarning:
+ filterwarnings("ignore", ".*mimetools has been removed",
+ DeprecationWarning)
+ import mimetools
+
+from _pydev_imps import _pydev_SocketServer as SocketServer
+
+# Default error message template
+DEFAULT_ERROR_MESSAGE = """\
+<head>
+<title>Error response</title>
+</head>
+<body>
+<h1>Error response</h1>
+<p>Error code %(code)d.
+<p>Message: %(message)s.
+<p>Error code explanation: %(code)s = %(explain)s.
+</body>
+"""
+
+DEFAULT_ERROR_CONTENT_TYPE = "text/html"
+
+def _quote_html(html):
+ return html.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;")
+
+class HTTPServer(SocketServer.TCPServer):
+
+ allow_reuse_address = 1 # Seems to make sense in testing environment
+
+ def server_bind(self):
+ """Override server_bind to store the server name."""
+ SocketServer.TCPServer.server_bind(self)
+ host, port = self.socket.getsockname()[:2]
+ self.server_name = socket.getfqdn(host)
+ self.server_port = port
+
+
+class BaseHTTPRequestHandler(SocketServer.StreamRequestHandler):
+
+ """HTTP request handler base class.
+
+ The following explanation of HTTP serves to guide you through the
+ code as well as to expose any misunderstandings I may have about
+ HTTP (so you don't need to read the code to figure out I'm wrong
+ :-).
+
+ HTTP (HyperText Transfer Protocol) is an extensible protocol on
+ top of a reliable stream transport (e.g. TCP/IP). The protocol
+ recognizes three parts to a request:
+
+ 1. One line identifying the request type and path
+ 2. An optional set of RFC-822-style headers
+ 3. An optional data part
+
+ The headers and data are separated by a blank line.
+
+ The first line of the request has the form
+
+ <command> <path> <version>
+
+ where <command> is a (case-sensitive) keyword such as GET or POST,
+ <path> is a string containing path information for the request,
+ and <version> should be the string "HTTP/1.0" or "HTTP/1.1".
+ <path> is encoded using the URL encoding scheme (using %xx to signify
+ the ASCII character with hex code xx).
+
+ The specification specifies that lines are separated by CRLF but
+ for compatibility with the widest range of clients recommends
+ servers also handle LF. Similarly, whitespace in the request line
+ is treated sensibly (allowing multiple spaces between components
+ and allowing trailing whitespace).
+
+ Similarly, for output, lines ought to be separated by CRLF pairs
+ but most clients grok LF characters just fine.
+
+ If the first line of the request has the form
+
+ <command> <path>
+
+ (i.e. <version> is left out) then this is assumed to be an HTTP
+ 0.9 request; this form has no optional headers and data part and
+ the reply consists of just the data.
+
+ The reply form of the HTTP 1.x protocol again has three parts:
+
+ 1. One line giving the response code
+ 2. An optional set of RFC-822-style headers
+ 3. The data
+
+ Again, the headers and data are separated by a blank line.
+
+ The response code line has the form
+
+ <version> <responsecode> <responsestring>
+
+ where <version> is the protocol version ("HTTP/1.0" or "HTTP/1.1"),
+ <responsecode> is a 3-digit response code indicating success or
+ failure of the request, and <responsestring> is an optional
+ human-readable string explaining what the response code means.
+
+ This server parses the request and the headers, and then calls a
+ function specific to the request type (<command>). Specifically,
+ a request SPAM will be handled by a method do_SPAM(). If no
+ such method exists the server sends an error response to the
+ client. If it exists, it is called with no arguments:
+
+ do_SPAM()
+
+ Note that the request name is case sensitive (i.e. SPAM and spam
+ are different requests).
+
+ The various request details are stored in instance variables:
+
+ - client_address is the client IP address in the form (host,
+ port);
+
+ - command, path and version are the broken-down request line;
+
+ - headers is an instance of mimetools.Message (or a derived
+ class) containing the header information;
+
+ - rfile is a file object open for reading positioned at the
+ start of the optional input data part;
+
+ - wfile is a file object open for writing.
+
+ IT IS IMPORTANT TO ADHERE TO THE PROTOCOL FOR WRITING!
+
+ The first thing to be written must be the response line. Then
+ follow 0 or more header lines, then a blank line, and then the
+ actual data (if any). The meaning of the header lines depends on
+ the command executed by the server; in most cases, when data is
+ returned, there should be at least one header line of the form
+
+ Content-type: <type>/<subtype>
+
+ where <type> and <subtype> should be registered MIME types,
+ e.g. "text/html" or "text/plain".
+
+ """
+
+ # The Python system version, truncated to its first component.
+ sys_version = "Python/" + sys.version.split()[0]
+
+ # The server software version. You may want to override this.
+ # The format is multiple whitespace-separated strings,
+ # where each string is of the form name[/version].
+ server_version = "BaseHTTP/" + __version__
+
+ # The default request version. This only affects responses up until
+ # the point where the request line is parsed, so it mainly decides what
+ # the client gets back when sending a malformed request line.
+ # Most web servers default to HTTP 0.9, i.e. don't send a status line.
+ default_request_version = "HTTP/0.9"
+
+ def parse_request(self):
+ """Parse a request (internal).
+
+ The request should be stored in self.raw_requestline; the results
+ are in self.command, self.path, self.request_version and
+ self.headers.
+
+ Return True for success, False for failure; on failure, an
+ error is sent back.
+
+ """
+ self.command = None # set in case of error on the first line
+ self.request_version = version = self.default_request_version
+ self.close_connection = 1
+ requestline = self.raw_requestline
+ requestline = requestline.rstrip('\r\n')
+ self.requestline = requestline
+ words = requestline.split()
+ if len(words) == 3:
+ command, path, version = words
+ if version[:5] != 'HTTP/':
+ self.send_error(400, "Bad request version (%r)" % version)
+ return False
+ try:
+ base_version_number = version.split('/', 1)[1]
+ version_number = base_version_number.split(".")
+ # RFC 2145 section 3.1 says there can be only one "." and
+ # - major and minor numbers MUST be treated as
+ # separate integers;
+ # - HTTP/2.4 is a lower version than HTTP/2.13, which in
+ # turn is lower than HTTP/12.3;
+ # - Leading zeros MUST be ignored by recipients.
+ if len(version_number) != 2:
+ raise ValueError
+ version_number = int(version_number[0]), int(version_number[1])
+ except (ValueError, IndexError):
+ self.send_error(400, "Bad request version (%r)" % version)
+ return False
+ if version_number >= (1, 1) and self.protocol_version >= "HTTP/1.1":
+ self.close_connection = 0
+ if version_number >= (2, 0):
+ self.send_error(505,
+ "Invalid HTTP Version (%s)" % base_version_number)
+ return False
+ elif len(words) == 2:
+ command, path = words
+ self.close_connection = 1
+ if command != 'GET':
+ self.send_error(400,
+ "Bad HTTP/0.9 request type (%r)" % command)
+ return False
+ elif not words:
+ return False
+ else:
+ self.send_error(400, "Bad request syntax (%r)" % requestline)
+ return False
+ self.command, self.path, self.request_version = command, path, version
+
+ # Examine the headers and look for a Connection directive
+ self.headers = self.MessageClass(self.rfile, 0)
+
+ conntype = self.headers.get('Connection', "")
+ if conntype.lower() == 'close':
+ self.close_connection = 1
+ elif (conntype.lower() == 'keep-alive' and
+ self.protocol_version >= "HTTP/1.1"):
+ self.close_connection = 0
+ return True
+
+ def handle_one_request(self):
+ """Handle a single HTTP request.
+
+ You normally don't need to override this method; see the class
+ __doc__ string for information on how to handle specific HTTP
+ commands such as GET and POST.
+
+ """
+ try:
+ self.raw_requestline = self.rfile.readline(65537)
+ if len(self.raw_requestline) > 65536:
+ self.requestline = ''
+ self.request_version = ''
+ self.command = ''
+ self.send_error(414)
+ return
+ if not self.raw_requestline:
+ self.close_connection = 1
+ return
+ if not self.parse_request():
+ # An error code has been sent, just exit
+ return
+ mname = 'do_' + self.command
+ if not hasattr(self, mname):
+ self.send_error(501, "Unsupported method (%r)" % self.command)
+ return
+ method = getattr(self, mname)
+ method()
+ self.wfile.flush() #actually send the response if not already done.
+ except socket.timeout:
+ #a read or a write timed out. Discard this connection
+ self.log_error("Request timed out: %r", sys.exc_info()[1])
+ self.close_connection = 1
+ return
+
+ def handle(self):
+ """Handle multiple requests if necessary."""
+ self.close_connection = 1
+
+ self.handle_one_request()
+ while not self.close_connection:
+ self.handle_one_request()
+
+ def send_error(self, code, message=None):
+ """Send and log an error reply.
+
+ Arguments are the error code, and a detailed message.
+ The detailed message defaults to the short entry matching the
+ response code.
+
+ This sends an error response (so it must be called before any
+ output has been generated), logs the error, and finally sends
+ a piece of HTML explaining the error to the user.
+
+ """
+
+ try:
+ short, long = self.responses[code]
+ except KeyError:
+ short, long = '???', '???'
+ if message is None:
+ message = short
+ explain = long
+ self.log_error("code %d, message %s", code, message)
+ # using _quote_html to prevent Cross Site Scripting attacks (see bug #1100201)
+ content = (self.error_message_format %
+ {'code': code, 'message': _quote_html(message), 'explain': explain})
+ self.send_response(code, message)
+ self.send_header("Content-Type", self.error_content_type)
+ self.send_header('Connection', 'close')
+ self.end_headers()
+ if self.command != 'HEAD' and code >= 200 and code not in (204, 304):
+ self.wfile.write(content)
+
+ error_message_format = DEFAULT_ERROR_MESSAGE
+ error_content_type = DEFAULT_ERROR_CONTENT_TYPE
+
+ def send_response(self, code, message=None):
+ """Send the response header and log the response code.
+
+ Also send two standard headers with the server software
+ version and the current date.
+
+ """
+ self.log_request(code)
+ if message is None:
+ if code in self.responses:
+ message = self.responses[code][0]
+ else:
+ message = ''
+ if self.request_version != 'HTTP/0.9':
+ self.wfile.write("%s %d %s\r\n" %
+ (self.protocol_version, code, message))
+ # print (self.protocol_version, code, message)
+ self.send_header('Server', self.version_string())
+ self.send_header('Date', self.date_time_string())
+
+ def send_header(self, keyword, value):
+ """Send a MIME header."""
+ if self.request_version != 'HTTP/0.9':
+ self.wfile.write("%s: %s\r\n" % (keyword, value))
+
+ if keyword.lower() == 'connection':
+ if value.lower() == 'close':
+ self.close_connection = 1
+ elif value.lower() == 'keep-alive':
+ self.close_connection = 0
+
+ def end_headers(self):
+ """Send the blank line ending the MIME headers."""
+ if self.request_version != 'HTTP/0.9':
+ self.wfile.write("\r\n")
+
+ def log_request(self, code='-', size='-'):
+ """Log an accepted request.
+
+ This is called by send_response().
+
+ """
+
+ self.log_message('"%s" %s %s',
+ self.requestline, str(code), str(size))
+
+ def log_error(self, format, *args):
+ """Log an error.
+
+ This is called when a request cannot be fulfilled. By
+ default it passes the message on to log_message().
+
+ Arguments are the same as for log_message().
+
+ XXX This should go to the separate error log.
+
+ """
+
+ self.log_message(format, *args)
+
+ def log_message(self, format, *args):
+ """Log an arbitrary message.
+
+ This is used by all other logging functions. Override
+ it if you have specific logging wishes.
+
+ The first argument, FORMAT, is a format string for the
+ message to be logged. If the format string contains
+ any % escapes requiring parameters, they should be
+ specified as subsequent arguments (it's just like
+ printf!).
+
+ The client host and current date/time are prefixed to
+ every message.
+
+ """
+
+ sys.stderr.write("%s - - [%s] %s\n" %
+ (self.address_string(),
+ self.log_date_time_string(),
+ format%args))
+
+ def version_string(self):
+ """Return the server software version string."""
+ return self.server_version + ' ' + self.sys_version
+
+ def date_time_string(self, timestamp=None):
+ """Return the current date and time formatted for a message header."""
+ if timestamp is None:
+ timestamp = time.time()
+ year, month, day, hh, mm, ss, wd, y, z = time.gmtime(timestamp)
+ s = "%s, %02d %3s %4d %02d:%02d:%02d GMT" % (
+ self.weekdayname[wd],
+ day, self.monthname[month], year,
+ hh, mm, ss)
+ return s
+
+ def log_date_time_string(self):
+ """Return the current time formatted for logging."""
+ now = time.time()
+ year, month, day, hh, mm, ss, x, y, z = time.localtime(now)
+ s = "%02d/%3s/%04d %02d:%02d:%02d" % (
+ day, self.monthname[month], year, hh, mm, ss)
+ return s
+
+ weekdayname = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
+
+ monthname = [None,
+ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
+ 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
+
+ def address_string(self):
+ """Return the client address formatted for logging.
+
+ This version looks up the full hostname using gethostbyaddr(),
+ and tries to find a name that contains at least one dot.
+
+ """
+
+ host, port = self.client_address[:2]
+ return socket.getfqdn(host)
+
+ # Essentially static class variables
+
+ # The version of the HTTP protocol we support.
+ # Set this to HTTP/1.1 to enable automatic keepalive
+ protocol_version = "HTTP/1.0"
+
+ # The Message-like class used to parse headers
+ MessageClass = mimetools.Message
+
+ # Table mapping response codes to messages; entries have the
+ # form {code: (shortmessage, longmessage)}.
+ # See RFC 2616.
+ responses = {
+ 100: ('Continue', 'Request received, please continue'),
+ 101: ('Switching Protocols',
+ 'Switching to new protocol; obey Upgrade header'),
+
+ 200: ('OK', 'Request fulfilled, document follows'),
+ 201: ('Created', 'Document created, URL follows'),
+ 202: ('Accepted',
+ 'Request accepted, processing continues off-line'),
+ 203: ('Non-Authoritative Information', 'Request fulfilled from cache'),
+ 204: ('No Content', 'Request fulfilled, nothing follows'),
+ 205: ('Reset Content', 'Clear input form for further input.'),
+ 206: ('Partial Content', 'Partial content follows.'),
+
+ 300: ('Multiple Choices',
+ 'Object has several resources -- see URI list'),
+ 301: ('Moved Permanently', 'Object moved permanently -- see URI list'),
+ 302: ('Found', 'Object moved temporarily -- see URI list'),
+ 303: ('See Other', 'Object moved -- see Method and URL list'),
+ 304: ('Not Modified',
+ 'Document has not changed since given time'),
+ 305: ('Use Proxy',
+ 'You must use proxy specified in Location to access this '
+ 'resource.'),
+ 307: ('Temporary Redirect',
+ 'Object moved temporarily -- see URI list'),
+
+ 400: ('Bad Request',
+ 'Bad request syntax or unsupported method'),
+ 401: ('Unauthorized',
+ 'No permission -- see authorization schemes'),
+ 402: ('Payment Required',
+ 'No payment -- see charging schemes'),
+ 403: ('Forbidden',
+ 'Request forbidden -- authorization will not help'),
+ 404: ('Not Found', 'Nothing matches the given URI'),
+ 405: ('Method Not Allowed',
+ 'Specified method is invalid for this resource.'),
+ 406: ('Not Acceptable', 'URI not available in preferred format.'),
+ 407: ('Proxy Authentication Required', 'You must authenticate with '
+ 'this proxy before proceeding.'),
+ 408: ('Request Timeout', 'Request timed out; try again later.'),
+ 409: ('Conflict', 'Request conflict.'),
+ 410: ('Gone',
+ 'URI no longer exists and has been permanently removed.'),
+ 411: ('Length Required', 'Client must specify Content-Length.'),
+ 412: ('Precondition Failed', 'Precondition in headers is false.'),
+ 413: ('Request Entity Too Large', 'Entity is too large.'),
+ 414: ('Request-URI Too Long', 'URI is too long.'),
+ 415: ('Unsupported Media Type', 'Entity body in unsupported format.'),
+ 416: ('Requested Range Not Satisfiable',
+ 'Cannot satisfy request range.'),
+ 417: ('Expectation Failed',
+ 'Expect condition could not be satisfied.'),
+
+ 500: ('Internal Server Error', 'Server got itself in trouble'),
+ 501: ('Not Implemented',
+ 'Server does not support this operation'),
+ 502: ('Bad Gateway', 'Invalid responses from another server/proxy.'),
+ 503: ('Service Unavailable',
+ 'The server cannot process the request due to a high load'),
+ 504: ('Gateway Timeout',
+ 'The gateway server did not receive a timely response'),
+ 505: ('HTTP Version Not Supported', 'Cannot fulfill request.'),
+ }
+
+
+def test(HandlerClass = BaseHTTPRequestHandler,
+ ServerClass = HTTPServer, protocol="HTTP/1.0"):
+ """Test the HTTP request handler class.
+
+ This runs an HTTP server on port 8000 (or the first command line
+ argument).
+
+ """
+
+ if sys.argv[1:]:
+ port = int(sys.argv[1])
+ else:
+ port = 8000
+ server_address = ('', port)
+
+ HandlerClass.protocol_version = protocol
+ httpd = ServerClass(server_address, HandlerClass)
+
+ sa = httpd.socket.getsockname()
+ print ("Serving HTTP on", sa[0], "port", sa[1], "...")
+ httpd.serve_forever()
+
+
+if __name__ == '__main__':
+ test()
diff --git a/python/helpers/pydev/_pydev_imps/_pydev_Queue.py b/python/helpers/pydev/_pydev_imps/_pydev_Queue.py
new file mode 100644
index 000000000000..d351b505a3e0
--- /dev/null
+++ b/python/helpers/pydev/_pydev_imps/_pydev_Queue.py
@@ -0,0 +1,244 @@
+"""A multi-producer, multi-consumer queue."""
+
+from _pydev_imps._pydev_time import time as _time
+try:
+ import _pydev_threading as _threading
+except ImportError:
+ import dummy_threading as _threading
+from collections import deque
+import heapq
+
+__all__ = ['Empty', 'Full', 'Queue', 'PriorityQueue', 'LifoQueue']
+
+class Empty(Exception):
+ "Exception raised by Queue.get(block=0)/get_nowait()."
+ pass
+
+class Full(Exception):
+ "Exception raised by Queue.put(block=0)/put_nowait()."
+ pass
+
+class Queue:
+ """Create a queue object with a given maximum size.
+
+ If maxsize is <= 0, the queue size is infinite.
+ """
+ def __init__(self, maxsize=0):
+ self.maxsize = maxsize
+ self._init(maxsize)
+ # mutex must be held whenever the queue is mutating. All methods
+ # that acquire mutex must release it before returning. mutex
+ # is shared between the three conditions, so acquiring and
+ # releasing the conditions also acquires and releases mutex.
+ self.mutex = _threading.Lock()
+ # Notify not_empty whenever an item is added to the queue; a
+ # thread waiting to get is notified then.
+ self.not_empty = _threading.Condition(self.mutex)
+ # Notify not_full whenever an item is removed from the queue;
+ # a thread waiting to put is notified then.
+ self.not_full = _threading.Condition(self.mutex)
+ # Notify all_tasks_done whenever the number of unfinished tasks
+ # drops to zero; thread waiting to join() is notified to resume
+ self.all_tasks_done = _threading.Condition(self.mutex)
+ self.unfinished_tasks = 0
+
+ def task_done(self):
+ """Indicate that a formerly enqueued task is complete.
+
+ Used by Queue consumer threads. For each get() used to fetch a task,
+ a subsequent call to task_done() tells the queue that the processing
+ on the task is complete.
+
+ If a join() is currently blocking, it will resume when all items
+ have been processed (meaning that a task_done() call was received
+ for every item that had been put() into the queue).
+
+ Raises a ValueError if called more times than there were items
+ placed in the queue.
+ """
+ self.all_tasks_done.acquire()
+ try:
+ unfinished = self.unfinished_tasks - 1
+ if unfinished <= 0:
+ if unfinished < 0:
+ raise ValueError('task_done() called too many times')
+ self.all_tasks_done.notify_all()
+ self.unfinished_tasks = unfinished
+ finally:
+ self.all_tasks_done.release()
+
+ def join(self):
+ """Blocks until all items in the Queue have been gotten and processed.
+
+ The count of unfinished tasks goes up whenever an item is added to the
+ queue. The count goes down whenever a consumer thread calls task_done()
+ to indicate the item was retrieved and all work on it is complete.
+
+ When the count of unfinished tasks drops to zero, join() unblocks.
+ """
+ self.all_tasks_done.acquire()
+ try:
+ while self.unfinished_tasks:
+ self.all_tasks_done.wait()
+ finally:
+ self.all_tasks_done.release()
+
+ def qsize(self):
+ """Return the approximate size of the queue (not reliable!)."""
+ self.mutex.acquire()
+ n = self._qsize()
+ self.mutex.release()
+ return n
+
+ def empty(self):
+ """Return True if the queue is empty, False otherwise (not reliable!)."""
+ self.mutex.acquire()
+ n = not self._qsize()
+ self.mutex.release()
+ return n
+
+ def full(self):
+ """Return True if the queue is full, False otherwise (not reliable!)."""
+ self.mutex.acquire()
+ n = 0 < self.maxsize == self._qsize()
+ self.mutex.release()
+ return n
+
+ def put(self, item, block=True, timeout=None):
+ """Put an item into the queue.
+
+ If optional args 'block' is true and 'timeout' is None (the default),
+ block if necessary until a free slot is available. If 'timeout' is
+ a positive number, it blocks at most 'timeout' seconds and raises
+ the Full exception if no free slot was available within that time.
+ Otherwise ('block' is false), put an item on the queue if a free slot
+ is immediately available, else raise the Full exception ('timeout'
+ is ignored in that case).
+ """
+ self.not_full.acquire()
+ try:
+ if self.maxsize > 0:
+ if not block:
+ if self._qsize() == self.maxsize:
+ raise Full
+ elif timeout is None:
+ while self._qsize() == self.maxsize:
+ self.not_full.wait()
+ elif timeout < 0:
+ raise ValueError("'timeout' must be a positive number")
+ else:
+ endtime = _time() + timeout
+ while self._qsize() == self.maxsize:
+ remaining = endtime - _time()
+ if remaining <= 0.0:
+ raise Full
+ self.not_full.wait(remaining)
+ self._put(item)
+ self.unfinished_tasks += 1
+ self.not_empty.notify()
+ finally:
+ self.not_full.release()
+
+ def put_nowait(self, item):
+ """Put an item into the queue without blocking.
+
+ Only enqueue the item if a free slot is immediately available.
+ Otherwise raise the Full exception.
+ """
+ return self.put(item, False)
+
+ def get(self, block=True, timeout=None):
+ """Remove and return an item from the queue.
+
+ If optional args 'block' is true and 'timeout' is None (the default),
+ block if necessary until an item is available. If 'timeout' is
+ a positive number, it blocks at most 'timeout' seconds and raises
+ the Empty exception if no item was available within that time.
+ Otherwise ('block' is false), return an item if one is immediately
+ available, else raise the Empty exception ('timeout' is ignored
+ in that case).
+ """
+ self.not_empty.acquire()
+ try:
+ if not block:
+ if not self._qsize():
+ raise Empty
+ elif timeout is None:
+ while not self._qsize():
+ self.not_empty.wait()
+ elif timeout < 0:
+ raise ValueError("'timeout' must be a positive number")
+ else:
+ endtime = _time() + timeout
+ while not self._qsize():
+ remaining = endtime - _time()
+ if remaining <= 0.0:
+ raise Empty
+ self.not_empty.wait(remaining)
+ item = self._get()
+ self.not_full.notify()
+ return item
+ finally:
+ self.not_empty.release()
+
+ def get_nowait(self):
+ """Remove and return an item from the queue without blocking.
+
+ Only get an item if one is immediately available. Otherwise
+ raise the Empty exception.
+ """
+ return self.get(False)
+
+ # Override these methods to implement other queue organizations
+ # (e.g. stack or priority queue).
+ # These will only be called with appropriate locks held
+
+ # Initialize the queue representation
+ def _init(self, maxsize):
+ self.queue = deque()
+
+ def _qsize(self, len=len):
+ return len(self.queue)
+
+ # Put a new item in the queue
+ def _put(self, item):
+ self.queue.append(item)
+
+ # Get an item from the queue
+ def _get(self):
+ return self.queue.popleft()
+
+
+class PriorityQueue(Queue):
+ '''Variant of Queue that retrieves open entries in priority order (lowest first).
+
+ Entries are typically tuples of the form: (priority number, data).
+ '''
+
+ def _init(self, maxsize):
+ self.queue = []
+
+ def _qsize(self, len=len):
+ return len(self.queue)
+
+ def _put(self, item, heappush=heapq.heappush):
+ heappush(self.queue, item)
+
+ def _get(self, heappop=heapq.heappop):
+ return heappop(self.queue)
+
+
+class LifoQueue(Queue):
+ '''Variant of Queue that retrieves most recently added entries first.'''
+
+ def _init(self, maxsize):
+ self.queue = []
+
+ def _qsize(self, len=len):
+ return len(self.queue)
+
+ def _put(self, item):
+ self.queue.append(item)
+
+ def _get(self):
+ return self.queue.pop()
diff --git a/python/helpers/pydev/_pydev_imps/_pydev_SimpleXMLRPCServer.py b/python/helpers/pydev/_pydev_imps/_pydev_SimpleXMLRPCServer.py
new file mode 100644
index 000000000000..5a0c2af83962
--- /dev/null
+++ b/python/helpers/pydev/_pydev_imps/_pydev_SimpleXMLRPCServer.py
@@ -0,0 +1,610 @@
+#Just a copy of the version in python 2.5 to be used if it's not available in jython 2.1
+
+"""Simple XML-RPC Server.
+
+This module can be used to create simple XML-RPC servers
+by creating a server and either installing functions, a
+class instance, or by extending the SimpleXMLRPCServer
+class.
+
+It can also be used to handle XML-RPC requests in a CGI
+environment using CGIXMLRPCRequestHandler.
+
+A list of possible usage patterns follows:
+
+1. Install functions:
+
+server = SimpleXMLRPCServer(("localhost", 8000))
+server.register_function(pow)
+server.register_function(lambda x,y: x+y, 'add')
+server.serve_forever()
+
+2. Install an instance:
+
+class MyFuncs:
+ def __init__(self):
+ # make all of the string functions available through
+ # string.func_name
+ import string
+ self.string = string
+ def _listMethods(self):
+ # implement this method so that system.listMethods
+ # knows to advertise the strings methods
+ return list_public_methods(self) + \
+ ['string.' + method for method in list_public_methods(self.string)]
+ def pow(self, x, y): return pow(x, y)
+ def add(self, x, y) : return x + y
+
+server = SimpleXMLRPCServer(("localhost", 8000))
+server.register_introspection_functions()
+server.register_instance(MyFuncs())
+server.serve_forever()
+
+3. Install an instance with custom dispatch method:
+
+class Math:
+ def _listMethods(self):
+ # this method must be present for system.listMethods
+ # to work
+ return ['add', 'pow']
+ def _methodHelp(self, method):
+ # this method must be present for system.methodHelp
+ # to work
+ if method == 'add':
+ return "add(2,3) => 5"
+ elif method == 'pow':
+ return "pow(x, y[, z]) => number"
+ else:
+ # By convention, return empty
+ # string if no help is available
+ return ""
+ def _dispatch(self, method, params):
+ if method == 'pow':
+ return pow(*params)
+ elif method == 'add':
+ return params[0] + params[1]
+ else:
+ raise 'bad method'
+
+server = SimpleXMLRPCServer(("localhost", 8000))
+server.register_introspection_functions()
+server.register_instance(Math())
+server.serve_forever()
+
+4. Subclass SimpleXMLRPCServer:
+
+class MathServer(SimpleXMLRPCServer):
+ def _dispatch(self, method, params):
+ try:
+ # We are forcing the 'export_' prefix on methods that are
+ # callable through XML-RPC to prevent potential security
+ # problems
+ func = getattr(self, 'export_' + method)
+ except AttributeError:
+ raise Exception('method "%s" is not supported' % method)
+ else:
+ return func(*params)
+
+ def export_add(self, x, y):
+ return x + y
+
+server = MathServer(("localhost", 8000))
+server.serve_forever()
+
+5. CGI script:
+
+server = CGIXMLRPCRequestHandler()
+server.register_function(pow)
+server.handle_request()
+"""
+
+# Written by Brian Quinlan (brian@sweetapp.com).
+# Based on code written by Fredrik Lundh.
+
+try:
+ True
+ False
+except:
+ import __builtin__
+ setattr(__builtin__, 'True', 1) #Python 3.0 does not accept __builtin__.True = 1 in its syntax
+ setattr(__builtin__, 'False', 0)
+
+
+from _pydev_imps import _pydev_xmlrpclib as xmlrpclib
+from _pydev_imps._pydev_xmlrpclib import Fault
+from _pydev_imps import _pydev_SocketServer as SocketServer
+from _pydev_imps import _pydev_BaseHTTPServer as BaseHTTPServer
+import sys
+import os
+try:
+ import fcntl
+except ImportError:
+ fcntl = None
+
+def resolve_dotted_attribute(obj, attr, allow_dotted_names=True):
+ """resolve_dotted_attribute(a, 'b.c.d') => a.b.c.d
+
+ Resolves a dotted attribute name to an object. Raises
+ an AttributeError if any attribute in the chain starts with a '_'.
+
+ If the optional allow_dotted_names argument is false, dots are not
+ supported and this function operates similar to getattr(obj, attr).
+ """
+
+ if allow_dotted_names:
+ attrs = attr.split('.')
+ else:
+ attrs = [attr]
+
+ for i in attrs:
+ if i.startswith('_'):
+ raise AttributeError(
+ 'attempt to access private attribute "%s"' % i
+ )
+ else:
+ obj = getattr(obj, i)
+ return obj
+
+def list_public_methods(obj):
+ """Returns a list of attribute strings, found in the specified
+ object, which represent callable attributes"""
+
+ return [member for member in dir(obj)
+ if not member.startswith('_') and
+ callable(getattr(obj, member))]
+
+def remove_duplicates(lst):
+ """remove_duplicates([2,2,2,1,3,3]) => [3,1,2]
+
+ Returns a copy of a list without duplicates. Every list
+ item must be hashable and the order of the items in the
+ resulting list is not defined.
+ """
+ u = {}
+ for x in lst:
+ u[x] = 1
+
+ return u.keys()
+
+class SimpleXMLRPCDispatcher:
+ """Mix-in class that dispatches XML-RPC requests.
+
+ This class is used to register XML-RPC method handlers
+ and then to dispatch them. There should never be any
+ reason to instantiate this class directly.
+ """
+
+ def __init__(self, allow_none, encoding):
+ self.funcs = {}
+ self.instance = None
+ self.allow_none = allow_none
+ self.encoding = encoding
+
+ def register_instance(self, instance, allow_dotted_names=False):
+ """Registers an instance to respond to XML-RPC requests.
+
+ Only one instance can be installed at a time.
+
+ If the registered instance has a _dispatch method then that
+ method will be called with the name of the XML-RPC method and
+ its parameters as a tuple
+ e.g. instance._dispatch('add',(2,3))
+
+ If the registered instance does not have a _dispatch method
+ then the instance will be searched to find a matching method
+ and, if found, will be called. Methods beginning with an '_'
+ are considered private and will not be called by
+ SimpleXMLRPCServer.
+
+ If a registered function matches a XML-RPC request, then it
+ will be called instead of the registered instance.
+
+ If the optional allow_dotted_names argument is true and the
+ instance does not have a _dispatch method, method names
+ containing dots are supported and resolved, as long as none of
+ the name segments start with an '_'.
+
+ *** SECURITY WARNING: ***
+
+ Enabling the allow_dotted_names options allows intruders
+ to access your module's global variables and may allow
+ intruders to execute arbitrary code on your machine. Only
+ use this option on a secure, closed network.
+
+ """
+
+ self.instance = instance
+ self.allow_dotted_names = allow_dotted_names
+
+ def register_function(self, function, name=None):
+ """Registers a function to respond to XML-RPC requests.
+
+ The optional name argument can be used to set a Unicode name
+ for the function.
+ """
+
+ if name is None:
+ name = function.__name__
+ self.funcs[name] = function
+
+ def register_introspection_functions(self):
+ """Registers the XML-RPC introspection methods in the system
+ namespace.
+
+ see http://xmlrpc.usefulinc.com/doc/reserved.html
+ """
+
+ self.funcs.update({'system.listMethods' : self.system_listMethods,
+ 'system.methodSignature' : self.system_methodSignature,
+ 'system.methodHelp' : self.system_methodHelp})
+
+ def register_multicall_functions(self):
+ """Registers the XML-RPC multicall method in the system
+ namespace.
+
+ see http://www.xmlrpc.com/discuss/msgReader$1208"""
+
+ self.funcs.update({'system.multicall' : self.system_multicall})
+
+ def _marshaled_dispatch(self, data, dispatch_method=None):
+ """Dispatches an XML-RPC method from marshalled (XML) data.
+
+ XML-RPC methods are dispatched from the marshalled (XML) data
+ using the _dispatch method and the result is returned as
+ marshalled data. For backwards compatibility, a dispatch
+ function can be provided as an argument (see comment in
+ SimpleXMLRPCRequestHandler.do_POST) but overriding the
+ existing method through subclassing is the prefered means
+ of changing method dispatch behavior.
+ """
+ try:
+ params, method = xmlrpclib.loads(data)
+
+ # generate response
+ if dispatch_method is not None:
+ response = dispatch_method(method, params)
+ else:
+ response = self._dispatch(method, params)
+ # wrap response in a singleton tuple
+ response = (response,)
+ response = xmlrpclib.dumps(response, methodresponse=1,
+ allow_none=self.allow_none, encoding=self.encoding)
+ except Fault, fault:
+ response = xmlrpclib.dumps(fault, allow_none=self.allow_none,
+ encoding=self.encoding)
+ except:
+ # report exception back to server
+ response = xmlrpclib.dumps(
+ xmlrpclib.Fault(1, "%s:%s" % (sys.exc_type, sys.exc_value)), #@UndefinedVariable exc_value only available when we actually have an exception
+ encoding=self.encoding, allow_none=self.allow_none,
+ )
+
+ return response
+
+ def system_listMethods(self):
+ """system.listMethods() => ['add', 'subtract', 'multiple']
+
+ Returns a list of the methods supported by the server."""
+
+ methods = self.funcs.keys()
+ if self.instance is not None:
+ # Instance can implement _listMethod to return a list of
+ # methods
+ if hasattr(self.instance, '_listMethods'):
+ methods = remove_duplicates(
+ methods + self.instance._listMethods()
+ )
+ # if the instance has a _dispatch method then we
+ # don't have enough information to provide a list
+ # of methods
+ elif not hasattr(self.instance, '_dispatch'):
+ methods = remove_duplicates(
+ methods + list_public_methods(self.instance)
+ )
+ methods.sort()
+ return methods
+
+ def system_methodSignature(self, method_name):
+ """system.methodSignature('add') => [double, int, int]
+
+ Returns a list describing the signature of the method. In the
+ above example, the add method takes two integers as arguments
+ and returns a double result.
+
+ This server does NOT support system.methodSignature."""
+
+ # See http://xmlrpc.usefulinc.com/doc/sysmethodsig.html
+
+ return 'signatures not supported'
+
+ def system_methodHelp(self, method_name):
+ """system.methodHelp('add') => "Adds two integers together"
+
+ Returns a string containing documentation for the specified method."""
+
+ method = None
+ if self.funcs.has_key(method_name):
+ method = self.funcs[method_name]
+ elif self.instance is not None:
+ # Instance can implement _methodHelp to return help for a method
+ if hasattr(self.instance, '_methodHelp'):
+ return self.instance._methodHelp(method_name)
+ # if the instance has a _dispatch method then we
+ # don't have enough information to provide help
+ elif not hasattr(self.instance, '_dispatch'):
+ try:
+ method = resolve_dotted_attribute(
+ self.instance,
+ method_name,
+ self.allow_dotted_names
+ )
+ except AttributeError:
+ pass
+
+ # Note that we aren't checking that the method actually
+ # be a callable object of some kind
+ if method is None:
+ return ""
+ else:
+ try:
+ import pydoc
+ except ImportError:
+ return "" #not there for jython
+ else:
+ return pydoc.getdoc(method)
+
+ def system_multicall(self, call_list):
+ """system.multicall([{'methodName': 'add', 'params': [2, 2]}, ...]) => \
+[[4], ...]
+
+ Allows the caller to package multiple XML-RPC calls into a single
+ request.
+
+ See http://www.xmlrpc.com/discuss/msgReader$1208
+ """
+
+ results = []
+ for call in call_list:
+ method_name = call['methodName']
+ params = call['params']
+
+ try:
+ # XXX A marshalling error in any response will fail the entire
+ # multicall. If someone cares they should fix this.
+ results.append([self._dispatch(method_name, params)])
+ except Fault, fault:
+ results.append(
+ {'faultCode' : fault.faultCode,
+ 'faultString' : fault.faultString}
+ )
+ except:
+ results.append(
+ {'faultCode' : 1,
+ 'faultString' : "%s:%s" % (sys.exc_type, sys.exc_value)} #@UndefinedVariable exc_value only available when we actually have an exception
+ )
+ return results
+
+ def _dispatch(self, method, params):
+ """Dispatches the XML-RPC method.
+
+ XML-RPC calls are forwarded to a registered function that
+ matches the called XML-RPC method name. If no such function
+ exists then the call is forwarded to the registered instance,
+ if available.
+
+ If the registered instance has a _dispatch method then that
+ method will be called with the name of the XML-RPC method and
+ its parameters as a tuple
+ e.g. instance._dispatch('add',(2,3))
+
+ If the registered instance does not have a _dispatch method
+ then the instance will be searched to find a matching method
+ and, if found, will be called.
+
+ Methods beginning with an '_' are considered private and will
+ not be called.
+ """
+
+ func = None
+ try:
+ # check to see if a matching function has been registered
+ func = self.funcs[method]
+ except KeyError:
+ if self.instance is not None:
+ # check for a _dispatch method
+ if hasattr(self.instance, '_dispatch'):
+ return self.instance._dispatch(method, params)
+ else:
+ # call instance method directly
+ try:
+ func = resolve_dotted_attribute(
+ self.instance,
+ method,
+ self.allow_dotted_names
+ )
+ except AttributeError:
+ pass
+
+ if func is not None:
+ return func(*params)
+ else:
+ raise Exception('method "%s" is not supported' % method)
+
+class SimpleXMLRPCRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
+ """Simple XML-RPC request handler class.
+
+ Handles all HTTP POST requests and attempts to decode them as
+ XML-RPC requests.
+ """
+
+ # Class attribute listing the accessible path components;
+ # paths not on this list will result in a 404 error.
+ rpc_paths = ('/', '/RPC2')
+
+ def is_rpc_path_valid(self):
+ if self.rpc_paths:
+ return self.path in self.rpc_paths
+ else:
+ # If .rpc_paths is empty, just assume all paths are legal
+ return True
+
+ def do_POST(self):
+ """Handles the HTTP POST request.
+
+ Attempts to interpret all HTTP POST requests as XML-RPC calls,
+ which are forwarded to the server's _dispatch method for handling.
+ """
+
+ # Check that the path is legal
+ if not self.is_rpc_path_valid():
+ self.report_404()
+ return
+
+ try:
+ # Get arguments by reading body of request.
+ # We read this in chunks to avoid straining
+ # socket.read(); around the 10 or 15Mb mark, some platforms
+ # begin to have problems (bug #792570).
+ max_chunk_size = 10 * 1024 * 1024
+ size_remaining = int(self.headers["content-length"])
+ L = []
+ while size_remaining:
+ chunk_size = min(size_remaining, max_chunk_size)
+ L.append(self.rfile.read(chunk_size))
+ size_remaining -= len(L[-1])
+ data = ''.join(L)
+
+ # In previous versions of SimpleXMLRPCServer, _dispatch
+ # could be overridden in this class, instead of in
+ # SimpleXMLRPCDispatcher. To maintain backwards compatibility,
+ # check to see if a subclass implements _dispatch and dispatch
+ # using that method if present.
+ response = self.server._marshaled_dispatch(
+ data, getattr(self, '_dispatch', None)
+ )
+ except: # This should only happen if the module is buggy
+ # internal error, report as HTTP server error
+ self.send_response(500)
+ self.end_headers()
+ else:
+ # got a valid XML RPC response
+ self.send_response(200)
+ self.send_header("Content-type", "text/xml")
+ self.send_header("Content-length", str(len(response)))
+ self.end_headers()
+ self.wfile.write(response)
+
+ # shut down the connection
+ self.wfile.flush()
+ self.connection.shutdown(1)
+
+ def report_404 (self):
+ # Report a 404 error
+ self.send_response(404)
+ response = 'No such page'
+ self.send_header("Content-type", "text/plain")
+ self.send_header("Content-length", str(len(response)))
+ self.end_headers()
+ self.wfile.write(response)
+ # shut down the connection
+ self.wfile.flush()
+ self.connection.shutdown(1)
+
+ def log_request(self, code='-', size='-'):
+ """Selectively log an accepted request."""
+
+ if self.server.logRequests:
+ BaseHTTPServer.BaseHTTPRequestHandler.log_request(self, code, size)
+
+class SimpleXMLRPCServer(SocketServer.TCPServer,
+ SimpleXMLRPCDispatcher):
+ """Simple XML-RPC server.
+
+ Simple XML-RPC server that allows functions and a single instance
+ to be installed to handle requests. The default implementation
+ attempts to dispatch XML-RPC calls to the functions or instance
+ installed in the server. Override the _dispatch method inhereted
+ from SimpleXMLRPCDispatcher to change this behavior.
+ """
+
+ allow_reuse_address = True
+
+ def __init__(self, addr, requestHandler=SimpleXMLRPCRequestHandler,
+ logRequests=True, allow_none=False, encoding=None):
+ self.logRequests = logRequests
+
+ SimpleXMLRPCDispatcher.__init__(self, allow_none, encoding)
+ SocketServer.TCPServer.__init__(self, addr, requestHandler)
+
+ # [Bug #1222790] If possible, set close-on-exec flag; if a
+ # method spawns a subprocess, the subprocess shouldn't have
+ # the listening socket open.
+ if fcntl is not None and hasattr(fcntl, 'FD_CLOEXEC'):
+ flags = fcntl.fcntl(self.fileno(), fcntl.F_GETFD)
+ flags |= fcntl.FD_CLOEXEC
+ fcntl.fcntl(self.fileno(), fcntl.F_SETFD, flags)
+
+class CGIXMLRPCRequestHandler(SimpleXMLRPCDispatcher):
+ """Simple handler for XML-RPC data passed through CGI."""
+
+ def __init__(self, allow_none=False, encoding=None):
+ SimpleXMLRPCDispatcher.__init__(self, allow_none, encoding)
+
+ def handle_xmlrpc(self, request_text):
+ """Handle a single XML-RPC request"""
+
+ response = self._marshaled_dispatch(request_text)
+
+ sys.stdout.write('Content-Type: text/xml\n')
+ sys.stdout.write('Content-Length: %d\n' % len(response))
+ sys.stdout.write('\n')
+
+ sys.stdout.write(response)
+
+ def handle_get(self):
+ """Handle a single HTTP GET request.
+
+ Default implementation indicates an error because
+ XML-RPC uses the POST method.
+ """
+
+ code = 400
+ message, explain = \
+ BaseHTTPServer.BaseHTTPRequestHandler.responses[code]
+
+ response = BaseHTTPServer.DEFAULT_ERROR_MESSAGE % { #@UndefinedVariable
+ 'code' : code,
+ 'message' : message,
+ 'explain' : explain
+ }
+ sys.stdout.write('Status: %d %s\n' % (code, message))
+ sys.stdout.write('Content-Type: text/html\n')
+ sys.stdout.write('Content-Length: %d\n' % len(response))
+ sys.stdout.write('\n')
+
+ sys.stdout.write(response)
+
+ def handle_request(self, request_text=None):
+ """Handle a single XML-RPC request passed through a CGI post method.
+
+ If no XML data is given then it is read from stdin. The resulting
+ XML-RPC response is printed to stdout along with the correct HTTP
+ headers.
+ """
+
+ if request_text is None and \
+ os.environ.get('REQUEST_METHOD', None) == 'GET':
+ self.handle_get()
+ else:
+ # POST data is normally available through stdin
+ if request_text is None:
+ request_text = sys.stdin.read()
+
+ self.handle_xmlrpc(request_text)
+
+if __name__ == '__main__':
+ sys.stdout.write('Running XML-RPC server on port 8000\n')
+ server = SimpleXMLRPCServer(("localhost", 8000))
+ server.register_function(pow)
+ server.register_function(lambda x, y: x + y, 'add')
+ server.serve_forever()
diff --git a/python/helpers/pydev/_pydev_imps/_pydev_SocketServer.py b/python/helpers/pydev/_pydev_imps/_pydev_SocketServer.py
new file mode 100644
index 000000000000..79cfb08f68a3
--- /dev/null
+++ b/python/helpers/pydev/_pydev_imps/_pydev_SocketServer.py
@@ -0,0 +1,715 @@
+"""Generic socket server classes.
+
+This module tries to capture the various aspects of defining a server:
+
+For socket-based servers:
+
+- address family:
+ - AF_INET{,6}: IP (Internet Protocol) sockets (default)
+ - AF_UNIX: Unix domain sockets
+ - others, e.g. AF_DECNET are conceivable (see <socket.h>
+- socket type:
+ - SOCK_STREAM (reliable stream, e.g. TCP)
+ - SOCK_DGRAM (datagrams, e.g. UDP)
+
+For request-based servers (including socket-based):
+
+- client address verification before further looking at the request
+ (This is actually a hook for any processing that needs to look
+ at the request before anything else, e.g. logging)
+- how to handle multiple requests:
+ - synchronous (one request is handled at a time)
+ - forking (each request is handled by a new process)
+ - threading (each request is handled by a new thread)
+
+The classes in this module favor the server type that is simplest to
+write: a synchronous TCP/IP server. This is bad class design, but
+save some typing. (There's also the issue that a deep class hierarchy
+slows down method lookups.)
+
+There are five classes in an inheritance diagram, four of which represent
+synchronous servers of four types:
+
+ +------------+
+ | BaseServer |
+ +------------+
+ |
+ v
+ +-----------+ +------------------+
+ | TCPServer |------->| UnixStreamServer |
+ +-----------+ +------------------+
+ |
+ v
+ +-----------+ +--------------------+
+ | UDPServer |------->| UnixDatagramServer |
+ +-----------+ +--------------------+
+
+Note that UnixDatagramServer derives from UDPServer, not from
+UnixStreamServer -- the only difference between an IP and a Unix
+stream server is the address family, which is simply repeated in both
+unix server classes.
+
+Forking and threading versions of each type of server can be created
+using the ForkingMixIn and ThreadingMixIn mix-in classes. For
+instance, a threading UDP server class is created as follows:
+
+ class ThreadingUDPServer(ThreadingMixIn, UDPServer): pass
+
+The Mix-in class must come first, since it overrides a method defined
+in UDPServer! Setting the various member variables also changes
+the behavior of the underlying server mechanism.
+
+To implement a service, you must derive a class from
+BaseRequestHandler and redefine its handle() method. You can then run
+various versions of the service by combining one of the server classes
+with your request handler class.
+
+The request handler class must be different for datagram or stream
+services. This can be hidden by using the request handler
+subclasses StreamRequestHandler or DatagramRequestHandler.
+
+Of course, you still have to use your head!
+
+For instance, it makes no sense to use a forking server if the service
+contains state in memory that can be modified by requests (since the
+modifications in the child process would never reach the initial state
+kept in the parent process and passed to each child). In this case,
+you can use a threading server, but you will probably have to use
+locks to avoid two requests that come in nearly simultaneous to apply
+conflicting changes to the server state.
+
+On the other hand, if you are building e.g. an HTTP server, where all
+data is stored externally (e.g. in the file system), a synchronous
+class will essentially render the service "deaf" while one request is
+being handled -- which may be for a very long time if a client is slow
+to read all the data it has requested. Here a threading or forking
+server is appropriate.
+
+In some cases, it may be appropriate to process part of a request
+synchronously, but to finish processing in a forked child depending on
+the request data. This can be implemented by using a synchronous
+server and doing an explicit fork in the request handler class
+handle() method.
+
+Another approach to handling multiple simultaneous requests in an
+environment that supports neither threads nor fork (or where these are
+too expensive or inappropriate for the service) is to maintain an
+explicit table of partially finished requests and to use select() to
+decide which request to work on next (or whether to handle a new
+incoming request). This is particularly important for stream services
+where each client can potentially be connected for a long time (if
+threads or subprocesses cannot be used).
+
+Future work:
+- Standard classes for Sun RPC (which uses either UDP or TCP)
+- Standard mix-in classes to implement various authentication
+ and encryption schemes
+- Standard framework for select-based multiplexing
+
+XXX Open problems:
+- What to do with out-of-band data?
+
+BaseServer:
+- split generic "request" functionality out into BaseServer class.
+ Copyright (C) 2000 Luke Kenneth Casson Leighton <lkcl@samba.org>
+
+ example: read entries from a SQL database (requires overriding
+ get_request() to return a table entry from the database).
+ entry is processed by a RequestHandlerClass.
+
+"""
+
+# Author of the BaseServer patch: Luke Kenneth Casson Leighton
+
+# XXX Warning!
+# There is a test suite for this module, but it cannot be run by the
+# standard regression test.
+# To run it manually, run Lib/test/test_socketserver.py.
+
+__version__ = "0.4"
+
+
+from _pydev_imps import _pydev_socket as socket
+from _pydev_imps import _pydev_select as select
+import sys
+import os
+try:
+ import _pydev_threading as threading
+except ImportError:
+ import dummy_threading as threading
+
+__all__ = ["TCPServer","UDPServer","ForkingUDPServer","ForkingTCPServer",
+ "ThreadingUDPServer","ThreadingTCPServer","BaseRequestHandler",
+ "StreamRequestHandler","DatagramRequestHandler",
+ "ThreadingMixIn", "ForkingMixIn"]
+if hasattr(socket, "AF_UNIX"):
+ __all__.extend(["UnixStreamServer","UnixDatagramServer",
+ "ThreadingUnixStreamServer",
+ "ThreadingUnixDatagramServer"])
+
+class BaseServer:
+
+ """Base class for server classes.
+
+ Methods for the caller:
+
+ - __init__(server_address, RequestHandlerClass)
+ - serve_forever(poll_interval=0.5)
+ - shutdown()
+ - handle_request() # if you do not use serve_forever()
+ - fileno() -> int # for select()
+
+ Methods that may be overridden:
+
+ - server_bind()
+ - server_activate()
+ - get_request() -> request, client_address
+ - handle_timeout()
+ - verify_request(request, client_address)
+ - server_close()
+ - process_request(request, client_address)
+ - shutdown_request(request)
+ - close_request(request)
+ - handle_error()
+
+ Methods for derived classes:
+
+ - finish_request(request, client_address)
+
+ Class variables that may be overridden by derived classes or
+ instances:
+
+ - timeout
+ - address_family
+ - socket_type
+ - allow_reuse_address
+
+ Instance variables:
+
+ - RequestHandlerClass
+ - socket
+
+ """
+
+ timeout = None
+
+ def __init__(self, server_address, RequestHandlerClass):
+ """Constructor. May be extended, do not override."""
+ self.server_address = server_address
+ self.RequestHandlerClass = RequestHandlerClass
+ self.__is_shut_down = threading.Event()
+ self.__shutdown_request = False
+
+ def server_activate(self):
+ """Called by constructor to activate the server.
+
+ May be overridden.
+
+ """
+ pass
+
+ def serve_forever(self, poll_interval=0.5):
+ """Handle one request at a time until shutdown.
+
+ Polls for shutdown every poll_interval seconds. Ignores
+ self.timeout. If you need to do periodic tasks, do them in
+ another thread.
+ """
+ self.__is_shut_down.clear()
+ try:
+ while not self.__shutdown_request:
+ # XXX: Consider using another file descriptor or
+ # connecting to the socket to wake this up instead of
+ # polling. Polling reduces our responsiveness to a
+ # shutdown request and wastes cpu at all other times.
+ r, w, e = select.select([self], [], [], poll_interval)
+ if self in r:
+ self._handle_request_noblock()
+ finally:
+ self.__shutdown_request = False
+ self.__is_shut_down.set()
+
+ def shutdown(self):
+ """Stops the serve_forever loop.
+
+ Blocks until the loop has finished. This must be called while
+ serve_forever() is running in another thread, or it will
+ deadlock.
+ """
+ self.__shutdown_request = True
+ self.__is_shut_down.wait()
+
+ # The distinction between handling, getting, processing and
+ # finishing a request is fairly arbitrary. Remember:
+ #
+ # - handle_request() is the top-level call. It calls
+ # select, get_request(), verify_request() and process_request()
+ # - get_request() is different for stream or datagram sockets
+ # - process_request() is the place that may fork a new process
+ # or create a new thread to finish the request
+ # - finish_request() instantiates the request handler class;
+ # this constructor will handle the request all by itself
+
+ def handle_request(self):
+ """Handle one request, possibly blocking.
+
+ Respects self.timeout.
+ """
+ # Support people who used socket.settimeout() to escape
+ # handle_request before self.timeout was available.
+ timeout = self.socket.gettimeout()
+ if timeout is None:
+ timeout = self.timeout
+ elif self.timeout is not None:
+ timeout = min(timeout, self.timeout)
+ fd_sets = select.select([self], [], [], timeout)
+ if not fd_sets[0]:
+ self.handle_timeout()
+ return
+ self._handle_request_noblock()
+
+ def _handle_request_noblock(self):
+ """Handle one request, without blocking.
+
+ I assume that select.select has returned that the socket is
+ readable before this function was called, so there should be
+ no risk of blocking in get_request().
+ """
+ try:
+ request, client_address = self.get_request()
+ except socket.error:
+ return
+ if self.verify_request(request, client_address):
+ try:
+ self.process_request(request, client_address)
+ except:
+ self.handle_error(request, client_address)
+ self.shutdown_request(request)
+
+ def handle_timeout(self):
+ """Called if no new request arrives within self.timeout.
+
+ Overridden by ForkingMixIn.
+ """
+ pass
+
+ def verify_request(self, request, client_address):
+ """Verify the request. May be overridden.
+
+ Return True if we should proceed with this request.
+
+ """
+ return True
+
+ def process_request(self, request, client_address):
+ """Call finish_request.
+
+ Overridden by ForkingMixIn and ThreadingMixIn.
+
+ """
+ self.finish_request(request, client_address)
+ self.shutdown_request(request)
+
+ def server_close(self):
+ """Called to clean-up the server.
+
+ May be overridden.
+
+ """
+ pass
+
+ def finish_request(self, request, client_address):
+ """Finish one request by instantiating RequestHandlerClass."""
+ self.RequestHandlerClass(request, client_address, self)
+
+ def shutdown_request(self, request):
+ """Called to shutdown and close an individual request."""
+ self.close_request(request)
+
+ def close_request(self, request):
+ """Called to clean up an individual request."""
+ pass
+
+ def handle_error(self, request, client_address):
+ """Handle an error gracefully. May be overridden.
+
+ The default is to print a traceback and continue.
+
+ """
+ print '-'*40
+ print 'Exception happened during processing of request from',
+ print client_address
+ import traceback
+ traceback.print_exc() # XXX But this goes to stderr!
+ print '-'*40
+
+
+class TCPServer(BaseServer):
+
+ """Base class for various socket-based server classes.
+
+ Defaults to synchronous IP stream (i.e., TCP).
+
+ Methods for the caller:
+
+ - __init__(server_address, RequestHandlerClass, bind_and_activate=True)
+ - serve_forever(poll_interval=0.5)
+ - shutdown()
+ - handle_request() # if you don't use serve_forever()
+ - fileno() -> int # for select()
+
+ Methods that may be overridden:
+
+ - server_bind()
+ - server_activate()
+ - get_request() -> request, client_address
+ - handle_timeout()
+ - verify_request(request, client_address)
+ - process_request(request, client_address)
+ - shutdown_request(request)
+ - close_request(request)
+ - handle_error()
+
+ Methods for derived classes:
+
+ - finish_request(request, client_address)
+
+ Class variables that may be overridden by derived classes or
+ instances:
+
+ - timeout
+ - address_family
+ - socket_type
+ - request_queue_size (only for stream sockets)
+ - allow_reuse_address
+
+ Instance variables:
+
+ - server_address
+ - RequestHandlerClass
+ - socket
+
+ """
+
+ address_family = socket.AF_INET
+
+ socket_type = socket.SOCK_STREAM
+
+ request_queue_size = 5
+
+ allow_reuse_address = False
+
+ def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True):
+ """Constructor. May be extended, do not override."""
+ BaseServer.__init__(self, server_address, RequestHandlerClass)
+ self.socket = socket.socket(self.address_family,
+ self.socket_type)
+ if bind_and_activate:
+ self.server_bind()
+ self.server_activate()
+
+ def server_bind(self):
+ """Called by constructor to bind the socket.
+
+ May be overridden.
+
+ """
+ if self.allow_reuse_address:
+ self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ self.socket.bind(self.server_address)
+ self.server_address = self.socket.getsockname()
+
+ def server_activate(self):
+ """Called by constructor to activate the server.
+
+ May be overridden.
+
+ """
+ self.socket.listen(self.request_queue_size)
+
+ def server_close(self):
+ """Called to clean-up the server.
+
+ May be overridden.
+
+ """
+ self.socket.close()
+
+ def fileno(self):
+ """Return socket file number.
+
+ Interface required by select().
+
+ """
+ return self.socket.fileno()
+
+ def get_request(self):
+ """Get the request and client address from the socket.
+
+ May be overridden.
+
+ """
+ return self.socket.accept()
+
+ def shutdown_request(self, request):
+ """Called to shutdown and close an individual request."""
+ try:
+ #explicitly shutdown. socket.close() merely releases
+ #the socket and waits for GC to perform the actual close.
+ request.shutdown(socket.SHUT_WR)
+ except socket.error:
+ pass #some platforms may raise ENOTCONN here
+ self.close_request(request)
+
+ def close_request(self, request):
+ """Called to clean up an individual request."""
+ request.close()
+
+
+class UDPServer(TCPServer):
+
+ """UDP server class."""
+
+ allow_reuse_address = False
+
+ socket_type = socket.SOCK_DGRAM
+
+ max_packet_size = 8192
+
+ def get_request(self):
+ data, client_addr = self.socket.recvfrom(self.max_packet_size)
+ return (data, self.socket), client_addr
+
+ def server_activate(self):
+ # No need to call listen() for UDP.
+ pass
+
+ def shutdown_request(self, request):
+ # No need to shutdown anything.
+ self.close_request(request)
+
+ def close_request(self, request):
+ # No need to close anything.
+ pass
+
+class ForkingMixIn:
+
+ """Mix-in class to handle each request in a new process."""
+
+ timeout = 300
+ active_children = None
+ max_children = 40
+
+ def collect_children(self):
+ """Internal routine to wait for children that have exited."""
+ if self.active_children is None: return
+ while len(self.active_children) >= self.max_children:
+ # XXX: This will wait for any child process, not just ones
+ # spawned by this library. This could confuse other
+ # libraries that expect to be able to wait for their own
+ # children.
+ try:
+ pid, status = os.waitpid(0, 0)
+ except os.error:
+ pid = None
+ if pid not in self.active_children: continue
+ self.active_children.remove(pid)
+
+ # XXX: This loop runs more system calls than it ought
+ # to. There should be a way to put the active_children into a
+ # process group and then use os.waitpid(-pgid) to wait for any
+ # of that set, but I couldn't find a way to allocate pgids
+ # that couldn't collide.
+ for child in self.active_children:
+ try:
+ pid, status = os.waitpid(child, os.WNOHANG)
+ except os.error:
+ pid = None
+ if not pid: continue
+ try:
+ self.active_children.remove(pid)
+ except ValueError, e:
+ raise ValueError('%s. x=%d and list=%r' % (e.message, pid,
+ self.active_children))
+
+ def handle_timeout(self):
+ """Wait for zombies after self.timeout seconds of inactivity.
+
+ May be extended, do not override.
+ """
+ self.collect_children()
+
+ def process_request(self, request, client_address):
+ """Fork a new subprocess to process the request."""
+ self.collect_children()
+ pid = os.fork()
+ if pid:
+ # Parent process
+ if self.active_children is None:
+ self.active_children = []
+ self.active_children.append(pid)
+ self.close_request(request) #close handle in parent process
+ return
+ else:
+ # Child process.
+ # This must never return, hence os._exit()!
+ try:
+ self.finish_request(request, client_address)
+ self.shutdown_request(request)
+ os._exit(0)
+ except:
+ try:
+ self.handle_error(request, client_address)
+ self.shutdown_request(request)
+ finally:
+ os._exit(1)
+
+
+class ThreadingMixIn:
+ """Mix-in class to handle each request in a new thread."""
+
+ # Decides how threads will act upon termination of the
+ # main process
+ daemon_threads = False
+
+ def process_request_thread(self, request, client_address):
+ """Same as in BaseServer but as a thread.
+
+ In addition, exception handling is done here.
+
+ """
+ try:
+ self.finish_request(request, client_address)
+ self.shutdown_request(request)
+ except:
+ self.handle_error(request, client_address)
+ self.shutdown_request(request)
+
+ def process_request(self, request, client_address):
+ """Start a new thread to process the request."""
+ t = threading.Thread(target = self.process_request_thread,
+ args = (request, client_address))
+ t.daemon = self.daemon_threads
+ t.start()
+
+
+class ForkingUDPServer(ForkingMixIn, UDPServer): pass
+class ForkingTCPServer(ForkingMixIn, TCPServer): pass
+
+class ThreadingUDPServer(ThreadingMixIn, UDPServer): pass
+class ThreadingTCPServer(ThreadingMixIn, TCPServer): pass
+
+if hasattr(socket, 'AF_UNIX'):
+
+ class UnixStreamServer(TCPServer):
+ address_family = socket.AF_UNIX
+
+ class UnixDatagramServer(UDPServer):
+ address_family = socket.AF_UNIX
+
+ class ThreadingUnixStreamServer(ThreadingMixIn, UnixStreamServer): pass
+
+ class ThreadingUnixDatagramServer(ThreadingMixIn, UnixDatagramServer): pass
+
+class BaseRequestHandler:
+
+ """Base class for request handler classes.
+
+ This class is instantiated for each request to be handled. The
+ constructor sets the instance variables request, client_address
+ and server, and then calls the handle() method. To implement a
+ specific service, all you need to do is to derive a class which
+ defines a handle() method.
+
+ The handle() method can find the request as self.request, the
+ client address as self.client_address, and the server (in case it
+ needs access to per-server information) as self.server. Since a
+ separate instance is created for each request, the handle() method
+ can define arbitrary other instance variariables.
+
+ """
+
+ def __init__(self, request, client_address, server):
+ self.request = request
+ self.client_address = client_address
+ self.server = server
+ self.setup()
+ try:
+ self.handle()
+ finally:
+ self.finish()
+
+ def setup(self):
+ pass
+
+ def handle(self):
+ pass
+
+ def finish(self):
+ pass
+
+
+# The following two classes make it possible to use the same service
+# class for stream or datagram servers.
+# Each class sets up these instance variables:
+# - rfile: a file object from which receives the request is read
+# - wfile: a file object to which the reply is written
+# When the handle() method returns, wfile is flushed properly
+
+
+class StreamRequestHandler(BaseRequestHandler):
+
+ """Define self.rfile and self.wfile for stream sockets."""
+
+ # Default buffer sizes for rfile, wfile.
+ # We default rfile to buffered because otherwise it could be
+ # really slow for large data (a getc() call per byte); we make
+ # wfile unbuffered because (a) often after a write() we want to
+ # read and we need to flush the line; (b) big writes to unbuffered
+ # files are typically optimized by stdio even when big reads
+ # aren't.
+ rbufsize = -1
+ wbufsize = 0
+
+ # A timeout to apply to the request socket, if not None.
+ timeout = None
+
+ # Disable nagle algorithm for this socket, if True.
+ # Use only when wbufsize != 0, to avoid small packets.
+ disable_nagle_algorithm = False
+
+ def setup(self):
+ self.connection = self.request
+ if self.timeout is not None:
+ self.connection.settimeout(self.timeout)
+ if self.disable_nagle_algorithm:
+ self.connection.setsockopt(socket.IPPROTO_TCP,
+ socket.TCP_NODELAY, True)
+ self.rfile = self.connection.makefile('rb', self.rbufsize)
+ self.wfile = self.connection.makefile('wb', self.wbufsize)
+
+ def finish(self):
+ if not self.wfile.closed:
+ self.wfile.flush()
+ self.wfile.close()
+ self.rfile.close()
+
+
+class DatagramRequestHandler(BaseRequestHandler):
+
+ # XXX Regrettably, I cannot get this working on Linux;
+ # s.recvfrom() doesn't return a meaningful client address.
+
+ """Define self.rfile and self.wfile for datagram sockets."""
+
+ def setup(self):
+ try:
+ from cStringIO import StringIO
+ except ImportError:
+ from StringIO import StringIO
+ self.packet, self.socket = self.request
+ self.rfile = StringIO(self.packet)
+ self.wfile = StringIO()
+
+ def finish(self):
+ self.socket.sendto(self.wfile.getvalue(), self.client_address)
diff --git a/python/helpers/pydev/_pydev_imps/_pydev_execfile.py b/python/helpers/pydev/_pydev_imps/_pydev_execfile.py
new file mode 100644
index 000000000000..954783c8d085
--- /dev/null
+++ b/python/helpers/pydev/_pydev_imps/_pydev_execfile.py
@@ -0,0 +1,18 @@
+#We must redefine it in Py3k if it's not already there
+def execfile(file, glob=None, loc=None):
+ if glob is None:
+ import sys
+ glob = sys._getframe().f_back.f_globals
+ if loc is None:
+ loc = glob
+
+ # It seems that the best way is using tokenize.open(): http://code.activestate.com/lists/python-dev/131251/
+ import tokenize
+ stream = tokenize.open(file)
+ try:
+ contents = stream.read()
+ finally:
+ stream.close()
+
+ #execute the script (note: it's important to compile first to have the filename set in debug mode)
+ exec(compile(contents+"\n", file, 'exec'), glob, loc) \ No newline at end of file
diff --git a/python/helpers/pydev/_pydev_imps/_pydev_inspect.py b/python/helpers/pydev/_pydev_imps/_pydev_inspect.py
new file mode 100644
index 000000000000..57147644e769
--- /dev/null
+++ b/python/helpers/pydev/_pydev_imps/_pydev_inspect.py
@@ -0,0 +1,794 @@
+"""Get useful information from live Python objects.
+
+This module encapsulates the interface provided by the internal special
+attributes (func_*, co_*, im_*, tb_*, etc.) in a friendlier fashion.
+It also provides some help for examining source code and class layout.
+
+Here are some of the useful functions provided by this module:
+
+ ismodule(), isclass(), ismethod(), isfunction(), istraceback(),
+ isframe(), iscode(), isbuiltin(), isroutine() - check object types
+ getmembers() - get members of an object that satisfy a given condition
+
+ getfile(), getsourcefile(), getsource() - find an object's source code
+ getdoc(), getcomments() - get documentation on an object
+ getmodule() - determine the module that an object came from
+ getclasstree() - arrange classes so as to represent their hierarchy
+
+ getargspec(), getargvalues() - get info about function arguments
+ formatargspec(), formatargvalues() - format an argument spec
+ getouterframes(), getinnerframes() - get info about frames
+ currentframe() - get the current stack frame
+ stack(), trace() - get info about frames on the stack or in a traceback
+"""
+
+# This module is in the public domain. No warranties.
+
+__author__ = 'Ka-Ping Yee <ping@lfw.org>'
+__date__ = '1 Jan 2001'
+
+import sys
+import os
+import types
+import string
+import re
+import imp
+import tokenize
+
+# ----------------------------------------------------------- type-checking
+def ismodule(object):
+ """Return true if the object is a module.
+
+ Module objects provide these attributes:
+ __doc__ documentation string
+ __file__ filename (missing for built-in modules)"""
+ return isinstance(object, types.ModuleType)
+
+def isclass(object):
+ """Return true if the object is a class.
+
+ Class objects provide these attributes:
+ __doc__ documentation string
+ __module__ name of module in which this class was defined"""
+ return isinstance(object, types.ClassType) or hasattr(object, '__bases__')
+
+def ismethod(object):
+ """Return true if the object is an instance method.
+
+ Instance method objects provide these attributes:
+ __doc__ documentation string
+ __name__ name with which this method was defined
+ im_class class object in which this method belongs
+ im_func function object containing implementation of method
+ im_self instance to which this method is bound, or None"""
+ return isinstance(object, types.MethodType)
+
+def ismethoddescriptor(object):
+ """Return true if the object is a method descriptor.
+
+ But not if ismethod() or isclass() or isfunction() are true.
+
+ This is new in Python 2.2, and, for example, is true of int.__add__.
+ An object passing this test has a __get__ attribute but not a __set__
+ attribute, but beyond that the set of attributes varies. __name__ is
+ usually sensible, and __doc__ often is.
+
+ Methods implemented via descriptors that also pass one of the other
+ tests return false from the ismethoddescriptor() test, simply because
+ the other tests promise more -- you can, e.g., count on having the
+ im_func attribute (etc) when an object passes ismethod()."""
+ return (hasattr(object, "__get__")
+ and not hasattr(object, "__set__") # else it's a data descriptor
+ and not ismethod(object) # mutual exclusion
+ and not isfunction(object)
+ and not isclass(object))
+
+def isfunction(object):
+ """Return true if the object is a user-defined function.
+
+ Function objects provide these attributes:
+ __doc__ documentation string
+ __name__ name with which this function was defined
+ func_code code object containing compiled function bytecode
+ func_defaults tuple of any default values for arguments
+ func_doc (same as __doc__)
+ func_globals global namespace in which this function was defined
+ func_name (same as __name__)"""
+ return isinstance(object, types.FunctionType)
+
+def istraceback(object):
+ """Return true if the object is a traceback.
+
+ Traceback objects provide these attributes:
+ tb_frame frame object at this level
+ tb_lasti index of last attempted instruction in bytecode
+ tb_lineno current line number in Python source code
+ tb_next next inner traceback object (called by this level)"""
+ return isinstance(object, types.TracebackType)
+
+def isframe(object):
+ """Return true if the object is a frame object.
+
+ Frame objects provide these attributes:
+ f_back next outer frame object (this frame's caller)
+ f_builtins built-in namespace seen by this frame
+ f_code code object being executed in this frame
+ f_exc_traceback traceback if raised in this frame, or None
+ f_exc_type exception type if raised in this frame, or None
+ f_exc_value exception value if raised in this frame, or None
+ f_globals global namespace seen by this frame
+ f_lasti index of last attempted instruction in bytecode
+ f_lineno current line number in Python source code
+ f_locals local namespace seen by this frame
+ f_restricted 0 or 1 if frame is in restricted execution mode
+ f_trace tracing function for this frame, or None"""
+ return isinstance(object, types.FrameType)
+
+def iscode(object):
+ """Return true if the object is a code object.
+
+ Code objects provide these attributes:
+ co_argcount number of arguments (not including * or ** args)
+ co_code string of raw compiled bytecode
+ co_consts tuple of constants used in the bytecode
+ co_filename name of file in which this code object was created
+ co_firstlineno number of first line in Python source code
+ co_flags bitmap: 1=optimized | 2=newlocals | 4=*arg | 8=**arg
+ co_lnotab encoded mapping of line numbers to bytecode indices
+ co_name name with which this code object was defined
+ co_names tuple of names of local variables
+ co_nlocals number of local variables
+ co_stacksize virtual machine stack space required
+ co_varnames tuple of names of arguments and local variables"""
+ return isinstance(object, types.CodeType)
+
+def isbuiltin(object):
+ """Return true if the object is a built-in function or method.
+
+ Built-in functions and methods provide these attributes:
+ __doc__ documentation string
+ __name__ original name of this function or method
+ __self__ instance to which a method is bound, or None"""
+ return isinstance(object, types.BuiltinFunctionType)
+
+def isroutine(object):
+ """Return true if the object is any kind of function or method."""
+ return (isbuiltin(object)
+ or isfunction(object)
+ or ismethod(object)
+ or ismethoddescriptor(object))
+
+def getmembers(object, predicate=None):
+ """Return all members of an object as (name, value) pairs sorted by name.
+ Optionally, only return members that satisfy a given predicate."""
+ results = []
+ for key in dir(object):
+ value = getattr(object, key)
+ if not predicate or predicate(value):
+ results.append((key, value))
+ results.sort()
+ return results
+
+def classify_class_attrs(cls):
+ """Return list of attribute-descriptor tuples.
+
+ For each name in dir(cls), the return list contains a 4-tuple
+ with these elements:
+
+ 0. The name (a string).
+
+ 1. The kind of attribute this is, one of these strings:
+ 'class method' created via classmethod()
+ 'static method' created via staticmethod()
+ 'property' created via property()
+ 'method' any other flavor of method
+ 'data' not a method
+
+ 2. The class which defined this attribute (a class).
+
+ 3. The object as obtained directly from the defining class's
+ __dict__, not via getattr. This is especially important for
+ data attributes: C.data is just a data object, but
+ C.__dict__['data'] may be a data descriptor with additional
+ info, like a __doc__ string.
+ """
+
+ mro = getmro(cls)
+ names = dir(cls)
+ result = []
+ for name in names:
+ # Get the object associated with the name.
+ # Getting an obj from the __dict__ sometimes reveals more than
+ # using getattr. Static and class methods are dramatic examples.
+ if name in cls.__dict__:
+ obj = cls.__dict__[name]
+ else:
+ obj = getattr(cls, name)
+
+ # Figure out where it was defined.
+ homecls = getattr(obj, "__objclass__", None)
+ if homecls is None:
+ # search the dicts.
+ for base in mro:
+ if name in base.__dict__:
+ homecls = base
+ break
+
+ # Get the object again, in order to get it from the defining
+ # __dict__ instead of via getattr (if possible).
+ if homecls is not None and name in homecls.__dict__:
+ obj = homecls.__dict__[name]
+
+ # Also get the object via getattr.
+ obj_via_getattr = getattr(cls, name)
+
+ # Classify the object.
+ if isinstance(obj, staticmethod):
+ kind = "static method"
+ elif isinstance(obj, classmethod):
+ kind = "class method"
+ elif isinstance(obj, property):
+ kind = "property"
+ elif (ismethod(obj_via_getattr) or
+ ismethoddescriptor(obj_via_getattr)):
+ kind = "method"
+ else:
+ kind = "data"
+
+ result.append((name, kind, homecls, obj))
+
+ return result
+
+# ----------------------------------------------------------- class helpers
+def _searchbases(cls, accum):
+ # Simulate the "classic class" search order.
+ if cls in accum:
+ return
+ accum.append(cls)
+ for base in cls.__bases__:
+ _searchbases(base, accum)
+
+def getmro(cls):
+ "Return tuple of base classes (including cls) in method resolution order."
+ if hasattr(cls, "__mro__"):
+ return cls.__mro__
+ else:
+ result = []
+ _searchbases(cls, result)
+ return tuple(result)
+
+# -------------------------------------------------- source code extraction
+def indentsize(line):
+ """Return the indent size, in spaces, at the start of a line of text."""
+ expline = string.expandtabs(line)
+ return len(expline) - len(string.lstrip(expline))
+
+def getdoc(object):
+ """Get the documentation string for an object.
+
+ All tabs are expanded to spaces. To clean up docstrings that are
+ indented to line up with blocks of code, any whitespace than can be
+ uniformly removed from the second line onwards is removed."""
+ try:
+ doc = object.__doc__
+ except AttributeError:
+ return None
+ if not isinstance(doc, (str, unicode)):
+ return None
+ try:
+ lines = string.split(string.expandtabs(doc), '\n')
+ except UnicodeError:
+ return None
+ else:
+ margin = None
+ for line in lines[1:]:
+ content = len(string.lstrip(line))
+ if not content: continue
+ indent = len(line) - content
+ if margin is None: margin = indent
+ else: margin = min(margin, indent)
+ if margin is not None:
+ for i in range(1, len(lines)): lines[i] = lines[i][margin:]
+ return string.join(lines, '\n')
+
+def getfile(object):
+ """Work out which source or compiled file an object was defined in."""
+ if ismodule(object):
+ if hasattr(object, '__file__'):
+ return object.__file__
+ raise TypeError, 'arg is a built-in module'
+ if isclass(object):
+ object = sys.modules.get(object.__module__)
+ if hasattr(object, '__file__'):
+ return object.__file__
+ raise TypeError, 'arg is a built-in class'
+ if ismethod(object):
+ object = object.im_func
+ if isfunction(object):
+ object = object.func_code
+ if istraceback(object):
+ object = object.tb_frame
+ if isframe(object):
+ object = object.f_code
+ if iscode(object):
+ return object.co_filename
+ raise TypeError, 'arg is not a module, class, method, ' \
+ 'function, traceback, frame, or code object'
+
+def getmoduleinfo(path):
+ """Get the module name, suffix, mode, and module type for a given file."""
+ filename = os.path.basename(path)
+ suffixes = map(lambda (suffix, mode, mtype):
+ (-len(suffix), suffix, mode, mtype), imp.get_suffixes())
+ suffixes.sort() # try longest suffixes first, in case they overlap
+ for neglen, suffix, mode, mtype in suffixes:
+ if filename[neglen:] == suffix:
+ return filename[:neglen], suffix, mode, mtype
+
+def getmodulename(path):
+ """Return the module name for a given file, or None."""
+ info = getmoduleinfo(path)
+ if info: return info[0]
+
+def getsourcefile(object):
+ """Return the Python source file an object was defined in, if it exists."""
+ filename = getfile(object)
+ if string.lower(filename[-4:]) in ['.pyc', '.pyo']:
+ filename = filename[:-4] + '.py'
+ for suffix, mode, kind in imp.get_suffixes():
+ if 'b' in mode and string.lower(filename[-len(suffix):]) == suffix:
+ # Looks like a binary file. We want to only return a text file.
+ return None
+ if os.path.exists(filename):
+ return filename
+
+def getabsfile(object):
+ """Return an absolute path to the source or compiled file for an object.
+
+ The idea is for each object to have a unique origin, so this routine
+ normalizes the result as much as possible."""
+ return os.path.normcase(
+ os.path.abspath(getsourcefile(object) or getfile(object)))
+
+modulesbyfile = {}
+
+def getmodule(object):
+ """Return the module an object was defined in, or None if not found."""
+ if ismodule(object):
+ return object
+ if isclass(object):
+ return sys.modules.get(object.__module__)
+ try:
+ file = getabsfile(object)
+ except TypeError:
+ return None
+ if modulesbyfile.has_key(file):
+ return sys.modules[modulesbyfile[file]]
+ for module in sys.modules.values():
+ if hasattr(module, '__file__'):
+ modulesbyfile[getabsfile(module)] = module.__name__
+ if modulesbyfile.has_key(file):
+ return sys.modules[modulesbyfile[file]]
+ main = sys.modules['__main__']
+ if hasattr(main, object.__name__):
+ mainobject = getattr(main, object.__name__)
+ if mainobject is object:
+ return main
+ builtin = sys.modules['__builtin__']
+ if hasattr(builtin, object.__name__):
+ builtinobject = getattr(builtin, object.__name__)
+ if builtinobject is object:
+ return builtin
+
+def findsource(object):
+ """Return the entire source file and starting line number for an object.
+
+ The argument may be a module, class, method, function, traceback, frame,
+ or code object. The source code is returned as a list of all the lines
+ in the file and the line number indexes a line in that list. An IOError
+ is raised if the source code cannot be retrieved."""
+ try:
+ file = open(getsourcefile(object))
+ except (TypeError, IOError):
+ raise IOError, 'could not get source code'
+ lines = file.readlines()
+ file.close()
+
+ if ismodule(object):
+ return lines, 0
+
+ if isclass(object):
+ name = object.__name__
+ pat = re.compile(r'^\s*class\s*' + name + r'\b')
+ for i in range(len(lines)):
+ if pat.match(lines[i]): return lines, i
+ else: raise IOError, 'could not find class definition'
+
+ if ismethod(object):
+ object = object.im_func
+ if isfunction(object):
+ object = object.func_code
+ if istraceback(object):
+ object = object.tb_frame
+ if isframe(object):
+ object = object.f_code
+ if iscode(object):
+ if not hasattr(object, 'co_firstlineno'):
+ raise IOError, 'could not find function definition'
+ lnum = object.co_firstlineno - 1
+ pat = re.compile(r'^(\s*def\s)|(.*\slambda(:|\s))')
+ while lnum > 0:
+ if pat.match(lines[lnum]): break
+ lnum = lnum - 1
+ return lines, lnum
+ raise IOError, 'could not find code object'
+
+def getcomments(object):
+ """Get lines of comments immediately preceding an object's source code."""
+ try: lines, lnum = findsource(object)
+ except IOError: return None
+
+ if ismodule(object):
+ # Look for a comment block at the top of the file.
+ start = 0
+ if lines and lines[0][:2] == '#!': start = 1
+ while start < len(lines) and string.strip(lines[start]) in ['', '#']:
+ start = start + 1
+ if start < len(lines) and lines[start][:1] == '#':
+ comments = []
+ end = start
+ while end < len(lines) and lines[end][:1] == '#':
+ comments.append(string.expandtabs(lines[end]))
+ end = end + 1
+ return string.join(comments, '')
+
+ # Look for a preceding block of comments at the same indentation.
+ elif lnum > 0:
+ indent = indentsize(lines[lnum])
+ end = lnum - 1
+ if end >= 0 and string.lstrip(lines[end])[:1] == '#' and \
+ indentsize(lines[end]) == indent:
+ comments = [string.lstrip(string.expandtabs(lines[end]))]
+ if end > 0:
+ end = end - 1
+ comment = string.lstrip(string.expandtabs(lines[end]))
+ while comment[:1] == '#' and indentsize(lines[end]) == indent:
+ comments[:0] = [comment]
+ end = end - 1
+ if end < 0: break
+ comment = string.lstrip(string.expandtabs(lines[end]))
+ while comments and string.strip(comments[0]) == '#':
+ comments[:1] = []
+ while comments and string.strip(comments[-1]) == '#':
+ comments[-1:] = []
+ return string.join(comments, '')
+
+class ListReader:
+ """Provide a readline() method to return lines from a list of strings."""
+ def __init__(self, lines):
+ self.lines = lines
+ self.index = 0
+
+ def readline(self):
+ i = self.index
+ if i < len(self.lines):
+ self.index = i + 1
+ return self.lines[i]
+ else: return ''
+
+class EndOfBlock(Exception): pass
+
+class BlockFinder:
+ """Provide a tokeneater() method to detect the end of a code block."""
+ def __init__(self):
+ self.indent = 0
+ self.started = 0
+ self.last = 0
+
+ def tokeneater(self, type, token, (srow, scol), (erow, ecol), line):
+ if not self.started:
+ if type == tokenize.NAME: self.started = 1
+ elif type == tokenize.NEWLINE:
+ self.last = srow
+ elif type == tokenize.INDENT:
+ self.indent = self.indent + 1
+ elif type == tokenize.DEDENT:
+ self.indent = self.indent - 1
+ if self.indent == 0: raise EndOfBlock, self.last
+ elif type == tokenize.NAME and scol == 0:
+ raise EndOfBlock, self.last
+
+def getblock(lines):
+ """Extract the block of code at the top of the given list of lines."""
+ try:
+ tokenize.tokenize(ListReader(lines).readline, BlockFinder().tokeneater)
+ except EndOfBlock, eob:
+ return lines[:eob.args[0]]
+ # Fooling the indent/dedent logic implies a one-line definition
+ return lines[:1]
+
+def getsourcelines(object):
+ """Return a list of source lines and starting line number for an object.
+
+ The argument may be a module, class, method, function, traceback, frame,
+ or code object. The source code is returned as a list of the lines
+ corresponding to the object and the line number indicates where in the
+ original source file the first line of code was found. An IOError is
+ raised if the source code cannot be retrieved."""
+ lines, lnum = findsource(object)
+
+ if ismodule(object): return lines, 0
+ else: return getblock(lines[lnum:]), lnum + 1
+
+def getsource(object):
+ """Return the text of the source code for an object.
+
+ The argument may be a module, class, method, function, traceback, frame,
+ or code object. The source code is returned as a single string. An
+ IOError is raised if the source code cannot be retrieved."""
+ lines, lnum = getsourcelines(object)
+ return string.join(lines, '')
+
+# --------------------------------------------------- class tree extraction
+def walktree(classes, children, parent):
+ """Recursive helper function for getclasstree()."""
+ results = []
+ classes.sort(lambda a, b: cmp(a.__name__, b.__name__))
+ for c in classes:
+ results.append((c, c.__bases__))
+ if children.has_key(c):
+ results.append(walktree(children[c], children, c))
+ return results
+
+def getclasstree(classes, unique=0):
+ """Arrange the given list of classes into a hierarchy of nested lists.
+
+ Where a nested list appears, it contains classes derived from the class
+ whose entry immediately precedes the list. Each entry is a 2-tuple
+ containing a class and a tuple of its base classes. If the 'unique'
+ argument is true, exactly one entry appears in the returned structure
+ for each class in the given list. Otherwise, classes using multiple
+ inheritance and their descendants will appear multiple times."""
+ children = {}
+ roots = []
+ for c in classes:
+ if c.__bases__:
+ for parent in c.__bases__:
+ if not children.has_key(parent):
+ children[parent] = []
+ children[parent].append(c)
+ if unique and parent in classes: break
+ elif c not in roots:
+ roots.append(c)
+ for parent in children.keys():
+ if parent not in classes:
+ roots.append(parent)
+ return walktree(roots, children, None)
+
+# ------------------------------------------------ argument list extraction
+# These constants are from Python's compile.h.
+CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS, CO_VARKEYWORDS = 1, 2, 4, 8
+
+def getargs(co):
+ """Get information about the arguments accepted by a code object.
+
+ Three things are returned: (args, varargs, varkw), where 'args' is
+ a list of argument names (possibly containing nested lists), and
+ 'varargs' and 'varkw' are the names of the * and ** arguments or None."""
+ if not iscode(co): raise TypeError, 'arg is not a code object'
+
+ nargs = co.co_argcount
+ names = co.co_varnames
+ args = list(names[:nargs])
+ step = 0
+
+ # The following acrobatics are for anonymous (tuple) arguments.
+ if not sys.platform.startswith('java'):#Jython doesn't have co_code
+ code = co.co_code
+ import dis
+ for i in range(nargs):
+ if args[i][:1] in ['', '.']:
+ stack, remain, count = [], [], []
+ while step < len(code):
+ op = ord(code[step])
+ step = step + 1
+ if op >= dis.HAVE_ARGUMENT:
+ opname = dis.opname[op]
+ value = ord(code[step]) + ord(code[step + 1]) * 256
+ step = step + 2
+ if opname in ['UNPACK_TUPLE', 'UNPACK_SEQUENCE']:
+ remain.append(value)
+ count.append(value)
+ elif opname == 'STORE_FAST':
+ stack.append(names[value])
+ remain[-1] = remain[-1] - 1
+ while remain[-1] == 0:
+ remain.pop()
+ size = count.pop()
+ stack[-size:] = [stack[-size:]]
+ if not remain: break
+ remain[-1] = remain[-1] - 1
+ if not remain: break
+ args[i] = stack[0]
+
+ varargs = None
+ if co.co_flags & CO_VARARGS:
+ varargs = co.co_varnames[nargs]
+ nargs = nargs + 1
+ varkw = None
+ if co.co_flags & CO_VARKEYWORDS:
+ varkw = co.co_varnames[nargs]
+ return args, varargs, varkw
+
+def getargspec(func):
+ """Get the names and default values of a function's arguments.
+
+ A tuple of four things is returned: (args, varargs, varkw, defaults).
+ 'args' is a list of the argument names (it may contain nested lists).
+ 'varargs' and 'varkw' are the names of the * and ** arguments or None.
+ 'defaults' is an n-tuple of the default values of the last n arguments."""
+ if ismethod(func):
+ func = func.im_func
+ if not isfunction(func): raise TypeError, 'arg is not a Python function'
+ args, varargs, varkw = getargs(func.func_code)
+ return args, varargs, varkw, func.func_defaults
+
+def getargvalues(frame):
+ """Get information about arguments passed into a particular frame.
+
+ A tuple of four things is returned: (args, varargs, varkw, locals).
+ 'args' is a list of the argument names (it may contain nested lists).
+ 'varargs' and 'varkw' are the names of the * and ** arguments or None.
+ 'locals' is the locals dictionary of the given frame."""
+ args, varargs, varkw = getargs(frame.f_code)
+ return args, varargs, varkw, frame.f_locals
+
+def joinseq(seq):
+ if len(seq) == 1:
+ return '(' + seq[0] + ',)'
+ else:
+ return '(' + string.join(seq, ', ') + ')'
+
+def strseq(object, convert, join=joinseq):
+ """Recursively walk a sequence, stringifying each element."""
+ if type(object) in [types.ListType, types.TupleType]:
+ return join(map(lambda o, c=convert, j=join: strseq(o, c, j), object))
+ else:
+ return convert(object)
+
+def formatargspec(args, varargs=None, varkw=None, defaults=None,
+ formatarg=str,
+ formatvarargs=lambda name: '*' + name,
+ formatvarkw=lambda name: '**' + name,
+ formatvalue=lambda value: '=' + repr(value),
+ join=joinseq):
+ """Format an argument spec from the 4 values returned by getargspec.
+
+ The first four arguments are (args, varargs, varkw, defaults). The
+ other four arguments are the corresponding optional formatting functions
+ that are called to turn names and values into strings. The ninth
+ argument is an optional function to format the sequence of arguments."""
+ specs = []
+ if defaults:
+ firstdefault = len(args) - len(defaults)
+ for i in range(len(args)):
+ spec = strseq(args[i], formatarg, join)
+ if defaults and i >= firstdefault:
+ spec = spec + formatvalue(defaults[i - firstdefault])
+ specs.append(spec)
+ if varargs:
+ specs.append(formatvarargs(varargs))
+ if varkw:
+ specs.append(formatvarkw(varkw))
+ return '(' + string.join(specs, ', ') + ')'
+
+def formatargvalues(args, varargs, varkw, locals,
+ formatarg=str,
+ formatvarargs=lambda name: '*' + name,
+ formatvarkw=lambda name: '**' + name,
+ formatvalue=lambda value: '=' + repr(value),
+ join=joinseq):
+ """Format an argument spec from the 4 values returned by getargvalues.
+
+ The first four arguments are (args, varargs, varkw, locals). The
+ next four arguments are the corresponding optional formatting functions
+ that are called to turn names and values into strings. The ninth
+ argument is an optional function to format the sequence of arguments."""
+ def convert(name, locals=locals,
+ formatarg=formatarg, formatvalue=formatvalue):
+ return formatarg(name) + formatvalue(locals[name])
+ specs = []
+ for i in range(len(args)):
+ specs.append(strseq(args[i], convert, join))
+ if varargs:
+ specs.append(formatvarargs(varargs) + formatvalue(locals[varargs]))
+ if varkw:
+ specs.append(formatvarkw(varkw) + formatvalue(locals[varkw]))
+ return '(' + string.join(specs, ', ') + ')'
+
+# -------------------------------------------------- stack frame extraction
+def getframeinfo(frame, context=1):
+ """Get information about a frame or traceback object.
+
+ A tuple of five things is returned: the filename, the line number of
+ the current line, the function name, a list of lines of context from
+ the source code, and the index of the current line within that list.
+ The optional second argument specifies the number of lines of context
+ to return, which are centered around the current line."""
+ raise NotImplementedError
+# if istraceback(frame):
+# frame = frame.tb_frame
+# if not isframe(frame):
+# raise TypeError, 'arg is not a frame or traceback object'
+#
+# filename = getsourcefile(frame)
+# lineno = getlineno(frame)
+# if context > 0:
+# start = lineno - 1 - context//2
+# try:
+# lines, lnum = findsource(frame)
+# except IOError:
+# lines = index = None
+# else:
+# start = max(start, 1)
+# start = min(start, len(lines) - context)
+# lines = lines[start:start+context]
+# index = lineno - 1 - start
+# else:
+# lines = index = None
+#
+# return (filename, lineno, frame.f_code.co_name, lines, index)
+
+def getlineno(frame):
+ """Get the line number from a frame object, allowing for optimization."""
+ # Written by Marc-Andr Lemburg; revised by Jim Hugunin and Fredrik Lundh.
+ lineno = frame.f_lineno
+ code = frame.f_code
+ if hasattr(code, 'co_lnotab'):
+ table = code.co_lnotab
+ lineno = code.co_firstlineno
+ addr = 0
+ for i in range(0, len(table), 2):
+ addr = addr + ord(table[i])
+ if addr > frame.f_lasti: break
+ lineno = lineno + ord(table[i + 1])
+ return lineno
+
+def getouterframes(frame, context=1):
+ """Get a list of records for a frame and all higher (calling) frames.
+
+ Each record contains a frame object, filename, line number, function
+ name, a list of lines of context, and index within the context."""
+ framelist = []
+ while frame:
+ framelist.append((frame,) + getframeinfo(frame, context))
+ frame = frame.f_back
+ return framelist
+
+def getinnerframes(tb, context=1):
+ """Get a list of records for a traceback's frame and all lower frames.
+
+ Each record contains a frame object, filename, line number, function
+ name, a list of lines of context, and index within the context."""
+ framelist = []
+ while tb:
+ framelist.append((tb.tb_frame,) + getframeinfo(tb, context))
+ tb = tb.tb_next
+ return framelist
+
+def currentframe():
+ """Return the frame object for the caller's stack frame."""
+ try:
+ raise 'catch me'
+ except:
+ return sys.exc_traceback.tb_frame.f_back #@UndefinedVariable
+
+if hasattr(sys, '_getframe'): currentframe = sys._getframe
+
+def stack(context=1):
+ """Return a list of records for the stack above the caller's frame."""
+ return getouterframes(currentframe().f_back, context)
+
+def trace(context=1):
+ """Return a list of records for the stack below the current exception."""
+ return getinnerframes(sys.exc_traceback, context) #@UndefinedVariable
diff --git a/python/helpers/pydev/_pydev_imps/_pydev_select.py b/python/helpers/pydev/_pydev_imps/_pydev_select.py
new file mode 100644
index 000000000000..b8dad03cc984
--- /dev/null
+++ b/python/helpers/pydev/_pydev_imps/_pydev_select.py
@@ -0,0 +1 @@
+from select import * \ No newline at end of file
diff --git a/python/helpers/pydev/_pydev_imps/_pydev_socket.py b/python/helpers/pydev/_pydev_imps/_pydev_socket.py
new file mode 100644
index 000000000000..9e96e800876c
--- /dev/null
+++ b/python/helpers/pydev/_pydev_imps/_pydev_socket.py
@@ -0,0 +1 @@
+from socket import * \ No newline at end of file
diff --git a/python/helpers/pydev/_pydev_imps/_pydev_thread.py b/python/helpers/pydev/_pydev_imps/_pydev_thread.py
new file mode 100644
index 000000000000..4d2fd5d8cf91
--- /dev/null
+++ b/python/helpers/pydev/_pydev_imps/_pydev_thread.py
@@ -0,0 +1,4 @@
+try:
+ from thread import *
+except:
+ from _thread import * #Py3k
diff --git a/python/helpers/pydev/_pydev_imps/_pydev_time.py b/python/helpers/pydev/_pydev_imps/_pydev_time.py
new file mode 100644
index 000000000000..72705db20bdc
--- /dev/null
+++ b/python/helpers/pydev/_pydev_imps/_pydev_time.py
@@ -0,0 +1 @@
+from time import *
diff --git a/python/helpers/pydev/_pydev_imps/_pydev_xmlrpclib.py b/python/helpers/pydev/_pydev_imps/_pydev_xmlrpclib.py
new file mode 100644
index 000000000000..5f6e2b7f138c
--- /dev/null
+++ b/python/helpers/pydev/_pydev_imps/_pydev_xmlrpclib.py
@@ -0,0 +1,1493 @@
+#Just a copy of the version in python 2.5 to be used if it's not available in jython 2.1
+import sys
+
+#
+# XML-RPC CLIENT LIBRARY
+#
+# an XML-RPC client interface for Python.
+#
+# the marshalling and response parser code can also be used to
+# implement XML-RPC servers.
+#
+# Notes:
+# this version is designed to work with Python 2.1 or newer.
+#
+# History:
+# 1999-01-14 fl Created
+# 1999-01-15 fl Changed dateTime to use localtime
+# 1999-01-16 fl Added Binary/base64 element, default to RPC2 service
+# 1999-01-19 fl Fixed array data element (from Skip Montanaro)
+# 1999-01-21 fl Fixed dateTime constructor, etc.
+# 1999-02-02 fl Added fault handling, handle empty sequences, etc.
+# 1999-02-10 fl Fixed problem with empty responses (from Skip Montanaro)
+# 1999-06-20 fl Speed improvements, pluggable parsers/transports (0.9.8)
+# 2000-11-28 fl Changed boolean to check the truth value of its argument
+# 2001-02-24 fl Added encoding/Unicode/SafeTransport patches
+# 2001-02-26 fl Added compare support to wrappers (0.9.9/1.0b1)
+# 2001-03-28 fl Make sure response tuple is a singleton
+# 2001-03-29 fl Don't require empty params element (from Nicholas Riley)
+# 2001-06-10 fl Folded in _xmlrpclib accelerator support (1.0b2)
+# 2001-08-20 fl Base xmlrpclib.Error on built-in Exception (from Paul Prescod)
+# 2001-09-03 fl Allow Transport subclass to override getparser
+# 2001-09-10 fl Lazy import of urllib, cgi, xmllib (20x import speedup)
+# 2001-10-01 fl Remove containers from memo cache when done with them
+# 2001-10-01 fl Use faster escape method (80% dumps speedup)
+# 2001-10-02 fl More dumps microtuning
+# 2001-10-04 fl Make sure import expat gets a parser (from Guido van Rossum)
+# 2001-10-10 sm Allow long ints to be passed as ints if they don't overflow
+# 2001-10-17 sm Test for int and long overflow (allows use on 64-bit systems)
+# 2001-11-12 fl Use repr() to marshal doubles (from Paul Felix)
+# 2002-03-17 fl Avoid buffered read when possible (from James Rucker)
+# 2002-04-07 fl Added pythondoc comments
+# 2002-04-16 fl Added __str__ methods to datetime/binary wrappers
+# 2002-05-15 fl Added error constants (from Andrew Kuchling)
+# 2002-06-27 fl Merged with Python CVS version
+# 2002-10-22 fl Added basic authentication (based on code from Phillip Eby)
+# 2003-01-22 sm Add support for the bool type
+# 2003-02-27 gvr Remove apply calls
+# 2003-04-24 sm Use cStringIO if available
+# 2003-04-25 ak Add support for nil
+# 2003-06-15 gn Add support for time.struct_time
+# 2003-07-12 gp Correct marshalling of Faults
+# 2003-10-31 mvl Add multicall support
+# 2004-08-20 mvl Bump minimum supported Python version to 2.1
+#
+# Copyright (c) 1999-2002 by Secret Labs AB.
+# Copyright (c) 1999-2002 by Fredrik Lundh.
+#
+# info@pythonware.com
+# http://www.pythonware.com
+#
+# --------------------------------------------------------------------
+# The XML-RPC client interface is
+#
+# Copyright (c) 1999-2002 by Secret Labs AB
+# Copyright (c) 1999-2002 by Fredrik Lundh
+#
+# By obtaining, using, and/or copying this software and/or its
+# associated documentation, you agree that you have read, understood,
+# and will comply with the following terms and conditions:
+#
+# Permission to use, copy, modify, and distribute this software and
+# its associated documentation for any purpose and without fee is
+# hereby granted, provided that the above copyright notice appears in
+# all copies, and that both that copyright notice and this permission
+# notice appear in supporting documentation, and that the name of
+# Secret Labs AB or the author not be used in advertising or publicity
+# pertaining to distribution of the software without specific, written
+# prior permission.
+#
+# SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-
+# ABILITY AND FITNESS. IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR
+# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+# --------------------------------------------------------------------
+
+#
+# things to look into some day:
+
+# TODO: sort out True/False/boolean issues for Python 2.3
+
+"""
+An XML-RPC client interface for Python.
+
+The marshalling and response parser code can also be used to
+implement XML-RPC servers.
+
+Exported exceptions:
+
+ Error Base class for client errors
+ ProtocolError Indicates an HTTP protocol error
+ ResponseError Indicates a broken response package
+ Fault Indicates an XML-RPC fault package
+
+Exported classes:
+
+ ServerProxy Represents a logical connection to an XML-RPC server
+
+ MultiCall Executor of boxcared xmlrpc requests
+ Boolean boolean wrapper to generate a "boolean" XML-RPC value
+ DateTime dateTime wrapper for an ISO 8601 string or time tuple or
+ localtime integer value to generate a "dateTime.iso8601"
+ XML-RPC value
+ Binary binary data wrapper
+
+ SlowParser Slow but safe standard parser (based on xmllib)
+ Marshaller Generate an XML-RPC params chunk from a Python data structure
+ Unmarshaller Unmarshal an XML-RPC response from incoming XML event message
+ Transport Handles an HTTP transaction to an XML-RPC server
+ SafeTransport Handles an HTTPS transaction to an XML-RPC server
+
+Exported constants:
+
+ True
+ False
+
+Exported functions:
+
+ boolean Convert any Python value to an XML-RPC boolean
+ getparser Create instance of the fastest available parser & attach
+ to an unmarshalling object
+ dumps Convert an argument tuple or a Fault instance to an XML-RPC
+ request (or response, if the methodresponse option is used).
+ loads Convert an XML-RPC packet to unmarshalled data plus a method
+ name (None if not present).
+"""
+
+import re, string, time, operator
+
+from types import *
+
+# --------------------------------------------------------------------
+# Internal stuff
+
+try:
+ unicode
+except NameError:
+ unicode = None # unicode support not available
+
+try:
+ import datetime
+except ImportError:
+ datetime = None
+
+try:
+ _bool_is_builtin = False.__class__.__name__ == "bool"
+except (NameError, AttributeError):
+ _bool_is_builtin = 0
+
+def _decode(data, encoding, is8bit=re.compile("[\x80-\xff]").search):
+ # decode non-ascii string (if possible)
+ if unicode and encoding and is8bit(data):
+ data = unicode(data, encoding)
+ return data
+
+def escape(s, replace=string.replace):
+ s = replace(s, "&", "&amp;")
+ s = replace(s, "<", "&lt;")
+ return replace(s, ">", "&gt;",)
+
+if unicode:
+ def _stringify(string):
+ # convert to 7-bit ascii if possible
+ try:
+ return string.encode("ascii")
+ except UnicodeError:
+ return string
+else:
+ def _stringify(string):
+ return string
+
+__version__ = "1.0.1"
+
+# xmlrpc integer limits
+try:
+ long
+except NameError:
+ long = int
+MAXINT = long(2) ** 31 - 1
+MININT = long(-2) ** 31
+
+# --------------------------------------------------------------------
+# Error constants (from Dan Libby's specification at
+# http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php)
+
+# Ranges of errors
+PARSE_ERROR = -32700
+SERVER_ERROR = -32600
+APPLICATION_ERROR = -32500
+SYSTEM_ERROR = -32400
+TRANSPORT_ERROR = -32300
+
+# Specific errors
+NOT_WELLFORMED_ERROR = -32700
+UNSUPPORTED_ENCODING = -32701
+INVALID_ENCODING_CHAR = -32702
+INVALID_XMLRPC = -32600
+METHOD_NOT_FOUND = -32601
+INVALID_METHOD_PARAMS = -32602
+INTERNAL_ERROR = -32603
+
+# --------------------------------------------------------------------
+# Exceptions
+
+##
+# Base class for all kinds of client-side errors.
+
+class Error(Exception):
+ """Base class for client errors."""
+ def __str__(self):
+ return repr(self)
+
+##
+# Indicates an HTTP-level protocol error. This is raised by the HTTP
+# transport layer, if the server returns an error code other than 200
+# (OK).
+#
+# @param url The target URL.
+# @param errcode The HTTP error code.
+# @param errmsg The HTTP error message.
+# @param headers The HTTP header dictionary.
+
+class ProtocolError(Error):
+ """Indicates an HTTP protocol error."""
+ def __init__(self, url, errcode, errmsg, headers):
+ Error.__init__(self)
+ self.url = url
+ self.errcode = errcode
+ self.errmsg = errmsg
+ self.headers = headers
+ def __repr__(self):
+ return (
+ "<ProtocolError for %s: %s %s>" %
+ (self.url, self.errcode, self.errmsg)
+ )
+
+##
+# Indicates a broken XML-RPC response package. This exception is
+# raised by the unmarshalling layer, if the XML-RPC response is
+# malformed.
+
+class ResponseError(Error):
+ """Indicates a broken response package."""
+ pass
+
+##
+# Indicates an XML-RPC fault response package. This exception is
+# raised by the unmarshalling layer, if the XML-RPC response contains
+# a fault string. This exception can also used as a class, to
+# generate a fault XML-RPC message.
+#
+# @param faultCode The XML-RPC fault code.
+# @param faultString The XML-RPC fault string.
+
+class Fault(Error):
+ """Indicates an XML-RPC fault package."""
+ def __init__(self, faultCode, faultString, **extra):
+ Error.__init__(self)
+ self.faultCode = faultCode
+ self.faultString = faultString
+ def __repr__(self):
+ return (
+ "<Fault %s: %s>" %
+ (self.faultCode, repr(self.faultString))
+ )
+
+# --------------------------------------------------------------------
+# Special values
+
+##
+# Wrapper for XML-RPC boolean values. Use the xmlrpclib.True and
+# xmlrpclib.False constants, or the xmlrpclib.boolean() function, to
+# generate boolean XML-RPC values.
+#
+# @param value A boolean value. Any true value is interpreted as True,
+# all other values are interpreted as False.
+
+if _bool_is_builtin:
+ boolean = Boolean = bool #@UndefinedVariable
+ # to avoid breaking code which references xmlrpclib.{True,False}
+ True, False = True, False
+else:
+ class Boolean:
+ """Boolean-value wrapper.
+
+ Use True or False to generate a "boolean" XML-RPC value.
+ """
+
+ def __init__(self, value=0):
+ self.value = operator.truth(value)
+
+ def encode(self, out):
+ out.write("<value><boolean>%d</boolean></value>\n" % self.value)
+
+ def __cmp__(self, other):
+ if isinstance(other, Boolean):
+ other = other.value
+ return cmp(self.value, other)
+
+ def __repr__(self):
+ if self.value:
+ return "<Boolean True at %x>" % id(self)
+ else:
+ return "<Boolean False at %x>" % id(self)
+
+ def __int__(self):
+ return self.value
+
+ def __nonzero__(self):
+ return self.value
+
+ True, False = Boolean(1), Boolean(0)
+
+ ##
+ # Map true or false value to XML-RPC boolean values.
+ #
+ # @def boolean(value)
+ # @param value A boolean value. Any true value is mapped to True,
+ # all other values are mapped to False.
+ # @return xmlrpclib.True or xmlrpclib.False.
+ # @see Boolean
+ # @see True
+ # @see False
+
+ def boolean(value, _truefalse=(False, True)):
+ """Convert any Python value to XML-RPC 'boolean'."""
+ return _truefalse[operator.truth(value)]
+
+##
+# Wrapper for XML-RPC DateTime values. This converts a time value to
+# the format used by XML-RPC.
+# <p>
+# The value can be given as a string in the format
+# "yyyymmddThh:mm:ss", as a 9-item time tuple (as returned by
+# time.localtime()), or an integer value (as returned by time.time()).
+# The wrapper uses time.localtime() to convert an integer to a time
+# tuple.
+#
+# @param value The time, given as an ISO 8601 string, a time
+# tuple, or a integer time value.
+
+class DateTime:
+ """DateTime wrapper for an ISO 8601 string or time tuple or
+ localtime integer value to generate 'dateTime.iso8601' XML-RPC
+ value.
+ """
+
+ def __init__(self, value=0):
+ if not isinstance(value, StringType):
+ if datetime and isinstance(value, datetime.datetime):
+ self.value = value.strftime("%Y%m%dT%H:%M:%S")
+ return
+ if datetime and isinstance(value, datetime.date):
+ self.value = value.strftime("%Y%m%dT%H:%M:%S")
+ return
+ if datetime and isinstance(value, datetime.time):
+ today = datetime.datetime.now().strftime("%Y%m%d")
+ self.value = value.strftime(today + "T%H:%M:%S")
+ return
+ if not isinstance(value, (TupleType, time.struct_time)): #@UndefinedVariable
+ if value == 0:
+ value = time.time()
+ value = time.localtime(value)
+ value = time.strftime("%Y%m%dT%H:%M:%S", value)
+ self.value = value
+
+ def __cmp__(self, other):
+ if isinstance(other, DateTime):
+ other = other.value
+ return cmp(self.value, other)
+
+ ##
+ # Get date/time value.
+ #
+ # @return Date/time value, as an ISO 8601 string.
+
+ def __str__(self):
+ return self.value
+
+ def __repr__(self):
+ return "<DateTime %s at %x>" % (repr(self.value), id(self))
+
+ def decode(self, data):
+ data = str(data)
+ self.value = string.strip(data)
+
+ def encode(self, out):
+ out.write("<value><dateTime.iso8601>")
+ out.write(self.value)
+ out.write("</dateTime.iso8601></value>\n")
+
+def _datetime(data):
+ # decode xml element contents into a DateTime structure.
+ value = DateTime()
+ value.decode(data)
+ return value
+
+def _datetime_type(data):
+ t = time.strptime(data, "%Y%m%dT%H:%M:%S") #@UndefinedVariable
+ return datetime.datetime(*tuple(t)[:6])
+
+##
+# Wrapper for binary data. This can be used to transport any kind
+# of binary data over XML-RPC, using BASE64 encoding.
+#
+# @param data An 8-bit string containing arbitrary data.
+
+import base64
+try:
+ import cStringIO as StringIO
+except ImportError:
+ import StringIO
+
+class Binary:
+ """Wrapper for binary data."""
+
+ def __init__(self, data=None):
+ self.data = data
+
+ ##
+ # Get buffer contents.
+ #
+ # @return Buffer contents, as an 8-bit string.
+
+ def __str__(self):
+ return self.data or ""
+
+ def __cmp__(self, other):
+ if isinstance(other, Binary):
+ other = other.data
+ return cmp(self.data, other)
+
+ def decode(self, data):
+ self.data = base64.decodestring(data)
+
+ def encode(self, out):
+ out.write("<value><base64>\n")
+ base64.encode(StringIO.StringIO(self.data), out)
+ out.write("</base64></value>\n")
+
+def _binary(data):
+ # decode xml element contents into a Binary structure
+ value = Binary()
+ value.decode(data)
+ return value
+
+WRAPPERS = (DateTime, Binary)
+if not _bool_is_builtin:
+ WRAPPERS = WRAPPERS + (Boolean,)
+
+# --------------------------------------------------------------------
+# XML parsers
+
+try:
+ # optional xmlrpclib accelerator
+ import _xmlrpclib #@UnresolvedImport
+ FastParser = _xmlrpclib.Parser
+ FastUnmarshaller = _xmlrpclib.Unmarshaller
+except (AttributeError, ImportError):
+ FastParser = FastUnmarshaller = None
+
+try:
+ import _xmlrpclib #@UnresolvedImport
+ FastMarshaller = _xmlrpclib.Marshaller
+except (AttributeError, ImportError):
+ FastMarshaller = None
+
+#
+# the SGMLOP parser is about 15x faster than Python's builtin
+# XML parser. SGMLOP sources can be downloaded from:
+#
+# http://www.pythonware.com/products/xml/sgmlop.htm
+#
+
+try:
+ import sgmlop
+ if not hasattr(sgmlop, "XMLParser"):
+ raise ImportError()
+except ImportError:
+ SgmlopParser = None # sgmlop accelerator not available
+else:
+ class SgmlopParser:
+ def __init__(self, target):
+
+ # setup callbacks
+ self.finish_starttag = target.start
+ self.finish_endtag = target.end
+ self.handle_data = target.data
+ self.handle_xml = target.xml
+
+ # activate parser
+ self.parser = sgmlop.XMLParser()
+ self.parser.register(self)
+ self.feed = self.parser.feed
+ self.entity = {
+ "amp": "&", "gt": ">", "lt": "<",
+ "apos": "'", "quot": '"'
+ }
+
+ def close(self):
+ try:
+ self.parser.close()
+ finally:
+ self.parser = self.feed = None # nuke circular reference
+
+ def handle_proc(self, tag, attr):
+ m = re.search("encoding\s*=\s*['\"]([^\"']+)[\"']", attr) #@UndefinedVariable
+ if m:
+ self.handle_xml(m.group(1), 1)
+
+ def handle_entityref(self, entity):
+ # <string> entity
+ try:
+ self.handle_data(self.entity[entity])
+ except KeyError:
+ self.handle_data("&%s;" % entity)
+
+try:
+ from xml.parsers import expat
+ if not hasattr(expat, "ParserCreate"):
+ raise ImportError()
+except ImportError:
+ ExpatParser = None # expat not available
+else:
+ class ExpatParser:
+ # fast expat parser for Python 2.0 and later. this is about
+ # 50% slower than sgmlop, on roundtrip testing
+ def __init__(self, target):
+ self._parser = parser = expat.ParserCreate(None, None)
+ self._target = target
+ parser.StartElementHandler = target.start
+ parser.EndElementHandler = target.end
+ parser.CharacterDataHandler = target.data
+ encoding = None
+ if not parser.returns_unicode:
+ encoding = "utf-8"
+ target.xml(encoding, None)
+
+ def feed(self, data):
+ self._parser.Parse(data, 0)
+
+ def close(self):
+ self._parser.Parse("", 1) # end of data
+ del self._target, self._parser # get rid of circular references
+
+class SlowParser:
+ """Default XML parser (based on xmllib.XMLParser)."""
+ # this is about 10 times slower than sgmlop, on roundtrip
+ # testing.
+ def __init__(self, target):
+ import xmllib # lazy subclassing (!)
+ if xmllib.XMLParser not in SlowParser.__bases__:
+ SlowParser.__bases__ = (xmllib.XMLParser,)
+ self.handle_xml = target.xml
+ self.unknown_starttag = target.start
+ self.handle_data = target.data
+ self.handle_cdata = target.data
+ self.unknown_endtag = target.end
+ try:
+ xmllib.XMLParser.__init__(self, accept_utf8=1)
+ except TypeError:
+ xmllib.XMLParser.__init__(self) # pre-2.0
+
+# --------------------------------------------------------------------
+# XML-RPC marshalling and unmarshalling code
+
+##
+# XML-RPC marshaller.
+#
+# @param encoding Default encoding for 8-bit strings. The default
+# value is None (interpreted as UTF-8).
+# @see dumps
+
+class Marshaller:
+ """Generate an XML-RPC params chunk from a Python data structure.
+
+ Create a Marshaller instance for each set of parameters, and use
+ the "dumps" method to convert your data (represented as a tuple)
+ to an XML-RPC params chunk. To write a fault response, pass a
+ Fault instance instead. You may prefer to use the "dumps" module
+ function for this purpose.
+ """
+
+ # by the way, if you don't understand what's going on in here,
+ # that's perfectly ok.
+
+ def __init__(self, encoding=None, allow_none=0):
+ self.memo = {}
+ self.data = None
+ self.encoding = encoding
+ self.allow_none = allow_none
+
+ dispatch = {}
+
+ def dumps(self, values):
+ out = []
+ write = out.append
+ dump = self.__dump
+ if isinstance(values, Fault):
+ # fault instance
+ write("<fault>\n")
+ dump({'faultCode': values.faultCode,
+ 'faultString': values.faultString},
+ write)
+ write("</fault>\n")
+ else:
+ # parameter block
+ # FIXME: the xml-rpc specification allows us to leave out
+ # the entire <params> block if there are no parameters.
+ # however, changing this may break older code (including
+ # old versions of xmlrpclib.py), so this is better left as
+ # is for now. See @XMLRPC3 for more information. /F
+ write("<params>\n")
+ for v in values:
+ write("<param>\n")
+ dump(v, write)
+ write("</param>\n")
+ write("</params>\n")
+ result = string.join(out, "")
+ return result
+
+ def __dump(self, value, write):
+ try:
+ f = self.dispatch[type(value)]
+ except KeyError:
+ raise TypeError("cannot marshal %s objects" % type(value))
+ else:
+ f(self, value, write)
+
+ def dump_nil (self, value, write):
+ if not self.allow_none:
+ raise TypeError("cannot marshal None unless allow_none is enabled")
+ write("<value><nil/></value>")
+ dispatch[NoneType] = dump_nil
+
+ def dump_int(self, value, write):
+ # in case ints are > 32 bits
+ if value > MAXINT or value < MININT:
+ raise OverflowError("int exceeds XML-RPC limits")
+ write("<value><int>")
+ write(str(value))
+ write("</int></value>\n")
+ dispatch[IntType] = dump_int
+
+ if _bool_is_builtin:
+ def dump_bool(self, value, write):
+ write("<value><boolean>")
+ write(value and "1" or "0")
+ write("</boolean></value>\n")
+ dispatch[bool] = dump_bool #@UndefinedVariable
+
+ def dump_long(self, value, write):
+ if value > MAXINT or value < MININT:
+ raise OverflowError("long int exceeds XML-RPC limits")
+ write("<value><int>")
+ write(str(int(value)))
+ write("</int></value>\n")
+ dispatch[LongType] = dump_long
+
+ def dump_double(self, value, write):
+ write("<value><double>")
+ write(repr(value))
+ write("</double></value>\n")
+ dispatch[FloatType] = dump_double
+
+ def dump_string(self, value, write, escape=escape):
+ write("<value><string>")
+ write(escape(value))
+ write("</string></value>\n")
+ dispatch[StringType] = dump_string
+
+ if unicode:
+ def dump_unicode(self, value, write, escape=escape):
+ value = value.encode(self.encoding)
+ write("<value><string>")
+ write(escape(value))
+ write("</string></value>\n")
+ dispatch[UnicodeType] = dump_unicode
+
+ def dump_array(self, value, write):
+ i = id(value)
+ if self.memo.has_key(i):
+ raise TypeError("cannot marshal recursive sequences")
+ self.memo[i] = None
+ dump = self.__dump
+ write("<value><array><data>\n")
+ for v in value:
+ dump(v, write)
+ write("</data></array></value>\n")
+ del self.memo[i]
+ dispatch[TupleType] = dump_array
+ dispatch[ListType] = dump_array
+
+ def dump_struct(self, value, write, escape=escape):
+ i = id(value)
+ if self.memo.has_key(i):
+ raise TypeError("cannot marshal recursive dictionaries")
+ self.memo[i] = None
+ dump = self.__dump
+ write("<value><struct>\n")
+ for k, v in value.items():
+ write("<member>\n")
+ if type(k) is not StringType:
+ if unicode and type(k) is UnicodeType:
+ k = k.encode(self.encoding)
+ else:
+ raise TypeError("dictionary key must be string")
+ write("<name>%s</name>\n" % escape(k))
+ dump(v, write)
+ write("</member>\n")
+ write("</struct></value>\n")
+ del self.memo[i]
+ dispatch[DictType] = dump_struct
+
+ if datetime:
+ def dump_datetime(self, value, write):
+ write("<value><dateTime.iso8601>")
+ write(value.strftime("%Y%m%dT%H:%M:%S"))
+ write("</dateTime.iso8601></value>\n")
+ dispatch[datetime.datetime] = dump_datetime
+
+ def dump_date(self, value, write):
+ write("<value><dateTime.iso8601>")
+ write(value.strftime("%Y%m%dT00:00:00"))
+ write("</dateTime.iso8601></value>\n")
+ dispatch[datetime.date] = dump_date
+
+ def dump_time(self, value, write):
+ write("<value><dateTime.iso8601>")
+ write(datetime.datetime.now().date().strftime("%Y%m%dT"))
+ write(value.strftime("%H:%M:%S"))
+ write("</dateTime.iso8601></value>\n")
+ dispatch[datetime.time] = dump_time
+
+ def dump_instance(self, value, write):
+ # check for special wrappers
+ if value.__class__ in WRAPPERS:
+ self.write = write
+ value.encode(self)
+ del self.write
+ else:
+ # store instance attributes as a struct (really?)
+ self.dump_struct(value.__dict__, write)
+ dispatch[InstanceType] = dump_instance
+
+##
+# XML-RPC unmarshaller.
+#
+# @see loads
+
+class Unmarshaller:
+ """Unmarshal an XML-RPC response, based on incoming XML event
+ messages (start, data, end). Call close() to get the resulting
+ data structure.
+
+ Note that this reader is fairly tolerant, and gladly accepts bogus
+ XML-RPC data without complaining (but not bogus XML).
+ """
+
+ # and again, if you don't understand what's going on in here,
+ # that's perfectly ok.
+
+ def __init__(self, use_datetime=0):
+ self._type = None
+ self._stack = []
+ self._marks = []
+ self._data = []
+ self._methodname = None
+ self._encoding = "utf-8"
+ self.append = self._stack.append
+ self._use_datetime = use_datetime
+ if use_datetime and not datetime:
+ raise ValueError("the datetime module is not available")
+
+ def close(self):
+ # return response tuple and target method
+ if self._type is None or self._marks:
+ raise ResponseError()
+ if self._type == "fault":
+ raise Fault(**self._stack[0])
+ return tuple(self._stack)
+
+ def getmethodname(self):
+ return self._methodname
+
+ #
+ # event handlers
+
+ def xml(self, encoding, standalone):
+ self._encoding = encoding
+ # FIXME: assert standalone == 1 ???
+
+ def start(self, tag, attrs):
+ # prepare to handle this element
+ if tag == "array" or tag == "struct":
+ self._marks.append(len(self._stack))
+ self._data = []
+ self._value = (tag == "value")
+
+ def data(self, text):
+ self._data.append(text)
+
+ def end(self, tag, join=string.join):
+ # call the appropriate end tag handler
+ try:
+ f = self.dispatch[tag]
+ except KeyError:
+ pass # unknown tag ?
+ else:
+ return f(self, join(self._data, ""))
+
+ #
+ # accelerator support
+
+ def end_dispatch(self, tag, data):
+ # dispatch data
+ try:
+ f = self.dispatch[tag]
+ except KeyError:
+ pass # unknown tag ?
+ else:
+ return f(self, data)
+
+ #
+ # element decoders
+
+ dispatch = {}
+
+ def end_nil (self, data):
+ self.append(None)
+ self._value = 0
+ dispatch["nil"] = end_nil
+
+ def end_boolean(self, data):
+ if data == "0":
+ self.append(False)
+ elif data == "1":
+ self.append(True)
+ else:
+ raise TypeError("bad boolean value")
+ self._value = 0
+ dispatch["boolean"] = end_boolean
+
+ def end_int(self, data):
+ self.append(int(data))
+ self._value = 0
+ dispatch["i4"] = end_int
+ dispatch["int"] = end_int
+
+ def end_double(self, data):
+ self.append(float(data))
+ self._value = 0
+ dispatch["double"] = end_double
+
+ def end_string(self, data):
+ if self._encoding:
+ data = _decode(data, self._encoding)
+ self.append(_stringify(data))
+ self._value = 0
+ dispatch["string"] = end_string
+ dispatch["name"] = end_string # struct keys are always strings
+
+ def end_array(self, data):
+ mark = self._marks.pop()
+ # map arrays to Python lists
+ self._stack[mark:] = [self._stack[mark:]]
+ self._value = 0
+ dispatch["array"] = end_array
+
+ def end_struct(self, data):
+ mark = self._marks.pop()
+ # map structs to Python dictionaries
+ dict = {}
+ items = self._stack[mark:]
+ for i in range(0, len(items), 2):
+ dict[_stringify(items[i])] = items[i + 1]
+ self._stack[mark:] = [dict]
+ self._value = 0
+ dispatch["struct"] = end_struct
+
+ def end_base64(self, data):
+ value = Binary()
+ value.decode(data)
+ self.append(value)
+ self._value = 0
+ dispatch["base64"] = end_base64
+
+ def end_dateTime(self, data):
+ value = DateTime()
+ value.decode(data)
+ if self._use_datetime:
+ value = _datetime_type(data)
+ self.append(value)
+ dispatch["dateTime.iso8601"] = end_dateTime
+
+ def end_value(self, data):
+ # if we stumble upon a value element with no internal
+ # elements, treat it as a string element
+ if self._value:
+ self.end_string(data)
+ dispatch["value"] = end_value
+
+ def end_params(self, data):
+ self._type = "params"
+ dispatch["params"] = end_params
+
+ def end_fault(self, data):
+ self._type = "fault"
+ dispatch["fault"] = end_fault
+
+ def end_methodName(self, data):
+ if self._encoding:
+ data = _decode(data, self._encoding)
+ self._methodname = data
+ self._type = "methodName" # no params
+ dispatch["methodName"] = end_methodName
+
+## Multicall support
+#
+
+class _MultiCallMethod:
+ # some lesser magic to store calls made to a MultiCall object
+ # for batch execution
+ def __init__(self, call_list, name):
+ self.__call_list = call_list
+ self.__name = name
+ def __getattr__(self, name):
+ return _MultiCallMethod(self.__call_list, "%s.%s" % (self.__name, name))
+ def __call__(self, *args):
+ self.__call_list.append((self.__name, args))
+
+class MultiCallIterator:
+ """Iterates over the results of a multicall. Exceptions are
+ thrown in response to xmlrpc faults."""
+
+ def __init__(self, results):
+ self.results = results
+
+ def __getitem__(self, i):
+ item = self.results[i]
+ if type(item) == type({}):
+ raise Fault(item['faultCode'], item['faultString'])
+ elif type(item) == type([]):
+ return item[0]
+ else:
+ raise ValueError("unexpected type in multicall result")
+
+class MultiCall:
+ """server -> a object used to boxcar method calls
+
+ server should be a ServerProxy object.
+
+ Methods can be added to the MultiCall using normal
+ method call syntax e.g.:
+
+ multicall = MultiCall(server_proxy)
+ multicall.add(2,3)
+ multicall.get_address("Guido")
+
+ To execute the multicall, call the MultiCall object e.g.:
+
+ add_result, address = multicall()
+ """
+
+ def __init__(self, server):
+ self.__server = server
+ self.__call_list = []
+
+ def __repr__(self):
+ return "<MultiCall at %x>" % id(self)
+
+ __str__ = __repr__
+
+ def __getattr__(self, name):
+ return _MultiCallMethod(self.__call_list, name)
+
+ def __call__(self):
+ marshalled_list = []
+ for name, args in self.__call_list:
+ marshalled_list.append({'methodName' : name, 'params' : args})
+
+ return MultiCallIterator(self.__server.system.multicall(marshalled_list))
+
+# --------------------------------------------------------------------
+# convenience functions
+
+##
+# Create a parser object, and connect it to an unmarshalling instance.
+# This function picks the fastest available XML parser.
+#
+# return A (parser, unmarshaller) tuple.
+
+def getparser(use_datetime=0):
+ """getparser() -> parser, unmarshaller
+
+ Create an instance of the fastest available parser, and attach it
+ to an unmarshalling object. Return both objects.
+ """
+ if use_datetime and not datetime:
+ raise ValueError("the datetime module is not available")
+ if FastParser and FastUnmarshaller:
+ if use_datetime:
+ mkdatetime = _datetime_type
+ else:
+ mkdatetime = _datetime
+ target = FastUnmarshaller(True, False, _binary, mkdatetime, Fault)
+ parser = FastParser(target)
+ else:
+ target = Unmarshaller(use_datetime=use_datetime)
+ if FastParser:
+ parser = FastParser(target)
+ elif SgmlopParser:
+ parser = SgmlopParser(target)
+ elif ExpatParser:
+ parser = ExpatParser(target)
+ else:
+ parser = SlowParser(target)
+ return parser, target
+
+##
+# Convert a Python tuple or a Fault instance to an XML-RPC packet.
+#
+# @def dumps(params, **options)
+# @param params A tuple or Fault instance.
+# @keyparam methodname If given, create a methodCall request for
+# this method name.
+# @keyparam methodresponse If given, create a methodResponse packet.
+# If used with a tuple, the tuple must be a singleton (that is,
+# it must contain exactly one element).
+# @keyparam encoding The packet encoding.
+# @return A string containing marshalled data.
+
+def dumps(params, methodname=None, methodresponse=None, encoding=None,
+ allow_none=0):
+ """data [,options] -> marshalled data
+
+ Convert an argument tuple or a Fault instance to an XML-RPC
+ request (or response, if the methodresponse option is used).
+
+ In addition to the data object, the following options can be given
+ as keyword arguments:
+
+ methodname: the method name for a methodCall packet
+
+ methodresponse: true to create a methodResponse packet.
+ If this option is used with a tuple, the tuple must be
+ a singleton (i.e. it can contain only one element).
+
+ encoding: the packet encoding (default is UTF-8)
+
+ All 8-bit strings in the data structure are assumed to use the
+ packet encoding. Unicode strings are automatically converted,
+ where necessary.
+ """
+
+ assert isinstance(params, TupleType) or isinstance(params, Fault), \
+ "argument must be tuple or Fault instance"
+
+ if isinstance(params, Fault):
+ methodresponse = 1
+ elif methodresponse and isinstance(params, TupleType):
+ assert len(params) == 1, "response tuple must be a singleton"
+
+ if not encoding:
+ encoding = "utf-8"
+
+ if FastMarshaller:
+ m = FastMarshaller(encoding)
+ else:
+ m = Marshaller(encoding, allow_none)
+
+ data = m.dumps(params)
+
+ if encoding != "utf-8":
+ xmlheader = "<?xml version='1.0' encoding='%s'?>\n" % str(encoding)
+ else:
+ xmlheader = "<?xml version='1.0'?>\n" # utf-8 is default
+
+ # standard XML-RPC wrappings
+ if methodname:
+ # a method call
+ if not isinstance(methodname, StringType):
+ methodname = methodname.encode(encoding)
+ data = (
+ xmlheader,
+ "<methodCall>\n"
+ "<methodName>", methodname, "</methodName>\n",
+ data,
+ "</methodCall>\n"
+ )
+ elif methodresponse:
+ # a method response, or a fault structure
+ data = (
+ xmlheader,
+ "<methodResponse>\n",
+ data,
+ "</methodResponse>\n"
+ )
+ else:
+ return data # return as is
+ return string.join(data, "")
+
+##
+# Convert an XML-RPC packet to a Python object. If the XML-RPC packet
+# represents a fault condition, this function raises a Fault exception.
+#
+# @param data An XML-RPC packet, given as an 8-bit string.
+# @return A tuple containing the unpacked data, and the method name
+# (None if not present).
+# @see Fault
+
+def loads(data, use_datetime=0):
+ """data -> unmarshalled data, method name
+
+ Convert an XML-RPC packet to unmarshalled data plus a method
+ name (None if not present).
+
+ If the XML-RPC packet represents a fault condition, this function
+ raises a Fault exception.
+ """
+ p, u = getparser(use_datetime=use_datetime)
+ p.feed(data)
+ p.close()
+ return u.close(), u.getmethodname()
+
+
+# --------------------------------------------------------------------
+# request dispatcher
+
+class _Method:
+ # some magic to bind an XML-RPC method to an RPC server.
+ # supports "nested" methods (e.g. examples.getStateName)
+ def __init__(self, send, name):
+ self.__send = send
+ self.__name = name
+ def __getattr__(self, name):
+ return _Method(self.__send, "%s.%s" % (self.__name, name))
+ def __call__(self, *args):
+ return self.__send(self.__name, args)
+
+##
+# Standard transport class for XML-RPC over HTTP.
+# <p>
+# You can create custom transports by subclassing this method, and
+# overriding selected methods.
+
+class Transport:
+ """Handles an HTTP transaction to an XML-RPC server."""
+
+ # client identifier (may be overridden)
+ user_agent = "xmlrpclib.py/%s (by www.pythonware.com)" % __version__
+
+ def __init__(self, use_datetime=0):
+ self._use_datetime = use_datetime
+
+ ##
+ # Send a complete request, and parse the response.
+ #
+ # @param host Target host.
+ # @param handler Target PRC handler.
+ # @param request_body XML-RPC request body.
+ # @param verbose Debugging flag.
+ # @return Parsed response.
+
+ def request(self, host, handler, request_body, verbose=0):
+ # issue XML-RPC request
+
+ h = self.make_connection(host)
+ if verbose:
+ h.set_debuglevel(1)
+
+ self.send_request(h, handler, request_body)
+ self.send_host(h, host)
+ self.send_user_agent(h)
+ self.send_content(h, request_body)
+
+ errcode, errmsg, headers = h.getreply()
+
+ if errcode != 200:
+ raise ProtocolError(
+ host + handler,
+ errcode, errmsg,
+ headers
+ )
+
+ self.verbose = verbose
+
+ try:
+ sock = h._conn.sock
+ except AttributeError:
+ sock = None
+
+ return self._parse_response(h.getfile(), sock)
+
+ ##
+ # Create parser.
+ #
+ # @return A 2-tuple containing a parser and a unmarshaller.
+
+ def getparser(self):
+ # get parser and unmarshaller
+ return getparser(use_datetime=self._use_datetime)
+
+ ##
+ # Get authorization info from host parameter
+ # Host may be a string, or a (host, x509-dict) tuple; if a string,
+ # it is checked for a "user:pw@host" format, and a "Basic
+ # Authentication" header is added if appropriate.
+ #
+ # @param host Host descriptor (URL or (URL, x509 info) tuple).
+ # @return A 3-tuple containing (actual host, extra headers,
+ # x509 info). The header and x509 fields may be None.
+
+ def get_host_info(self, host):
+
+ x509 = {}
+ if isinstance(host, TupleType):
+ host, x509 = host
+
+ import urllib
+ auth, host = urllib.splituser(host)
+
+ if auth:
+ import base64
+ auth = base64.encodestring(urllib.unquote(auth))
+ auth = string.join(string.split(auth), "") # get rid of whitespace
+ extra_headers = [
+ ("Authorization", "Basic " + auth)
+ ]
+ else:
+ extra_headers = None
+
+ return host, extra_headers, x509
+
+ ##
+ # Connect to server.
+ #
+ # @param host Target host.
+ # @return A connection handle.
+
+ def make_connection(self, host):
+ # create a HTTP connection object from a host descriptor
+ import httplib
+ host, extra_headers, x509 = self.get_host_info(host)
+ return httplib.HTTP(host)
+
+ ##
+ # Send request header.
+ #
+ # @param connection Connection handle.
+ # @param handler Target RPC handler.
+ # @param request_body XML-RPC body.
+
+ def send_request(self, connection, handler, request_body):
+ connection.putrequest("POST", handler)
+
+ ##
+ # Send host name.
+ #
+ # @param connection Connection handle.
+ # @param host Host name.
+
+ def send_host(self, connection, host):
+ host, extra_headers, x509 = self.get_host_info(host)
+ connection.putheader("Host", host)
+ if extra_headers:
+ if isinstance(extra_headers, DictType):
+ extra_headers = extra_headers.items()
+ for key, value in extra_headers:
+ connection.putheader(key, value)
+
+ ##
+ # Send user-agent identifier.
+ #
+ # @param connection Connection handle.
+
+ def send_user_agent(self, connection):
+ connection.putheader("User-Agent", self.user_agent)
+
+ ##
+ # Send request body.
+ #
+ # @param connection Connection handle.
+ # @param request_body XML-RPC request body.
+
+ def send_content(self, connection, request_body):
+ connection.putheader("Content-Type", "text/xml")
+ connection.putheader("Content-Length", str(len(request_body)))
+ connection.endheaders()
+ if request_body:
+ connection.send(request_body)
+
+ ##
+ # Parse response.
+ #
+ # @param file Stream.
+ # @return Response tuple and target method.
+
+ def parse_response(self, file):
+ # compatibility interface
+ return self._parse_response(file, None)
+
+ ##
+ # Parse response (alternate interface). This is similar to the
+ # parse_response method, but also provides direct access to the
+ # underlying socket object (where available).
+ #
+ # @param file Stream.
+ # @param sock Socket handle (or None, if the socket object
+ # could not be accessed).
+ # @return Response tuple and target method.
+
+ def _parse_response(self, file, sock):
+ # read response from input file/socket, and parse it
+
+ p, u = self.getparser()
+
+ while 1:
+ if sock:
+ response = sock.recv(1024)
+ else:
+ response = file.read(1024)
+ if not response:
+ break
+ if self.verbose:
+ sys.stdout.write("body: %s\n" % repr(response))
+ p.feed(response)
+
+ file.close()
+ p.close()
+
+ return u.close()
+
+##
+# Standard transport class for XML-RPC over HTTPS.
+
+class SafeTransport(Transport):
+ """Handles an HTTPS transaction to an XML-RPC server."""
+
+ # FIXME: mostly untested
+
+ def make_connection(self, host):
+ # create a HTTPS connection object from a host descriptor
+ # host may be a string, or a (host, x509-dict) tuple
+ import httplib
+ host, extra_headers, x509 = self.get_host_info(host)
+ try:
+ HTTPS = httplib.HTTPS
+ except AttributeError:
+ raise NotImplementedError(
+ "your version of httplib doesn't support HTTPS"
+ )
+ else:
+ return HTTPS(host, None, **(x509 or {}))
+
+##
+# Standard server proxy. This class establishes a virtual connection
+# to an XML-RPC server.
+# <p>
+# This class is available as ServerProxy and Server. New code should
+# use ServerProxy, to avoid confusion.
+#
+# @def ServerProxy(uri, **options)
+# @param uri The connection point on the server.
+# @keyparam transport A transport factory, compatible with the
+# standard transport class.
+# @keyparam encoding The default encoding used for 8-bit strings
+# (default is UTF-8).
+# @keyparam verbose Use a true value to enable debugging output.
+# (printed to standard output).
+# @see Transport
+
+class ServerProxy:
+ """uri [,options] -> a logical connection to an XML-RPC server
+
+ uri is the connection point on the server, given as
+ scheme://host/target.
+
+ The standard implementation always supports the "http" scheme. If
+ SSL socket support is available (Python 2.0), it also supports
+ "https".
+
+ If the target part and the slash preceding it are both omitted,
+ "/RPC2" is assumed.
+
+ The following options can be given as keyword arguments:
+
+ transport: a transport factory
+ encoding: the request encoding (default is UTF-8)
+
+ All 8-bit strings passed to the server proxy are assumed to use
+ the given encoding.
+ """
+
+ def __init__(self, uri, transport=None, encoding=None, verbose=0,
+ allow_none=0, use_datetime=0):
+ # establish a "logical" server connection
+
+ # get the url
+ import urllib
+ type, uri = urllib.splittype(uri)
+ if type not in ("http", "https"):
+ raise IOError("unsupported XML-RPC protocol")
+ self.__host, self.__handler = urllib.splithost(uri)
+ if not self.__handler:
+ self.__handler = "/RPC2"
+
+ if transport is None:
+ if type == "https":
+ transport = SafeTransport(use_datetime=use_datetime)
+ else:
+ transport = Transport(use_datetime=use_datetime)
+ self.__transport = transport
+
+ self.__encoding = encoding
+ self.__verbose = verbose
+ self.__allow_none = allow_none
+
+ def __request(self, methodname, params):
+ # call a method on the remote server
+
+ request = dumps(params, methodname, encoding=self.__encoding,
+ allow_none=self.__allow_none)
+
+ response = self.__transport.request(
+ self.__host,
+ self.__handler,
+ request,
+ verbose=self.__verbose
+ )
+
+ if len(response) == 1:
+ response = response[0]
+
+ return response
+
+ def __repr__(self):
+ return (
+ "<ServerProxy for %s%s>" %
+ (self.__host, self.__handler)
+ )
+
+ __str__ = __repr__
+
+ def __getattr__(self, name):
+ # magic method dispatcher
+ return _Method(self.__request, name)
+
+ # note: to call a remote object with an non-standard name, use
+ # result getattr(server, "strange-python-name")(args)
+
+# compatibility
+
+Server = ServerProxy
+
+# --------------------------------------------------------------------
+# test code
+
+if __name__ == "__main__":
+
+ # simple test program (from the XML-RPC specification)
+
+ # server = ServerProxy("http://localhost:8000") # local server
+ server = ServerProxy("http://time.xmlrpc.com/RPC2")
+
+ sys.stdout.write('%s\n' % server)
+
+ try:
+ sys.stdout.write('%s\n' % (server.currentTime.getCurrentTime(),))
+ except Error:
+ import traceback;traceback.print_exc()
+
+ multi = MultiCall(server)
+ multi.currentTime.getCurrentTime()
+ multi.currentTime.getCurrentTime()
+ try:
+ for response in multi():
+ sys.stdout.write('%s\n' % (response,))
+ except Error:
+ import traceback;traceback.print_exc()
diff --git a/python/helpers/pydev/_pydev_jy_imports_tipper.py b/python/helpers/pydev/_pydev_jy_imports_tipper.py
index 43e4d0b67140..1691e3e1f1dc 100644
--- a/python/helpers/pydev/_pydev_jy_imports_tipper.py
+++ b/python/helpers/pydev/_pydev_jy_imports_tipper.py
@@ -1,7 +1,5 @@
import StringIO
import traceback
-from java.lang import StringBuffer #@UnresolvedImport
-from java.lang import String #@UnresolvedImport
import java.lang #@UnresolvedImport
import sys
from _pydev_tipper_common import DoFind
@@ -14,12 +12,16 @@ except NameError: # version < 2.3 -- didn't have the True/False builtins
import __builtin__
setattr(__builtin__, 'True', 1)
setattr(__builtin__, 'False', 0)
-
-
+
+
from org.python.core import PyReflectedFunction #@UnresolvedImport
from org.python import core #@UnresolvedImport
-from org.python.core import PyClass #@UnresolvedImport
+
+try:
+ xrange
+except:
+ xrange = range
#completion types.
@@ -48,11 +50,11 @@ def Find(name):
name = 'org.python.core.PyString'
elif name == '__builtin__.dict':
name = 'org.python.core.PyDictionary'
-
+
mod = _imp(name)
parent = mod
foundAs = ''
-
+
if hasattr(mod, '__file__'):
f = mod.__file__
@@ -68,29 +70,29 @@ def Find(name):
except AttributeError:
if old_comp != comp:
raise
-
+
if hasattr(mod, '__file__'):
f = mod.__file__
else:
if len(foundAs) > 0:
foundAs = foundAs + '.'
foundAs = foundAs + comp
-
+
old_comp = comp
-
+
return f, mod, parent, foundAs
def formatParamClassName(paramClassName):
if paramClassName.startswith('['):
if paramClassName == '[C':
paramClassName = 'char[]'
-
+
elif paramClassName == '[B':
paramClassName = 'byte[]'
-
+
elif paramClassName == '[I':
paramClassName = 'int[]'
-
+
elif paramClassName.startswith('[L') and paramClassName.endswith(';'):
paramClassName = paramClassName[2:-1]
paramClassName += '[]'
@@ -101,17 +103,17 @@ def GenerateTip(data, log=None):
data = data.replace('\n', '')
if data.endswith('.'):
data = data.rstrip('.')
-
+
f, mod, parent, foundAs = Find(data)
tips = GenerateImportsTipForModule(mod)
return f, tips
-
+
#=======================================================================================================================
# Info
#=======================================================================================================================
class Info:
-
+
def __init__(self, name, **kwargs):
self.name = name
self.doc = kwargs.get('doc', None)
@@ -119,47 +121,47 @@ class Info:
self.varargs = kwargs.get('varargs', None) #string
self.kwargs = kwargs.get('kwargs', None) #string
self.ret = kwargs.get('ret', None) #string
-
+
def basicAsStr(self):
'''@returns this class information as a string (just basic format)
'''
-
+
s = 'function:%s args=%s, varargs=%s, kwargs=%s, docs:%s' % \
(str(self.name), str(self.args), str(self.varargs), str(self.kwargs), str(self.doc))
return s
-
+
def getAsDoc(self):
s = str(self.name)
if self.doc:
s += '\n@doc %s\n' % str(self.doc)
-
+
if self.args:
s += '\n@params '
for arg in self.args:
s += str(formatParamClassName(arg))
s += ' '
-
+
if self.varargs:
s += '\n@varargs '
s += str(self.varargs)
-
+
if self.kwargs:
s += '\n@kwargs '
s += str(self.kwargs)
-
+
if self.ret:
s += '\n@return '
s += str(formatParamClassName(str(self.ret)))
-
+
return str(s)
-
+
def isclass(cls):
return isinstance(cls, core.PyClass)
def ismethod(func):
'''this function should return the information gathered on a function
-
+
@param func: this is the function we want to get info on
@return a tuple where:
0 = indicates whether the parameter passed is a method or not
@@ -167,24 +169,24 @@ def ismethod(func):
this is a list because when we have methods from java with the same name and different signatures,
we actually have many methods, each with its own set of arguments
'''
-
+
try:
if isinstance(func, core.PyFunction):
#ok, this is from python, created by jython
#print_ ' PyFunction'
-
+
def getargs(func_code):
"""Get information about the arguments accepted by a code object.
-
+
Three things are returned: (args, varargs, varkw), where 'args' is
a list of argument names (possibly containing nested lists), and
'varargs' and 'varkw' are the names of the * and ** arguments or None."""
-
+
nargs = func_code.co_argcount
names = func_code.co_varnames
args = list(names[:nargs])
step = 0
-
+
varargs = None
if func_code.co_flags & func_code.CO_VARARGS:
varargs = func_code.co_varnames[nargs]
@@ -193,35 +195,35 @@ def ismethod(func):
if func_code.co_flags & func_code.CO_VARKEYWORDS:
varkw = func_code.co_varnames[nargs]
return args, varargs, varkw
-
+
args = getargs(func.func_code)
return 1, [Info(func.func_name, args=args[0], varargs=args[1], kwargs=args[2], doc=func.func_doc)]
-
+
if isinstance(func, core.PyMethod):
#this is something from java itself, and jython just wrapped it...
-
+
#things to play in func:
#['__call__', '__class__', '__cmp__', '__delattr__', '__dir__', '__doc__', '__findattr__', '__name__', '_doget', 'im_class',
#'im_func', 'im_self', 'toString']
#print_ ' PyMethod'
#that's the PyReflectedFunction... keep going to get it
func = func.im_func
-
+
if isinstance(func, PyReflectedFunction):
#this is something from java itself, and jython just wrapped it...
-
+
#print_ ' PyReflectedFunction'
-
+
infos = []
- for i in range(len(func.argslist)):
+ for i in xrange(len(func.argslist)):
#things to play in func.argslist[i]:
-
+
#'PyArgsCall', 'PyArgsKeywordsCall', 'REPLACE', 'StandardCall', 'args', 'compare', 'compareTo', 'data', 'declaringClass'
#'flags', 'isStatic', 'matches', 'precedence']
-
+
#print_ ' ', func.argslist[i].data.__class__
#func.argslist[i].data.__class__ == java.lang.reflect.Method
-
+
if func.argslist[i]:
met = func.argslist[i].data
name = met.getName()
@@ -230,9 +232,9 @@ def ismethod(func):
except AttributeError:
ret = ''
parameterTypes = met.getParameterTypes()
-
+
args = []
- for j in range(len(parameterTypes)):
+ for j in xrange(len(parameterTypes)):
paramTypesClass = parameterTypes[j]
try:
try:
@@ -246,7 +248,7 @@ def ismethod(func):
except:
paramClassName = repr(paramTypesClass) #just in case something else happens... it will at least be visible
#if the parameter equals [C, it means it it a char array, so, let's change it
-
+
a = formatParamClassName(paramClassName)
#a = a.replace('[]','Array')
#a = a.replace('Object', 'obj')
@@ -255,18 +257,18 @@ def ismethod(func):
#a = a.replace('Char', 'c')
#a = a.replace('Double', 'd')
args.append(a) #so we don't leave invalid code
-
-
+
+
info = Info(name, args=args, ret=ret)
#print_ info.basicAsStr()
infos.append(info)
-
+
return 1, infos
- except Exception, e:
+ except Exception:
s = StringIO.StringIO()
traceback.print_exc(file=s)
return 1, [Info(str('ERROR'), doc=s.getvalue())]
-
+
return 0, None
def ismodule(mod):
@@ -274,7 +276,7 @@ def ismodule(mod):
if not hasattr(mod, 'getClass') and not hasattr(mod, '__class__') \
and hasattr(mod, '__name__'):
return 1
-
+
return isinstance(mod, core.PyModule)
@@ -293,11 +295,11 @@ def dirObj(obj):
except TypeError:
#may happen on jython when getting the java.lang.Class class
c = obj.getSuperclass(obj)
-
+
while c != None:
classes.append(c)
c = c.getSuperclass()
-
+
#get info about interfaces
interfs = []
for obj in classes:
@@ -306,57 +308,57 @@ def dirObj(obj):
except TypeError:
interfs.extend(obj.getInterfaces(obj))
classes.extend(interfs)
-
+
#now is the time when we actually get info on the declared methods and fields
for obj in classes:
try:
declaredMethods = obj.getDeclaredMethods()
except TypeError:
declaredMethods = obj.getDeclaredMethods(obj)
-
+
try:
declaredFields = obj.getDeclaredFields()
except TypeError:
declaredFields = obj.getDeclaredFields(obj)
-
- for i in range(len(declaredMethods)):
+
+ for i in xrange(len(declaredMethods)):
name = declaredMethods[i].getName()
ret.append(name)
found.put(name, 1)
-
- for i in range(len(declaredFields)):
+
+ for i in xrange(len(declaredFields)):
name = declaredFields[i].getName()
ret.append(name)
found.put(name, 1)
-
-
- elif isclass(obj.__class__):
+
+
+ elif isclass(obj.__class__):
d = dir(obj.__class__)
for name in d:
ret.append(name)
found.put(name, 1)
-
+
#this simple dir does not always get all the info, that's why we have the part before
- #(e.g.: if we do a dir on String, some methods that are from other interfaces such as
+ #(e.g.: if we do a dir on String, some methods that are from other interfaces such as
#charAt don't appear)
d = dir(original)
for name in d:
if found.get(name) != 1:
ret.append(name)
-
+
return ret
def formatArg(arg):
'''formats an argument to be shown
'''
-
+
s = str(arg)
dot = s.rfind('.')
if dot >= 0:
s = s[dot + 1:]
-
+
s = s.replace(';', '')
s = s.replace('[]', 'Array')
if len(s) > 0:
@@ -364,13 +366,13 @@ def formatArg(arg):
s = c + s[1:]
return s
-
-
-
+
+
+
def Search(data):
'''@return file, line, col
'''
-
+
data = data.replace('\n', '')
if data.endswith('.'):
data = data.rstrip('.')
@@ -379,8 +381,8 @@ def Search(data):
return DoFind(f, mod), foundAs
except:
return DoFind(f, parent), foundAs
-
-
+
+
def GenerateImportsTipForModule(obj_to_complete, dirComps=None, getattr=getattr, filter=lambda name:True):
'''
@param obj_to_complete: the object from where we should get the completions
@@ -391,18 +393,18 @@ def GenerateImportsTipForModule(obj_to_complete, dirComps=None, getattr=getattr,
name, doc, args, type (from the TYPE_* constants)
'''
ret = []
-
+
if dirComps is None:
dirComps = dirObj(obj_to_complete)
-
+
for d in dirComps:
if d is None:
continue
-
+
if not filter(d):
continue
-
+
args = ''
doc = ''
retType = TYPE_BUILTIN
@@ -421,7 +423,7 @@ def GenerateImportsTipForModule(obj_to_complete, dirComps=None, getattr=getattr,
#note: this only happens when we add things to the sys.path at runtime, if they are added to the classpath
#before the run, everything goes fine.
#
- #The code below ilustrates what I mean...
+ #The code below ilustrates what I mean...
#
#import sys
#sys.path.insert(1, r"C:\bin\eclipse310\plugins\org.junit_3.8.1\junit.jar" )
@@ -429,7 +431,7 @@ def GenerateImportsTipForModule(obj_to_complete, dirComps=None, getattr=getattr,
#import junit.framework
#print_ dir(junit.framework) #shows the TestCase class here
#
- #import junit.framework.TestCase
+ #import junit.framework.TestCase
#
#raises the error:
#Traceback (innermost last):
@@ -458,19 +460,19 @@ def GenerateImportsTipForModule(obj_to_complete, dirComps=None, getattr=getattr,
except TypeError:
traceback.print_exc()
args = '()'
-
+
retType = TYPE_FUNCTION
-
+
elif isclass(obj):
retType = TYPE_CLASS
-
+
elif ismodule(obj):
retType = TYPE_IMPORT
-
+
#add token and doc to return - assure only strings.
ret.append((d, doc, args, retType))
-
-
+
+
return ret
diff --git a/python/helpers/pydev/_pydev_thread.py b/python/helpers/pydev/_pydev_thread.py
deleted file mode 100644
index 3971c79d2c64..000000000000
--- a/python/helpers/pydev/_pydev_thread.py
+++ /dev/null
@@ -1 +0,0 @@
-from thread import * \ No newline at end of file
diff --git a/python/helpers/pydev/_pydev_threading.py b/python/helpers/pydev/_pydev_threading.py
index 52d48c93ed3e..d7bfadf04308 100644
--- a/python/helpers/pydev/_pydev_threading.py
+++ b/python/helpers/pydev/_pydev_threading.py
@@ -2,14 +2,10 @@
import sys as _sys
-try:
- import _pydev_thread as thread
-except ImportError:
- import thread
-
+from _pydev_imps import _pydev_thread as thread
import warnings
-from _pydev_time import time as _time, sleep as _sleep
+from _pydev_imps._pydev_time import time as _time, sleep as _sleep
from traceback import format_exc as _format_exc
# Note regarding PEP 8 compliant aliases
@@ -854,7 +850,7 @@ _shutdown = _MainThread()._exitfunc
# module, or from the python fallback
try:
- from _pydev_thread import _local as local
+ from _pydev_imps._pydev_thread import _local as local
except ImportError:
from _threading_local import local
diff --git a/python/helpers/pydev/_pydev_tipper_common.py b/python/helpers/pydev/_pydev_tipper_common.py
index f8c46d232b10..8e6267fd27ea 100644
--- a/python/helpers/pydev/_pydev_tipper_common.py
+++ b/python/helpers/pydev/_pydev_tipper_common.py
@@ -2,7 +2,7 @@ try:
import inspect
except:
try:
- import _pydev_inspect as inspect # for older versions
+ from _pydev_imps import _pydev_inspect as inspect
except:
import traceback;traceback.print_exc() #Ok, no inspect available (search will not work)
@@ -10,57 +10,58 @@ try:
import re
except:
try:
- import _pydev_re as re # for older versions @UnresolvedImport
+ import sre as re # for older versions
except:
import traceback;traceback.print_exc() #Ok, no inspect available (search will not work)
+from pydevd_constants import xrange
def DoFind(f, mod):
import linecache
if inspect.ismodule(mod):
return f, 0, 0
-
+
lines = linecache.getlines(f)
-
+
if inspect.isclass(mod):
name = mod.__name__
pat = re.compile(r'^\s*class\s*' + name + r'\b')
- for i in range(len(lines)):
- if pat.match(lines[i]):
+ for i in xrange(len(lines)):
+ if pat.match(lines[i]):
return f, i, 0
-
+
return f, 0, 0
if inspect.ismethod(mod):
mod = mod.im_func
-
+
if inspect.isfunction(mod):
try:
mod = mod.func_code
except AttributeError:
mod = mod.__code__ #python 3k
-
+
if inspect.istraceback(mod):
mod = mod.tb_frame
-
+
if inspect.isframe(mod):
mod = mod.f_code
if inspect.iscode(mod):
if not hasattr(mod, 'co_filename'):
return None, 0, 0
-
+
if not hasattr(mod, 'co_firstlineno'):
return mod.co_filename, 0, 0
-
+
lnum = mod.co_firstlineno
pat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)')
while lnum > 0:
- if pat.match(lines[lnum]):
+ if pat.match(lines[lnum]):
break
lnum -= 1
-
+
return f, lnum, 0
raise RuntimeError('Do not know about: ' + f + ' ' + str(mod))
diff --git a/python/helpers/pydev/_pydev_xmlrpc_hook.py b/python/helpers/pydev/_pydev_xmlrpc_hook.py
deleted file mode 100644
index 22d445a0c867..000000000000
--- a/python/helpers/pydev/_pydev_xmlrpc_hook.py
+++ /dev/null
@@ -1,74 +0,0 @@
-from pydev_imports import SimpleXMLRPCServer
-from pydev_ipython.inputhook import get_inputhook, set_return_control_callback
-import select
-import sys
-
-select_fn = select.select
-if sys.platform.startswith('java'):
- select_fn = select.cpython_compatible_select
-
-class InputHookedXMLRPCServer(SimpleXMLRPCServer):
- ''' An XML-RPC Server that can run hooks while polling for new requests.
-
- This code was designed to work with IPython's inputhook methods and
- to allow Debug framework to have a place to run commands during idle
- too.
- '''
- def __init__(self, *args, **kwargs):
- SimpleXMLRPCServer.__init__(self, *args, **kwargs)
- # Tell the inputhook mechanisms when control should be returned
- set_return_control_callback(self.return_control)
- self.debug_hook = None
- self.return_control_osc = False
-
- def return_control(self):
- ''' A function that the inputhooks can call (via inputhook.stdin_ready()) to find
- out if they should cede control and return '''
- if self.debug_hook:
- # Some of the input hooks check return control without doing
- # a single operation, so we don't return True on every
- # call when the debug hook is in place to allow the GUI to run
- # XXX: Eventually the inputhook code will have diverged enough
- # from the IPython source that it will be worthwhile rewriting
- # it rather than pretending to maintain the old API
- self.return_control_osc = not self.return_control_osc
- if self.return_control_osc:
- return True
- r, unused_w, unused_e = select_fn([self], [], [], 0)
- return bool(r)
-
- def setDebugHook(self, debug_hook):
- self.debug_hook = debug_hook
-
- def serve_forever(self):
- ''' Serve forever, running defined hooks regularly and when idle.
- Does not support shutdown '''
- inputhook = get_inputhook()
- while True:
- # Block for default 1/2 second when no GUI is in progress
- timeout = 0.5
- if self.debug_hook:
- self.debug_hook()
- timeout = 0.1
- if inputhook:
- try:
- inputhook()
- # The GUI has given us an opportunity to try receiving, normally
- # this happens because the input hook has already polled the
- # server has knows something is waiting
- timeout = 0.020
- except:
- inputhook = None
- r, unused_w, unused_e = select_fn([self], [], [], timeout)
- if self in r:
- try:
- self._handle_request_noblock()
- except AttributeError:
- # Older libraries do not support _handle_request_noblock, so fall
- # back to the handle_request version
- self.handle_request()
- # Running the request may have changed the inputhook in use
- inputhook = get_inputhook()
-
- def shutdown(self):
- raise NotImplementedError('InputHookedXMLRPCServer does not support shutdown')
diff --git a/python/helpers/pydev/_pydevd_re.py b/python/helpers/pydev/_pydevd_re.py
deleted file mode 100644
index cd0067200b5f..000000000000
--- a/python/helpers/pydev/_pydevd_re.py
+++ /dev/null
@@ -1,11 +0,0 @@
-
-__all__ = [ "match", "search", "sub", "subn", "split", "findall",
- "compile", "purge", "template", "escape", "I", "L", "M", "S", "X",
- "U", "IGNORECASE", "LOCALE", "MULTILINE", "DOTALL", "VERBOSE",
- "UNICODE", "error" ]
-
-import sre, sys
-module = sys.modules['re']
-for name in __all__:
- setattr(module, name, getattr(sre, name))
-
diff --git a/python/helpers/pydev/django_debug.py b/python/helpers/pydev/django_debug.py
index 37ee04299cc6..417ff0190e84 100644
--- a/python/helpers/pydev/django_debug.py
+++ b/python/helpers/pydev/django_debug.py
@@ -1,28 +1,19 @@
import inspect
-from django_frame import DjangoTemplateFrame, get_template_file_name, get_template_line
+from django_frame import DjangoTemplateFrame
from pydevd_comm import CMD_SET_BREAK
-from pydevd_constants import DJANGO_SUSPEND, GetThreadId
-from pydevd_file_utils import NormFileToServer
-from runfiles import DictContains
+from pydevd_constants import DJANGO_SUSPEND, GetThreadId, DictContains
from pydevd_breakpoints import LineBreakpoint
import pydevd_vars
import traceback
class DjangoLineBreakpoint(LineBreakpoint):
- def __init__(self, type, file, line, flag, condition, func_name, expression):
- self.file = file
- self.line = line
- LineBreakpoint.__init__(self, type, flag, condition, func_name, expression)
- def __eq__(self, other):
- if not isinstance(other, DjangoLineBreakpoint):
- return False
- return self.file == other.file and self.line == other.line
+ def __init__(self, file, line, condition, func_name, expression):
+ self.file = file
+ LineBreakpoint.__init__(self, line, condition, func_name, expression)
- def is_triggered(self, frame):
- file = get_template_file_name(frame)
- line = get_template_line(frame)
- return self.file == file and self.line == line
+ def is_triggered(self, template_frame_file, template_frame_line):
+ return self.file == template_frame_file and self.line == template_frame_line
def __str__(self):
return "DjangoLineBreakpoint: %s-%d" %(self.file, self.line)
diff --git a/python/helpers/pydev/django_frame.py b/python/helpers/pydev/django_frame.py
index 762df2d16579..4181572aed3c 100644
--- a/python/helpers/pydev/django_frame.py
+++ b/python/helpers/pydev/django_frame.py
@@ -1,11 +1,14 @@
from pydevd_file_utils import GetFileNameAndBaseFromFile
import pydev_log
import traceback
+from pydevd_constants import DictContains
def read_file(filename):
f = open(filename, "r")
- s = f.read()
- f.close()
+ try:
+ s = f.read()
+ finally:
+ f.close()
return s
@@ -34,7 +37,9 @@ def get_source(frame):
if hasattr(node, 'source'):
return node.source
else:
- pydev_log.error_once("WARNING: Template path is not available. Please set TEMPLATE_DEBUG=True in your settings.py to make django template breakpoints working")
+ pydev_log.error_once(
+ "WARNING: Template path is not available. Please set TEMPLATE_DEBUG=True "
+ "in your settings.py to make django template breakpoints working")
return None
except:
@@ -61,41 +66,50 @@ def get_template_file_name(frame):
return None
-def get_template_line(frame):
+def get_template_line(frame, template_frame_file):
source = get_source(frame)
- file_name = get_template_file_name(frame)
try:
- return offset_to_line_number(read_file(file_name), source[1][0])
+ return offset_to_line_number(read_file(template_frame_file), source[1][0])
except:
return None
class DjangoTemplateFrame:
- def __init__(self, frame):
- file_name = get_template_file_name(frame)
+ def __init__(
+ self,
+ frame,
+ template_frame_file=None,
+ template_frame_line=None):
+
+ if template_frame_file is None:
+ template_frame_file = get_template_file_name(frame)
+
self.back_context = frame.f_locals['context']
- self.f_code = FCode('Django Template', file_name)
- self.f_lineno = get_template_line(frame)
+ self.f_code = FCode('Django Template', template_frame_file)
+
+ if template_frame_line is None:
+ template_frame_line = get_template_line(frame, template_frame_file)
+ self.f_lineno = template_frame_line
+
self.f_back = frame
self.f_globals = {}
- self.f_locals = self.collect_context(self.back_context)
+ self.f_locals = self.collect_context()
self.f_trace = None
- def collect_context(self, context):
+ def collect_context(self):
res = {}
try:
- for d in context.dicts:
- for k, v in d.items():
- res[k] = v
- except AttributeError:
+ for d in self.back_context.dicts:
+ res.update(d)
+ except AttributeError:
pass
return res
def changeVariable(self, name, value):
for d in self.back_context.dicts:
- for k, v in d.items():
- if k == name:
- d[k] = value
+ if DictContains(d, name):
+ d[name] = value
+ self.f_locals[name] = value
class FCode:
@@ -106,10 +120,9 @@ class FCode:
def is_django_exception_break_context(frame):
try:
- name = frame.f_code.co_name
+ return frame.f_code.co_name in ['_resolve_lookup', 'find_template']
except:
- name = None
- return name in ['_resolve_lookup', 'find_template']
+ return False
def just_raised(trace):
diff --git a/python/helpers/pydev/merge_pydev_pycharm.txt b/python/helpers/pydev/merge_pydev_pycharm.txt
new file mode 100644
index 000000000000..1cbd356958ae
--- /dev/null
+++ b/python/helpers/pydev/merge_pydev_pycharm.txt
@@ -0,0 +1,138 @@
+Done in the merge (started from the PyCharm version and bringing in things from PyDev):
+
+- Added modules which were unused in PyCharm but are used in PyDev.
+
+- execfile was upgraded to the PyDev version (it had errors with BOM in utf-8).
+
+- pydevd_file_utils: automatically doing normcase.
+
+- pyded: multiprocessing supporting 2 approaches (use new connection/use same connection).
+
+- pydev_monkey: fixes from PyDev to properly deal with windows command lines.
+
+- Private variables (name-mangled) are now evaluated (so they can be hovered).
+
+- Exceptions raised from lines with a #@IgnoreException are ignored.
+
+- Fixed exception changing variable in django debugging.
+
+- Made debugging with Django breakpoints a bit faster.
+
+- Exceptions separated by caught/uncaught, so, it's no longer needed to check
+ an additional attribute to check it.
+
+- When exception is thrown evaluating breakpoint condition, the debugger will stop
+ (can be configured in main_debugger.suspend_on_breakpoint_exception).
+
+- #@DontTrace comments can be used on methods so that they are ignored when stepping
+ in (needs UI for CMD_ENABLE_DONT_TRACE).
+
+- Code which stops tracing inside python properties integrated (CMD_SET_PROPERTY_TRACE).
+
+- Find Referrers integrated.
+
+- Using same facade for IPython integration.
+
+- When the code is interrupted, the buffer in the python side is cleared.
+
+- GEvent debugging: for remote debugging, one has to import pydevd before doing the gevent patching -- even if
+ pydevd.settrace will only be done later.
+
+ Also, the gevent debugging should probably be closer to the stackless debugging,
+ where we actually show the live stackless threads -- so, we should show the live
+ gevent greenlets -- which the current version doesn't do.
+
+
+Things to be fixed in PyCharm:
+--------------------------------
+
+1. CMD_VERSION now should receive that it wants breakpoints by ID (and it
+ should give a breakpoint id which should be used to remove it later
+ when setting a breakpoint).
+
+2. Setting breakpoint: the func_name is not being properly passed from PyCharm
+ (and as such, PyCharm debugging is slower than it should be).
+
+ Note that it works passing 'None', but the func_name should be given when possible.
+
+ I.e.:
+
+ class MyClass(object):
+ def __init__(self):
+ print('here') # Break here: '__init__' as func_name
+ print(a)
+
+ def bar(self):
+ print('bar') # Break here: 'bar' as func_name
+
+3. Note (may not need to change anything):
+ Removed support for removing breakpoint without knowing its type (i.e.:
+ remove breakpoint tried to remove a breakpoint if the type wasn't
+ python-line nor django-line, now, it'll give an exception).
+
+4. break_on_exceptions_thrown_in_same_context / ignore_exceptions_thrown_in_lines_with_ignore_exception
+
+ These are currently set in the bulk operation to add exceptions, but
+ it does make sense to create a separate command for that (but it's only
+ worth doing it when/if PyCharm gets an UI to add it).
+
+5. UI to ignore exception from additional places (not only from #@IgnoreException code-comments)
+ i.e.: UI for CMD_IGNORE_THROWN_EXCEPTION_AT.
+
+6. UI to show the current exception (i.e.: deal with CMD_SEND_CURR_EXCEPTION_TRACE and
+ CMD_SEND_CURR_EXCEPTION_TRACE_PROCEEDED in the client side).
+
+7. When an exception is detected on a breakpoint condition evaluation, we'll send
+ a CMD_GET_BREAKPOINT_EXCEPTION (which should be handled by PyCharm to show some
+ UI notification).
+
+8. The CMD_ENABLE_DONT_TRACE must be sent from the UI to skip methods which have
+ an #@DontTrace above it.
+
+9. The CMD_SET_PROPERTY_TRACE must be sent from the UI to skip setter/getter/deleter
+ python properties.
+
+10. Integrate find referrers UI in PyCharm. In the backend it uses a CMD_RUN_CUSTOM_OPERATION with:
+ from pydevd_referrers import get_referrer_info
+ get_referrer_info
+
+11. CMD_RELOAD_CODE has to be integrated (when a file changes it should be issued
+ for 'hot' auto-reload of the code -- note that it's not needed if the
+ user already has some sort of auto-reload builtin -- i.e.: django without the noreload option).
+
+12. Console Completions: See: pydev_ipython_console_011.PyDevFrontEnd.getCompletions
+ Now we're completing as they come from the IPython backend (i.e.: not stripping %
+ for magic commands).
+
+13. In PyDev, interrupt can be used to clear the current buffer (whereas in PyCharm it's only
+ possible to activate it to stop the execution of a command) -- note that this is only a
+ client-side limitation.
+
+14. Console GUI event loop can have some UI integrated.
+ Note that the user can enable it manually (i.e.: by writing something as "%gui qt"
+ the qt backend is integrated, but it's possible to call 'enableGui' with the
+ backend to use from PyCharm too -- in PyDev this is an option with the possible backends).
+
+
+Things to be fixed in PyDev:
+--------------------------------
+
+.Provide UI for 'smart step into' (later)
+
+. Check what to do with 'message' from xml (later)
+
+. Deal with sendSignatureCallTrace (later)
+
+. Set IPYTHONENABLE to False/True to use IPython console (later)
+
+
+Manual test:
+---------------
+
+* Support for IPython GUI event loop in console
+* Django template debugging
+* Gevent debugging
+* Smart step into
+* Collection of type information of arguments in debug mode
+* Ability to stop tracing
+* Ability to run debugger and console on remote interpreter
diff --git a/python/helpers/pydev/pycompletion.py b/python/helpers/pydev/pycompletion.py
index e706d5410f3d..33697806c102 100644
--- a/python/helpers/pydev/pycompletion.py
+++ b/python/helpers/pydev/pycompletion.py
@@ -2,12 +2,10 @@
'''
@author Radim Kubacki
'''
-import __builtin__
import _pydev_imports_tipper
import traceback
import StringIO
import sys
-import time
import urllib
import pycompletionserver
@@ -24,7 +22,7 @@ def GetImports(module_name):
except:
s = StringIO.StringIO()
exc_info = sys.exc_info()
-
+
traceback.print_exception(exc_info[0], exc_info[1], exc_info[2], limit=None, file=s)
err = s.getvalue()
pycompletionserver.dbg('Received error: ' + str(err), pycompletionserver.ERROR)
@@ -38,4 +36,4 @@ if __name__ == '__main__':
mod_name = sys.argv[1]
print(GetImports(mod_name))
-
+
diff --git a/python/helpers/pydev/pycompletionserver.py b/python/helpers/pydev/pycompletionserver.py
index 2fdd53903fb1..0b11cb6ff4f7 100644
--- a/python/helpers/pydev/pycompletionserver.py
+++ b/python/helpers/pydev/pycompletionserver.py
@@ -37,10 +37,7 @@ except ImportError:
import _pydev_imports_tipper
-if pydevd_constants.USE_LIB_COPY:
- import _pydev_socket as socket
-else:
- import socket
+from _pydev_imps import _pydev_socket as socket
import sys
if sys.platform == "darwin":
@@ -65,10 +62,7 @@ for name, mod in sys.modules.items():
import traceback
-if pydevd_constants.USE_LIB_COPY:
- import _pydev_time as time
-else:
- import time
+from _pydev_imps import _pydev_time as time
try:
import StringIO
@@ -93,7 +87,7 @@ def dbg(s, prior):
# f = open('c:/temp/test.txt', 'a')
# print_ >> f, s
# f.close()
-
+
import pydev_localhost
HOST = pydev_localhost.get_localhost() # Symbolic name meaning the local host
@@ -203,7 +197,7 @@ class T(Thread):
def connectToServer(self):
- import socket
+ from _pydev_imps import _pydev_socket as socket
self.socket = s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
diff --git a/python/helpers/pydev/pydev_console_utils.py b/python/helpers/pydev/pydev_console_utils.py
index 571ae871b3ab..bd7b7de073d2 100644
--- a/python/helpers/pydev/pydev_console_utils.py
+++ b/python/helpers/pydev/pydev_console_utils.py
@@ -1,36 +1,12 @@
-from pydev_imports import xmlrpclib
+from pydev_imports import xmlrpclib, _queue, Exec
import sys
-
-import traceback
-
from pydevd_constants import USE_LIB_COPY
from pydevd_constants import IS_JYTHON
-
-try:
- if USE_LIB_COPY:
- import _pydev_Queue as _queue
- else:
- import Queue as _queue
-except:
- import queue as _queue
-
-try:
- from pydevd_exec import Exec
-except:
- from pydevd_exec2 import Exec
-
-try:
- if USE_LIB_COPY:
- import _pydev_thread as thread
- else:
- import thread
-except:
- import _thread as thread
-
+from _pydev_imps import _pydev_thread as thread
import pydevd_xml
import pydevd_vars
-
-from pydevd_utils import *
+from pydevd_utils import * # @UnusedWildImport
+import traceback
#=======================================================================================================================
# Null
@@ -137,7 +113,7 @@ class CodeFragment:
def __init__(self, text, is_single_line=True):
self.text = text
self.is_single_line = is_single_line
-
+
def append(self, code_fragment):
self.text = self.text + "\n" + code_fragment.text
if not code_fragment.is_single_line:
@@ -173,9 +149,12 @@ class BaseInterpreterInterface:
self.buffer = code_fragment
else:
self.buffer.append(code_fragment)
-
+
return self.needMoreForCode(self.buffer.text)
+ def createStdIn(self):
+ return StdIn(self, self.host, self.client_port)
+
def addExec(self, code_fragment):
original_in = sys.stdin
try:
@@ -194,7 +173,7 @@ class BaseInterpreterInterface:
more = False
try:
- sys.stdin = StdIn(self, self.host, self.client_port)
+ sys.stdin = self.createStdIn()
try:
if help is not None:
#This will enable the help() function to work.
@@ -209,8 +188,6 @@ class BaseInterpreterInterface:
self._input_error_printed = True
sys.stderr.write('\nError when trying to update pydoc.help.input\n')
sys.stderr.write('(help() may not work -- please report this as a bug in the pydev bugtracker).\n\n')
- import traceback
-
traceback.print_exc()
try:
@@ -241,8 +218,6 @@ class BaseInterpreterInterface:
except SystemExit:
raise
except:
- import traceback;
-
traceback.print_exc()
return more
@@ -251,7 +226,7 @@ class BaseInterpreterInterface:
def doAddExec(self, codeFragment):
'''
Subclasses should override.
-
+
@return: more (True if more input is needed to complete the statement and False if the statement is complete).
'''
raise NotImplementedError()
@@ -260,7 +235,7 @@ class BaseInterpreterInterface:
def getNamespace(self):
'''
Subclasses should override.
-
+
@return: dict with namespace.
'''
raise NotImplementedError()
@@ -312,14 +287,14 @@ class BaseInterpreterInterface:
pass
try:
- #if no attempt succeeded, try to return repr()...
+ #if no attempt succeeded, try to return repr()...
return repr(obj)
except:
try:
- #otherwise the class
+ #otherwise the class
return str(obj.__class__)
except:
- #if all fails, go to an empty string
+ #if all fails, go to an empty string
return ''
except:
traceback.print_exc()
@@ -353,6 +328,7 @@ class BaseInterpreterInterface:
def interrupt(self):
+ self.buffer = None # Also clear the buffer when it's interrupted.
try:
if self.interruptable:
if hasattr(thread, 'interrupt_main'): #Jython doesn't have it
@@ -371,11 +347,13 @@ class BaseInterpreterInterface:
self.interruptable = True
def get_server(self):
- if self.host is not None:
+ if getattr(self, 'host', None) is not None:
return xmlrpclib.Server('http://%s:%s' % (self.host, self.client_port))
else:
return None
+ server = property(get_server)
+
def finishExec(self, more):
self.interruptable = False
@@ -409,7 +387,12 @@ class BaseInterpreterInterface:
return xml
def changeVariable(self, attr, value):
- Exec('%s=%s' % (attr, value), self.getNamespace(), self.getNamespace())
+ def do_change_variable():
+ Exec('%s=%s' % (attr, value), self.getNamespace(), self.getNamespace())
+
+ # Important: it has to be really enabled in the main thread, so, schedule
+ # it to run in the main thread.
+ self.exec_queue.put(do_change_variable)
def _findFrame(self, thread_id, frame_id):
'''
@@ -431,39 +414,48 @@ class BaseInterpreterInterface:
Used to show console with variables connection.
Mainly, monkey-patches things in the debugger structure so that the debugger protocol works.
'''
- try:
- # Try to import the packages needed to attach the debugger
- import pydevd
- import pydevd_vars
- import threading
- except:
- # This happens on Jython embedded in host eclipse
- import traceback;traceback.print_exc()
- return ('pydevd is not available, cannot connect',)
+ def do_connect_to_debugger():
+ try:
+ # Try to import the packages needed to attach the debugger
+ import pydevd
+ if USE_LIB_COPY:
+ import _pydev_threading as threading
+ else:
+ import threading
- import pydev_localhost
- threading.currentThread().__pydevd_id__ = "console_main"
+ except:
+ # This happens on Jython embedded in host eclipse
+ traceback.print_exc()
+ sys.stderr.write('pydevd is not available, cannot connect\n',)
- self.orig_findFrame = pydevd_vars.findFrame
- pydevd_vars.findFrame = self._findFrame
+ import pydev_localhost
+ threading.currentThread().__pydevd_id__ = "console_main"
- self.debugger = pydevd.PyDB()
- try:
- self.debugger.connect(pydev_localhost.get_localhost(), debuggerPort)
- self.debugger.prepareToRun()
- import pydevd_tracing
- pydevd_tracing.SetTrace(None)
- except:
- import traceback;traceback.print_exc()
- return ('Failed to connect to target debugger.')
+ self.orig_findFrame = pydevd_vars.findFrame
+ pydevd_vars.findFrame = self._findFrame
- # Register to process commands when idle
- self.debugrunning = False
- try:
- self.server.setDebugHook(self.debugger.processInternalCommands)
- except:
- import traceback;traceback.print_exc()
- return ('Version of Python does not support debuggable Interactive Console.')
+ self.debugger = pydevd.PyDB()
+ try:
+ self.debugger.connect(pydev_localhost.get_localhost(), debuggerPort)
+ self.debugger.prepareToRun()
+ import pydevd_tracing
+ pydevd_tracing.SetTrace(None)
+ except:
+ traceback.print_exc()
+ sys.stderr.write('Failed to connect to target debugger.\n')
+
+ # Register to process commands when idle
+ self.debugrunning = False
+ try:
+ import pydevconsole
+ pydevconsole.set_debug_hook(self.debugger.processInternalCommands)
+ except:
+ traceback.print_exc()
+ sys.stderr.write('Version of Python does not support debuggable Interactive Console.\n')
+
+ # Important: it has to be really enabled in the main thread, so, schedule
+ # it to run in the main thread.
+ self.exec_queue.put(do_connect_to_debugger)
return ('connect complete',)
@@ -476,19 +468,24 @@ class BaseInterpreterInterface:
As with IPython, enabling multiple GUIs isn't an error, but
only the last one's main loop runs and it may not work
'''
- from pydev_versioncheck import versionok_for_gui
- if versionok_for_gui():
- try:
- from pydev_ipython.inputhook import enable_gui
- enable_gui(guiname)
- except:
- sys.stderr.write("Failed to enable GUI event loop integration for '%s'\n" % guiname)
- import traceback;traceback.print_exc()
- elif guiname not in ['none', '', None]:
- # Only print a warning if the guiname was going to do something
- sys.stderr.write("PyDev console: Python version does not support GUI event loop integration for '%s'\n" % guiname)
- # Return value does not matter, so return back what was sent
- return guiname
+ def do_enable_gui():
+ from pydev_versioncheck import versionok_for_gui
+ if versionok_for_gui():
+ try:
+ from pydev_ipython.inputhook import enable_gui
+ enable_gui(guiname)
+ except:
+ sys.stderr.write("Failed to enable GUI event loop integration for '%s'\n" % guiname)
+ traceback.print_exc()
+ elif guiname not in ['none', '', None]:
+ # Only print a warning if the guiname was going to do something
+ sys.stderr.write("PyDev console: Python version does not support GUI event loop integration for '%s'\n" % guiname)
+ # Return value does not matter, so return back what was sent
+ return guiname
+
+ # Important: it has to be really enabled in the main thread, so, schedule
+ # it to run in the main thread.
+ self.exec_queue.put(do_enable_gui)
#=======================================================================================================================
# FakeFrame
diff --git a/python/helpers/pydev/pydev_coverage.py b/python/helpers/pydev/pydev_coverage.py
new file mode 100644
index 000000000000..1690f8ccc54f
--- /dev/null
+++ b/python/helpers/pydev/pydev_coverage.py
@@ -0,0 +1,54 @@
+def execute():
+ import os
+ import sys
+
+ files = None
+ if 'combine' not in sys.argv:
+
+ if '--pydev-analyze' in sys.argv:
+
+ #Ok, what we want here is having the files passed through stdin (because
+ #there may be too many files for passing in the command line -- we could
+ #just pass a dir and make the find files here, but as that's already
+ #given in the java side, let's just gather that info here).
+ sys.argv.remove('--pydev-analyze')
+ try:
+ s = raw_input()
+ except:
+ s = input()
+ s = s.replace('\r', '')
+ s = s.replace('\n', '')
+ files = s.split('|')
+ files = [v for v in files if len(v) > 0]
+
+ #Note that in this case we'll already be in the working dir with the coverage files, so, the
+ #coverage file location is not passed.
+
+ else:
+ #For all commands, the coverage file is configured in pydev, and passed as the first argument
+ #in the command line, so, let's make sure this gets to the coverage module.
+ os.environ['COVERAGE_FILE'] = sys.argv[1]
+ del sys.argv[1]
+
+ try:
+ import coverage #@UnresolvedImport
+ except:
+ sys.stderr.write('Error: coverage module could not be imported\n')
+ sys.stderr.write('Please make sure that the coverage module (http://nedbatchelder.com/code/coverage/)\n')
+ sys.stderr.write('is properly installed in your interpreter: %s\n' % (sys.executable,))
+
+ import traceback;traceback.print_exc()
+ return
+
+ #print(coverage.__version__) TODO: Check if the version is a version we support (should be at least 3.4) -- note that maybe the attr is not there.
+ from coverage.cmdline import main #@UnresolvedImport
+
+ if files is not None:
+ sys.argv.append('-r')
+ sys.argv.append('-m')
+ sys.argv += files
+
+ main()
+
+if __name__ == '__main__':
+ execute() \ No newline at end of file
diff --git a/python/helpers/pydev/pydev_imports.py b/python/helpers/pydev/pydev_imports.py
index 06858750c97d..69804a871eaf 100644
--- a/python/helpers/pydev/pydev_imports.py
+++ b/python/helpers/pydev/pydev_imports.py
@@ -1,40 +1,52 @@
-from pydevd_constants import USE_LIB_COPY
+from pydevd_constants import USE_LIB_COPY, izip
+
+
try:
try:
if USE_LIB_COPY:
- import _pydev_xmlrpclib as xmlrpclib
+ from _pydev_imps import _pydev_xmlrpclib as xmlrpclib
else:
import xmlrpclib
except ImportError:
import xmlrpc.client as xmlrpclib
except ImportError:
- import _pydev_xmlrpclib as xmlrpclib
+ from _pydev_imps import _pydev_xmlrpclib as xmlrpclib
+
+
try:
try:
if USE_LIB_COPY:
- from _pydev_SimpleXMLRPCServer import SimpleXMLRPCServer
+ from _pydev_imps._pydev_SimpleXMLRPCServer import SimpleXMLRPCServer
else:
from SimpleXMLRPCServer import SimpleXMLRPCServer
except ImportError:
from xmlrpc.server import SimpleXMLRPCServer
except ImportError:
- from _pydev_SimpleXMLRPCServer import SimpleXMLRPCServer
+ from _pydev_imps._pydev_SimpleXMLRPCServer import SimpleXMLRPCServer
+
+
+
try:
from StringIO import StringIO
except ImportError:
from io import StringIO
+
+
try:
execfile=execfile #Not in Py3k
except NameError:
- from _pydev_execfile import execfile
+ from _pydev_imps._pydev_execfile import execfile
+
+
try:
if USE_LIB_COPY:
- import _pydev_Queue as _queue
+ from _pydev_imps import _pydev_Queue as _queue
else:
import Queue as _queue
except:
import queue as _queue #@UnresolvedImport
+
try:
from pydevd_exec import Exec
except:
@@ -80,7 +92,7 @@ except:
return start
i = 0
- for start_seg, dest_seg in zip(orig_list, dest_list):
+ for start_seg, dest_seg in izip(orig_list, dest_list):
if start_seg != os.path.normcase(dest_seg):
break
i += 1
diff --git a/python/helpers/pydev/pydev_ipython/inputhookglut.py b/python/helpers/pydev/pydev_ipython/inputhookglut.py
index f0683ba5890e..e1e67e9930ed 100644
--- a/python/helpers/pydev/pydev_ipython/inputhookglut.py
+++ b/python/helpers/pydev/pydev_ipython/inputhookglut.py
@@ -29,9 +29,8 @@ GLUT Inputhook support functions
#-----------------------------------------------------------------------------
# Imports
#-----------------------------------------------------------------------------
-import os
import sys
-import time
+from _pydev_imps import _pydev_time as time
import signal
import OpenGL.GLUT as glut
import OpenGL.platform as platform
diff --git a/python/helpers/pydev/pydev_ipython/inputhookpyglet.py b/python/helpers/pydev/pydev_ipython/inputhookpyglet.py
index 0cbb87f34b6d..64dd2e559545 100644
--- a/python/helpers/pydev/pydev_ipython/inputhookpyglet.py
+++ b/python/helpers/pydev/pydev_ipython/inputhookpyglet.py
@@ -20,9 +20,8 @@ Authors
# Imports
#-----------------------------------------------------------------------------
-import os
import sys
-import time
+from _pydev_imps import _pydev_time as time
from timeit import default_timer as clock
import pyglet
from pydev_ipython.inputhook import stdin_ready
diff --git a/python/helpers/pydev/pydev_ipython/inputhookqt4.py b/python/helpers/pydev/pydev_ipython/inputhookqt4.py
index f4f32a344e8a..27598fa742fe 100644
--- a/python/helpers/pydev/pydev_ipython/inputhookqt4.py
+++ b/python/helpers/pydev/pydev_ipython/inputhookqt4.py
@@ -18,7 +18,13 @@ Author: Christian Boos
import os
import signal
-import threading
+
+from pydevd_constants import USE_LIB_COPY
+if USE_LIB_COPY:
+ import _pydev_threading as threading
+else:
+ import threading
+
from pydev_ipython.qt_for_kernel import QtCore, QtGui
from pydev_ipython.inputhook import allow_CTRL_C, ignore_CTRL_C, stdin_ready
diff --git a/python/helpers/pydev/pydev_ipython/inputhookwx.py b/python/helpers/pydev/pydev_ipython/inputhookwx.py
index 6640884663ad..19ffdc72eff9 100644
--- a/python/helpers/pydev/pydev_ipython/inputhookwx.py
+++ b/python/helpers/pydev/pydev_ipython/inputhookwx.py
@@ -19,7 +19,7 @@ Authors: Robin Dunn, Brian Granger, Ondrej Certik
import sys
import signal
-import time
+from _pydev_imps import _pydev_time as time
from timeit import default_timer as clock
import wx
diff --git a/python/helpers/pydev/pydev_ipython_console.py b/python/helpers/pydev/pydev_ipython_console.py
index 859157e022ad..0c51dfe3ed44 100644
--- a/python/helpers/pydev/pydev_ipython_console.py
+++ b/python/helpers/pydev/pydev_ipython_console.py
@@ -1,20 +1,15 @@
import sys
from pydev_console_utils import BaseInterpreterInterface
-import re
import os
os.environ['TERM'] = 'emacs' #to use proper page_more() for paging
-#Uncomment to force PyDev standard shell.
-#raise ImportError()
+# Uncomment to force PyDev standard shell.
+# raise ImportError()
-try:
- #IPython 0.11 broke compatibility...
- from pydev_ipython_console_011 import PyDevFrontEnd
-except:
- from pydev_ipython_console_010 import PyDevFrontEnd
+from pydev_ipython_console_011 import PyDevFrontEnd
#=======================================================================================================================
# InterpreterInterface
@@ -28,7 +23,7 @@ class InterpreterInterface(BaseInterpreterInterface):
BaseInterpreterInterface.__init__(self, mainThread)
self.client_port = client_port
self.host = host
- self.interpreter = PyDevFrontEnd()
+ self.interpreter = PyDevFrontEnd(host, client_port)
self._input_error_printed = False
self.notification_succeeded = False
self.notification_tries = 0
@@ -57,58 +52,11 @@ class InterpreterInterface(BaseInterpreterInterface):
def getCompletions(self, text, act_tok):
- try:
- ipython_completion = text.startswith('%')
- if not ipython_completion:
- s = re.search(r'\bcd\b', text)
- if s is not None and s.start() == 0:
- ipython_completion = True
-
- if text is None:
- text = ""
-
- TYPE_LOCAL = '9'
- _line, completions = self.interpreter.complete(text)
-
- ret = []
- append = ret.append
- for completion in completions:
- if completion.startswith('%'):
- append((completion[1:], '', '%', TYPE_LOCAL))
- else:
- append((completion, '', '', TYPE_LOCAL))
-
- if ipython_completion:
- return ret
-
- #Otherwise, use the default PyDev completer (to get nice icons)
- from _pydev_completer import Completer
-
- completer = Completer(self.getNamespace(), None)
- completions = completer.complete(act_tok)
- cset = set()
- for c in completions:
- cset.add(c[0])
- for c in ret:
- if c[0] not in cset:
- completions.append(c)
-
- return completions
-
- except:
- import traceback
-
- traceback.print_exc()
- return []
+ return self.interpreter.getCompletions(text, act_tok)
def close(self):
sys.exit(0)
- def ipython_editor(self, file, line):
- server = self.get_server()
-
- if server is not None:
- return server.IPythonEditor(os.path.realpath(file), line)
def notify_about_magic(self):
if not self.notification_succeeded:
diff --git a/python/helpers/pydev/pydev_ipython_console_010.py b/python/helpers/pydev/pydev_ipython_console_010.py
deleted file mode 100644
index e093fefe9a32..000000000000
--- a/python/helpers/pydev/pydev_ipython_console_010.py
+++ /dev/null
@@ -1,129 +0,0 @@
-from IPython.frontend.prefilterfrontend import PrefilterFrontEnd
-from pydev_console_utils import Null
-import sys
-original_stdout = sys.stdout
-original_stderr = sys.stderr
-
-
-#=======================================================================================================================
-# PyDevFrontEnd
-#=======================================================================================================================
-class PyDevFrontEnd(PrefilterFrontEnd):
-
-
- def __init__(self, *args, **kwargs):
- PrefilterFrontEnd.__init__(self, *args, **kwargs)
- #Disable the output trap: we want all that happens to go to the output directly
- self.shell.output_trap = Null()
- self._curr_exec_lines = []
- self._continuation_prompt = ''
-
-
- def capture_output(self):
- pass
-
-
- def release_output(self):
- pass
-
-
- def continuation_prompt(self):
- return self._continuation_prompt
-
-
- def write(self, txt, refresh=True):
- original_stdout.write(txt)
-
-
- def new_prompt(self, prompt):
- self.input_buffer = ''
- #The java side takes care of this part.
- #self.write(prompt)
-
-
- def show_traceback(self):
- import traceback;traceback.print_exc()
-
-
- def write_out(self, txt, *args, **kwargs):
- original_stdout.write(txt)
-
-
- def write_err(self, txt, *args, **kwargs):
- original_stderr.write(txt)
-
-
- def getNamespace(self):
- return self.shell.user_ns
-
-
- def is_complete(self, string):
- #Based on IPython 0.10.1
-
- if string in ('', '\n'):
- # Prefiltering, eg through ipython0, may return an empty
- # string although some operations have been accomplished. We
- # thus want to consider an empty string as a complete
- # statement.
- return True
- else:
- try:
- # Add line returns here, to make sure that the statement is
- # complete (except if '\' was used).
- # This should probably be done in a different place (like
- # maybe 'prefilter_input' method? For now, this works.
- clean_string = string.rstrip('\n')
- if not clean_string.endswith('\\'): clean_string += '\n\n'
- is_complete = codeop.compile_command(clean_string,
- "<string>", "exec")
- except Exception:
- # XXX: Hack: return True so that the
- # code gets executed and the error captured.
- is_complete = True
- return is_complete
-
-
- def addExec(self, line):
- if self._curr_exec_lines:
- if not line:
- self._curr_exec_lines.append(line)
-
- #Would be the line below, but we've set the continuation_prompt to ''.
- #buf = self.continuation_prompt() + ('\n' + self.continuation_prompt()).join(self._curr_exec_lines)
- buf = '\n'.join(self._curr_exec_lines)
-
- self.input_buffer = buf + '\n'
- if self._on_enter():
- del self._curr_exec_lines[:]
- return False #execute complete (no more)
-
- return True #needs more
- else:
- self._curr_exec_lines.append(line)
- return True #needs more
-
- else:
-
- self.input_buffer = line
- if not self._on_enter():
- #Did not execute
- self._curr_exec_lines.append(line)
- return True #needs more
-
- return False #execute complete (no more)
-
- def update(self, globals, locals):
- locals['_oh'] = self.shell.user_ns['_oh']
- locals['_ip'] = self.shell.user_ns['_ip']
- self.shell.user_global_ns = globals
- self.shell.user_ns = locals
-
- def is_automagic(self):
- if self.ipython0.rc.automagic:
- return True
- else:
- return False
-
- def get_greeting_msg(self):
- return 'PyDev console: using IPython 0.10\n'
-
diff --git a/python/helpers/pydev/pydev_ipython_console_011.py b/python/helpers/pydev/pydev_ipython_console_011.py
index 198d40f07ec7..54458e7c4af5 100644
--- a/python/helpers/pydev/pydev_ipython_console_011.py
+++ b/python/helpers/pydev/pydev_ipython_console_011.py
@@ -1,23 +1,295 @@
+# TODO that would make IPython integration better
+# - show output other times then when enter was pressed
+# - support proper exit to allow IPython to cleanup (e.g. temp files created with %edit)
+# - support Ctrl-D (Ctrl-Z on Windows)
+# - use IPython (numbered) prompts in PyDev
+# - better integration of IPython and PyDev completions
+# - some of the semantics on handling the code completion are not correct:
+# eg: Start a line with % and then type c should give %cd as a completion by it doesn't
+# however type %c and request completions and %cd is given as an option
+# eg: Completing a magic when user typed it without the leading % causes the % to be inserted
+# to the left of what should be the first colon.
+"""Interface to TerminalInteractiveShell for PyDev Interactive Console frontend
+ for IPython 0.11 to 1.0+.
+"""
+
+from __future__ import print_function
+
+import os
+import codeop
+
+from IPython.core.error import UsageError
+from IPython.core.inputsplitter import IPythonInputSplitter
+from IPython.core.completer import IPCompleter
+from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC
+from IPython.core.usage import default_banner_parts
+from IPython.utils.strdispatch import StrDispatch
+import IPython.core.release as IPythonRelease
try:
from IPython.terminal.interactiveshell import TerminalInteractiveShell
except ImportError:
+ # Versions of IPython [0.11,1.0) had an extra hierarchy level
from IPython.frontend.terminal.interactiveshell import TerminalInteractiveShell
-from IPython.utils import io
-import sys
-import codeop, re
-original_stdout = sys.stdout
-original_stderr = sys.stderr
+from IPython.utils.traitlets import CBool, Unicode
from IPython.core import release
+from pydev_imports import xmlrpclib
+
+pydev_banner_parts = [
+ '\n',
+ 'PyDev -- Python IDE for Eclipse\n', # TODO can we get a version number in here?
+ 'For help on using PyDev\'s Console see http://pydev.org/manual_adv_interactive_console.html\n',
+]
+
+default_pydev_banner_parts = default_banner_parts + pydev_banner_parts
+
+default_pydev_banner = ''.join(default_pydev_banner_parts)
+
+def show_in_pager(self, strng):
+ """ Run a string through pager """
+ # On PyDev we just output the string, there are scroll bars in the console
+ # to handle "paging". This is the same behaviour as when TERM==dump (see
+ # page.py)
+ print(strng)
+
+def create_editor_hook(pydev_host, pydev_client_port):
+ def call_editor(self, filename, line=0, wait=True):
+ """ Open an editor in PyDev """
+ if line is None:
+ line = 0
+
+ # Make sure to send an absolution path because unlike most editor hooks
+ # we don't launch a process. This is more like what happens in the zmqshell
+ filename = os.path.abspath(filename)
+
+ # Tell PyDev to open the editor
+ server = xmlrpclib.Server('http://%s:%s' % (pydev_host, pydev_client_port))
+ server.IPythonEditor(filename, str(line))
+
+ if wait:
+ try:
+ raw_input("Press Enter when done editing:")
+ except NameError:
+ input("Press Enter when done editing:")
+ return call_editor
+
+
+
+class PyDevIPCompleter(IPCompleter):
+
+ def __init__(self, *args, **kwargs):
+ """ Create a Completer that reuses the advanced completion support of PyDev
+ in addition to the completion support provided by IPython """
+ IPCompleter.__init__(self, *args, **kwargs)
+ # Use PyDev for python matches, see getCompletions below
+ self.matchers.remove(self.python_matches)
+
+class PyDevTerminalInteractiveShell(TerminalInteractiveShell):
+ banner1 = Unicode(default_pydev_banner, config=True,
+ help="""The part of the banner to be printed before the profile"""
+ )
+
+ # TODO term_title: (can PyDev's title be changed???, see terminal.py for where to inject code, in particular set_term_title as used by %cd)
+ # for now, just disable term_title
+ term_title = CBool(False)
+
+ # Note in version 0.11 there is no guard in the IPython code about displaying a
+ # warning, so with 0.11 you get:
+ # WARNING: Readline services not available or not loaded.
+ # WARNING: The auto-indent feature requires the readline library
+ # Disable readline, readline type code is all handled by PyDev (on Java side)
+ readline_use = CBool(False)
+ # autoindent has no meaning in PyDev (PyDev always handles that on the Java side),
+ # and attempting to enable it will print a warning in the absence of readline.
+ autoindent = CBool(False)
+ # Force console to not give warning about color scheme choice and default to NoColor.
+ # TODO It would be nice to enable colors in PyDev but:
+ # - The PyDev Console (Eclipse Console) does not support the full range of colors, so the
+ # effect isn't as nice anyway at the command line
+ # - If done, the color scheme should default to LightBG, but actually be dependent on
+ # any settings the user has (such as if a dark theme is in use, then Linux is probably
+ # a better theme).
+ colors_force = CBool(True)
+ colors = Unicode("NoColor")
+
+ # In the PyDev Console, GUI control is done via hookable XML-RPC server
+ @staticmethod
+ def enable_gui(gui=None, app=None):
+ """Switch amongst GUI input hooks by name.
+ """
+ # Deferred import
+ from pydev_ipython.inputhook import enable_gui as real_enable_gui
+ try:
+ return real_enable_gui(gui, app)
+ except ValueError as e:
+ raise UsageError("%s" % e)
+
+ #-------------------------------------------------------------------------
+ # Things related to hooks
+ #-------------------------------------------------------------------------
+
+ def init_hooks(self):
+ super(PyDevTerminalInteractiveShell, self).init_hooks()
+ self.set_hook('show_in_pager', show_in_pager)
+
+ #-------------------------------------------------------------------------
+ # Things related to exceptions
+ #-------------------------------------------------------------------------
+
+ def showtraceback(self, exc_tuple=None, filename=None, tb_offset=None,
+ exception_only=False):
+ # IPython does a lot of clever stuff with Exceptions. However mostly
+ # it is related to IPython running in a terminal instead of an IDE.
+ # (e.g. it prints out snippets of code around the stack trace)
+ # PyDev does a lot of clever stuff too, so leave exception handling
+ # with default print_exc that PyDev can parse and do its clever stuff
+ # with (e.g. it puts links back to the original source code)
+ import traceback;traceback.print_exc()
+
+
+ #-------------------------------------------------------------------------
+ # Things related to text completion
+ #-------------------------------------------------------------------------
+
+ # The way to construct an IPCompleter changed in most versions,
+ # so we have a custom, per version implementation of the construction
+
+ def _new_completer_011(self):
+ return PyDevIPCompleter(self,
+ self.user_ns,
+ self.user_global_ns,
+ self.readline_omit__names,
+ self.alias_manager.alias_table,
+ self.has_readline)
+
+
+ def _new_completer_012(self):
+ completer = PyDevIPCompleter(shell=self,
+ namespace=self.user_ns,
+ global_namespace=self.user_global_ns,
+ alias_table=self.alias_manager.alias_table,
+ use_readline=self.has_readline,
+ config=self.config,
+ )
+ self.configurables.append(completer)
+ return completer
+
+
+ def _new_completer_100(self):
+ completer = PyDevIPCompleter(shell=self,
+ namespace=self.user_ns,
+ global_namespace=self.user_global_ns,
+ alias_table=self.alias_manager.alias_table,
+ use_readline=self.has_readline,
+ parent=self,
+ )
+ self.configurables.append(completer)
+ return completer
+
+ def _new_completer_200(self):
+ # As of writing this, IPython 2.0.0 is in dev mode so subject to change
+ completer = PyDevIPCompleter(shell=self,
+ namespace=self.user_ns,
+ global_namespace=self.user_global_ns,
+ use_readline=self.has_readline,
+ parent=self,
+ )
+ self.configurables.append(completer)
+ return completer
+
+
+
+ def init_completer(self):
+ """Initialize the completion machinery.
+
+ This creates a completer that provides the completions that are
+ IPython specific. We use this to supplement PyDev's core code
+ completions.
+ """
+ # PyDev uses its own completer and custom hooks so that it uses
+ # most completions from PyDev's core completer which provides
+ # extra information.
+ # See getCompletions for where the two sets of results are merged
+
+ from IPython.core.completerlib import magic_run_completer, cd_completer
+ try:
+ from IPython.core.completerlib import reset_completer
+ except ImportError:
+ # reset_completer was added for rel-0.13
+ reset_completer = None
+
+ if IPythonRelease._version_major >= 2:
+ self.Completer = self._new_completer_200()
+ elif IPythonRelease._version_major >= 1:
+ self.Completer = self._new_completer_100()
+ elif IPythonRelease._version_minor >= 12:
+ self.Completer = self._new_completer_012()
+ else:
+ self.Completer = self._new_completer_011()
+
+ # Add custom completers to the basic ones built into IPCompleter
+ sdisp = self.strdispatchers.get('complete_command', StrDispatch())
+ self.strdispatchers['complete_command'] = sdisp
+ self.Completer.custom_completers = sdisp
+
+ self.set_hook('complete_command', magic_run_completer, str_key='%run')
+ self.set_hook('complete_command', cd_completer, str_key='%cd')
+ if reset_completer:
+ self.set_hook('complete_command', reset_completer, str_key='%reset')
+
+ # Only configure readline if we truly are using readline. IPython can
+ # do tab-completion over the network, in GUIs, etc, where readline
+ # itself may be absent
+ if self.has_readline:
+ self.set_readline_completer()
+
+
+ #-------------------------------------------------------------------------
+ # Things related to aliases
+ #-------------------------------------------------------------------------
+
+ def init_alias(self):
+ # InteractiveShell defines alias's we want, but TerminalInteractiveShell defines
+ # ones we don't. So don't use super and instead go right to InteractiveShell
+ InteractiveShell.init_alias(self)
+
+ #-------------------------------------------------------------------------
+ # Things related to exiting
+ #-------------------------------------------------------------------------
+ def ask_exit(self):
+ """ Ask the shell to exit. Can be overiden and used as a callback. """
+ # TODO PyDev's console does not have support from the Python side to exit
+ # the console. If user forces the exit (with sys.exit()) then the console
+ # simply reports errors. e.g.:
+ # >>> import sys
+ # >>> sys.exit()
+ # Failed to create input stream: Connection refused
+ # >>>
+ # Console already exited with value: 0 while waiting for an answer.
+ # Error stream:
+ # Output stream:
+ # >>>
+ #
+ # Alternatively if you use the non-IPython shell this is what happens
+ # >>> exit()
+ # <type 'exceptions.SystemExit'>:None
+ # >>>
+ # <type 'exceptions.SystemExit'>:None
+ # >>>
+ #
+ super(PyDevTerminalInteractiveShell, self).ask_exit()
+ print('To exit the PyDev Console, terminate the console within Eclipse.')
+
+ #-------------------------------------------------------------------------
+ # Things related to magics
+ #-------------------------------------------------------------------------
+
+ def init_magics(self):
+ super(PyDevTerminalInteractiveShell, self).init_magics()
+ # TODO Any additional magics for PyDev?
+
+InteractiveShellABC.register(PyDevTerminalInteractiveShell) # @UndefinedVariable
-#=======================================================================================================================
-# _showtraceback
-#=======================================================================================================================
-def _showtraceback(*args, **kwargs):
- import traceback;traceback.print_exc()
-
-
-
#=======================================================================================================================
# PyDevFrontEnd
#=======================================================================================================================
@@ -25,49 +297,23 @@ class PyDevFrontEnd:
version = release.__version__
-
- def __init__(self, *args, **kwargs):
- #Initialization based on: from IPython.testing.globalipapp import start_ipython
-
- self._curr_exec_line = 0
- # Store certain global objects that IPython modifies
- _displayhook = sys.displayhook
- _excepthook = sys.excepthook
-
- class ClosablePyDevTerminalInteractiveShell(TerminalInteractiveShell):
- '''Override ask_exit() method for correct exit, exit(), etc. handling.'''
- def ask_exit(self):
- sys.exit()
+ def __init__(self, pydev_host, pydev_client_port, *args, **kwarg):
# Create and initialize our IPython instance.
- shell = ClosablePyDevTerminalInteractiveShell.instance()
-
- shell.showtraceback = _showtraceback
- # IPython is ready, now clean up some global state...
-
- # Deactivate the various python system hooks added by ipython for
- # interactive convenience so we don't confuse the doctest system
- sys.displayhook = _displayhook
- sys.excepthook = _excepthook
-
- # So that ipython magics and aliases can be doctested (they work by making
- # a call into a global _ip object). Also make the top-level get_ipython
- # now return this without recursively calling here again.
- get_ipython = shell.get_ipython
- try:
- import __builtin__
- except:
- import builtins as __builtin__
- __builtin__._ip = shell
- __builtin__.get_ipython = get_ipython
+ self.ipython = PyDevTerminalInteractiveShell.instance()
+
+ # Back channel to PyDev to open editors (in the future other
+ # info may go back this way. This is the same channel that is
+ # used to get stdin, see StdIn in pydev_console_utils)
+ self.ipython.set_hook('editor', create_editor_hook(pydev_host, pydev_client_port))
- # We want to print to stdout/err as usual.
- io.stdout = original_stdout
- io.stderr = original_stderr
+ # Display the IPython banner, this has version info and
+ # help info
+ self.ipython.show_banner()
+ self._curr_exec_line = 0
self._curr_exec_lines = []
- self.ipython = shell
def update(self, globals, locals):
@@ -95,7 +341,7 @@ class PyDevFrontEnd:
def is_complete(self, string):
#Based on IPython 0.10.1
-
+
if string in ('', '\n'):
# Prefiltering, eg through ipython0, may return an empty
# string although some operations have been accomplished. We
@@ -109,20 +355,64 @@ class PyDevFrontEnd:
# This should probably be done in a different place (like
# maybe 'prefilter_input' method? For now, this works.
clean_string = string.rstrip('\n')
- if not clean_string.endswith('\\'): clean_string += '\n\n'
- is_complete = codeop.compile_command(clean_string,
- "<string>", "exec")
+ if not clean_string.endswith('\\'):
+ clean_string += '\n\n'
+
+ is_complete = codeop.compile_command(
+ clean_string,
+ "<string>",
+ "exec"
+ )
except Exception:
# XXX: Hack: return True so that the
# code gets executed and the error captured.
is_complete = True
return is_complete
-
-
+
+
+ def getCompletions(self, text, act_tok):
+ # Get completions from IPython and from PyDev and merge the results
+ # IPython only gives context free list of completions, while PyDev
+ # gives detailed information about completions.
+ try:
+ TYPE_IPYTHON = '11'
+ TYPE_IPYTHON_MAGIC = '12'
+ _line, ipython_completions = self.complete(text)
+
+ from _pydev_completer import Completer
+ completer = Completer(self.getNamespace(), None)
+ ret = completer.complete(act_tok)
+ append = ret.append
+ ip = self.ipython
+ pydev_completions = set([f[0] for f in ret])
+ for ipython_completion in ipython_completions:
+
+ #PyCharm was not expecting completions with '%'...
+ #Could be fixed in the backend, but it's probably better
+ #fixing it at PyCharm.
+ #if ipython_completion.startswith('%'):
+ # ipython_completion = ipython_completion[1:]
+
+ if ipython_completion not in pydev_completions:
+ pydev_completions.add(ipython_completion)
+ inf = ip.object_inspect(ipython_completion)
+ if inf['type_name'] == 'Magic function':
+ pydev_type = TYPE_IPYTHON_MAGIC
+ else:
+ pydev_type = TYPE_IPYTHON
+ pydev_doc = inf['docstring']
+ if pydev_doc is None:
+ pydev_doc = ''
+ append((ipython_completion, pydev_doc, '', pydev_type))
+ return ret
+ except:
+ import traceback;traceback.print_exc()
+ return []
+
+
def getNamespace(self):
return self.ipython.user_ns
-
def addExec(self, line):
if self._curr_exec_lines:
self._curr_exec_lines.append(line)
@@ -155,5 +445,21 @@ class PyDevFrontEnd:
return self.ipython.automagic
def get_greeting_msg(self):
- return 'PyDev console: using IPython %s' % self.version
+ return 'PyDev console: using IPython %s\n' % self.version
+
+# If we have succeeded in importing this module, then monkey patch inputhook
+# in IPython to redirect to PyDev's version. This is essential to make
+# %gui in 0.11 work (0.12+ fixes it by calling self.enable_gui, which is implemented
+# above, instead of inputhook.enable_gui).
+# See testGui (test_pydev_ipython_011.TestRunningCode) which fails on 0.11 without
+# this patch
+import IPython.lib.inputhook
+import pydev_ipython.inputhook
+IPython.lib.inputhook.enable_gui = pydev_ipython.inputhook.enable_gui
+# In addition to enable_gui, make all publics in pydev_ipython.inputhook replace
+# the IPython versions. This enables the examples in IPython's examples/lib/gui-*
+# to operate properly because those examples don't use %gui magic and instead
+# rely on using the inputhooks directly.
+for name in pydev_ipython.inputhook.__all__:
+ setattr(IPython.lib.inputhook, name, getattr(pydev_ipython.inputhook, name))
diff --git a/python/helpers/pydev/pydev_localhost.py b/python/helpers/pydev/pydev_localhost.py
index 4e7a4d95fc12..13c4d02bba9e 100644
--- a/python/helpers/pydev/pydev_localhost.py
+++ b/python/helpers/pydev/pydev_localhost.py
@@ -1,21 +1,18 @@
-import pydevd_constants
-if pydevd_constants.USE_LIB_COPY:
- import _pydev_socket as socket
-else:
- import socket
+
+from _pydev_imps import _pydev_socket as socket
_cache = None
def get_localhost():
'''
Should return 127.0.0.1 in ipv4 and ::1 in ipv6
-
+
localhost is not used because on windows vista/windows 7, there can be issues where the resolving doesn't work
- properly and takes a lot of time (had this issue on the pyunit server).
-
+ properly and takes a lot of time (had this issue on the pyunit server).
+
Using the IP directly solves the problem.
'''
#TODO: Needs better investigation!
-
+
global _cache
if _cache is None:
try:
diff --git a/python/helpers/pydev/pydev_monkey.py b/python/helpers/pydev/pydev_monkey.py
index ed6fea53ff58..2b12ed27522c 100644
--- a/python/helpers/pydev/pydev_monkey.py
+++ b/python/helpers/pydev/pydev_monkey.py
@@ -1,10 +1,11 @@
import os
-import shlex
import sys
import pydev_log
import traceback
-helpers = os.path.dirname(__file__).replace('\\', '/')
+pydev_src_dir = os.path.dirname(__file__)
+
+from pydevd_constants import xrange
def is_python(path):
if path.endswith("'") or path.endswith('"'):
@@ -38,7 +39,9 @@ def patch_args(args):
if port is not None:
new_args.extend(args)
- new_args[indC + 1] = "import sys; sys.path.append('%s'); import pydevd; pydevd.settrace(host='%s', port=%s, suspend=False); %s"%(helpers, host, port, args[indC + 1])
+ new_args[indC + 1] = ("import sys; sys.path.append(r'%s'); import pydevd; "
+ "pydevd.settrace(host='%s', port=%s, suspend=False, trace_only_current_thread=False, patch_multiprocessing=True); %s") % (
+ pydev_src_dir, host, port, args[indC + 1])
return new_args
else:
new_args.append(args[0])
@@ -52,14 +55,14 @@ def patch_args(args):
new_args.append(args[i])
else:
break
- i+=1
+ i += 1
if args[i].endswith('pydevd.py'): #no need to add pydevd twice
return args
for x in sys.original_argv:
if sys.platform == "win32" and not x.endswith('"'):
- arg = '"%s"'%x
+ arg = '"%s"' % x
else:
arg = x
new_args.append(arg)
@@ -68,7 +71,7 @@ def patch_args(args):
while i < len(args):
new_args.append(args[i])
- i+=1
+ i += 1
return new_args
except:
@@ -82,26 +85,101 @@ def args_to_str(args):
if x.startswith('"') and x.endswith('"'):
quoted_args.append(x)
else:
+ x = x.replace('"', '\\"')
quoted_args.append('"%s"' % x)
return ' '.join(quoted_args)
-def remove_quotes(str):
- if str.startswith('"') and str.endswith('"'):
- return str[1:-1]
- else:
- return str
-def str_to_args(str):
- return [remove_quotes(x) for x in shlex.split(str)]
+def str_to_args_windows(args):
+ # see http:#msdn.microsoft.com/en-us/library/a1y7w461.aspx
+ result = []
+
+ DEFAULT = 0
+ ARG = 1
+ IN_DOUBLE_QUOTE = 2
+
+ state = DEFAULT
+ backslashes = 0
+ buf = ''
+
+ args_len = len(args)
+ for i in xrange(args_len):
+ ch = args[i]
+ if (ch == '\\'):
+ backslashes+=1
+ continue
+ elif (backslashes != 0):
+ if ch == '"':
+ while backslashes >= 2:
+ backslashes -= 2
+ buf += '\\'
+ if (backslashes == 1):
+ if (state == DEFAULT):
+ state = ARG
+
+ buf += '"'
+ backslashes = 0
+ continue
+ # else fall through to switch
+ else:
+ # false alarm, treat passed backslashes literally...
+ if (state == DEFAULT):
+ state = ARG
+
+ while backslashes > 0:
+ backslashes-=1
+ buf += '\\'
+ # fall through to switch
+ if ch in (' ', '\t'):
+ if (state == DEFAULT):
+ # skip
+ continue
+ elif (state == ARG):
+ state = DEFAULT
+ result.append(buf)
+ buf = ''
+ continue
+
+ if state in (DEFAULT, ARG):
+ if ch == '"':
+ state = IN_DOUBLE_QUOTE
+ else:
+ state = ARG
+ buf += ch
+
+ elif state == IN_DOUBLE_QUOTE:
+ if ch == '"':
+ if (i + 1 < args_len and args[i + 1] == '"'):
+ # Undocumented feature in Windows:
+ # Two consecutive double quotes inside a double-quoted argument are interpreted as
+ # a single double quote.
+ buf += '"'
+ i+=1
+ elif len(buf) == 0:
+ # empty string on Windows platform. Account for bug in constructor of JDK's java.lang.ProcessImpl.
+ result.append("\"\"")
+ state = DEFAULT
+ else:
+ state = ARG
+ else:
+ buf += ch
+
+ else:
+ raise RuntimeError('Illegal condition')
+
+ if len(buf) > 0 or state != DEFAULT:
+ result.append(buf)
+
+ return result
+
def patch_arg_str_win(arg_str):
- new_arg_str = arg_str.replace('\\', '/')
- args = str_to_args(new_arg_str)
+ args = str_to_args_windows(arg_str)
if not is_python(args[0]):
return arg_str
arg_str = args_to_str(patch_args(args))
- pydev_log.debug("New args: %s"% arg_str)
+ pydev_log.debug("New args: %s" % arg_str)
return arg_str
def monkey_patch_module(module, funcname, create_func):
@@ -120,7 +198,8 @@ def warn_multiproc():
import pydev_log
pydev_log.error_once(
- "New process is launching. Breakpoints won't work.\n To debug that process please enable 'Attach to subprocess automatically while debugging' option in the debugger settings.\n")
+ "pydev debugger: New process is launching (breakpoints won't work in the new process).\n"
+ "pydev debugger: To debug that process please enable 'Attach to subprocess automatically while debugging?' option in the debugger settings.\n")
def create_warn_multiproc(original_name):
@@ -308,3 +387,110 @@ def patch_new_process_functions_with_warning():
except ImportError:
import _winapi as _subprocess
monkey_patch_module(_subprocess, 'CreateProcess', create_CreateProcessWarnMultiproc)
+
+
+
+class _NewThreadStartupWithTrace:
+
+ def __init__(self, original_func):
+ self.original_func = original_func
+
+ def __call__(self, *args, **kwargs):
+ from pydevd_comm import GetGlobalDebugger
+ global_debugger = GetGlobalDebugger()
+ if global_debugger is not None:
+ global_debugger.SetTrace(global_debugger.trace_dispatch)
+
+ return self.original_func(*args, **kwargs)
+
+class _NewThreadStartupWithoutTrace:
+
+ def __init__(self, original_func):
+ self.original_func = original_func
+
+ def __call__(self, *args, **kwargs):
+ return self.original_func(*args, **kwargs)
+
+_UseNewThreadStartup = _NewThreadStartupWithTrace
+
+def _get_threading_modules():
+ threading_modules = []
+ from _pydev_imps import _pydev_thread
+ threading_modules.append(_pydev_thread)
+ try:
+ import thread as _thread
+ threading_modules.append(_thread)
+ except:
+ import _thread
+ threading_modules.append(_thread)
+ return threading_modules
+
+threading_modules = _get_threading_modules()
+
+
+
+def patch_thread_module(thread):
+
+ if getattr(thread, '_original_start_new_thread', None) is None:
+ _original_start_new_thread = thread._original_start_new_thread = thread.start_new_thread
+ else:
+ _original_start_new_thread = thread._original_start_new_thread
+
+
+ class ClassWithPydevStartNewThread:
+
+ def pydev_start_new_thread(self, function, args, kwargs={}):
+ '''
+ We need to replace the original thread.start_new_thread with this function so that threads started
+ through it and not through the threading module are properly traced.
+ '''
+ return _original_start_new_thread(_UseNewThreadStartup(function), args, kwargs)
+
+ # This is a hack for the situation where the thread.start_new_thread is declared inside a class, such as the one below
+ # class F(object):
+ # start_new_thread = thread.start_new_thread
+ #
+ # def start_it(self):
+ # self.start_new_thread(self.function, args, kwargs)
+ # So, if it's an already bound method, calling self.start_new_thread won't really receive a different 'self' -- it
+ # does work in the default case because in builtins self isn't passed either.
+ pydev_start_new_thread = ClassWithPydevStartNewThread().pydev_start_new_thread
+
+ try:
+ # We need to replace the original thread.start_new_thread with this function so that threads started through
+ # it and not through the threading module are properly traced.
+ thread.start_new_thread = pydev_start_new_thread
+ thread.start_new = pydev_start_new_thread
+ except:
+ pass
+
+def patch_thread_modules():
+ for t in threading_modules:
+ patch_thread_module(t)
+
+def undo_patch_thread_modules():
+ for t in threading_modules:
+ try:
+ t.start_new_thread = t._original_start_new_thread
+ except:
+ pass
+
+ try:
+ t.start_new = t._original_start_new_thread
+ except:
+ pass
+
+def disable_trace_thread_modules():
+ '''
+ Can be used to temporarily stop tracing threads created with thread.start_new_thread.
+ '''
+ global _UseNewThreadStartup
+ _UseNewThreadStartup = _NewThreadStartupWithoutTrace
+
+
+def enable_trace_thread_modules():
+ '''
+ Can be used to start tracing threads created with thread.start_new_thread again.
+ '''
+ global _UseNewThreadStartup
+ _UseNewThreadStartup = _NewThreadStartupWithTrace
diff --git a/python/helpers/pydev/pydev_override.py b/python/helpers/pydev/pydev_override.py
new file mode 100644
index 000000000000..bb0c50438125
--- /dev/null
+++ b/python/helpers/pydev/pydev_override.py
@@ -0,0 +1,49 @@
+def overrides(method):
+ '''
+ Initially meant to be used as
+
+ class B:
+ @overrides(A.m1)
+ def m1(self):
+ pass
+
+ but as we want to be compatible with Jython 2.1 where decorators have an uglier syntax (needing an assign
+ after the method), it should now be used without being a decorator as below (in which case we don't even check
+ for anything, just that the parent name was actually properly loaded).
+
+ i.e.:
+
+ class B:
+ overrides(A.m1)
+ def m1(self):
+ pass
+ '''
+ return
+
+# def wrapper(func):
+# if func.__name__ != method.__name__:
+# msg = "Wrong @override: %r expected, but overwriting %r."
+# msg = msg % (func.__name__, method.__name__)
+# raise AssertionError(msg)
+#
+# if func.__doc__ is None:
+# func.__doc__ = method.__doc__
+#
+# return func
+#
+# return wrapper
+
+def implements(method):
+ return
+# def wrapper(func):
+# if func.__name__ != method.__name__:
+# msg = "Wrong @implements: %r expected, but implementing %r."
+# msg = msg % (func.__name__, method.__name__)
+# raise AssertionError(msg)
+#
+# if func.__doc__ is None:
+# func.__doc__ = method.__doc__
+#
+# return func
+#
+# return wrapper \ No newline at end of file
diff --git a/python/helpers/pydev/pydev_pysrc.py b/python/helpers/pydev/pydev_pysrc.py
new file mode 100644
index 000000000000..b9ed49e8005e
--- /dev/null
+++ b/python/helpers/pydev/pydev_pysrc.py
@@ -0,0 +1 @@
+'''An empty file in pysrc that can be imported (from sitecustomize) to find the location of pysrc''' \ No newline at end of file
diff --git a/python/helpers/pydev/pydev_runfiles.py b/python/helpers/pydev/pydev_runfiles.py
new file mode 100644
index 000000000000..bb704db3f240
--- /dev/null
+++ b/python/helpers/pydev/pydev_runfiles.py
@@ -0,0 +1,831 @@
+from __future__ import nested_scopes
+
+import fnmatch
+import os.path
+from pydev_runfiles_coverage import StartCoverageSupport
+import pydev_runfiles_unittest
+from pydevd_constants import * #@UnusedWildImport
+import re
+import time
+import unittest
+
+
+#=======================================================================================================================
+# Configuration
+#=======================================================================================================================
+class Configuration:
+
+ def __init__(
+ self,
+ files_or_dirs='',
+ verbosity=2,
+ include_tests=None,
+ tests=None,
+ port=None,
+ files_to_tests=None,
+ jobs=1,
+ split_jobs='tests',
+ coverage_output_dir=None,
+ coverage_include=None,
+ coverage_output_file=None,
+ exclude_files=None,
+ exclude_tests=None,
+ include_files=None,
+ django=False,
+ ):
+ self.files_or_dirs = files_or_dirs
+ self.verbosity = verbosity
+ self.include_tests = include_tests
+ self.tests = tests
+ self.port = port
+ self.files_to_tests = files_to_tests
+ self.jobs = jobs
+ self.split_jobs = split_jobs
+ self.django = django
+
+ if include_tests:
+ assert isinstance(include_tests, (list, tuple))
+
+ if exclude_files:
+ assert isinstance(exclude_files, (list, tuple))
+
+ if exclude_tests:
+ assert isinstance(exclude_tests, (list, tuple))
+
+ self.exclude_files = exclude_files
+ self.include_files = include_files
+ self.exclude_tests = exclude_tests
+
+ self.coverage_output_dir = coverage_output_dir
+ self.coverage_include = coverage_include
+ self.coverage_output_file = coverage_output_file
+
+ def __str__(self):
+ return '''Configuration
+ - files_or_dirs: %s
+ - verbosity: %s
+ - tests: %s
+ - port: %s
+ - files_to_tests: %s
+ - jobs: %s
+ - split_jobs: %s
+
+ - include_files: %s
+ - include_tests: %s
+
+ - exclude_files: %s
+ - exclude_tests: %s
+
+ - coverage_output_dir: %s
+ - coverage_include_dir: %s
+ - coverage_output_file: %s
+
+ - django: %s
+''' % (
+ self.files_or_dirs,
+ self.verbosity,
+ self.tests,
+ self.port,
+ self.files_to_tests,
+ self.jobs,
+ self.split_jobs,
+
+ self.include_files,
+ self.include_tests,
+
+ self.exclude_files,
+ self.exclude_tests,
+
+ self.coverage_output_dir,
+ self.coverage_include,
+ self.coverage_output_file,
+
+ self.django,
+ )
+
+
+#=======================================================================================================================
+# parse_cmdline
+#=======================================================================================================================
+def parse_cmdline(argv=None):
+ """
+ Parses command line and returns test directories, verbosity, test filter and test suites
+
+ usage:
+ runfiles.py -v|--verbosity <level> -t|--tests <Test.test1,Test2> dirs|files
+
+ Multiprocessing options:
+ jobs=number (with the number of jobs to be used to run the tests)
+ split_jobs='module'|'tests'
+ if == module, a given job will always receive all the tests from a module
+ if == tests, the tests will be split independently of their originating module (default)
+
+ --exclude_files = comma-separated list of patterns with files to exclude (fnmatch style)
+ --include_files = comma-separated list of patterns with files to include (fnmatch style)
+ --exclude_tests = comma-separated list of patterns with test names to exclude (fnmatch style)
+
+ Note: if --tests is given, --exclude_files, --include_files and --exclude_tests are ignored!
+ """
+ if argv is None:
+ argv = sys.argv
+
+ verbosity = 2
+ include_tests = None
+ tests = None
+ port = None
+ jobs = 1
+ split_jobs = 'tests'
+ files_to_tests = {}
+ coverage_output_dir = None
+ coverage_include = None
+ exclude_files = None
+ exclude_tests = None
+ include_files = None
+ django = False
+
+ from _pydev_getopt import gnu_getopt
+ optlist, dirs = gnu_getopt(
+ argv[1:], "",
+ [
+ "verbosity=",
+ "tests=",
+
+ "port=",
+ "config_file=",
+
+ "jobs=",
+ "split_jobs=",
+
+ "include_tests=",
+ "include_files=",
+
+ "exclude_files=",
+ "exclude_tests=",
+
+ "coverage_output_dir=",
+ "coverage_include=",
+
+ "django="
+ ]
+ )
+
+ for opt, value in optlist:
+ if opt in ("-v", "--verbosity"):
+ verbosity = value
+
+ elif opt in ("-p", "--port"):
+ port = int(value)
+
+ elif opt in ("-j", "--jobs"):
+ jobs = int(value)
+
+ elif opt in ("-s", "--split_jobs"):
+ split_jobs = value
+ if split_jobs not in ('module', 'tests'):
+ raise AssertionError('Expected split to be either "module" or "tests". Was :%s' % (split_jobs,))
+
+ elif opt in ("-d", "--coverage_output_dir",):
+ coverage_output_dir = value.strip()
+
+ elif opt in ("-i", "--coverage_include",):
+ coverage_include = value.strip()
+
+ elif opt in ("-I", "--include_tests"):
+ include_tests = value.split(',')
+
+ elif opt in ("-E", "--exclude_files"):
+ exclude_files = value.split(',')
+
+ elif opt in ("-F", "--include_files"):
+ include_files = value.split(',')
+
+ elif opt in ("-e", "--exclude_tests"):
+ exclude_tests = value.split(',')
+
+ elif opt in ("-t", "--tests"):
+ tests = value.split(',')
+
+ elif opt in ("--django",):
+ django = value.strip() in ['true', 'True', '1']
+
+ elif opt in ("-c", "--config_file"):
+ config_file = value.strip()
+ if os.path.exists(config_file):
+ f = open(config_file, 'rU')
+ try:
+ config_file_contents = f.read()
+ finally:
+ f.close()
+
+ if config_file_contents:
+ config_file_contents = config_file_contents.strip()
+
+ if config_file_contents:
+ for line in config_file_contents.splitlines():
+ file_and_test = line.split('|')
+ if len(file_and_test) == 2:
+ file, test = file_and_test
+ if DictContains(files_to_tests, file):
+ files_to_tests[file].append(test)
+ else:
+ files_to_tests[file] = [test]
+
+ else:
+ sys.stderr.write('Could not find config file: %s\n' % (config_file,))
+
+ if type([]) != type(dirs):
+ dirs = [dirs]
+
+ ret_dirs = []
+ for d in dirs:
+ if '|' in d:
+ #paths may come from the ide separated by |
+ ret_dirs.extend(d.split('|'))
+ else:
+ ret_dirs.append(d)
+
+ verbosity = int(verbosity)
+
+ if tests:
+ if verbosity > 4:
+ sys.stdout.write('--tests provided. Ignoring --exclude_files, --exclude_tests and --include_files\n')
+ exclude_files = exclude_tests = include_files = None
+
+ config = Configuration(
+ ret_dirs,
+ verbosity,
+ include_tests,
+ tests,
+ port,
+ files_to_tests,
+ jobs,
+ split_jobs,
+ coverage_output_dir,
+ coverage_include,
+ exclude_files=exclude_files,
+ exclude_tests=exclude_tests,
+ include_files=include_files,
+ django=django,
+ )
+
+ if verbosity > 5:
+ sys.stdout.write(str(config) + '\n')
+ return config
+
+
+#=======================================================================================================================
+# PydevTestRunner
+#=======================================================================================================================
+class PydevTestRunner(object):
+ """ finds and runs a file or directory of files as a unit test """
+
+ __py_extensions = ["*.py", "*.pyw"]
+ __exclude_files = ["__init__.*"]
+
+ #Just to check that only this attributes will be written to this file
+ __slots__ = [
+ 'verbosity', #Always used
+
+ 'files_to_tests', #If this one is given, the ones below are not used
+
+ 'files_or_dirs', #Files or directories received in the command line
+ 'include_tests', #The filter used to collect the tests
+ 'tests', #Strings with the tests to be run
+
+ 'jobs', #Integer with the number of jobs that should be used to run the test cases
+ 'split_jobs', #String with 'tests' or 'module' (how should the jobs be split)
+
+ 'configuration',
+ 'coverage',
+ ]
+
+ def __init__(self, configuration):
+ self.verbosity = configuration.verbosity
+
+ self.jobs = configuration.jobs
+ self.split_jobs = configuration.split_jobs
+
+ files_to_tests = configuration.files_to_tests
+ if files_to_tests:
+ self.files_to_tests = files_to_tests
+ self.files_or_dirs = list(files_to_tests.keys())
+ self.tests = None
+ else:
+ self.files_to_tests = {}
+ self.files_or_dirs = configuration.files_or_dirs
+ self.tests = configuration.tests
+
+ self.configuration = configuration
+ self.__adjust_path()
+
+
+ def __adjust_path(self):
+ """ add the current file or directory to the python path """
+ path_to_append = None
+ for n in xrange(len(self.files_or_dirs)):
+ dir_name = self.__unixify(self.files_or_dirs[n])
+ if os.path.isdir(dir_name):
+ if not dir_name.endswith("/"):
+ self.files_or_dirs[n] = dir_name + "/"
+ path_to_append = os.path.normpath(dir_name)
+ elif os.path.isfile(dir_name):
+ path_to_append = os.path.dirname(dir_name)
+ else:
+ if not os.path.exists(dir_name):
+ block_line = '*' * 120
+ sys.stderr.write('\n%s\n* PyDev test runner error: %s does not exist.\n%s\n' % (block_line, dir_name, block_line))
+ return
+ msg = ("unknown type. \n%s\nshould be file or a directory.\n" % (dir_name))
+ raise RuntimeError(msg)
+ if path_to_append is not None:
+ #Add it as the last one (so, first things are resolved against the default dirs and
+ #if none resolves, then we try a relative import).
+ sys.path.append(path_to_append)
+
+ def __is_valid_py_file(self, fname):
+ """ tests that a particular file contains the proper file extension
+ and is not in the list of files to exclude """
+ is_valid_fname = 0
+ for invalid_fname in self.__class__.__exclude_files:
+ is_valid_fname += int(not fnmatch.fnmatch(fname, invalid_fname))
+ if_valid_ext = 0
+ for ext in self.__class__.__py_extensions:
+ if_valid_ext += int(fnmatch.fnmatch(fname, ext))
+ return is_valid_fname > 0 and if_valid_ext > 0
+
+ def __unixify(self, s):
+ """ stupid windows. converts the backslash to forwardslash for consistency """
+ return os.path.normpath(s).replace(os.sep, "/")
+
+ def __importify(self, s, dir=False):
+ """ turns directory separators into dots and removes the ".py*" extension
+ so the string can be used as import statement """
+ if not dir:
+ dirname, fname = os.path.split(s)
+
+ if fname.count('.') > 1:
+ #if there's a file named xxx.xx.py, it is not a valid module, so, let's not load it...
+ return
+
+ imp_stmt_pieces = [dirname.replace("\\", "/").replace("/", "."), os.path.splitext(fname)[0]]
+
+ if len(imp_stmt_pieces[0]) == 0:
+ imp_stmt_pieces = imp_stmt_pieces[1:]
+
+ return ".".join(imp_stmt_pieces)
+
+ else: #handle dir
+ return s.replace("\\", "/").replace("/", ".")
+
+ def __add_files(self, pyfiles, root, files):
+ """ if files match, appends them to pyfiles. used by os.path.walk fcn """
+ for fname in files:
+ if self.__is_valid_py_file(fname):
+ name_without_base_dir = self.__unixify(os.path.join(root, fname))
+ pyfiles.append(name_without_base_dir)
+
+
+ def find_import_files(self):
+ """ return a list of files to import """
+ if self.files_to_tests:
+ pyfiles = self.files_to_tests.keys()
+ else:
+ pyfiles = []
+
+ for base_dir in self.files_or_dirs:
+ if os.path.isdir(base_dir):
+ if hasattr(os, 'walk'):
+ for root, dirs, files in os.walk(base_dir):
+
+ #Note: handling directories that should be excluded from the search because
+ #they don't have __init__.py
+ exclude = {}
+ for d in dirs:
+ for init in ['__init__.py', '__init__.pyo', '__init__.pyc', '__init__.pyw']:
+ if os.path.exists(os.path.join(root, d, init).replace('\\', '/')):
+ break
+ else:
+ exclude[d] = 1
+
+ if exclude:
+ new = []
+ for d in dirs:
+ if d not in exclude:
+ new.append(d)
+
+ dirs[:] = new
+
+ self.__add_files(pyfiles, root, files)
+ else:
+ # jython2.1 is too old for os.walk!
+ os.path.walk(base_dir, self.__add_files, pyfiles)
+
+ elif os.path.isfile(base_dir):
+ pyfiles.append(base_dir)
+
+ if self.configuration.exclude_files or self.configuration.include_files:
+ ret = []
+ for f in pyfiles:
+ add = True
+ basename = os.path.basename(f)
+ if self.configuration.include_files:
+ add = False
+
+ for pat in self.configuration.include_files:
+ if fnmatch.fnmatchcase(basename, pat):
+ add = True
+ break
+
+ if not add:
+ if self.verbosity > 3:
+ sys.stdout.write('Skipped file: %s (did not match any include_files pattern: %s)\n' % (f, self.configuration.include_files))
+
+ elif self.configuration.exclude_files:
+ for pat in self.configuration.exclude_files:
+ if fnmatch.fnmatchcase(basename, pat):
+ if self.verbosity > 3:
+ sys.stdout.write('Skipped file: %s (matched exclude_files pattern: %s)\n' % (f, pat))
+
+ elif self.verbosity > 2:
+ sys.stdout.write('Skipped file: %s\n' % (f,))
+
+ add = False
+ break
+
+ if add:
+ if self.verbosity > 3:
+ sys.stdout.write('Adding file: %s for test discovery.\n' % (f,))
+ ret.append(f)
+
+ pyfiles = ret
+
+
+ return pyfiles
+
+ def __get_module_from_str(self, modname, print_exception, pyfile):
+ """ Import the module in the given import path.
+ * Returns the "final" module, so importing "coilib40.subject.visu"
+ returns the "visu" module, not the "coilib40" as returned by __import__ """
+ try:
+ mod = __import__(modname)
+ for part in modname.split('.')[1:]:
+ mod = getattr(mod, part)
+ return mod
+ except:
+ if print_exception:
+ import pydev_runfiles_xml_rpc
+ import pydevd_io
+ buf_err = pydevd_io.StartRedirect(keep_original_redirection=True, std='stderr')
+ buf_out = pydevd_io.StartRedirect(keep_original_redirection=True, std='stdout')
+ try:
+ import traceback;traceback.print_exc()
+ sys.stderr.write('ERROR: Module: %s could not be imported (file: %s).\n' % (modname, pyfile))
+ finally:
+ pydevd_io.EndRedirect('stderr')
+ pydevd_io.EndRedirect('stdout')
+
+ pydev_runfiles_xml_rpc.notifyTest(
+ 'error', buf_out.getvalue(), buf_err.getvalue(), pyfile, modname, 0)
+
+ return None
+
+ def find_modules_from_files(self, pyfiles):
+ """ returns a list of modules given a list of files """
+ #let's make sure that the paths we want are in the pythonpath...
+ imports = [(s, self.__importify(s)) for s in pyfiles]
+
+ system_paths = []
+ for s in sys.path:
+ system_paths.append(self.__importify(s, True))
+
+
+ ret = []
+ for pyfile, imp in imports:
+ if imp is None:
+ continue #can happen if a file is not a valid module
+ choices = []
+ for s in system_paths:
+ if imp.startswith(s):
+ add = imp[len(s) + 1:]
+ if add:
+ choices.append(add)
+ #sys.stdout.write(' ' + add + ' ')
+
+ if not choices:
+ sys.stdout.write('PYTHONPATH not found for file: %s\n' % imp)
+ else:
+ for i, import_str in enumerate(choices):
+ print_exception = i == len(choices) - 1
+ mod = self.__get_module_from_str(import_str, print_exception, pyfile)
+ if mod is not None:
+ ret.append((pyfile, mod, import_str))
+ break
+
+
+ return ret
+
+ #===================================================================================================================
+ # GetTestCaseNames
+ #===================================================================================================================
+ class GetTestCaseNames:
+ """Yes, we need a class for that (cannot use outer context on jython 2.1)"""
+
+ def __init__(self, accepted_classes, accepted_methods):
+ self.accepted_classes = accepted_classes
+ self.accepted_methods = accepted_methods
+
+ def __call__(self, testCaseClass):
+ """Return a sorted sequence of method names found within testCaseClass"""
+ testFnNames = []
+ className = testCaseClass.__name__
+
+ if DictContains(self.accepted_classes, className):
+ for attrname in dir(testCaseClass):
+ #If a class is chosen, we select all the 'test' methods'
+ if attrname.startswith('test') and hasattr(getattr(testCaseClass, attrname), '__call__'):
+ testFnNames.append(attrname)
+
+ else:
+ for attrname in dir(testCaseClass):
+ #If we have the class+method name, we must do a full check and have an exact match.
+ if DictContains(self.accepted_methods, className + '.' + attrname):
+ if hasattr(getattr(testCaseClass, attrname), '__call__'):
+ testFnNames.append(attrname)
+
+ #sorted() is not available in jython 2.1
+ testFnNames.sort()
+ return testFnNames
+
+
+ def _decorate_test_suite(self, suite, pyfile, module_name):
+ if isinstance(suite, unittest.TestSuite):
+ add = False
+ suite.__pydev_pyfile__ = pyfile
+ suite.__pydev_module_name__ = module_name
+
+ for t in suite._tests:
+ t.__pydev_pyfile__ = pyfile
+ t.__pydev_module_name__ = module_name
+ if self._decorate_test_suite(t, pyfile, module_name):
+ add = True
+
+ return add
+
+ elif isinstance(suite, unittest.TestCase):
+ return True
+
+ else:
+ return False
+
+
+
+ def find_tests_from_modules(self, file_and_modules_and_module_name):
+ """ returns the unittests given a list of modules """
+ #Use our own suite!
+ unittest.TestLoader.suiteClass = pydev_runfiles_unittest.PydevTestSuite
+ loader = unittest.TestLoader()
+
+ ret = []
+ if self.files_to_tests:
+ for pyfile, m, module_name in file_and_modules_and_module_name:
+ accepted_classes = {}
+ accepted_methods = {}
+ tests = self.files_to_tests[pyfile]
+ for t in tests:
+ accepted_methods[t] = t
+
+ loader.getTestCaseNames = self.GetTestCaseNames(accepted_classes, accepted_methods)
+
+ suite = loader.loadTestsFromModule(m)
+ if self._decorate_test_suite(suite, pyfile, module_name):
+ ret.append(suite)
+ return ret
+
+
+ if self.tests:
+ accepted_classes = {}
+ accepted_methods = {}
+
+ for t in self.tests:
+ splitted = t.split('.')
+ if len(splitted) == 1:
+ accepted_classes[t] = t
+
+ elif len(splitted) == 2:
+ accepted_methods[t] = t
+
+ loader.getTestCaseNames = self.GetTestCaseNames(accepted_classes, accepted_methods)
+
+
+ for pyfile, m, module_name in file_and_modules_and_module_name:
+ suite = loader.loadTestsFromModule(m)
+ if self._decorate_test_suite(suite, pyfile, module_name):
+ ret.append(suite)
+
+ return ret
+
+
+ def filter_tests(self, test_objs, internal_call=False):
+ """ based on a filter name, only return those tests that have
+ the test case names that match """
+ if not internal_call:
+ if not self.configuration.include_tests and not self.tests and not self.configuration.exclude_tests:
+ #No need to filter if we have nothing to filter!
+ return test_objs
+
+ if self.verbosity > 1:
+ if self.configuration.include_tests:
+ sys.stdout.write('Tests to include: %s\n' % (self.configuration.include_tests,))
+
+ if self.tests:
+ sys.stdout.write('Tests to run: %s\n' % (self.tests,))
+
+ if self.configuration.exclude_tests:
+ sys.stdout.write('Tests to exclude: %s\n' % (self.configuration.exclude_tests,))
+
+ test_suite = []
+ for test_obj in test_objs:
+
+ if isinstance(test_obj, unittest.TestSuite):
+ #Note: keep the suites as they are and just 'fix' the tests (so, don't use the iter_tests).
+ if test_obj._tests:
+ test_obj._tests = self.filter_tests(test_obj._tests, True)
+ if test_obj._tests: #Only add the suite if we still have tests there.
+ test_suite.append(test_obj)
+
+ elif isinstance(test_obj, unittest.TestCase):
+ try:
+ testMethodName = test_obj._TestCase__testMethodName
+ except AttributeError:
+ #changed in python 2.5
+ testMethodName = test_obj._testMethodName
+
+ add = True
+ if self.configuration.exclude_tests:
+ for pat in self.configuration.exclude_tests:
+ if fnmatch.fnmatchcase(testMethodName, pat):
+ if self.verbosity > 3:
+ sys.stdout.write('Skipped test: %s (matched exclude_tests pattern: %s)\n' % (testMethodName, pat))
+
+ elif self.verbosity > 2:
+ sys.stdout.write('Skipped test: %s\n' % (testMethodName,))
+
+ add = False
+ break
+
+ if add:
+ if self.__match_tests(self.tests, test_obj, testMethodName):
+ include = True
+ if self.configuration.include_tests:
+ include = False
+ for pat in self.configuration.include_tests:
+ if fnmatch.fnmatchcase(testMethodName, pat):
+ include = True
+ break
+ if include:
+ test_suite.append(test_obj)
+ else:
+ if self.verbosity > 3:
+ sys.stdout.write('Skipped test: %s (did not match any include_tests pattern %s)\n' % (self.configuration.include_tests,))
+ return test_suite
+
+
+ def iter_tests(self, test_objs):
+ #Note: not using yield because of Jython 2.1.
+ tests = []
+ for test_obj in test_objs:
+ if isinstance(test_obj, unittest.TestSuite):
+ tests.extend(self.iter_tests(test_obj._tests))
+
+ elif isinstance(test_obj, unittest.TestCase):
+ tests.append(test_obj)
+ return tests
+
+
+ def list_test_names(self, test_objs):
+ names = []
+ for tc in self.iter_tests(test_objs):
+ try:
+ testMethodName = tc._TestCase__testMethodName
+ except AttributeError:
+ #changed in python 2.5
+ testMethodName = tc._testMethodName
+ names.append(testMethodName)
+ return names
+
+
+ def __match_tests(self, tests, test_case, test_method_name):
+ if not tests:
+ return 1
+
+ for t in tests:
+ class_and_method = t.split('.')
+ if len(class_and_method) == 1:
+ #only class name
+ if class_and_method[0] == test_case.__class__.__name__:
+ return 1
+
+ elif len(class_and_method) == 2:
+ if class_and_method[0] == test_case.__class__.__name__ and class_and_method[1] == test_method_name:
+ return 1
+
+ return 0
+
+
+ def __match(self, filter_list, name):
+ """ returns whether a test name matches the test filter """
+ if filter_list is None:
+ return 1
+ for f in filter_list:
+ if re.match(f, name):
+ return 1
+ return 0
+
+
+ def run_tests(self, handle_coverage=True):
+ """ runs all tests """
+ sys.stdout.write("Finding files... ")
+ files = self.find_import_files()
+ if self.verbosity > 3:
+ sys.stdout.write('%s ... done.\n' % (self.files_or_dirs))
+ else:
+ sys.stdout.write('done.\n')
+ sys.stdout.write("Importing test modules ... ")
+
+
+ if handle_coverage:
+ coverage_files, coverage = StartCoverageSupport(self.configuration)
+
+ file_and_modules_and_module_name = self.find_modules_from_files(files)
+ sys.stdout.write("done.\n")
+
+ all_tests = self.find_tests_from_modules(file_and_modules_and_module_name)
+ all_tests = self.filter_tests(all_tests)
+
+ test_suite = pydev_runfiles_unittest.PydevTestSuite(all_tests)
+ import pydev_runfiles_xml_rpc
+ pydev_runfiles_xml_rpc.notifyTestsCollected(test_suite.countTestCases())
+
+ start_time = time.time()
+
+ def run_tests():
+ executed_in_parallel = False
+ if self.jobs > 1:
+ import pydev_runfiles_parallel
+
+ #What may happen is that the number of jobs needed is lower than the number of jobs requested
+ #(e.g.: 2 jobs were requested for running 1 test) -- in which case ExecuteTestsInParallel will
+ #return False and won't run any tests.
+ executed_in_parallel = pydev_runfiles_parallel.ExecuteTestsInParallel(
+ all_tests, self.jobs, self.split_jobs, self.verbosity, coverage_files, self.configuration.coverage_include)
+
+ if not executed_in_parallel:
+ #If in coverage, we don't need to pass anything here (coverage is already enabled for this execution).
+ runner = pydev_runfiles_unittest.PydevTextTestRunner(stream=sys.stdout, descriptions=1, verbosity=self.verbosity)
+ sys.stdout.write('\n')
+ runner.run(test_suite)
+
+ if self.configuration.django:
+ MyDjangoTestSuiteRunner(run_tests).run_tests([])
+ else:
+ run_tests()
+
+ if handle_coverage:
+ coverage.stop()
+ coverage.save()
+
+ total_time = 'Finished in: %.2f secs.' % (time.time() - start_time,)
+ pydev_runfiles_xml_rpc.notifyTestRunFinished(total_time)
+
+
+try:
+ from django.test.simple import DjangoTestSuiteRunner
+except:
+ class DjangoTestSuiteRunner:
+ def __init__(self):
+ pass
+
+ def run_tests(self, *args, **kwargs):
+ raise AssertionError("Unable to run suite with DjangoTestSuiteRunner because it couldn't be imported.")
+
+class MyDjangoTestSuiteRunner(DjangoTestSuiteRunner):
+
+ def __init__(self, on_run_suite):
+ DjangoTestSuiteRunner.__init__(self)
+ self.on_run_suite = on_run_suite
+
+ def build_suite(self, *args, **kwargs):
+ pass
+
+ def suite_result(self, *args, **kwargs):
+ pass
+
+ def run_suite(self, *args, **kwargs):
+ self.on_run_suite()
+
+
+#=======================================================================================================================
+# main
+#=======================================================================================================================
+def main(configuration):
+ PydevTestRunner(configuration).run_tests()
diff --git a/python/helpers/pydev/pydev_runfiles_coverage.py b/python/helpers/pydev/pydev_runfiles_coverage.py
new file mode 100644
index 000000000000..55bec062ed90
--- /dev/null
+++ b/python/helpers/pydev/pydev_runfiles_coverage.py
@@ -0,0 +1,76 @@
+import os.path
+import sys
+from pydevd_constants import Null
+
+
+#=======================================================================================================================
+# GetCoverageFiles
+#=======================================================================================================================
+def GetCoverageFiles(coverage_output_dir, number_of_files):
+ base_dir = coverage_output_dir
+ ret = []
+ i = 0
+ while len(ret) < number_of_files:
+ while True:
+ f = os.path.join(base_dir, '.coverage.%s' % i)
+ i += 1
+ if not os.path.exists(f):
+ ret.append(f)
+ break #Break only inner for.
+ return ret
+
+
+#=======================================================================================================================
+# StartCoverageSupport
+#=======================================================================================================================
+def StartCoverageSupport(configuration):
+ return StartCoverageSupportFromParams(
+ configuration.coverage_output_dir,
+ configuration.coverage_output_file,
+ configuration.jobs,
+ configuration.coverage_include,
+ )
+
+
+#=======================================================================================================================
+# StartCoverageSupportFromParams
+#=======================================================================================================================
+def StartCoverageSupportFromParams(coverage_output_dir, coverage_output_file, jobs, coverage_include):
+ coverage_files = []
+ coverage_instance = Null()
+ if coverage_output_dir or coverage_output_file:
+ try:
+ import coverage #@UnresolvedImport
+ except:
+ sys.stderr.write('Error: coverage module could not be imported\n')
+ sys.stderr.write('Please make sure that the coverage module (http://nedbatchelder.com/code/coverage/)\n')
+ sys.stderr.write('is properly installed in your interpreter: %s\n' % (sys.executable,))
+
+ import traceback;traceback.print_exc()
+ else:
+ if coverage_output_dir:
+ if not os.path.exists(coverage_output_dir):
+ sys.stderr.write('Error: directory for coverage output (%s) does not exist.\n' % (coverage_output_dir,))
+
+ elif not os.path.isdir(coverage_output_dir):
+ sys.stderr.write('Error: expected (%s) to be a directory.\n' % (coverage_output_dir,))
+
+ else:
+ n = jobs
+ if n <= 0:
+ n += 1
+ n += 1 #Add 1 more for the current process (which will do the initial import).
+ coverage_files = GetCoverageFiles(coverage_output_dir, n)
+ os.environ['COVERAGE_FILE'] = coverage_files.pop(0)
+
+ coverage_instance = coverage.coverage(source=[coverage_include])
+ coverage_instance.start()
+
+ elif coverage_output_file:
+ #Client of parallel run.
+ os.environ['COVERAGE_FILE'] = coverage_output_file
+ coverage_instance = coverage.coverage(source=[coverage_include])
+ coverage_instance.start()
+
+ return coverage_files, coverage_instance
+
diff --git a/python/helpers/pydev/pydev_runfiles_nose.py b/python/helpers/pydev/pydev_runfiles_nose.py
new file mode 100644
index 000000000000..422d2a62a83a
--- /dev/null
+++ b/python/helpers/pydev/pydev_runfiles_nose.py
@@ -0,0 +1,180 @@
+from nose.plugins.multiprocess import MultiProcessTestRunner # @UnresolvedImport
+from nose.plugins.base import Plugin # @UnresolvedImport
+import sys
+import pydev_runfiles_xml_rpc
+import time
+from pydev_runfiles_coverage import StartCoverageSupport
+
+#=======================================================================================================================
+# PydevPlugin
+#=======================================================================================================================
+class PydevPlugin(Plugin):
+
+ def __init__(self, configuration):
+ self.configuration = configuration
+ Plugin.__init__(self)
+
+
+ def begin(self):
+ # Called before any test is run (it's always called, with multiprocess or not)
+ self.start_time = time.time()
+ self.coverage_files, self.coverage = StartCoverageSupport(self.configuration)
+
+
+ def finalize(self, result):
+ # Called after all tests are run (it's always called, with multiprocess or not)
+ self.coverage.stop()
+ self.coverage.save()
+
+ pydev_runfiles_xml_rpc.notifyTestRunFinished('Finished in: %.2f secs.' % (time.time() - self.start_time,))
+
+
+
+ #===================================================================================================================
+ # Methods below are not called with multiprocess (so, we monkey-patch MultiProcessTestRunner.consolidate
+ # so that they're called, but unfortunately we loose some info -- i.e.: the time for each test in this
+ # process).
+ #===================================================================================================================
+
+
+ def reportCond(self, cond, test, captured_output, error=''):
+ '''
+ @param cond: fail, error, ok
+ '''
+
+ # test.address() is something as:
+ # ('D:\\workspaces\\temp\\test_workspace\\pytesting1\\src\\mod1\\hello.py', 'mod1.hello', 'TestCase.testMet1')
+ #
+ # and we must pass: location, test
+ # E.g.: ['D:\\src\\mod1\\hello.py', 'TestCase.testMet1']
+ try:
+ if hasattr(test, 'address'):
+ address = test.address()
+ address = address[0], address[2]
+ else:
+ # multiprocess
+ try:
+ address = test[0], test[1]
+ except TypeError:
+ # It may be an error at setup, in which case it's not really a test, but a Context object.
+ f = test.context.__file__
+ if f.endswith('.pyc'):
+ f = f[:-1]
+ address = f, '?'
+ except:
+ sys.stderr.write("PyDev: Internal pydev error getting test address. Please report at the pydev bug tracker\n")
+ import traceback;traceback.print_exc()
+ sys.stderr.write("\n\n\n")
+ address = '?', '?'
+
+ error_contents = self.getIoFromError(error)
+ try:
+ time_str = '%.2f' % (time.time() - test._pydev_start_time)
+ except:
+ time_str = '?'
+
+ pydev_runfiles_xml_rpc.notifyTest(cond, captured_output, error_contents, address[0], address[1], time_str)
+
+
+ def startTest(self, test):
+ test._pydev_start_time = time.time()
+ if hasattr(test, 'address'):
+ address = test.address()
+ file, test = address[0], address[2]
+ else:
+ # multiprocess
+ file, test = test
+ pydev_runfiles_xml_rpc.notifyStartTest(file, test)
+
+
+ def getIoFromError(self, err):
+ if type(err) == type(()):
+ if len(err) != 3:
+ if len(err) == 2:
+ return err[1] # multiprocess
+ try:
+ from StringIO import StringIO
+ except:
+ from io import StringIO
+ s = StringIO()
+ etype, value, tb = err
+ import traceback;traceback.print_exception(etype, value, tb, file=s)
+ return s.getvalue()
+ return err
+
+
+ def getCapturedOutput(self, test):
+ if hasattr(test, 'capturedOutput') and test.capturedOutput:
+ return test.capturedOutput
+ return ''
+
+
+ def addError(self, test, err):
+ self.reportCond(
+ 'error',
+ test,
+ self.getCapturedOutput(test),
+ err,
+ )
+
+
+ def addFailure(self, test, err):
+ self.reportCond(
+ 'fail',
+ test,
+ self.getCapturedOutput(test),
+ err,
+ )
+
+
+ def addSuccess(self, test):
+ self.reportCond(
+ 'ok',
+ test,
+ self.getCapturedOutput(test),
+ '',
+ )
+
+
+PYDEV_NOSE_PLUGIN_SINGLETON = None
+def StartPydevNosePluginSingleton(configuration):
+ global PYDEV_NOSE_PLUGIN_SINGLETON
+ PYDEV_NOSE_PLUGIN_SINGLETON = PydevPlugin(configuration)
+ return PYDEV_NOSE_PLUGIN_SINGLETON
+
+
+
+
+original = MultiProcessTestRunner.consolidate
+#=======================================================================================================================
+# NewConsolidate
+#=======================================================================================================================
+def NewConsolidate(self, result, batch_result):
+ '''
+ Used so that it can work with the multiprocess plugin.
+ Monkeypatched because nose seems a bit unsupported at this time (ideally
+ the plugin would have this support by default).
+ '''
+ ret = original(self, result, batch_result)
+
+ parent_frame = sys._getframe().f_back
+ # addr is something as D:\pytesting1\src\mod1\hello.py:TestCase.testMet4
+ # so, convert it to what reportCond expects
+ addr = parent_frame.f_locals['addr']
+ i = addr.rindex(':')
+ addr = [addr[:i], addr[i + 1:]]
+
+ output, testsRun, failures, errors, errorClasses = batch_result
+ if failures or errors:
+ for failure in failures:
+ PYDEV_NOSE_PLUGIN_SINGLETON.reportCond('fail', addr, output, failure)
+
+ for error in errors:
+ PYDEV_NOSE_PLUGIN_SINGLETON.reportCond('error', addr, output, error)
+ else:
+ PYDEV_NOSE_PLUGIN_SINGLETON.reportCond('ok', addr, output)
+
+
+ return ret
+
+MultiProcessTestRunner.consolidate = NewConsolidate
diff --git a/python/helpers/pydev/pydev_runfiles_parallel.py b/python/helpers/pydev/pydev_runfiles_parallel.py
new file mode 100644
index 000000000000..e14f36d79139
--- /dev/null
+++ b/python/helpers/pydev/pydev_runfiles_parallel.py
@@ -0,0 +1,298 @@
+import unittest
+try:
+ import Queue
+except:
+ import queue as Queue #@UnresolvedImport
+from pydevd_constants import * #@UnusedWildImport
+import pydev_runfiles_xml_rpc
+import time
+import os
+
+#=======================================================================================================================
+# FlattenTestSuite
+#=======================================================================================================================
+def FlattenTestSuite(test_suite, ret):
+ if isinstance(test_suite, unittest.TestSuite):
+ for t in test_suite._tests:
+ FlattenTestSuite(t, ret)
+
+ elif isinstance(test_suite, unittest.TestCase):
+ ret.append(test_suite)
+
+
+#=======================================================================================================================
+# ExecuteTestsInParallel
+#=======================================================================================================================
+def ExecuteTestsInParallel(tests, jobs, split, verbosity, coverage_files, coverage_include):
+ '''
+ @param tests: list(PydevTestSuite)
+ A list with the suites to be run
+
+ @param split: str
+ Either 'module' or the number of tests that should be run in each batch
+
+ @param coverage_files: list(file)
+ A list with the files that should be used for giving coverage information (if empty, coverage information
+ should not be gathered).
+
+ @param coverage_include: str
+ The pattern that should be included in the coverage.
+
+ @return: bool
+ Returns True if the tests were actually executed in parallel. If the tests were not executed because only 1
+ should be used (e.g.: 2 jobs were requested for running 1 test), False will be returned and no tests will be
+ run.
+
+ It may also return False if in debug mode (in which case, multi-processes are not accepted)
+ '''
+ try:
+ from pydevd_comm import GetGlobalDebugger
+ if GetGlobalDebugger() is not None:
+ return False
+ except:
+ pass #Ignore any error here.
+
+ #This queue will receive the tests to be run. Each entry in a queue is a list with the tests to be run together When
+ #split == 'tests', each list will have a single element, when split == 'module', each list will have all the tests
+ #from a given module.
+ tests_queue = []
+
+ queue_elements = []
+ if split == 'module':
+ module_to_tests = {}
+ for test in tests:
+ lst = []
+ FlattenTestSuite(test, lst)
+ for test in lst:
+ key = (test.__pydev_pyfile__, test.__pydev_module_name__)
+ module_to_tests.setdefault(key, []).append(test)
+
+ for key, tests in module_to_tests.items():
+ queue_elements.append(tests)
+
+ if len(queue_elements) < jobs:
+ #Don't create jobs we will never use.
+ jobs = len(queue_elements)
+
+ elif split == 'tests':
+ for test in tests:
+ lst = []
+ FlattenTestSuite(test, lst)
+ for test in lst:
+ queue_elements.append([test])
+
+ if len(queue_elements) < jobs:
+ #Don't create jobs we will never use.
+ jobs = len(queue_elements)
+
+ else:
+ raise AssertionError('Do not know how to handle: %s' % (split,))
+
+ for test_cases in queue_elements:
+ test_queue_elements = []
+ for test_case in test_cases:
+ try:
+ test_name = test_case.__class__.__name__+"."+test_case._testMethodName
+ except AttributeError:
+ #Support for jython 2.1 (__testMethodName is pseudo-private in the test case)
+ test_name = test_case.__class__.__name__+"."+test_case._TestCase__testMethodName
+
+ test_queue_elements.append(test_case.__pydev_pyfile__+'|'+test_name)
+
+ tests_queue.append(test_queue_elements)
+
+ if jobs < 2:
+ return False
+
+ sys.stdout.write('Running tests in parallel with: %s jobs.\n' %(jobs,))
+
+
+ queue = Queue.Queue()
+ for item in tests_queue:
+ queue.put(item, block=False)
+
+
+ providers = []
+ clients = []
+ for i in range(jobs):
+ test_cases_provider = CommunicationThread(queue)
+ providers.append(test_cases_provider)
+
+ test_cases_provider.start()
+ port = test_cases_provider.port
+
+ if coverage_files:
+ clients.append(ClientThread(i, port, verbosity, coverage_files.pop(0), coverage_include))
+ else:
+ clients.append(ClientThread(i, port, verbosity))
+
+ for client in clients:
+ client.start()
+
+ client_alive = True
+ while client_alive:
+ client_alive = False
+ for client in clients:
+ #Wait for all the clients to exit.
+ if not client.finished:
+ client_alive = True
+ time.sleep(.2)
+ break
+
+ for provider in providers:
+ provider.shutdown()
+
+ return True
+
+
+
+#=======================================================================================================================
+# CommunicationThread
+#=======================================================================================================================
+class CommunicationThread(threading.Thread):
+
+ def __init__(self, tests_queue):
+ threading.Thread.__init__(self)
+ self.setDaemon(True)
+ self.queue = tests_queue
+ self.finished = False
+ from pydev_imports import SimpleXMLRPCServer
+
+
+ # This is a hack to patch slow socket.getfqdn calls that
+ # BaseHTTPServer (and its subclasses) make.
+ # See: http://bugs.python.org/issue6085
+ # See: http://www.answermysearches.com/xmlrpc-server-slow-in-python-how-to-fix/2140/
+ try:
+ import BaseHTTPServer
+ def _bare_address_string(self):
+ host, port = self.client_address[:2]
+ return '%s' % host
+ BaseHTTPServer.BaseHTTPRequestHandler.address_string = _bare_address_string
+
+ except:
+ pass
+ # End hack.
+
+
+ # Create server
+
+ import pydev_localhost
+ server = SimpleXMLRPCServer((pydev_localhost.get_localhost(), 0), logRequests=False)
+ server.register_function(self.GetTestsToRun)
+ server.register_function(self.notifyStartTest)
+ server.register_function(self.notifyTest)
+ server.register_function(self.notifyCommands)
+ self.port = server.socket.getsockname()[1]
+ self.server = server
+
+
+ def GetTestsToRun(self, job_id):
+ '''
+ @param job_id:
+
+ @return: list(str)
+ Each entry is a string in the format: filename|Test.testName
+ '''
+ try:
+ ret = self.queue.get(block=False)
+ return ret
+ except: #Any exception getting from the queue (empty or not) means we finished our work on providing the tests.
+ self.finished = True
+ return []
+
+
+ def notifyCommands(self, job_id, commands):
+ #Batch notification.
+ for command in commands:
+ getattr(self, command[0])(job_id, *command[1], **command[2])
+
+ return True
+
+ def notifyStartTest(self, job_id, *args, **kwargs):
+ pydev_runfiles_xml_rpc.notifyStartTest(*args, **kwargs)
+ return True
+
+
+ def notifyTest(self, job_id, *args, **kwargs):
+ pydev_runfiles_xml_rpc.notifyTest(*args, **kwargs)
+ return True
+
+ def shutdown(self):
+ if hasattr(self.server, 'shutdown'):
+ self.server.shutdown()
+ else:
+ self._shutdown = True
+
+ def run(self):
+ if hasattr(self.server, 'shutdown'):
+ self.server.serve_forever()
+ else:
+ self._shutdown = False
+ while not self._shutdown:
+ self.server.handle_request()
+
+
+
+#=======================================================================================================================
+# Client
+#=======================================================================================================================
+class ClientThread(threading.Thread):
+
+ def __init__(self, job_id, port, verbosity, coverage_output_file=None, coverage_include=None):
+ threading.Thread.__init__(self)
+ self.setDaemon(True)
+ self.port = port
+ self.job_id = job_id
+ self.verbosity = verbosity
+ self.finished = False
+ self.coverage_output_file = coverage_output_file
+ self.coverage_include = coverage_include
+
+
+ def _reader_thread(self, pipe, target):
+ while True:
+ target.write(pipe.read(1))
+
+
+ def run(self):
+ try:
+ import pydev_runfiles_parallel_client
+ #TODO: Support Jython:
+ #
+ #For jython, instead of using sys.executable, we should use:
+ #r'D:\bin\jdk_1_5_09\bin\java.exe',
+ #'-classpath',
+ #'D:/bin/jython-2.2.1/jython.jar',
+ #'org.python.util.jython',
+
+ args = [
+ sys.executable,
+ pydev_runfiles_parallel_client.__file__,
+ str(self.job_id),
+ str(self.port),
+ str(self.verbosity),
+ ]
+
+ if self.coverage_output_file and self.coverage_include:
+ args.append(self.coverage_output_file)
+ args.append(self.coverage_include)
+
+ import subprocess
+ if False:
+ proc = subprocess.Popen(args, env=os.environ, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+
+ stdout_thread = threading.Thread(target=self._reader_thread,args=(proc.stdout, sys.stdout))
+ stdout_thread.setDaemon(True)
+ stdout_thread.start()
+
+ stderr_thread = threading.Thread(target=self._reader_thread,args=(proc.stderr, sys.stderr))
+ stderr_thread.setDaemon(True)
+ stderr_thread.start()
+ else:
+ proc = subprocess.Popen(args, env=os.environ, shell=False)
+ proc.wait()
+
+ finally:
+ self.finished = True
+
diff --git a/python/helpers/pydev/pydev_runfiles_parallel_client.py b/python/helpers/pydev/pydev_runfiles_parallel_client.py
new file mode 100644
index 000000000000..7e5187ea8461
--- /dev/null
+++ b/python/helpers/pydev/pydev_runfiles_parallel_client.py
@@ -0,0 +1,214 @@
+from pydevd_constants import * #@UnusedWildImport
+from pydev_imports import xmlrpclib, _queue
+Queue = _queue.Queue
+import traceback
+from pydev_runfiles_coverage import StartCoverageSupportFromParams
+
+
+
+#=======================================================================================================================
+# ParallelNotification
+#=======================================================================================================================
+class ParallelNotification(object):
+
+ def __init__(self, method, args, kwargs):
+ self.method = method
+ self.args = args
+ self.kwargs = kwargs
+
+ def ToTuple(self):
+ return self.method, self.args, self.kwargs
+
+
+#=======================================================================================================================
+# KillServer
+#=======================================================================================================================
+class KillServer(object):
+ pass
+
+
+
+#=======================================================================================================================
+# ServerComm
+#=======================================================================================================================
+class ServerComm(threading.Thread):
+
+
+
+ def __init__(self, job_id, server):
+ self.notifications_queue = Queue()
+ threading.Thread.__init__(self)
+ self.setDaemon(False) #Wait for all the notifications to be passed before exiting!
+ assert job_id is not None
+ assert port is not None
+ self.job_id = job_id
+
+ self.finished = False
+ self.server = server
+
+
+ def run(self):
+ while True:
+ kill_found = False
+ commands = []
+ command = self.notifications_queue.get(block=True)
+ if isinstance(command, KillServer):
+ kill_found = True
+ else:
+ assert isinstance(command, ParallelNotification)
+ commands.append(command.ToTuple())
+
+ try:
+ while True:
+ command = self.notifications_queue.get(block=False) #No block to create a batch.
+ if isinstance(command, KillServer):
+ kill_found = True
+ else:
+ assert isinstance(command, ParallelNotification)
+ commands.append(command.ToTuple())
+ except:
+ pass #That's OK, we're getting it until it becomes empty so that we notify multiple at once.
+
+
+ if commands:
+ try:
+ #Batch notification.
+ self.server.lock.acquire()
+ try:
+ self.server.notifyCommands(self.job_id, commands)
+ finally:
+ self.server.lock.release()
+ except:
+ traceback.print_exc()
+
+ if kill_found:
+ self.finished = True
+ return
+
+
+
+#=======================================================================================================================
+# ServerFacade
+#=======================================================================================================================
+class ServerFacade(object):
+
+
+ def __init__(self, notifications_queue):
+ self.notifications_queue = notifications_queue
+
+
+ def notifyTestsCollected(self, *args, **kwargs):
+ pass #This notification won't be passed
+
+
+ def notifyTestRunFinished(self, *args, **kwargs):
+ pass #This notification won't be passed
+
+
+ def notifyStartTest(self, *args, **kwargs):
+ self.notifications_queue.put_nowait(ParallelNotification('notifyStartTest', args, kwargs))
+
+
+ def notifyTest(self, *args, **kwargs):
+ self.notifications_queue.put_nowait(ParallelNotification('notifyTest', args, kwargs))
+
+
+
+#=======================================================================================================================
+# run_client
+#=======================================================================================================================
+def run_client(job_id, port, verbosity, coverage_output_file, coverage_include):
+ job_id = int(job_id)
+
+ import pydev_localhost
+ server = xmlrpclib.Server('http://%s:%s' % (pydev_localhost.get_localhost(), port))
+ server.lock = threading.Lock()
+
+
+ server_comm = ServerComm(job_id, server)
+ server_comm.start()
+
+ try:
+ server_facade = ServerFacade(server_comm.notifications_queue)
+ import pydev_runfiles
+ import pydev_runfiles_xml_rpc
+ pydev_runfiles_xml_rpc.SetServer(server_facade)
+
+ #Starts None and when the 1st test is gotten, it's started (because a server may be initiated and terminated
+ #before receiving any test -- which would mean a different process got all the tests to run).
+ coverage = None
+
+ try:
+ tests_to_run = [1]
+ while tests_to_run:
+ #Investigate: is it dangerous to use the same xmlrpclib server from different threads?
+ #It seems it should be, as it creates a new connection for each request...
+ server.lock.acquire()
+ try:
+ tests_to_run = server.GetTestsToRun(job_id)
+ finally:
+ server.lock.release()
+
+ if not tests_to_run:
+ break
+
+ if coverage is None:
+ _coverage_files, coverage = StartCoverageSupportFromParams(
+ None, coverage_output_file, 1, coverage_include)
+
+
+ files_to_tests = {}
+ for test in tests_to_run:
+ filename_and_test = test.split('|')
+ if len(filename_and_test) == 2:
+ files_to_tests.setdefault(filename_and_test[0], []).append(filename_and_test[1])
+
+ configuration = pydev_runfiles.Configuration(
+ '',
+ verbosity,
+ None,
+ None,
+ None,
+ files_to_tests,
+ 1, #Always single job here
+ None,
+
+ #The coverage is handled in this loop.
+ coverage_output_file=None,
+ coverage_include=None,
+ )
+ test_runner = pydev_runfiles.PydevTestRunner(configuration)
+ sys.stdout.flush()
+ test_runner.run_tests(handle_coverage=False)
+ finally:
+ if coverage is not None:
+ coverage.stop()
+ coverage.save()
+
+
+ except:
+ traceback.print_exc()
+ server_comm.notifications_queue.put_nowait(KillServer())
+
+
+
+#=======================================================================================================================
+# main
+#=======================================================================================================================
+if __name__ == '__main__':
+ if len(sys.argv) -1 == 3:
+ job_id, port, verbosity = sys.argv[1:]
+ coverage_output_file, coverage_include = None, None
+
+ elif len(sys.argv) -1 == 5:
+ job_id, port, verbosity, coverage_output_file, coverage_include = sys.argv[1:]
+
+ else:
+ raise AssertionError('Could not find out how to handle the parameters: '+sys.argv[1:])
+
+ job_id = int(job_id)
+ port = int(port)
+ verbosity = int(verbosity)
+ run_client(job_id, port, verbosity, coverage_output_file, coverage_include)
+
+
diff --git a/python/helpers/pydev/pydev_runfiles_pytest2.py b/python/helpers/pydev/pydev_runfiles_pytest2.py
new file mode 100644
index 000000000000..e40d60f12e24
--- /dev/null
+++ b/python/helpers/pydev/pydev_runfiles_pytest2.py
@@ -0,0 +1,230 @@
+import pickle
+import zlib
+import base64
+import os
+import py
+from py._code import code # @UnresolvedImport
+import pydev_runfiles_xml_rpc
+from pydevd_file_utils import _NormFile
+import pytest
+import sys
+import time
+
+
+
+#===================================================================================================
+# Load filters with tests we should skip
+#===================================================================================================
+py_test_accept_filter = None
+
+def _load_filters():
+ global py_test_accept_filter
+ if py_test_accept_filter is None:
+ py_test_accept_filter = os.environ.get('PYDEV_PYTEST_SKIP')
+ if py_test_accept_filter:
+ py_test_accept_filter = pickle.loads(zlib.decompress(base64.b64decode(py_test_accept_filter)))
+ else:
+ py_test_accept_filter = {}
+
+
+def connect_to_server_for_communication_to_xml_rpc_on_xdist():
+ main_pid = os.environ.get('PYDEV_MAIN_PID')
+ if main_pid and main_pid != str(os.getpid()):
+ port = os.environ.get('PYDEV_PYTEST_SERVER')
+ if not port:
+ sys.stderr.write('Error: no PYDEV_PYTEST_SERVER environment variable defined.\n')
+ else:
+ pydev_runfiles_xml_rpc.InitializeServer(int(port), daemon=True)
+
+
+#===================================================================================================
+# Mocking to get clickable file representations
+#===================================================================================================
+def _MockFileRepresentation():
+ code.ReprFileLocation._original_toterminal = code.ReprFileLocation.toterminal
+
+ def toterminal(self, tw):
+ # filename and lineno output for each entry,
+ # using an output format that most editors understand
+ msg = self.message
+ i = msg.find("\n")
+ if i != -1:
+ msg = msg[:i]
+
+ tw.line('File "%s", line %s\n%s' %(os.path.abspath(self.path), self.lineno, msg))
+
+ code.ReprFileLocation.toterminal = toterminal
+
+
+def _UninstallMockFileRepresentation():
+ code.ReprFileLocation.toterminal = code.ReprFileLocation._original_toterminal #@UndefinedVariable
+
+
+class State:
+ numcollected = 0
+ start_time = time.time()
+
+
+def pytest_configure(*args, **kwargs):
+ _MockFileRepresentation()
+
+
+def pytest_collectreport(report):
+
+ i = 0
+ for x in report.result:
+ if isinstance(x, pytest.Item):
+ try:
+ # Call our setup (which may do a skip, in which
+ # case we won't count it).
+ pytest_runtest_setup(x)
+ i += 1
+ except:
+ continue
+ State.numcollected += i
+
+
+def pytest_collection_modifyitems():
+ connect_to_server_for_communication_to_xml_rpc_on_xdist()
+ pydev_runfiles_xml_rpc.notifyTestsCollected(State.numcollected)
+ State.numcollected = 0
+
+
+def pytest_unconfigure(*args, **kwargs):
+ _UninstallMockFileRepresentation()
+ pydev_runfiles_xml_rpc.notifyTestRunFinished('Finished in: %.2f secs.' % (time.time() - State.start_time,))
+
+
+def pytest_runtest_setup(item):
+ filename = item.fspath.strpath
+ test = item.location[2]
+ State.start_test_time = time.time()
+
+ pydev_runfiles_xml_rpc.notifyStartTest(filename, test)
+
+
+def report_test(cond, filename, test, captured_output, error_contents, delta):
+ '''
+ @param filename: 'D:\\src\\mod1\\hello.py'
+ @param test: 'TestCase.testMet1'
+ @param cond: fail, error, ok
+ '''
+ time_str = '%.2f' % (delta,)
+ pydev_runfiles_xml_rpc.notifyTest(cond, captured_output, error_contents, filename, test, time_str)
+
+
+def pytest_runtest_makereport(item, call):
+ report_when = call.when
+ report_duration = call.stop-call.start
+ excinfo = call.excinfo
+
+ if not call.excinfo:
+ report_outcome = "passed"
+ report_longrepr = None
+ else:
+ excinfo = call.excinfo
+ if not isinstance(excinfo, py.code.ExceptionInfo):
+ report_outcome = "failed"
+ report_longrepr = excinfo
+
+ elif excinfo.errisinstance(py.test.skip.Exception):
+ report_outcome = "skipped"
+ r = excinfo._getreprcrash()
+ report_longrepr = None #(str(r.path), r.lineno, r.message)
+
+ else:
+ report_outcome = "failed"
+ if call.when == "call":
+ report_longrepr = item.repr_failure(excinfo)
+
+ else: # exception in setup or teardown
+ report_longrepr = item._repr_failure_py(excinfo, style=item.config.option.tbstyle)
+
+ filename = item.fspath.strpath
+ test = item.location[2]
+
+ status = 'ok'
+ captured_output = ''
+ error_contents = ''
+
+ if report_outcome in ('passed', 'skipped'):
+ #passed or skipped: no need to report if in setup or teardown (only on the actual test if it passed).
+ if report_when in ('setup', 'teardown'):
+ return
+
+ else:
+ #It has only passed, skipped and failed (no error), so, let's consider error if not on call.
+ if report_when == 'setup':
+ if status == 'ok':
+ status = 'error'
+
+ elif report_when == 'teardown':
+ if status == 'ok':
+ status = 'error'
+
+ else:
+ #any error in the call (not in setup or teardown) is considered a regular failure.
+ status = 'fail'
+
+
+ if call.excinfo:
+ rep = report_longrepr
+ if hasattr(rep, 'reprcrash'):
+ reprcrash = rep.reprcrash
+ error_contents += str(reprcrash)
+ error_contents += '\n'
+
+ if hasattr(rep, 'reprtraceback'):
+ error_contents += str(rep.reprtraceback)
+
+ if hasattr(rep, 'sections'):
+ for name, content, sep in rep.sections:
+ error_contents += sep * 40
+ error_contents += name
+ error_contents += sep * 40
+ error_contents += '\n'
+ error_contents += content
+ error_contents += '\n'
+
+ if status != 'skip': #I.e.: don't event report skips...
+ report_test(status, filename, test, captured_output, error_contents, report_duration)
+
+
+
+@pytest.mark.tryfirst
+def pytest_runtest_setup(item):
+ '''
+ Skips tests. With xdist will be on a secondary process.
+ '''
+ _load_filters()
+ if not py_test_accept_filter:
+ return #Keep on going (nothing to filter)
+
+ f = _NormFile(str(item.parent.fspath))
+ name = item.name
+
+ if f not in py_test_accept_filter:
+ pytest.skip() # Skip the file
+
+ accept_tests = py_test_accept_filter[f]
+
+ if item.cls is not None:
+ class_name = item.cls.__name__
+ else:
+ class_name = None
+ for test in accept_tests:
+ if test == name:
+ #Direct match of the test (just go on with the default loading)
+ return
+
+ if class_name is not None:
+ if test == class_name + '.' + name:
+ return
+
+ if class_name == test:
+ return
+
+ # If we had a match it'd have returned already.
+ pytest.skip() # Skip the test
+
+
diff --git a/python/helpers/pydev/pydev_runfiles_unittest.py b/python/helpers/pydev/pydev_runfiles_unittest.py
new file mode 100644
index 000000000000..78dfa524cf40
--- /dev/null
+++ b/python/helpers/pydev/pydev_runfiles_unittest.py
@@ -0,0 +1,174 @@
+try:
+ import unittest2 as python_unittest
+except:
+ import unittest as python_unittest
+
+import pydev_runfiles_xml_rpc
+import time
+import pydevd_io
+import traceback
+from pydevd_constants import * #@UnusedWildImport
+
+
+#=======================================================================================================================
+# PydevTextTestRunner
+#=======================================================================================================================
+class PydevTextTestRunner(python_unittest.TextTestRunner):
+
+ def _makeResult(self):
+ return PydevTestResult(self.stream, self.descriptions, self.verbosity)
+
+
+_PythonTextTestResult = python_unittest.TextTestRunner()._makeResult().__class__
+
+#=======================================================================================================================
+# PydevTestResult
+#=======================================================================================================================
+class PydevTestResult(_PythonTextTestResult):
+
+
+ def startTest(self, test):
+ _PythonTextTestResult.startTest(self, test)
+ self.buf = pydevd_io.StartRedirect(keep_original_redirection=True, std='both')
+ self.start_time = time.time()
+ self._current_errors_stack = []
+ self._current_failures_stack = []
+
+ try:
+ test_name = test.__class__.__name__+"."+test._testMethodName
+ except AttributeError:
+ #Support for jython 2.1 (__testMethodName is pseudo-private in the test case)
+ test_name = test.__class__.__name__+"."+test._TestCase__testMethodName
+
+ pydev_runfiles_xml_rpc.notifyStartTest(
+ test.__pydev_pyfile__, test_name)
+
+
+
+
+ def getTestName(self, test):
+ try:
+ try:
+ test_name = test.__class__.__name__ + "." + test._testMethodName
+ except AttributeError:
+ #Support for jython 2.1 (__testMethodName is pseudo-private in the test case)
+ try:
+ test_name = test.__class__.__name__ + "." + test._TestCase__testMethodName
+ #Support for class/module exceptions (test is instance of _ErrorHolder)
+ except:
+ test_name = test.description.split()[1][1:-1] + ' <' + test.description.split()[0] + '>'
+ except:
+ traceback.print_exc()
+ return '<unable to get test name>'
+ return test_name
+
+
+ def stopTest(self, test):
+ end_time = time.time()
+ pydevd_io.EndRedirect(std='both')
+
+ _PythonTextTestResult.stopTest(self, test)
+
+ captured_output = self.buf.getvalue()
+ del self.buf
+ error_contents = ''
+ test_name = self.getTestName(test)
+
+
+ diff_time = '%.2f' % (end_time - self.start_time)
+ if not self._current_errors_stack and not self._current_failures_stack:
+ pydev_runfiles_xml_rpc.notifyTest(
+ 'ok', captured_output, error_contents, test.__pydev_pyfile__, test_name, diff_time)
+ else:
+ self._reportErrors(self._current_errors_stack, self._current_failures_stack, captured_output, test_name)
+
+
+ def _reportErrors(self, errors, failures, captured_output, test_name, diff_time=''):
+ error_contents = []
+ for test, s in errors+failures:
+ if type(s) == type((1,)): #If it's a tuple (for jython 2.1)
+ sio = StringIO()
+ traceback.print_exception(s[0], s[1], s[2], file=sio)
+ s = sio.getvalue()
+ error_contents.append(s)
+
+ sep = '\n'+self.separator1
+ error_contents = sep.join(error_contents)
+
+ if errors and not failures:
+ try:
+ pydev_runfiles_xml_rpc.notifyTest(
+ 'error', captured_output, error_contents, test.__pydev_pyfile__, test_name, diff_time)
+ except:
+ file_start = error_contents.find('File "')
+ file_end = error_contents.find('", ', file_start)
+ if file_start != -1 and file_end != -1:
+ file = error_contents[file_start+6:file_end]
+ else:
+ file = '<unable to get file>'
+ pydev_runfiles_xml_rpc.notifyTest(
+ 'error', captured_output, error_contents, file, test_name, diff_time)
+
+ elif failures and not errors:
+ pydev_runfiles_xml_rpc.notifyTest(
+ 'fail', captured_output, error_contents, test.__pydev_pyfile__, test_name, diff_time)
+
+ else: #Ok, we got both, errors and failures. Let's mark it as an error in the end.
+ pydev_runfiles_xml_rpc.notifyTest(
+ 'error', captured_output, error_contents, test.__pydev_pyfile__, test_name, diff_time)
+
+
+
+ def addError(self, test, err):
+ _PythonTextTestResult.addError(self, test, err)
+ #Support for class/module exceptions (test is instance of _ErrorHolder)
+ if not hasattr(self, '_current_errors_stack') or test.__class__.__name__ == '_ErrorHolder':
+ #Not in start...end, so, report error now (i.e.: django pre/post-setup)
+ self._reportErrors([self.errors[-1]], [], '', self.getTestName(test))
+ else:
+ self._current_errors_stack.append(self.errors[-1])
+
+
+ def addFailure(self, test, err):
+ _PythonTextTestResult.addFailure(self, test, err)
+ if not hasattr(self, '_current_failures_stack'):
+ #Not in start...end, so, report error now (i.e.: django pre/post-setup)
+ self._reportErrors([], [self.failures[-1]], '', self.getTestName(test))
+ else:
+ self._current_failures_stack.append(self.failures[-1])
+
+
+try:
+ #Version 2.7 onwards has a different structure... Let's not make any changes in it for now
+ #(waiting for bug: http://bugs.python.org/issue11798)
+ try:
+ from unittest2 import suite
+ except ImportError:
+ from unittest import suite
+ #===================================================================================================================
+ # PydevTestSuite
+ #===================================================================================================================
+ class PydevTestSuite(python_unittest.TestSuite):
+ pass
+
+
+except ImportError:
+
+ #===================================================================================================================
+ # PydevTestSuite
+ #===================================================================================================================
+ class PydevTestSuite(python_unittest.TestSuite):
+
+
+ def run(self, result):
+ for index, test in enumerate(self._tests):
+ if result.shouldStop:
+ break
+ test(result)
+
+ # Let the memory be released!
+ self._tests[index] = None
+
+ return result
+
+
diff --git a/python/helpers/pydev/pydev_runfiles_xml_rpc.py b/python/helpers/pydev/pydev_runfiles_xml_rpc.py
new file mode 100644
index 000000000000..bcaa38a53ae2
--- /dev/null
+++ b/python/helpers/pydev/pydev_runfiles_xml_rpc.py
@@ -0,0 +1,269 @@
+import traceback
+import warnings
+
+from _pydev_filesystem_encoding import getfilesystemencoding
+from pydev_imports import xmlrpclib, _queue
+Queue = _queue.Queue
+from pydevd_constants import *
+
+#This may happen in IronPython (in Python it shouldn't happen as there are
+#'fast' replacements that are used in xmlrpclib.py)
+warnings.filterwarnings(
+ 'ignore', 'The xmllib module is obsolete.*', DeprecationWarning)
+
+
+file_system_encoding = getfilesystemencoding()
+
+#=======================================================================================================================
+# _ServerHolder
+#=======================================================================================================================
+class _ServerHolder:
+ '''
+ Helper so that we don't have to use a global here.
+ '''
+ SERVER = None
+
+
+#=======================================================================================================================
+# SetServer
+#=======================================================================================================================
+def SetServer(server):
+ _ServerHolder.SERVER = server
+
+
+
+#=======================================================================================================================
+# ParallelNotification
+#=======================================================================================================================
+class ParallelNotification(object):
+
+ def __init__(self, method, args):
+ self.method = method
+ self.args = args
+
+ def ToTuple(self):
+ return self.method, self.args
+
+
+
+#=======================================================================================================================
+# KillServer
+#=======================================================================================================================
+class KillServer(object):
+ pass
+
+
+#=======================================================================================================================
+# ServerFacade
+#=======================================================================================================================
+class ServerFacade(object):
+
+
+ def __init__(self, notifications_queue):
+ self.notifications_queue = notifications_queue
+
+
+ def notifyTestsCollected(self, *args):
+ self.notifications_queue.put_nowait(ParallelNotification('notifyTestsCollected', args))
+
+ def notifyConnected(self, *args):
+ self.notifications_queue.put_nowait(ParallelNotification('notifyConnected', args))
+
+
+ def notifyTestRunFinished(self, *args):
+ self.notifications_queue.put_nowait(ParallelNotification('notifyTestRunFinished', args))
+
+
+ def notifyStartTest(self, *args):
+ self.notifications_queue.put_nowait(ParallelNotification('notifyStartTest', args))
+
+
+ def notifyTest(self, *args):
+ self.notifications_queue.put_nowait(ParallelNotification('notifyTest', args))
+
+
+
+
+
+#=======================================================================================================================
+# ServerComm
+#=======================================================================================================================
+class ServerComm(threading.Thread):
+
+
+
+ def __init__(self, notifications_queue, port, daemon=False):
+ threading.Thread.__init__(self)
+ self.setDaemon(daemon) # If False, wait for all the notifications to be passed before exiting!
+ self.finished = False
+ self.notifications_queue = notifications_queue
+
+ import pydev_localhost
+
+ # It is necessary to specify an encoding, that matches
+ # the encoding of all bytes-strings passed into an
+ # XMLRPC call: "All 8-bit strings in the data structure are assumed to use the
+ # packet encoding. Unicode strings are automatically converted,
+ # where necessary."
+ # Byte strings most likely come from file names.
+ encoding = file_system_encoding
+ if encoding == "mbcs":
+ # Windos symbolic name for the system encoding CP_ACP.
+ # We need to convert it into a encoding that is recognized by Java.
+ # Unfortunately this is not always possible. You could use
+ # GetCPInfoEx and get a name similar to "windows-1251". Then
+ # you need a table to translate on a best effort basis. Much to complicated.
+ # ISO-8859-1 is good enough.
+ encoding = "ISO-8859-1"
+
+ self.server = xmlrpclib.Server('http://%s:%s' % (pydev_localhost.get_localhost(), port),
+ encoding=encoding)
+
+
+ def run(self):
+ while True:
+ kill_found = False
+ commands = []
+ command = self.notifications_queue.get(block=True)
+ if isinstance(command, KillServer):
+ kill_found = True
+ else:
+ assert isinstance(command, ParallelNotification)
+ commands.append(command.ToTuple())
+
+ try:
+ while True:
+ command = self.notifications_queue.get(block=False) #No block to create a batch.
+ if isinstance(command, KillServer):
+ kill_found = True
+ else:
+ assert isinstance(command, ParallelNotification)
+ commands.append(command.ToTuple())
+ except:
+ pass #That's OK, we're getting it until it becomes empty so that we notify multiple at once.
+
+
+ if commands:
+ try:
+ self.server.notifyCommands(commands)
+ except:
+ traceback.print_exc()
+
+ if kill_found:
+ self.finished = True
+ return
+
+
+
+#=======================================================================================================================
+# InitializeServer
+#=======================================================================================================================
+def InitializeServer(port, daemon=False):
+ if _ServerHolder.SERVER is None:
+ if port is not None:
+ notifications_queue = Queue()
+ _ServerHolder.SERVER = ServerFacade(notifications_queue)
+ _ServerHolder.SERVER_COMM = ServerComm(notifications_queue, port, daemon)
+ _ServerHolder.SERVER_COMM.start()
+ else:
+ #Create a null server, so that we keep the interface even without any connection.
+ _ServerHolder.SERVER = Null()
+ _ServerHolder.SERVER_COMM = Null()
+
+ try:
+ _ServerHolder.SERVER.notifyConnected()
+ except:
+ traceback.print_exc()
+
+
+
+#=======================================================================================================================
+# notifyTest
+#=======================================================================================================================
+def notifyTestsCollected(tests_count):
+ assert tests_count is not None
+ try:
+ _ServerHolder.SERVER.notifyTestsCollected(tests_count)
+ except:
+ traceback.print_exc()
+
+
+#=======================================================================================================================
+# notifyStartTest
+#=======================================================================================================================
+def notifyStartTest(file, test):
+ '''
+ @param file: the tests file (c:/temp/test.py)
+ @param test: the test ran (i.e.: TestCase.test1)
+ '''
+ assert file is not None
+ if test is None:
+ test = '' #Could happen if we have an import error importing module.
+
+ try:
+ _ServerHolder.SERVER.notifyStartTest(file, test)
+ except:
+ traceback.print_exc()
+
+
+def _encode_if_needed(obj):
+ if not IS_PY3K:
+ if isinstance(obj, str):
+ try:
+ return xmlrpclib.Binary(obj.encode('ISO-8859-1', 'xmlcharrefreplace'))
+ except:
+ return xmlrpclib.Binary(obj)
+
+ elif isinstance(obj, unicode):
+ return xmlrpclib.Binary(obj.encode('ISO-8859-1', 'xmlcharrefreplace'))
+
+ else:
+ if isinstance(obj, str):
+ return obj.encode('ISO-8859-1', 'xmlcharrefreplace')
+
+ return obj
+
+
+#=======================================================================================================================
+# notifyTest
+#=======================================================================================================================
+def notifyTest(cond, captured_output, error_contents, file, test, time):
+ '''
+ @param cond: ok, fail, error
+ @param captured_output: output captured from stdout
+ @param captured_output: output captured from stderr
+ @param file: the tests file (c:/temp/test.py)
+ @param test: the test ran (i.e.: TestCase.test1)
+ @param time: float with the number of seconds elapsed
+ '''
+ assert cond is not None
+ assert captured_output is not None
+ assert error_contents is not None
+ assert file is not None
+ if test is None:
+ test = '' #Could happen if we have an import error importing module.
+ assert time is not None
+ try:
+ captured_output = _encode_if_needed(captured_output)
+ error_contents = _encode_if_needed(error_contents)
+
+ _ServerHolder.SERVER.notifyTest(cond, captured_output, error_contents, file, test, time)
+ except:
+ traceback.print_exc()
+
+#=======================================================================================================================
+# notifyTestRunFinished
+#=======================================================================================================================
+def notifyTestRunFinished(total_time):
+ assert total_time is not None
+ try:
+ _ServerHolder.SERVER.notifyTestRunFinished(total_time)
+ except:
+ traceback.print_exc()
+
+
+#=======================================================================================================================
+# forceServerKill
+#=======================================================================================================================
+def forceServerKill():
+ _ServerHolder.SERVER_COMM.notifications_queue.put_nowait(KillServer())
diff --git a/python/helpers/pydev/pydev_sitecustomize/__not_in_default_pythonpath.txt b/python/helpers/pydev/pydev_sitecustomize/__not_in_default_pythonpath.txt
new file mode 100644
index 000000000000..29cdc5bc1078
--- /dev/null
+++ b/python/helpers/pydev/pydev_sitecustomize/__not_in_default_pythonpath.txt
@@ -0,0 +1 @@
+(no __init__.py file) \ No newline at end of file
diff --git a/python/helpers/pydev/pydev_sitecustomize/sitecustomize.py b/python/helpers/pydev/pydev_sitecustomize/sitecustomize.py
new file mode 100644
index 000000000000..78b9c794eef4
--- /dev/null
+++ b/python/helpers/pydev/pydev_sitecustomize/sitecustomize.py
@@ -0,0 +1,192 @@
+'''
+ This module will:
+ - change the input() and raw_input() commands to change \r\n or \r into \n
+ - execute the user site customize -- if available
+ - change raw_input() and input() to also remove any trailing \r
+
+ Up to PyDev 3.4 it also was setting the default encoding, but it was removed because of differences when
+ running from a shell (i.e.: now we just set the PYTHONIOENCODING related to that -- which is properly
+ treated on Py 2.7 onwards).
+'''
+DEBUG = 0 #0 or 1 because of jython
+
+import sys
+encoding = None
+
+IS_PYTHON_3K = 0
+
+try:
+ if sys.version_info[0] == 3:
+ IS_PYTHON_3K = 1
+
+except:
+ #That's OK, not all versions of python have sys.version_info
+ if DEBUG:
+ import traceback;traceback.print_exc() #@Reimport
+
+#-----------------------------------------------------------------------------------------------------------------------
+#Line buffering
+if IS_PYTHON_3K:
+ #Python 3 has a bug (http://bugs.python.org/issue4705) in which -u doesn't properly make output/input unbuffered
+ #so, we need to enable that ourselves here.
+ try:
+ sys.stdout._line_buffering = True
+ except:
+ pass
+ try:
+ sys.stderr._line_buffering = True
+ except:
+ pass
+ try:
+ sys.stdin._line_buffering = True
+ except:
+ pass
+
+
+try:
+ import org.python.core.PyDictionary #@UnresolvedImport @UnusedImport -- just to check if it could be valid
+ def DictContains(d, key):
+ return d.has_key(key)
+except:
+ try:
+ #Py3k does not have has_key anymore, and older versions don't have __contains__
+ DictContains = dict.__contains__
+ except:
+ try:
+ DictContains = dict.has_key
+ except NameError:
+ def DictContains(d, key):
+ return d.has_key(key)
+
+
+#-----------------------------------------------------------------------------------------------------------------------
+#now that we've finished the needed pydev sitecustomize, let's run the default one (if available)
+
+#Ok, some weirdness going on in Python 3k: when removing this module from the sys.module to import the 'real'
+#sitecustomize, all the variables in this scope become None (as if it was garbage-collected), so, the the reference
+#below is now being kept to create a cyclic reference so that it neven dies)
+__pydev_sitecustomize_module__ = sys.modules.get('sitecustomize') #A ref to this module
+
+
+#remove the pydev site customize (and the pythonpath for it)
+paths_removed = []
+try:
+ for c in sys.path[:]:
+ #Pydev controls the whole classpath in Jython already, so, we don't want a a duplicate for
+ #what we've already added there (this is needed to support Jython 2.5b1 onwards -- otherwise, as
+ #we added the sitecustomize to the pythonpath and to the classpath, we'd have to remove it from the
+ #classpath too -- and I don't think there's a way to do that... or not?)
+ if c.find('pydev_sitecustomize') != -1 or c == '__classpath__' or c == '__pyclasspath__' or \
+ c == '__classpath__/' or c == '__pyclasspath__/' or c == '__classpath__\\' or c == '__pyclasspath__\\':
+ sys.path.remove(c)
+ if c.find('pydev_sitecustomize') == -1:
+ #We'll re-add any paths removed but the pydev_sitecustomize we added from pydev.
+ paths_removed.append(c)
+
+ if DictContains(sys.modules, 'sitecustomize'):
+ del sys.modules['sitecustomize'] #this module
+except:
+ #print the error... should never happen (so, always show, and not only on debug)!
+ import traceback;traceback.print_exc() #@Reimport
+else:
+ #Now, execute the default sitecustomize
+ try:
+ import sitecustomize #@UnusedImport
+ sitecustomize.__pydev_sitecustomize_module__ = __pydev_sitecustomize_module__
+ except:
+ pass
+
+ if not DictContains(sys.modules, 'sitecustomize'):
+ #If there was no sitecustomize, re-add the pydev sitecustomize (pypy gives a KeyError if it's not there)
+ sys.modules['sitecustomize'] = __pydev_sitecustomize_module__
+
+ try:
+ if paths_removed:
+ if sys is None:
+ import sys
+ if sys is not None:
+ #And after executing the default sitecustomize, restore the paths (if we didn't remove it before,
+ #the import sitecustomize would recurse).
+ sys.path.extend(paths_removed)
+ except:
+ #print the error... should never happen (so, always show, and not only on debug)!
+ import traceback;traceback.print_exc() #@Reimport
+
+
+
+
+if not IS_PYTHON_3K:
+ try:
+ #Redefine input and raw_input only after the original sitecustomize was executed
+ #(because otherwise, the original raw_input and input would still not be defined)
+ import __builtin__
+ original_raw_input = __builtin__.raw_input
+ original_input = __builtin__.input
+
+
+ def raw_input(prompt=''):
+ #the original raw_input would only remove a trailing \n, so, at
+ #this point if we had a \r\n the \r would remain (which is valid for eclipse)
+ #so, let's remove the remaining \r which python didn't expect.
+ ret = original_raw_input(prompt)
+
+ if ret.endswith('\r'):
+ return ret[:-1]
+
+ return ret
+ raw_input.__doc__ = original_raw_input.__doc__
+
+ def input(prompt=''):
+ #input must also be rebinded for using the new raw_input defined
+ return eval(raw_input(prompt))
+ input.__doc__ = original_input.__doc__
+
+
+ __builtin__.raw_input = raw_input
+ __builtin__.input = input
+
+ except:
+ #Don't report errors at this stage
+ if DEBUG:
+ import traceback;traceback.print_exc() #@Reimport
+
+else:
+ try:
+ import builtins #Python 3.0 does not have the __builtin__ module @UnresolvedImport
+ original_input = builtins.input
+ def input(prompt=''):
+ #the original input would only remove a trailing \n, so, at
+ #this point if we had a \r\n the \r would remain (which is valid for eclipse)
+ #so, let's remove the remaining \r which python didn't expect.
+ ret = original_input(prompt)
+
+ if ret.endswith('\r'):
+ return ret[:-1]
+
+ return ret
+ input.__doc__ = original_input.__doc__
+ builtins.input = input
+ except:
+ #Don't report errors at this stage
+ if DEBUG:
+ import traceback;traceback.print_exc() #@Reimport
+
+
+
+try:
+ #The original getpass doesn't work from the eclipse console, so, let's put a replacement
+ #here (note that it'll not go into echo mode in the console, so, what' the user writes
+ #will actually be seen)
+ import getpass #@UnresolvedImport
+ if IS_PYTHON_3K:
+ def pydev_getpass(msg='Password: '):
+ return input(msg)
+ else:
+ def pydev_getpass(msg='Password: '):
+ return raw_input(msg)
+
+ getpass.getpass = pydev_getpass
+except:
+ #Don't report errors at this stage
+ if DEBUG:
+ import traceback;traceback.print_exc() #@Reimport
diff --git a/python/helpers/pydev/pydev_umd.py b/python/helpers/pydev/pydev_umd.py
new file mode 100644
index 000000000000..0bfeda74a1a6
--- /dev/null
+++ b/python/helpers/pydev/pydev_umd.py
@@ -0,0 +1,172 @@
+"""
+The UserModuleDeleter and runfile methods are copied from
+Spyder and carry their own license agreement.
+http://code.google.com/p/spyderlib/source/browse/spyderlib/widgets/externalshell/sitecustomize.py
+
+Spyder License Agreement (MIT License)
+--------------------------------------
+
+Copyright (c) 2009-2012 Pierre Raybaut
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+"""
+
+import sys
+import os
+
+# The following classes and functions are mainly intended to be used from
+# an interactive Python session
+class UserModuleDeleter:
+ """
+ User Module Deleter (UMD) aims at deleting user modules
+ to force Python to deeply reload them during import
+
+ pathlist [list]: blacklist in terms of module path
+ namelist [list]: blacklist in terms of module name
+ """
+ def __init__(self, namelist=None, pathlist=None):
+ if namelist is None:
+ namelist = []
+ self.namelist = namelist
+ if pathlist is None:
+ pathlist = []
+ self.pathlist = pathlist
+ try:
+ # blacklist all files in org.python.pydev/pysrc
+ import pydev_pysrc, inspect
+ self.pathlist.append(os.path.dirname(pydev_pysrc.__file__))
+ except:
+ pass
+ self.previous_modules = list(sys.modules.keys())
+
+ def is_module_blacklisted(self, modname, modpath):
+ for path in [sys.prefix] + self.pathlist:
+ if modpath.startswith(path):
+ return True
+ else:
+ return set(modname.split('.')) & set(self.namelist)
+
+ def run(self, verbose=False):
+ """
+ Del user modules to force Python to deeply reload them
+
+ Do not del modules which are considered as system modules, i.e.
+ modules installed in subdirectories of Python interpreter's binary
+ Do not del C modules
+ """
+ log = []
+ modules_copy = dict(sys.modules)
+ for modname, module in modules_copy.items():
+ if modname == 'aaaaa':
+ print(modname, module)
+ print(self.previous_modules)
+ if modname not in self.previous_modules:
+ modpath = getattr(module, '__file__', None)
+ if modpath is None:
+ # *module* is a C module that is statically linked into the
+ # interpreter. There is no way to know its path, so we
+ # choose to ignore it.
+ continue
+ if not self.is_module_blacklisted(modname, modpath):
+ log.append(modname)
+ del sys.modules[modname]
+ if verbose and log:
+ print("\x1b[4;33m%s\x1b[24m%s\x1b[0m" % ("UMD has deleted",
+ ": " + ", ".join(log)))
+
+__umd__ = None
+
+_get_globals_callback = None
+def _set_globals_function(get_globals):
+ global _get_globals_callback
+ _get_globals_callback = get_globals
+def _get_globals():
+ """Return current Python interpreter globals namespace"""
+ if _get_globals_callback is not None:
+ return _get_globals_callback()
+ else:
+ try:
+ from __main__ import __dict__ as namespace
+ except ImportError:
+ try:
+ # The import fails on IronPython
+ import __main__
+ namespace = __main__.__dict__
+ except:
+ namespace
+ shell = namespace.get('__ipythonshell__')
+ if shell is not None and hasattr(shell, 'user_ns'):
+ # IPython 0.12+ kernel
+ return shell.user_ns
+ else:
+ # Python interpreter
+ return namespace
+ return namespace
+
+
+def runfile(filename, args=None, wdir=None, namespace=None):
+ """
+ Run filename
+ args: command line arguments (string)
+ wdir: working directory
+ """
+ try:
+ if hasattr(filename, 'decode'):
+ filename = filename.decode('utf-8')
+ except (UnicodeError, TypeError):
+ pass
+ global __umd__
+ if os.environ.get("PYDEV_UMD_ENABLED", "").lower() == "true":
+ if __umd__ is None:
+ namelist = os.environ.get("PYDEV_UMD_NAMELIST", None)
+ if namelist is not None:
+ namelist = namelist.split(',')
+ __umd__ = UserModuleDeleter(namelist=namelist)
+ else:
+ verbose = os.environ.get("PYDEV_UMD_VERBOSE", "").lower() == "true"
+ __umd__.run(verbose=verbose)
+ if args is not None and not isinstance(args, basestring):
+ raise TypeError("expected a character buffer object")
+ if namespace is None:
+ namespace = _get_globals()
+ if '__file__' in namespace:
+ old_file = namespace['__file__']
+ else:
+ old_file = None
+ namespace['__file__'] = filename
+ sys.argv = [filename]
+ if args is not None:
+ for arg in args.split():
+ sys.argv.append(arg)
+ if wdir is not None:
+ try:
+ if hasattr(wdir, 'decode'):
+ wdir = wdir.decode('utf-8')
+ except (UnicodeError, TypeError):
+ pass
+ os.chdir(wdir)
+ execfile(filename, namespace)
+ sys.argv = ['']
+ if old_file is None:
+ del namespace['__file__']
+ else:
+ namespace['__file__'] = old_file
diff --git a/python/helpers/pydev/pydevconsole.py b/python/helpers/pydev/pydevconsole.py
index 6c0640fb621d..2f07a826aa7d 100644
--- a/python/helpers/pydev/pydevconsole.py
+++ b/python/helpers/pydev/pydevconsole.py
@@ -10,7 +10,6 @@ import os
import sys
from pydevd_constants import USE_LIB_COPY
-from pydevd_constants import IS_JYTHON
if USE_LIB_COPY:
import _pydev_threading as threading
@@ -23,15 +22,7 @@ fix_getpass.fixGetpass()
import pydevd_vars
-from pydev_imports import Exec
-
-try:
- if USE_LIB_COPY:
- import _pydev_Queue as _queue
- else:
- import Queue as _queue
-except:
- import queue as _queue
+from pydev_imports import Exec, _queue
try:
import __builtin__
@@ -47,7 +38,7 @@ except NameError: # version < 2.3 -- didn't have the True/False builtins
setattr(__builtin__, 'True', 1) #Python 3.0 does not accept __builtin__.True = 1 in its syntax
setattr(__builtin__, 'False', 0)
-from pydev_console_utils import BaseInterpreterInterface
+from pydev_console_utils import BaseInterpreterInterface, BaseStdIn
from pydev_console_utils import CodeFragment
IS_PYTHON_3K = False
@@ -59,17 +50,6 @@ except:
#That's OK, not all versions of python have sys.version_info
pass
-try:
- try:
- if USE_LIB_COPY:
- import _pydev_xmlrpclib as xmlrpclib
- else:
- import xmlrpclib
- except ImportError:
- import xmlrpc.client as xmlrpclib
-except ImportError:
- import _pydev_xmlrpclib as xmlrpclib
-
class Command:
def __init__(self, interpreter, code_fragment):
@@ -145,23 +125,71 @@ class InterpreterInterface(BaseInterpreterInterface):
traceback.print_exc()
return []
-
+
def close(self):
sys.exit(0)
def get_greeting_msg(self):
- return 'PyDev console: starting.'
+ return 'PyDev console: starting.\n'
+
+
+class _ProcessExecQueueHelper:
+ _debug_hook = None
+ _return_control_osc = False
+
+def set_debug_hook(debug_hook):
+ _ProcessExecQueueHelper._debug_hook = debug_hook
def process_exec_queue(interpreter):
+
+ from pydev_ipython.inputhook import get_inputhook, set_return_control_callback
+
+ def return_control():
+ ''' A function that the inputhooks can call (via inputhook.stdin_ready()) to find
+ out if they should cede control and return '''
+ if _ProcessExecQueueHelper._debug_hook:
+ # Some of the input hooks check return control without doing
+ # a single operation, so we don't return True on every
+ # call when the debug hook is in place to allow the GUI to run
+ # XXX: Eventually the inputhook code will have diverged enough
+ # from the IPython source that it will be worthwhile rewriting
+ # it rather than pretending to maintain the old API
+ _ProcessExecQueueHelper._return_control_osc = not _ProcessExecQueueHelper._return_control_osc
+ if _ProcessExecQueueHelper._return_control_osc:
+ return True
+
+ if not interpreter.exec_queue.empty():
+ return True
+ return False
+
+ set_return_control_callback(return_control)
+
while 1:
+ # Running the request may have changed the inputhook in use
+ inputhook = get_inputhook()
+
+ if _ProcessExecQueueHelper._debug_hook:
+ _ProcessExecQueueHelper._debug_hook()
+
+ if inputhook:
+ try:
+ # Note: it'll block here until return_control returns True.
+ inputhook()
+ except:
+ import traceback;traceback.print_exc()
try:
try:
- codeFragment = interpreter.exec_queue.get(block=True, timeout=0.05)
+ code_fragment = interpreter.exec_queue.get(block=True, timeout=1/20.) # 20 calls/second
except _queue.Empty:
continue
- more = interpreter.addExec(codeFragment)
+ if callable(code_fragment):
+ # It can be a callable (i.e.: something that must run in the main
+ # thread can be put in the queue for later execution).
+ code_fragment()
+ else:
+ more = interpreter.addExec(code_fragment)
except KeyboardInterrupt:
interpreter.buffer = None
continue
@@ -221,16 +249,6 @@ def handshake():
return "PyCharm"
-def ipython_editor(interpreter):
- def editor(file, line):
- if file is None:
- file = ""
- if line is None:
- line = "-1"
- interpreter.ipython_editor(file, line)
-
- return editor
-
#=======================================================================================================================
# StartServer
#=======================================================================================================================
@@ -238,11 +256,8 @@ def start_server(host, port, interpreter):
if port == 0:
host = ''
- try:
- from _pydev_xmlrpc_hook import InputHookedXMLRPCServer as XMLRPCServer #@UnusedImport
- except:
- #I.e.: supporting the internal Jython version in PyDev to create a Jython interactive console inside Eclipse.
- from pydev_imports import SimpleXMLRPCServer as XMLRPCServer #@Reimport
+ #I.e.: supporting the internal Jython version in PyDev to create a Jython interactive console inside Eclipse.
+ from pydev_imports import SimpleXMLRPCServer as XMLRPCServer #@Reimport
try:
server = XMLRPCServer((host, port), logRequests=False, allow_none=True)
@@ -262,12 +277,10 @@ def start_server(host, port, interpreter):
server.register_function(interpreter.interrupt)
server.register_function(handshake)
server.register_function(interpreter.connectToDebugger)
+ server.register_function(interpreter.hello)
- if IPYTHON:
- try:
- interpreter.interpreter.ipython.hooks.editor = ipython_editor(interpreter)
- except:
- pass
+ # Functions for GUI main loop integration
+ server.register_function(interpreter.enableGui)
if port == 0:
(h, port) = server.socket.getsockname()
@@ -279,7 +292,6 @@ def start_server(host, port, interpreter):
sys.stderr.write(interpreter.get_greeting_msg())
sys.stderr.flush()
- interpreter.server = server
server.serve_forever()
return server
@@ -318,10 +330,9 @@ def get_completions(text, token, globals, locals):
return interpreterInterface.getCompletions(text, token)
-def get_frame():
- interpreterInterface = get_interpreter()
-
- return interpreterInterface.getFrame()
+#===============================================================================
+# Debugger integration
+#===============================================================================
def exec_code(code, globals, locals):
interpreterInterface = get_interpreter()
@@ -338,20 +349,6 @@ def exec_code(code, globals, locals):
return False
-def read_line(s):
- ret = ''
-
- while True:
- c = s.recv(1)
-
- if c == '\n' or c == '':
- break
- else:
- ret += c
-
- return ret
-
-# Debugger integration
class ConsoleWriter(InteractiveInterpreter):
skip = 0
@@ -408,7 +405,7 @@ class ConsoleWriter(InteractiveInterpreter):
sys.stderr.write(''.join(lines))
def consoleExec(thread_id, frame_id, expression):
- """returns 'False' in case expression is partialy correct
+ """returns 'False' in case expression is partially correct
"""
frame = pydevd_vars.findFrame(thread_id, frame_id)
@@ -452,9 +449,8 @@ def consoleExec(thread_id, frame_id, expression):
#=======================================================================================================================
# main
#=======================================================================================================================
-
-
if __name__ == '__main__':
+ sys.stdin = BaseStdIn()
port, client_port = sys.argv[1:3]
import pydev_localhost
diff --git a/python/helpers/pydev/pydevd.py b/python/helpers/pydev/pydevd.py
index 2077903ea091..1733c26b5e91 100644
--- a/python/helpers/pydev/pydevd.py
+++ b/python/helpers/pydev/pydevd.py
@@ -1,4 +1,6 @@
#IMPORTANT: pydevd_constants must be the 1st thing defined because it'll keep a reference to the original sys._getframe
+from __future__ import nested_scopes # Jython 2.1 support
+
import traceback
from django_debug import DjangoLineBreakpoint
@@ -35,7 +37,7 @@ from pydevd_comm import CMD_CHANGE_VARIABLE, \
CMD_ADD_DJANGO_EXCEPTION_BREAK, \
CMD_REMOVE_DJANGO_EXCEPTION_BREAK, \
CMD_SMART_STEP_INTO,\
- InternalChangeVariable, \
+ InternalChangeVariable, \
InternalGetCompletions, \
InternalEvaluateExpression, \
InternalConsoleExec, \
@@ -55,23 +57,35 @@ from pydevd_comm import CMD_CHANGE_VARIABLE, \
PydevdLog, \
StartClient, \
StartServer, \
- InternalSetNextStatementThread, ReloadCodeCommand
+ InternalSetNextStatementThread, \
+ ReloadCodeCommand, \
+ CMD_SET_PY_EXCEPTION, \
+ CMD_IGNORE_THROWN_EXCEPTION_AT,\
+ InternalGetBreakpointException, \
+ InternalSendCurrExceptionTrace,\
+ InternalSendCurrExceptionTraceProceeded,\
+ CMD_ENABLE_DONT_TRACE, \
+ CMD_GET_FILE_CONTENTS,\
+ CMD_SET_PROPERTY_TRACE, CMD_RUN_CUSTOM_OPERATION,\
+ InternalRunCustomOperation, CMD_EVALUATE_CONSOLE_EXPRESSION, InternalEvaluateConsoleExpression,\
+ InternalConsoleGetCompletions
+
from pydevd_file_utils import NormFileToServer, GetFilenameAndBase
import pydevd_file_utils
import pydevd_vars
import pydevd_vm_type
import pydevd_tracing
import pydevd_io
-import pydev_monkey
from pydevd_additional_thread_info import PyDBAdditionalThreadInfo
from pydevd_custom_frames import CustomFramesContainer, CustomFramesContainerInit
+import pydevd_dont_trace
+import pydevd_traceproperty
+from _pydev_imps import _pydev_time as time
if USE_LIB_COPY:
- import _pydev_time as time
import _pydev_threading as threading
else:
- import time
import threading
import os
@@ -80,10 +94,13 @@ import os
threadingEnumerate = threading.enumerate
threadingCurrentThread = threading.currentThread
+try:
+ 'dummy'.encode('utf-8') # Added because otherwise Jython 2.2.1 wasn't finding the encoding (if it wasn't loaded in the main thread).
+except:
+ pass
DONT_TRACE = {
# commonly used things from the stdlib that we don't want to trace
- 'threading.py':1,
'Queue.py':1,
'queue.py':1,
'socket.py':1,
@@ -92,12 +109,19 @@ DONT_TRACE = {
'threading.py':1,
#things from pydev that we don't want to trace
+ '_pydev_execfile.py':1,
+ '_pydev_jython_execfile.py':1,
+ '_pydev_threading':1,
+ 'django_debug.py':1,
+ 'django_frame.py':1,
+ 'pydev_log.py':1,
'pydevd.py':1 ,
'pydevd_additional_thread_info.py':1,
- 'pydevd_custom_frames.py':1,
'pydevd_comm.py':1,
'pydevd_console.py':1 ,
'pydevd_constants.py':1,
+ 'pydevd_custom_frames.py':1,
+ 'pydevd_dont_trace.py':1,
'pydevd_exec.py':1,
'pydevd_exec2.py':1,
'pydevd_file_utils.py':1,
@@ -105,17 +129,18 @@ DONT_TRACE = {
'pydevd_import_class.py':1 ,
'pydevd_io.py':1 ,
'pydevd_psyco_stub.py':1,
+ 'pydevd_referrers.py':1 ,
'pydevd_reload.py':1 ,
'pydevd_resolver.py':1 ,
+ 'pydevd_save_locals.py':1 ,
+ 'pydevd_signature.py':1,
'pydevd_stackless.py':1 ,
'pydevd_traceproperty.py':1,
'pydevd_tracing.py':1 ,
- 'pydevd_signature.py':1,
'pydevd_utils.py':1,
'pydevd_vars.py':1,
'pydevd_vm_type.py':1,
- '_pydev_execfile.py':1,
- '_pydev_jython_execfile.py':1
+ 'pydevd_xml.py':1,
}
if IS_PY3K:
@@ -135,17 +160,28 @@ remote = False
from _pydev_filesystem_encoding import getfilesystemencoding
file_system_encoding = getfilesystemencoding()
-def isThreadAlive(t):
- try:
- # If thread is not started yet we treat it as alive.
- # It is required to debug threads started by start_new_thread in Python 3.4
- if hasattr(t, '_is_stopped'):
- alive = not t._is_stopped
- else:
- alive = not t.__stopped
- except:
- alive = t.isAlive()
- return alive
+
+# Hack for https://sw-brainwy.rhcloud.com/tracker/PyDev/363 (i.e.: calling isAlive() can throw AssertionError under some circumstances)
+# It is required to debug threads started by start_new_thread in Python 3.4
+_temp = threading.Thread()
+if hasattr(_temp, '_is_stopped'): # Python 3.4 has this
+ def isThreadAlive(t):
+ try:
+ return not t._is_stopped
+ except:
+ return t.isAlive()
+
+elif hasattr(_temp, '_Thread__stopped'): # Python 2.7 has this
+ def isThreadAlive(t):
+ try:
+ return not t._Thread__stopped
+ except:
+ return t.isAlive()
+
+else: # Haven't checked all other versions, so, let's use the regular isAlive call in this case.
+ def isThreadAlive(t):
+ return t.isAlive()
+del _temp
#=======================================================================================================================
# PyDBCommandThread
@@ -159,7 +195,7 @@ class PyDBCommandThread(PyDBDaemonThread):
self.setName('pydevd.CommandThread')
def OnRun(self):
- for i in range(1, 10):
+ for i in xrange(1, 10):
time.sleep(0.5) #this one will only start later on (because otherwise we may not have any non-daemon threads
if self.killReceived:
return
@@ -187,7 +223,7 @@ def killAllPydevThreads():
for t in threads:
if hasattr(t, 'doKillPydevThread'):
t.doKillPydevThread()
-
+
#=======================================================================================================================
# PyDBCheckAliveThread
@@ -220,62 +256,6 @@ class PyDBCheckAliveThread(PyDBDaemonThread):
def doKillPydevThread(self):
pass
-if USE_LIB_COPY:
- import _pydev_thread as thread
-else:
- try:
- import thread
- except ImportError:
- import _thread as thread #Py3K changed it.
-
-_original_start_new_thread = thread.start_new_thread
-
-if getattr(thread, '_original_start_new_thread', None) is None:
- thread._original_start_new_thread = thread.start_new_thread
-
-#=======================================================================================================================
-# NewThreadStartup
-#=======================================================================================================================
-class NewThreadStartup:
-
- def __init__(self, original_func, args, kwargs):
- self.original_func = original_func
- self.args = args
- self.kwargs = kwargs
-
- def __call__(self):
- global_debugger = GetGlobalDebugger()
- global_debugger.SetTrace(global_debugger.trace_dispatch)
- self.original_func(*self.args, **self.kwargs)
-
-thread.NewThreadStartup = NewThreadStartup
-
-#=======================================================================================================================
-# pydev_start_new_thread
-#=======================================================================================================================
-def _pydev_start_new_thread(function, args, kwargs={}):
- '''
- We need to replace the original thread.start_new_thread with this function so that threads started through
- it and not through the threading module are properly traced.
- '''
- if USE_LIB_COPY:
- import _pydev_thread as thread
- else:
- try:
- import thread
- except ImportError:
- import _thread as thread #Py3K changed it.
-
- return thread._original_start_new_thread(thread.NewThreadStartup(function, args, kwargs), ())
-
-class PydevStartNewThread(object):
- def __get__(self, obj, type=None):
- return self
-
- def __call__(self, function, args, kwargs={}):
- return _pydev_start_new_thread(function, args, kwargs)
-
-pydev_start_new_thread = PydevStartNewThread()
#=======================================================================================================================
@@ -304,10 +284,18 @@ class PyDB:
self.quitting = None
self.cmdFactory = NetCommandFactory()
self._cmd_queue = {} # the hash of Queues. Key is thread id, value is thread
+
self.breakpoints = {}
self.django_breakpoints = {}
- self.exception_set = {}
- self.always_exception_set = set()
+
+ self.file_to_id_to_line_breakpoint = {}
+ self.file_to_id_to_django_breakpoint = {}
+
+ # Note: breakpoints dict should not be mutated: a copy should be created
+ # and later it should be assigned back (to prevent concurrency issues).
+ self.break_on_uncaught_exceptions = {}
+ self.break_on_caught_exceptions = {}
+
self.django_exception_break = {}
self.readyToRun = False
self._main_lock = threading.Lock()
@@ -316,15 +304,31 @@ class PyDB:
CustomFramesContainer._py_db_command_thread_event = self._py_db_command_thread_event
self._finishDebuggingSession = False
self._terminationEventSent = False
- self.force_post_mortem_stop = 0
self.signature_factory = None
self.SetTrace = pydevd_tracing.SetTrace
+ self.break_on_exceptions_thrown_in_same_context = False
+ self.ignore_exceptions_thrown_in_lines_with_ignore_exception = True
+
+ # Suspend debugger even if breakpoint condition raises an exception
+ SUSPEND_ON_BREAKPOINT_EXCEPTION = True
+ self.suspend_on_breakpoint_exception = SUSPEND_ON_BREAKPOINT_EXCEPTION
+
+ # By default user can step into properties getter/setter/deleter methods
+ self.disable_property_trace = False
+ self.disable_property_getter_trace = False
+ self.disable_property_setter_trace = False
+ self.disable_property_deleter_trace = False
#this is a dict of thread ids pointing to thread ids. Whenever a command is passed to the java end that
#acknowledges that a thread was created, the thread id should be passed here -- and if at some time we do not
#find that thread alive anymore, we must remove it from this list and make the java side know that the thread
#was killed.
self._running_thread_ids = {}
+ self._set_breakpoints_with_id = False
+
+ # This attribute holds the file-> lines which have an @IgnoreException.
+ self.filename_to_lines_where_exceptions_are_ignored = {}
+
def haveAliveThreads(self):
for t in threadingEnumerate():
@@ -398,12 +402,12 @@ class PyDB:
global bufferStdErrToServer
if bufferStdOutToServer:
- initStdoutRedirect()
- self.checkOutput(sys.stdoutBuf, 1) #@UndefinedVariable
+ initStdoutRedirect()
+ self.checkOutput(sys.stdoutBuf, 1) #@UndefinedVariable
if bufferStdErrToServer:
- initStderrRedirect()
- self.checkOutput(sys.stderrBuf, 2) #@UndefinedVariable
+ initStderrRedirect()
+ self.checkOutput(sys.stderrBuf, 2) #@UndefinedVariable
def checkOutput(self, out, outCtx):
'''Checks the output to see if we have to send some buffered output to the debug server
@@ -521,6 +525,58 @@ class PyDB:
additionalInfo = None
+ def consolidate_breakpoints(self, file, id_to_breakpoint, breakpoints):
+ break_dict = {}
+ for breakpoint_id, pybreakpoint in DictIterItems(id_to_breakpoint):
+ break_dict[pybreakpoint.line] = pybreakpoint
+
+ breakpoints[file] = break_dict
+
+
+ def add_break_on_exception(
+ self,
+ exception,
+ notify_always,
+ notify_on_terminate,
+ notify_on_first_raise_only,
+ ):
+ eb = ExceptionBreakpoint(
+ exception,
+ notify_always,
+ notify_on_terminate,
+ notify_on_first_raise_only,
+ )
+
+ if eb.notify_on_terminate:
+ cp = self.break_on_uncaught_exceptions.copy()
+ cp[exception] = eb
+ if DebugInfoHolder.DEBUG_TRACE_BREAKPOINTS > 0:
+ pydev_log.error("Exceptions to hook on terminate: %s\n" % (cp,))
+ self.break_on_uncaught_exceptions = cp
+
+ if eb.notify_always:
+ cp = self.break_on_caught_exceptions.copy()
+ cp[exception] = eb
+ if DebugInfoHolder.DEBUG_TRACE_BREAKPOINTS > 0:
+ pydev_log.error("Exceptions to hook always: %s\n" % (cp,))
+ self.break_on_caught_exceptions = cp
+
+ return eb
+
+ def update_after_exceptions_added(self, added):
+ updated_on_caught = False
+ updated_on_uncaught = False
+
+ for eb in added:
+ if not updated_on_uncaught and eb.notify_on_terminate:
+ updated_on_uncaught = True
+ update_exception_hook(self)
+
+ if not updated_on_caught and eb.notify_always:
+ updated_on_caught = True
+ self.setTracingForUntracedContexts()
+
+
def processNetCommand(self, cmd_id, seq, text):
'''Processes a command received from the Java side
@@ -536,6 +592,7 @@ class PyDB:
it may be worth refactoring it (actually, reordering the ifs so that the ones used mostly come before
probably will give better performance).
'''
+ #print ID_TO_MEANING[str(cmd_id)], repr(text)
self._main_lock.acquire()
try:
@@ -546,9 +603,28 @@ class PyDB:
elif cmd_id == CMD_VERSION:
# response is version number
- local_version, pycharm_os = text.split('\t', 1)
+ # ide_os should be 'WINDOWS' or 'UNIX'.
+ ide_os = 'WINDOWS'
+
+ # Breakpoints can be grouped by 'LINE' or by 'ID'.
+ breakpoints_by = 'LINE'
- pydevd_file_utils.set_pycharm_os(pycharm_os)
+ splitted = text.split('\t')
+ if len(splitted) == 1:
+ _local_version = splitted
+
+ elif len(splitted) == 2:
+ _local_version, ide_os = splitted
+
+ elif len(splitted) == 3:
+ _local_version, ide_os, breakpoints_by = splitted
+
+ if breakpoints_by == 'ID':
+ self._set_breakpoints_with_id = True
+ else:
+ self._set_breakpoints_with_id = False
+
+ pydevd_file_utils.set_ide_os(ide_os)
cmd = self.cmdFactory.makeVersionMessage(seq)
@@ -684,26 +760,42 @@ class PyDB:
elif cmd_id == CMD_SET_BREAK:
# func name: 'None': match anything. Empty: match global, specified: only method context.
-
# command to add some breakpoint.
# text is file\tline. Add to breakpoints dictionary
- type, file, line, condition, expression = text.split('\t', 4)
+ if self._set_breakpoints_with_id:
+ breakpoint_id, type, file, line, func_name, condition, expression = text.split('\t', 6)
- if not IS_PY3K: # In Python 3, the frame object will have unicode for the file, whereas on python 2 it has a byte-array encoded with the filesystem encoding.
- file = file.encode(file_system_encoding)
-
- if condition.startswith('**FUNC**'):
- func_name, condition = condition.split('\t', 1)
+ breakpoint_id = int(breakpoint_id)
+ line = int(line)
# We must restore new lines and tabs as done in
# AbstractDebugTarget.breakpointAdded
condition = condition.replace("@_@NEW_LINE_CHAR@_@", '\n').\
replace("@_@TAB_CHAR@_@", '\t').strip()
- func_name = func_name[8:]
+ expression = expression.replace("@_@NEW_LINE_CHAR@_@", '\n').\
+ replace("@_@TAB_CHAR@_@", '\t').strip()
else:
- func_name = 'None' # Match anything if not specified.
+ #Note: this else should be removed after PyCharm migrates to setting
+ #breakpoints by id (and ideally also provides func_name).
+ type, file, line, condition, expression = text.split('\t', 4)
+ # If we don't have an id given for each breakpoint, consider
+ # the id to be the line.
+ breakpoint_id = line = int(line)
+ if condition.startswith('**FUNC**'):
+ func_name, condition = condition.split('\t', 1)
+
+ # We must restore new lines and tabs as done in
+ # AbstractDebugTarget.breakpointAdded
+ condition = condition.replace("@_@NEW_LINE_CHAR@_@", '\n').\
+ replace("@_@TAB_CHAR@_@", '\t').strip()
+
+ func_name = func_name[8:]
+ else:
+ func_name = 'None' # Match anything if not specified.
+ if not IS_PY3K: # In Python 3, the frame object will have unicode for the file, whereas on python 2 it has a byte-array encoded with the filesystem encoding.
+ file = file.encode(file_system_encoding)
file = NormFileToServer(file)
@@ -712,7 +804,6 @@ class PyDB:
' to file that does not exist: %s (will have no effect)\n' % (file,))
sys.stderr.flush()
- line = int(line)
if len(condition) <= 0 or condition is None or condition == "None":
condition = None
@@ -721,57 +812,68 @@ class PyDB:
expression = None
if type == 'python-line':
- breakpoint = LineBreakpoint(type, True, condition, func_name, expression)
- breakpoint.add(self.breakpoints, file, line, func_name)
+ breakpoint = LineBreakpoint(line, condition, func_name, expression)
+ breakpoints = self.breakpoints
+ file_to_id_to_breakpoint = self.file_to_id_to_line_breakpoint
elif type == 'django-line':
- breakpoint = DjangoLineBreakpoint(type, file, line, True, condition, func_name, expression)
- breakpoint.add(self.django_breakpoints, file, line, func_name)
+ breakpoint = DjangoLineBreakpoint(file, line, condition, func_name, expression)
+ breakpoints = self.django_breakpoints
+ file_to_id_to_breakpoint = self.file_to_id_to_django_breakpoint
else:
raise NameError(type)
+ if DebugInfoHolder.DEBUG_TRACE_BREAKPOINTS > 0:
+ pydev_log.debug('Added breakpoint:%s - line:%s - func_name:%s\n' % (file, line, func_name.encode('utf-8')))
+ sys.stderr.flush()
+
+ if DictContains(file_to_id_to_breakpoint, file):
+ id_to_pybreakpoint = file_to_id_to_breakpoint[file]
+ else:
+ id_to_pybreakpoint = file_to_id_to_breakpoint[file] = {}
+
+ id_to_pybreakpoint[breakpoint_id] = breakpoint
+ self.consolidate_breakpoints(file, id_to_pybreakpoint, breakpoints)
+
self.setTracingForUntracedContexts()
elif cmd_id == CMD_REMOVE_BREAK:
#command to remove some breakpoint
- #text is file\tline. Remove from breakpoints dictionary
- type, file, line = text.split('\t', 2)
+ #text is type\file\tid. Remove from breakpoints dictionary
+ breakpoint_type, file, breakpoint_id = text.split('\t', 2)
+
+ if not IS_PY3K: # In Python 3, the frame object will have unicode for the file, whereas on python 2 it has a byte-array encoded with the filesystem encoding.
+ file = file.encode(file_system_encoding)
+
file = NormFileToServer(file)
+
try:
- line = int(line)
+ breakpoint_id = int(breakpoint_id)
except ValueError:
- pass
+ pydev_log.error('Error removing breakpoint. Expected breakpoint_id to be an int. Found: %s' % (breakpoint_id,))
else:
- found = False
- try:
- if type == 'django-line':
- del self.django_breakpoints[file][line]
- elif type == 'python-line':
- del self.breakpoints[file][line] #remove the breakpoint in that line
- else:
- try:
- del self.django_breakpoints[file][line]
- found = True
- except:
- pass
- try:
- del self.breakpoints[file][line] #remove the breakpoint in that line
- found = True
- except:
- pass
+ if breakpoint_type == 'python-line':
+ breakpoints = self.breakpoints
+ file_to_id_to_breakpoint = self.file_to_id_to_line_breakpoint
+ elif breakpoint_type == 'django-line':
+ breakpoints = self.django_breakpoints
+ file_to_id_to_breakpoint = self.file_to_id_to_django_breakpoint
+ else:
+ raise NameError(breakpoint_type)
+ try:
+ id_to_pybreakpoint = file_to_id_to_breakpoint[file]
if DebugInfoHolder.DEBUG_TRACE_BREAKPOINTS > 0:
- sys.stderr.write('Removed breakpoint:%s - %s\n' % (file, line))
- sys.stderr.flush()
+ existing = id_to_pybreakpoint[breakpoint_id]
+ sys.stderr.write('Removed breakpoint:%s - line:%s - func_name:%s (id: %s)\n' % (
+ file, existing.line, existing.func_name.encode('utf-8'), breakpoint_id))
+
+ del id_to_pybreakpoint[breakpoint_id]
+ self.consolidate_breakpoints(file, id_to_pybreakpoint, breakpoints)
except KeyError:
- found = False
+ pydev_log.error("Error removing breakpoint: Breakpoint id not found: %s id: %s. Available ids: %s\n" % (
+ file, breakpoint_id, DictKeys(id_to_pybreakpoint)))
- if not found:
- #ok, it's not there...
- if DebugInfoHolder.DEBUG_TRACE_BREAKPOINTS > 0:
- #Sometimes, when adding a breakpoint, it adds a remove command before (don't really know why)
- sys.stderr.write("breakpoint not found: %s - %s\n" % (file, line))
- sys.stderr.flush()
elif cmd_id == CMD_EVALUATE_EXPRESSION or cmd_id == CMD_EXEC_EXPRESSION:
#command to evaluate the given expression
@@ -790,29 +892,118 @@ class PyDB:
int_cmd = InternalConsoleExec(seq, thread_id, frame_id, expression)
self.postInternalCommand(int_cmd, thread_id)
- elif cmd_id == CMD_ADD_EXCEPTION_BREAK:
- exception, notify_always, notify_on_terminate = text.split('\t', 2)
+ elif cmd_id == CMD_SET_PY_EXCEPTION:
+ # Command which receives set of exceptions on which user wants to break the debugger
+ # text is: break_on_uncaught;break_on_caught;TypeError;ImportError;zipimport.ZipImportError;
+ # This API is optional and works 'in bulk' -- it's possible
+ # to get finer-grained control with CMD_ADD_EXCEPTION_BREAK/CMD_REMOVE_EXCEPTION_BREAK
+ # which allows setting caught/uncaught per exception.
+ #
+ splitted = text.split(';')
+ self.break_on_uncaught_exceptions = {}
+ self.break_on_caught_exceptions = {}
+ added = []
+ if len(splitted) >= 4:
+ if splitted[0] == 'true':
+ break_on_uncaught = True
+ else:
+ break_on_uncaught = False
- eb = ExceptionBreakpoint(exception, notify_always, notify_on_terminate)
+ if splitted[1] == 'true':
+ break_on_caught = True
+ else:
+ break_on_caught = False
- self.exception_set[exception] = eb
+ if splitted[2] == 'true':
+ self.break_on_exceptions_thrown_in_same_context = True
+ else:
+ self.break_on_exceptions_thrown_in_same_context = False
- if eb.notify_on_terminate:
- update_exception_hook(self)
- if DebugInfoHolder.DEBUG_TRACE_BREAKPOINTS > 0:
- pydev_log.error("Exceptions to hook on terminate: %s\n" % (self.exception_set,))
+ if splitted[3] == 'true':
+ self.ignore_exceptions_thrown_in_lines_with_ignore_exception = True
+ else:
+ self.ignore_exceptions_thrown_in_lines_with_ignore_exception = False
+
+ for exception_type in splitted[4:]:
+ exception_type = exception_type.strip()
+ if not exception_type:
+ continue
+
+ exception_breakpoint = self.add_break_on_exception(
+ exception_type,
+ notify_always=break_on_caught,
+ notify_on_terminate=break_on_uncaught,
+ notify_on_first_raise_only=False,
+ )
+ added.append(exception_breakpoint)
- if eb.notify_always:
- self.always_exception_set.add(exception)
- if DebugInfoHolder.DEBUG_TRACE_BREAKPOINTS > 0:
- pydev_log.error("Exceptions to hook always: %s\n" % (self.always_exception_set,))
- self.setTracingForUntracedContexts()
+ self.update_after_exceptions_added(added)
+
+ else:
+ sys.stderr.write("Error when setting exception list. Received: %s\n" % (text,))
+
+ elif cmd_id == CMD_GET_FILE_CONTENTS:
+
+ if not IS_PY3K: # In Python 3, the frame object will have unicode for the file, whereas on python 2 it has a byte-array encoded with the filesystem encoding.
+ text = text.encode(file_system_encoding)
+
+ if os.path.exists(text):
+ f = open(text, 'r')
+ try:
+ source = f.read()
+ finally:
+ f.close()
+ cmd = self.cmdFactory.makeGetFileContents(seq, source)
+
+ elif cmd_id == CMD_SET_PROPERTY_TRACE:
+ # Command which receives whether to trace property getter/setter/deleter
+ # text is feature_state(true/false);disable_getter/disable_setter/disable_deleter
+ if text != "":
+ splitted = text.split(';')
+ if len(splitted) >= 3:
+ if self.disable_property_trace is False and splitted[0] == 'true':
+ # Replacing property by custom property only when the debugger starts
+ pydevd_traceproperty.replace_builtin_property()
+ self.disable_property_trace = True
+ # Enable/Disable tracing of the property getter
+ if splitted[1] == 'true':
+ self.disable_property_getter_trace = True
+ else:
+ self.disable_property_getter_trace = False
+ # Enable/Disable tracing of the property setter
+ if splitted[2] == 'true':
+ self.disable_property_setter_trace = True
+ else:
+ self.disable_property_setter_trace = False
+ # Enable/Disable tracing of the property deleter
+ if splitted[3] == 'true':
+ self.disable_property_deleter_trace = True
+ else:
+ self.disable_property_deleter_trace = False
+ else:
+ # User hasn't configured any settings for property tracing
+ pass
+
+ elif cmd_id == CMD_ADD_EXCEPTION_BREAK:
+ exception, notify_always, notify_on_terminate = text.split('\t', 2)
+ exception_breakpoint = self.add_break_on_exception(
+ exception,
+ notify_always=int(notify_always) > 0,
+ notify_on_terminate = int(notify_on_terminate) == 1,
+ notify_on_first_raise_only=int(notify_always) == 2
+ )
+ self.update_after_exceptions_added([exception_breakpoint])
elif cmd_id == CMD_REMOVE_EXCEPTION_BREAK:
exception = text
try:
- del self.exception_set[exception]
- self.always_exception_set.remove(exception)
+ cp = self.break_on_uncaught_exceptions.copy()
+ DictPop(cp, exception, None)
+ self.break_on_uncaught_exceptions = cp
+
+ cp = self.break_on_caught_exceptions.copy()
+ DictPop(cp, exception, None)
+ self.break_on_caught_exceptions = cp
except:
pydev_log.debug("Error while removing exception %s"%sys.exc_info()[0]);
update_exception_hook(self)
@@ -840,6 +1031,77 @@ class PyDB:
except :
pass
+ elif cmd_id == CMD_EVALUATE_CONSOLE_EXPRESSION:
+ # Command which takes care for the debug console communication
+ if text != "":
+ thread_id, frame_id, console_command = text.split('\t', 2)
+ console_command, line = console_command.split('\t')
+ if console_command == 'EVALUATE':
+ int_cmd = InternalEvaluateConsoleExpression(seq, thread_id, frame_id, line)
+ elif console_command == 'GET_COMPLETIONS':
+ int_cmd = InternalConsoleGetCompletions(seq, thread_id, frame_id, line)
+ self.postInternalCommand(int_cmd, thread_id)
+
+ elif cmd_id == CMD_RUN_CUSTOM_OPERATION:
+ # Command which runs a custom operation
+ if text != "":
+ try:
+ location, custom = text.split('||', 1)
+ except:
+ sys.stderr.write('Custom operation now needs a || separator. Found: %s\n' % (text,))
+ raise
+
+ thread_id, frame_id, scopeattrs = location.split('\t', 2)
+
+ if scopeattrs.find('\t') != -1: # there are attributes beyond scope
+ scope, attrs = scopeattrs.split('\t', 1)
+ else:
+ scope, attrs = (scopeattrs, None)
+
+ # : style: EXECFILE or EXEC
+ # : encoded_code_or_file: file to execute or code
+ # : fname: name of function to be executed in the resulting namespace
+ style, encoded_code_or_file, fnname = custom.split('\t', 3)
+ int_cmd = InternalRunCustomOperation(seq, thread_id, frame_id, scope, attrs,
+ style, encoded_code_or_file, fnname)
+ self.postInternalCommand(int_cmd, thread_id)
+
+ elif cmd_id == CMD_IGNORE_THROWN_EXCEPTION_AT:
+ if text:
+ replace = 'REPLACE:' # Not all 3.x versions support u'REPLACE:', so, doing workaround.
+ if not IS_PY3K:
+ replace = unicode(replace)
+
+ if text.startswith(replace):
+ text = text[8:]
+ self.filename_to_lines_where_exceptions_are_ignored.clear()
+
+ if text:
+ for line in text.split('||'): # Can be bulk-created (one in each line)
+ filename, line_number = line.split('|')
+ if not IS_PY3K:
+ filename = filename.encode(file_system_encoding)
+
+ filename = NormFileToServer(filename)
+
+ if os.path.exists(filename):
+ lines_ignored = self.filename_to_lines_where_exceptions_are_ignored.get(filename)
+ if lines_ignored is None:
+ lines_ignored = self.filename_to_lines_where_exceptions_are_ignored[filename] = {}
+ lines_ignored[int(line_number)] = 1
+ else:
+ sys.stderr.write('pydev debugger: warning: trying to ignore exception thrown'\
+ ' on file that does not exist: %s (will have no effect)\n' % (filename,))
+
+ elif cmd_id == CMD_ENABLE_DONT_TRACE:
+ if text:
+ true_str = 'true' # Not all 3.x versions support u'str', so, doing workaround.
+ if not IS_PY3K:
+ true_str = unicode(true_str)
+
+ mode = text.strip() == true_str
+ pydevd_dont_trace.trace_filter(mode)
+
else:
#I have no idea what this is all about
cmd = self.cmdFactory.makeErrorMessage(seq, "unexpected command " + str(cmd_id))
@@ -881,6 +1143,44 @@ class PyDB:
thread.additionalInfo.pydev_state = STATE_SUSPEND
thread.stop_reason = stop_reason
+ # If conditional breakpoint raises any exception during evaluation send details to Java
+ if stop_reason == CMD_SET_BREAK and self.suspend_on_breakpoint_exception:
+ self.sendBreakpointConditionException(thread)
+
+
+ def sendBreakpointConditionException(self, thread):
+ """If conditional breakpoint raises an exception during evaluation
+ send exception details to java
+ """
+ thread_id = GetThreadId(thread)
+ conditional_breakpoint_exception_tuple = thread.additionalInfo.conditional_breakpoint_exception
+ # conditional_breakpoint_exception_tuple - should contain 2 values (exception_type, stacktrace)
+ if conditional_breakpoint_exception_tuple and len(conditional_breakpoint_exception_tuple) == 2:
+ exc_type, stacktrace = conditional_breakpoint_exception_tuple
+ int_cmd = InternalGetBreakpointException(thread_id, exc_type, stacktrace)
+ # Reset the conditional_breakpoint_exception details to None
+ thread.additionalInfo.conditional_breakpoint_exception = None
+ self.postInternalCommand(int_cmd, thread_id)
+
+
+ def sendCaughtExceptionStack(self, thread, arg, curr_frame_id):
+ """Sends details on the exception which was caught (and where we stopped) to the java side.
+
+ arg is: exception type, description, traceback object
+ """
+ thread_id = GetThreadId(thread)
+ int_cmd = InternalSendCurrExceptionTrace(thread_id, arg, curr_frame_id)
+ self.postInternalCommand(int_cmd, thread_id)
+
+
+ def sendCaughtExceptionStackProceeded(self, thread):
+ """Sends that some thread was resumed and is no longer showing an exception trace.
+ """
+ thread_id = GetThreadId(thread)
+ int_cmd = InternalSendCurrExceptionTraceProceeded(thread_id)
+ self.postInternalCommand(int_cmd, thread_id)
+ self.processInternalCommands()
+
def doWaitSuspend(self, thread, frame, event, arg): #@UnusedVariable
""" busy waits until the thread state changes to RUN
@@ -898,7 +1198,7 @@ class PyDB:
try:
from_this_thread = []
- for frame_id, custom_frame in CustomFramesContainer.custom_frames.items():
+ for frame_id, custom_frame in DictIterItems(CustomFramesContainer.custom_frames):
if custom_frame.thread_id == thread.ident:
# print >> sys.stderr, 'Frame created: ', frame_id
self.writer.addCommand(self.cmdFactory.makeCustomFrameCreatedMessage(frame_id, custom_frame.name))
@@ -991,7 +1291,6 @@ class PyDB:
def handle_post_mortem_stop(self, additionalInfo, t):
pydev_log.debug("We are stopping in post-mortem\n")
- self.force_post_mortem_stop -= 1
frame, frames_byid = additionalInfo.pydev_force_stop_at_exception
thread_id = GetThreadId(t)
pydevd_vars.addAdditionalFrameById(thread_id, frames_byid)
@@ -1060,9 +1359,9 @@ class PyDB:
if additionalInfo.is_tracing:
f = frame
while f is not None:
- fname, bs = GetFilenameAndBase(f)
- if bs == 'pydevd_frame.py':
- if 'trace_dispatch' == f.f_code.co_name:
+ if 'trace_dispatch' == f.f_code.co_name:
+ _fname, bs = GetFilenameAndBase(f)
+ if bs == 'pydevd_frame.py':
return None #we don't wan't to trace code invoked from pydevd_frame.trace_dispatch
f = f.f_back
@@ -1071,9 +1370,6 @@ class PyDB:
self.processThreadNotAlive(GetThreadId(t))
return None # suspend tracing
- if is_file_to_ignore:
- return None
-
# each new frame...
return additionalInfo.CreateDbFrame((self, filename, additionalInfo, t, frame)).trace_dispatch(frame, event, arg)
@@ -1120,18 +1416,18 @@ class PyDB:
def update_trace(self, frame, dispatch_func, overwrite_prev):
if frame.f_trace is None:
- frame.f_trace = dispatch_func
+ frame.f_trace = dispatch_func
else:
- if overwrite_prev:
- frame.f_trace = dispatch_func
- else:
- try:
- #If it's the trace_exception, go back to the frame trace dispatch!
- if frame.f_trace.im_func.__name__ == 'trace_exception':
- frame.f_trace = frame.f_trace.im_self.trace_dispatch
- except AttributeError:
- pass
- frame = frame.f_back
+ if overwrite_prev:
+ frame.f_trace = dispatch_func
+ else:
+ try:
+ #If it's the trace_exception, go back to the frame trace dispatch!
+ if frame.f_trace.im_func.__name__ == 'trace_exception':
+ frame.f_trace = frame.f_trace.im_self.trace_dispatch
+ except AttributeError:
+ pass
+ frame = frame.f_back
del frame
def prepareToRun(self):
@@ -1150,6 +1446,7 @@ class PyDB:
PyDBCommandThread(self).start()
PyDBCheckAliveThread(self).start()
+
def patch_threads(self):
try:
# not available in jython!
@@ -1157,11 +1454,8 @@ class PyDB:
except:
pass
- try:
- thread.start_new_thread = pydev_start_new_thread
- thread.start_new = pydev_start_new_thread
- except:
- pass
+ from pydev_monkey import patch_thread_modules
+ patch_thread_modules()
def run(self, file, globals=None, locals=None, set_trace=True):
@@ -1185,7 +1479,7 @@ class PyDB:
sys.modules['__main__'] = m
if hasattr(sys.modules['pydevd'], '__loader__'):
setattr(m, '__loader__', getattr(sys.modules['pydevd'], '__loader__'))
-
+
m.__file__ = file
globals = m.__dict__
try:
@@ -1246,7 +1540,8 @@ def processCommandLine(argv):
setup['server'] = False
setup['port'] = 0
setup['file'] = ''
- setup['multiproc'] = False
+ setup['multiproc'] = False #Used by PyCharm (reuses connection: ssh tunneling)
+ setup['multiprocess'] = False # Used by PyDev (creates new connection to ide)
setup['save-signatures'] = False
i = 0
del argv[0]
@@ -1279,6 +1574,9 @@ def processCommandLine(argv):
elif (argv[i] == '--multiproc'):
del argv[i]
setup['multiproc'] = True
+ elif (argv[i] == '--multiprocess'):
+ del argv[i]
+ setup['multiprocess'] = True
elif (argv[i] == '--save-signatures'):
del argv[i]
setup['save-signatures'] = True
@@ -1423,7 +1721,7 @@ def _locked_settrace(
CustomFramesContainer.custom_frames_lock.acquire()
try:
- for _frameId, custom_frame in CustomFramesContainer.custom_frames.items():
+ for _frameId, custom_frame in DictIterItems(CustomFramesContainer.custom_frames):
debugger.SetTraceForFrameAndParents(custom_frame.frame, False)
finally:
CustomFramesContainer.custom_frames_lock.release()
@@ -1492,24 +1790,21 @@ def stoptrace():
threading.settrace(None) # for all future threads
except:
pass
-
- try:
- thread.start_new_thread = _original_start_new_thread
- thread.start_new = _original_start_new_thread
- except:
- pass
-
+
+ from pydev_monkey import undo_patch_thread_modules
+ undo_patch_thread_modules()
+
debugger = GetGlobalDebugger()
-
+
if debugger:
debugger.trace_dispatch = None
-
+
debugger.SetTraceForFrameAndParents(GetFrame(), False)
-
+
debugger.exiting()
-
- killAllPydevThreads()
-
+
+ killAllPydevThreads()
+
connected = False
class Dispatcher(object):
@@ -1544,21 +1839,28 @@ class DispatchReader(ReaderThread):
self.killReceived = True
+DISPATCH_APPROACH_NEW_CONNECTION = 1 # Used by PyDev
+DISPATCH_APPROACH_EXISTING_CONNECTION = 2 # Used by PyCharm
+DISPATCH_APPROACH = DISPATCH_APPROACH_NEW_CONNECTION
+
def dispatch():
- argv = sys.original_argv[:]
- setup = processCommandLine(argv)
+ setup = SetupHolder.setup
host = setup['client']
port = setup['port']
- dispatcher = Dispatcher()
- try:
- dispatcher.connect(host, port)
- port = dispatcher.port
- finally:
- dispatcher.close()
+ if DISPATCH_APPROACH == DISPATCH_APPROACH_EXISTING_CONNECTION:
+ dispatcher = Dispatcher()
+ try:
+ dispatcher.connect(host, port)
+ port = dispatcher.port
+ finally:
+ dispatcher.close()
return host, port
def settrace_forked():
+ '''
+ When creating a fork from a process in the debugger, we need to reset the whole debugger environment!
+ '''
host, port = dispatch()
import pydevd_tracing
@@ -1578,6 +1880,15 @@ def settrace_forked():
overwrite_prev_trace=True,
patch_multiprocessing=True,
)
+
+#=======================================================================================================================
+# SetupHolder
+#=======================================================================================================================
+class SetupHolder:
+
+ setup = None
+
+
#=======================================================================================================================
# main
#=======================================================================================================================
@@ -1586,6 +1897,7 @@ if __name__ == '__main__':
try:
sys.original_argv = sys.argv[:]
setup = processCommandLine(sys.argv)
+ SetupHolder.setup = setup
except ValueError:
traceback.print_exc()
usage(1)
@@ -1611,62 +1923,73 @@ if __name__ == '__main__':
f = setup['file']
fix_app_engine_debug = False
- if setup['multiproc']:
- pydev_log.debug("Started in multiproc mode\n")
-
- dispatcher = Dispatcher()
- try:
- dispatcher.connect(host, port)
- if dispatcher.port is not None:
- port = dispatcher.port
- pydev_log.debug("Received port %d\n" %port)
- pydev_log.info("pydev debugger: process %d is connecting\n"% os.getpid())
- try:
- pydev_monkey.patch_new_process_functions()
- except:
- pydev_log.error("Error patching process functions\n")
- traceback.print_exc()
- else:
- pydev_log.error("pydev debugger: couldn't get port for new debug process\n")
- finally:
- dispatcher.close()
+ try:
+ import pydev_monkey
+ except:
+ pass #Not usable on jython 2.1
else:
- pydev_log.info("pydev debugger: starting\n")
+ if setup['multiprocess']: # PyDev
+ pydev_monkey.patch_new_process_functions()
- try:
- pydev_monkey.patch_new_process_functions_with_warning()
- except:
- pydev_log.error("Error patching process functions\n")
- traceback.print_exc()
+ elif setup['multiproc']: # PyCharm
+ pydev_log.debug("Started in multiproc mode\n")
+ # Note: we're not inside method, so, no need for 'global'
+ DISPATCH_APPROACH = DISPATCH_APPROACH_EXISTING_CONNECTION
+
+ dispatcher = Dispatcher()
+ try:
+ dispatcher.connect(host, port)
+ if dispatcher.port is not None:
+ port = dispatcher.port
+ pydev_log.debug("Received port %d\n" %port)
+ pydev_log.info("pydev debugger: process %d is connecting\n"% os.getpid())
- # Only do this patching if we're not running with multiprocess turned on.
- if f.find('dev_appserver.py') != -1:
- if os.path.basename(f).startswith('dev_appserver.py'):
- appserver_dir = os.path.dirname(f)
- version_file = os.path.join(appserver_dir, 'VERSION')
- if os.path.exists(version_file):
try:
- stream = open(version_file, 'r')
- try:
- for line in stream.read().splitlines():
- line = line.strip()
- if line.startswith('release:'):
- line = line[8:].strip()
- version = line.replace('"', '')
- version = version.split('.')
- if int(version[0]) > 1:
- fix_app_engine_debug = True
-
- elif int(version[0]) == 1:
- if int(version[1]) >= 7:
- # Only fix from 1.7 onwards
- fix_app_engine_debug = True
- break
- finally:
- stream.close()
+ pydev_monkey.patch_new_process_functions()
except:
+ pydev_log.error("Error patching process functions\n")
traceback.print_exc()
+ else:
+ pydev_log.error("pydev debugger: couldn't get port for new debug process\n")
+ finally:
+ dispatcher.close()
+ else:
+ pydev_log.info("pydev debugger: starting\n")
+
+ try:
+ pydev_monkey.patch_new_process_functions_with_warning()
+ except:
+ pydev_log.error("Error patching process functions\n")
+ traceback.print_exc()
+
+ # Only do this patching if we're not running with multiprocess turned on.
+ if f.find('dev_appserver.py') != -1:
+ if os.path.basename(f).startswith('dev_appserver.py'):
+ appserver_dir = os.path.dirname(f)
+ version_file = os.path.join(appserver_dir, 'VERSION')
+ if os.path.exists(version_file):
+ try:
+ stream = open(version_file, 'r')
+ try:
+ for line in stream.read().splitlines():
+ line = line.strip()
+ if line.startswith('release:'):
+ line = line[8:].strip()
+ version = line.replace('"', '')
+ version = version.split('.')
+ if int(version[0]) > 1:
+ fix_app_engine_debug = True
+
+ elif int(version[0]) == 1:
+ if int(version[1]) >= 7:
+ # Only fix from 1.7 onwards
+ fix_app_engine_debug = True
+ break
+ finally:
+ stream.close()
+ except:
+ traceback.print_exc()
try:
# In the default run (i.e.: run directly on debug mode), we try to patch stackless as soon as possible
@@ -1718,16 +2041,21 @@ if __name__ == '__main__':
import pydevd_psyco_stub
sys.modules['psyco'] = pydevd_psyco_stub
- debugger = PyDB()
+ debugger = PyDB()
- if setup['save-signatures']:
- if pydevd_vm_type.GetVmType() == pydevd_vm_type.PydevdVmType.JYTHON:
- sys.stderr.write("Collecting run-time type information is not supported for Jython\n")
- else:
- debugger.signature_factory = SignatureFactory()
+ if setup['save-signatures']:
+ if pydevd_vm_type.GetVmType() == pydevd_vm_type.PydevdVmType.JYTHON:
+ sys.stderr.write("Collecting run-time type information is not supported for Jython\n")
+ else:
+ debugger.signature_factory = SignatureFactory()
- debugger.connect(host, port)
+ try:
+ debugger.connect(host, port)
+ except:
+ sys.stderr.write("Could not connect to %s: %s\n" % (host, port))
+ traceback.print_exc()
+ sys.exit(1)
- connected = True #Mark that we're connected when started from inside ide.
+ connected = True # Mark that we're connected when started from inside ide.
- debugger.run(setup['file'], None, None)
+ debugger.run(setup['file'], None, None)
diff --git a/python/helpers/pydev/pydevd_additional_thread_info.py b/python/helpers/pydev/pydevd_additional_thread_info.py
index 1b0fc2cdd633..fa906adf385e 100644
--- a/python/helpers/pydev/pydevd_additional_thread_info.py
+++ b/python/helpers/pydev/pydevd_additional_thread_info.py
@@ -12,7 +12,7 @@ import weakref
#=======================================================================================================================
class AbstractPyDBAdditionalThreadInfo:
def __init__(self):
- self.pydev_state = STATE_RUN
+ self.pydev_state = STATE_RUN
self.pydev_step_stop = None
self.pydev_step_cmd = None
self.pydev_notify_kill = False
@@ -20,51 +20,52 @@ class AbstractPyDBAdditionalThreadInfo:
self.pydev_smart_step_stop = None
self.pydev_django_resolve_frame = None
self.is_tracing = False
+ self.conditional_breakpoint_exception = None
+
-
def IterFrames(self):
raise NotImplementedError()
-
+
def CreateDbFrame(self, args):
#args = mainDebugger, filename, base, additionalInfo, t, frame
raise NotImplementedError()
-
+
def __str__(self):
return 'State:%s Stop:%s Cmd: %s Kill:%s' % (self.pydev_state, self.pydev_step_stop, self.pydev_step_cmd, self.pydev_notify_kill)
-
+
#=======================================================================================================================
# PyDBAdditionalThreadInfoWithCurrentFramesSupport
#=======================================================================================================================
class PyDBAdditionalThreadInfoWithCurrentFramesSupport(AbstractPyDBAdditionalThreadInfo):
-
+
def IterFrames(self):
#sys._current_frames(): dictionary with thread id -> topmost frame
return sys._current_frames().values() #return a copy... don't know if it's changed if we did get an iterator
#just create the db frame directly
CreateDbFrame = PyDBFrame
-
+
#=======================================================================================================================
# PyDBAdditionalThreadInfoWithoutCurrentFramesSupport
#=======================================================================================================================
class PyDBAdditionalThreadInfoWithoutCurrentFramesSupport(AbstractPyDBAdditionalThreadInfo):
-
+
def __init__(self):
AbstractPyDBAdditionalThreadInfo.__init__(self)
- #That's where the last frame entered is kept. That's needed so that we're able to
+ #That's where the last frame entered is kept. That's needed so that we're able to
#trace contexts that were previously untraced and are currently active. So, the bad thing
#is that the frame may be kept alive longer than it would if we go up on the frame stack,
#and is only disposed when some other frame is removed.
- #A better way would be if we could get the topmost frame for each thread, but that's
+ #A better way would be if we could get the topmost frame for each thread, but that's
#not possible (until python 2.5 -- which is the PyDBAdditionalThreadInfoWithCurrentFramesSupport version)
#Or if the user compiled threadframe (from http://www.majid.info/mylos/stories/2004/06/10/threadframe.html)
-
+
#NOT RLock!! (could deadlock if it was)
self.lock = threading.Lock()
self._acquire_lock = self.lock.acquire
self._release_lock = self.lock.release
-
+
#collection with the refs
d = {}
self.pydev_existing_frames = d
@@ -72,8 +73,8 @@ class PyDBAdditionalThreadInfoWithoutCurrentFramesSupport(AbstractPyDBAdditional
self._iter_frames = d.iterkeys
except AttributeError:
self._iter_frames = d.keys
-
-
+
+
def _OnDbFrameCollected(self, ref):
'''
Callback to be called when a given reference is garbage-collected.
@@ -83,8 +84,8 @@ class PyDBAdditionalThreadInfoWithoutCurrentFramesSupport(AbstractPyDBAdditional
del self.pydev_existing_frames[ref]
finally:
self._release_lock()
-
-
+
+
def _AddDbFrame(self, db_frame):
self._acquire_lock()
try:
@@ -94,8 +95,8 @@ class PyDBAdditionalThreadInfoWithoutCurrentFramesSupport(AbstractPyDBAdditional
self.pydev_existing_frames[r] = r
finally:
self._release_lock()
-
-
+
+
def CreateDbFrame(self, args):
#the frame must be cached as a weak-ref (we return the actual db frame -- which will be kept
#alive until its trace_dispatch method is not referenced anymore).
@@ -106,14 +107,14 @@ class PyDBAdditionalThreadInfoWithoutCurrentFramesSupport(AbstractPyDBAdditional
db_frame.frame = args[-1]
self._AddDbFrame(db_frame)
return db_frame
-
-
+
+
def IterFrames(self):
#We cannot use yield (because of the lock)
self._acquire_lock()
try:
ret = []
-
+
for weak_db_frame in self._iter_frames():
try:
ret.append(weak_db_frame().frame)
diff --git a/python/helpers/pydev/pydevd_breakpoints.py b/python/helpers/pydev/pydevd_breakpoints.py
index beebebf4abed..82a230db2f47 100644
--- a/python/helpers/pydev/pydevd_breakpoints.py
+++ b/python/helpers/pydev/pydevd_breakpoints.py
@@ -2,14 +2,12 @@ from pydevd_constants import *
import pydevd_tracing
import sys
import pydev_log
+import pydevd_import_class
_original_excepthook = None
_handle_exceptions = None
-NOTIFY_ALWAYS="NOTIFY_ALWAYS"
-NOTIFY_ON_TERMINATE="NOTIFY_ON_TERMINATE"
-
if USE_LIB_COPY:
import _pydev_threading as threading
else:
@@ -20,52 +18,39 @@ threadingCurrentThread = threading.currentThread
from pydevd_comm import GetGlobalDebugger
class ExceptionBreakpoint:
- def __init__(self, qname, notify_always, notify_on_terminate):
- exctype = get_class(qname)
+
+ def __init__(
+ self,
+ qname,
+ notify_always,
+ notify_on_terminate,
+ notify_on_first_raise_only,
+ ):
+ exctype = _get_class(qname)
self.qname = qname
if exctype is not None:
self.name = exctype.__name__
else:
self.name = None
- self.notify_on_terminate = int(notify_on_terminate) == 1
- self.notify_always = int(notify_always) > 0
- self.notify_on_first_raise_only = int(notify_always) == 2
+ self.notify_on_terminate = notify_on_terminate
+ self.notify_always = notify_always
+ self.notify_on_first_raise_only = notify_on_first_raise_only
self.type = exctype
- self.notify = {NOTIFY_ALWAYS: self.notify_always, NOTIFY_ON_TERMINATE: self.notify_on_terminate}
def __str__(self):
return self.qname
class LineBreakpoint:
- def __init__(self, type, flag, condition, func_name, expression):
- self.type = type
+
+ def __init__(self, line, condition, func_name, expression):
+ self.line = line
self.condition = condition
self.func_name = func_name
self.expression = expression
- def get_break_dict(self, breakpoints, file):
- if DictContains(breakpoints, file):
- breakDict = breakpoints[file]
- else:
- breakDict = {}
- breakpoints[file] = breakDict
- return breakDict
-
- def trace(self, file, line, func_name):
- if DebugInfoHolder.DEBUG_TRACE_BREAKPOINTS > 0:
- pydev_log.debug('Added breakpoint:%s - line:%s - func_name:%s\n' % (file, line, func_name))
- sys.stderr.flush()
-
- def add(self, breakpoints, file, line, func_name):
- self.trace(file, line, func_name)
-
- breakDict = self.get_break_dict(breakpoints, file)
-
- breakDict[line] = self
-
def get_exception_full_qname(exctype):
if not exctype:
return None
@@ -77,41 +62,41 @@ def get_exception_name(exctype):
return exctype.__name__
-def get_exception_breakpoint(exctype, exceptions, notify_class):
- name = get_exception_full_qname(exctype)
+def get_exception_breakpoint(exctype, exceptions):
+ exception_full_qname = get_exception_full_qname(exctype)
+
exc = None
if exceptions is not None:
- for k, e in exceptions.items():
- if e.notify[notify_class]:
- if name == k:
- return e
- if (e.type is not None and issubclass(exctype, e.type)):
- if exc is None or issubclass(e.type, exc.type):
- exc = e
+ try:
+ return exceptions[exception_full_qname]
+ except KeyError:
+ for exception_breakpoint in DictIterValues(exceptions):
+ if exception_breakpoint.type is not None and issubclass(exctype, exception_breakpoint.type):
+ if exc is None or issubclass(exception_breakpoint.type, exc.type):
+ exc = exception_breakpoint
return exc
#=======================================================================================================================
-# excepthook
+# _excepthook
#=======================================================================================================================
-def excepthook(exctype, value, tb):
+def _excepthook(exctype, value, tb):
global _handle_exceptions
- if _handle_exceptions is not None:
- exception_breakpoint = get_exception_breakpoint(exctype, _handle_exceptions, NOTIFY_ON_TERMINATE)
+ if _handle_exceptions:
+ exception_breakpoint = get_exception_breakpoint(exctype, _handle_exceptions)
else:
exception_breakpoint = None
- if exception_breakpoint is None:
- return _original_excepthook(exctype, value, tb)
-
#Always call the original excepthook before going on to call the debugger post mortem to show it.
_original_excepthook(exctype, value, tb)
+ if not exception_breakpoint:
+ return
+
if tb is None: #sometimes it can be None, e.g. with GTK
- return
+ return
frames = []
- traceback = tb
while tb:
frames.append(tb.tb_frame)
tb = tb.tb_next
@@ -122,9 +107,7 @@ def excepthook(exctype, value, tb):
thread.additionalInfo.exception = (exctype, value, tb)
thread.additionalInfo.pydev_force_stop_at_exception = (frame, frames_byid)
thread.additionalInfo.message = exception_breakpoint.qname
- #sys.exc_info = lambda : (exctype, value, traceback)
debugger = GetGlobalDebugger()
- debugger.force_post_mortem_stop += 1
pydevd_tracing.SetTrace(None) #no tracing from here
@@ -133,38 +116,27 @@ def excepthook(exctype, value, tb):
debugger.handle_post_mortem_stop(thread.additionalInfo, thread)
#=======================================================================================================================
-# set_pm_excepthook
+# _set_pm_excepthook
#=======================================================================================================================
-def set_pm_excepthook(handle_exceptions_arg=None):
+def _set_pm_excepthook(handle_exceptions_dict=None):
'''
Should be called to register the excepthook to be used.
- It's only useful for uncaucht exceptions. I.e.: exceptions that go up to the excepthook.
-
- Can receive a parameter to stop only on some exceptions.
-
- E.g.:
- register_excepthook((IndexError, ValueError))
-
- or
+ It's only useful for uncaught exceptions. I.e.: exceptions that go up to the excepthook.
- register_excepthook(IndexError)
-
- if passed without a parameter, will break on any exception
-
- @param handle_exceptions: exception or tuple(exceptions)
+ @param handle_exceptions: dict(exception -> ExceptionBreakpoint)
The exceptions that should be handled.
'''
global _handle_exceptions
global _original_excepthook
- if sys.excepthook != excepthook:
- #Only keep the original if it's not our own excepthook (if called many times).
+ if sys.excepthook != _excepthook:
+ #Only keep the original if it's not our own _excepthook (if called many times).
_original_excepthook = sys.excepthook
- _handle_exceptions = handle_exceptions_arg
- sys.excepthook = excepthook
+ _handle_exceptions = handle_exceptions_dict
+ sys.excepthook = _excepthook
-def restore_pm_excepthook():
+def _restore_pm_excepthook():
global _original_excepthook
if _original_excepthook:
sys.excepthook = _original_excepthook
@@ -172,27 +144,16 @@ def restore_pm_excepthook():
def update_exception_hook(dbg):
- if dbg.exception_set:
- set_pm_excepthook(dict(dbg.exception_set))
+ if dbg.break_on_uncaught_exceptions:
+ _set_pm_excepthook(dbg.break_on_uncaught_exceptions)
else:
- restore_pm_excepthook()
+ _restore_pm_excepthook()
-def get_class( kls ):
+def _get_class( kls ):
if IS_PY24 and "BaseException" == kls:
kls = "Exception"
- parts = kls.split('.')
- module = ".".join(parts[:-1])
- if module == "":
- if IS_PY3K:
- module = "builtins"
- else:
- module = "__builtin__"
+
try:
- m = __import__( module )
- for comp in parts[-1:]:
- if m is None:
- return None
- m = getattr(m, comp, None)
- return m
- except ImportError:
- return None \ No newline at end of file
+ return eval(kls)
+ except:
+ return pydevd_import_class.ImportName(kls)
diff --git a/python/helpers/pydev/pydevd_comm.py b/python/helpers/pydev/pydevd_comm.py
index b4cf585e5cc2..c7f39a16c483 100644
--- a/python/helpers/pydev/pydevd_comm.py
+++ b/python/helpers/pydev/pydevd_comm.py
@@ -61,32 +61,14 @@ from pydevd_constants import * #@UnusedWildImport
import sys
+from _pydev_imps import _pydev_time as time
+
if USE_LIB_COPY:
- import _pydev_time as time
import _pydev_threading as threading
- try:
- import _pydev_thread as thread
- except ImportError:
- import _thread as thread #Py3K changed it.
- import _pydev_Queue as _queue
- from _pydev_socket import socket
- from _pydev_socket import AF_INET, SOCK_STREAM
- from _pydev_socket import SHUT_RD, SHUT_WR
else:
- import time
import threading
- try:
- import thread
- except ImportError:
- import _thread as thread #Py3K changed it.
-
- try:
- import Queue as _queue
- except ImportError:
- import queue as _queue
- from socket import socket
- from socket import AF_INET, SOCK_STREAM
- from socket import SHUT_RD, SHUT_WR
+from _pydev_imps._pydev_socket import socket, AF_INET, SOCK_STREAM, SHUT_RD, SHUT_WR
+from pydev_imports import _queue
try:
from urllib import quote, quote_plus, unquote, unquote_plus
@@ -103,6 +85,8 @@ import pydev_log
import _pydev_completer
from pydevd_tracing import GetExceptionTracebackStr
+import pydevd_console
+from pydev_monkey import disable_trace_thread_modules, enable_trace_thread_modules
@@ -126,6 +110,8 @@ CMD_CHANGE_VARIABLE = 117
CMD_RUN_TO_LINE = 118
CMD_RELOAD_CODE = 119
CMD_GET_COMPLETIONS = 120
+
+# Note: renumbered (conflicted on merge)
CMD_CONSOLE_EXEC = 121
CMD_ADD_EXCEPTION_BREAK = 122
CMD_REMOVE_EXCEPTION_BREAK = 123
@@ -136,6 +122,24 @@ CMD_SET_NEXT_STATEMENT = 127
CMD_SMART_STEP_INTO = 128
CMD_EXIT = 129
CMD_SIGNATURE_CALL_TRACE = 130
+
+
+
+CMD_SET_PY_EXCEPTION = 131
+CMD_GET_FILE_CONTENTS = 132
+CMD_SET_PROPERTY_TRACE = 133
+# Pydev debug console commands
+CMD_EVALUATE_CONSOLE_EXPRESSION = 134
+CMD_RUN_CUSTOM_OPERATION = 135
+CMD_GET_BREAKPOINT_EXCEPTION = 136
+CMD_STEP_CAUGHT_EXCEPTION = 137
+CMD_SEND_CURR_EXCEPTION_TRACE = 138
+CMD_SEND_CURR_EXCEPTION_TRACE_PROCEEDED = 139
+CMD_IGNORE_THROWN_EXCEPTION_AT = 140
+CMD_ENABLE_DONT_TRACE = 141
+
+
+
CMD_VERSION = 501
CMD_RETURN = 502
CMD_ERROR = 901
@@ -171,6 +175,19 @@ ID_TO_MEANING = {
'128':'CMD_SMART_STEP_INTO',
'129': 'CMD_EXIT',
'130': 'CMD_SIGNATURE_CALL_TRACE',
+
+ '131': 'CMD_SET_PY_EXCEPTION',
+ '132': 'CMD_GET_FILE_CONTENTS',
+ '133': 'CMD_SET_PROPERTY_TRACE',
+ '134': 'CMD_EVALUATE_CONSOLE_EXPRESSION',
+ '135': 'CMD_RUN_CUSTOM_OPERATION',
+ '136': 'CMD_GET_BREAKPOINT_EXCEPTION',
+ '137': 'CMD_STEP_CAUGHT_EXCEPTION',
+ '138': 'CMD_SEND_CURR_EXCEPTION_TRACE',
+ '139': 'CMD_SEND_CURR_EXCEPTION_TRACE_PROCEEDED',
+ '140': 'CMD_IGNORE_THROWN_EXCEPTION_AT',
+ '141': 'CMD_ENABLE_DONT_TRACE',
+
'501':'CMD_VERSION',
'502':'CMD_RETURN',
'901':'CMD_ERROR',
@@ -274,7 +291,7 @@ class ReaderThread(PyDBDaemonThread):
#We must close the socket so that it doesn't stay halted there.
self.killReceived = True
try:
- self.sock.shutdown(SHUT_RD) #shotdown the socket for read
+ self.sock.shutdown(SHUT_RD) #shutdown the socket for read
except:
#just ignore that
pass
@@ -564,68 +581,69 @@ class NetCommandFactory:
except:
return self.makeErrorMessage(0, GetExceptionTracebackStr())
- def makeThreadSuspendMessage(self, thread_id, frame, stop_reason, message):
-
+ def makeThreadSuspendStr(self, thread_id, frame, stop_reason, message):
""" <xml>
<thread id="id" stop_reason="reason">
<frame id="id" name="functionName " file="file" line="line">
<var variable stuffff....
</frame>
</thread>
- """
- try:
- cmdTextList = ["<xml>"]
+ """
+ cmdTextList = ["<xml>"]
- if message:
- message = pydevd_vars.makeValidXmlValue(str(message))
+ if message:
+ message = pydevd_vars.makeValidXmlValue(str(message))
- cmdTextList.append('<thread id="%s" stop_reason="%s" message="%s">' % (thread_id, stop_reason, message))
+ cmdTextList.append('<thread id="%s" stop_reason="%s" message="%s">' % (thread_id, stop_reason, message))
- curFrame = frame
- try:
- while curFrame:
- #print cmdText
- myId = str(id(curFrame))
- #print "id is ", myId
+ curFrame = frame
+ try:
+ while curFrame:
+ #print cmdText
+ myId = str(id(curFrame))
+ #print "id is ", myId
- if curFrame.f_code is None:
- break #Iron Python sometimes does not have it!
+ if curFrame.f_code is None:
+ break #Iron Python sometimes does not have it!
- myName = curFrame.f_code.co_name #method name (if in method) or ? if global
- if myName is None:
- break #Iron Python sometimes does not have it!
+ myName = curFrame.f_code.co_name #method name (if in method) or ? if global
+ if myName is None:
+ break #Iron Python sometimes does not have it!
- #print "name is ", myName
+ #print "name is ", myName
- filename, base = pydevd_file_utils.GetFilenameAndBase(curFrame)
+ filename, base = pydevd_file_utils.GetFilenameAndBase(curFrame)
- myFile = pydevd_file_utils.NormFileToClient(filename)
- if file_system_encoding.lower() != "utf-8" and hasattr(myFile, "decode"):
- # myFile is a byte string encoded using the file system encoding
- # convert it to utf8
- myFile = myFile.decode(file_system_encoding).encode("utf-8")
+ myFile = pydevd_file_utils.NormFileToClient(filename)
+ if file_system_encoding.lower() != "utf-8" and hasattr(myFile, "decode"):
+ # myFile is a byte string encoded using the file system encoding
+ # convert it to utf8
+ myFile = myFile.decode(file_system_encoding).encode("utf-8")
- #print "file is ", myFile
- #myFile = inspect.getsourcefile(curFrame) or inspect.getfile(frame)
+ #print "file is ", myFile
+ #myFile = inspect.getsourcefile(curFrame) or inspect.getfile(frame)
- myLine = str(curFrame.f_lineno)
- #print "line is ", myLine
+ myLine = str(curFrame.f_lineno)
+ #print "line is ", myLine
- #the variables are all gotten 'on-demand'
- #variables = pydevd_vars.frameVarsToXML(curFrame.f_locals)
+ #the variables are all gotten 'on-demand'
+ #variables = pydevd_vars.frameVarsToXML(curFrame.f_locals)
- variables = ''
- cmdTextList.append('<frame id="%s" name="%s" ' % (myId , pydevd_vars.makeValidXmlValue(myName)))
- cmdTextList.append('file="%s" line="%s">"' % (quote(myFile, '/>_= \t'), myLine))
- cmdTextList.append(variables)
- cmdTextList.append("</frame>")
- curFrame = curFrame.f_back
- except :
- traceback.print_exc()
+ variables = ''
+ cmdTextList.append('<frame id="%s" name="%s" ' % (myId , pydevd_vars.makeValidXmlValue(myName)))
+ cmdTextList.append('file="%s" line="%s">"' % (quote(myFile, '/>_= \t'), myLine))
+ cmdTextList.append(variables)
+ cmdTextList.append("</frame>")
+ curFrame = curFrame.f_back
+ except :
+ traceback.print_exc()
+
+ cmdTextList.append("</thread></xml>")
+ return ''.join(cmdTextList)
- cmdTextList.append("</thread></xml>")
- cmdText = ''.join(cmdTextList)
- return NetCommand(CMD_THREAD_SUSPEND, 0, cmdText)
+ def makeThreadSuspendMessage(self, thread_id, frame, stop_reason, message):
+ try:
+ return NetCommand(CMD_THREAD_SUSPEND, 0, self.makeThreadSuspendStr(thread_id, frame, stop_reason, message))
except:
return self.makeErrorMessage(0, GetExceptionTracebackStr())
@@ -660,6 +678,51 @@ class NetCommandFactory:
except Exception:
return self.makeErrorMessage(seq, GetExceptionTracebackStr())
+ def makeGetFileContents(self, seq, payload):
+ try:
+ return NetCommand(CMD_GET_FILE_CONTENTS, seq, payload)
+ except Exception:
+ return self.makeErrorMessage(seq, GetExceptionTracebackStr())
+
+ def makeSendBreakpointExceptionMessage(self, seq, payload):
+ try:
+ return NetCommand(CMD_GET_BREAKPOINT_EXCEPTION, seq, payload)
+ except Exception:
+ return self.makeErrorMessage(seq, GetExceptionTracebackStr())
+
+ def makeSendCurrExceptionTraceMessage(self, seq, thread_id, curr_frame_id, exc_type, exc_desc, trace_obj):
+ try:
+ while trace_obj.tb_next is not None:
+ trace_obj = trace_obj.tb_next
+
+ exc_type = pydevd_vars.makeValidXmlValue(str(exc_type)).replace('\t', ' ') or 'exception: type unknown'
+ exc_desc = pydevd_vars.makeValidXmlValue(str(exc_desc)).replace('\t', ' ') or 'exception: no description'
+
+ payload = str(curr_frame_id) + '\t' + exc_type + "\t" + exc_desc + "\t" + \
+ self.makeThreadSuspendStr(thread_id, trace_obj.tb_frame, CMD_SEND_CURR_EXCEPTION_TRACE, '')
+
+ return NetCommand(CMD_SEND_CURR_EXCEPTION_TRACE, seq, payload)
+ except Exception:
+ return self.makeErrorMessage(seq, GetExceptionTracebackStr())
+
+ def makeSendCurrExceptionTraceProceededMessage(self, seq, thread_id):
+ try:
+ return NetCommand(CMD_SEND_CURR_EXCEPTION_TRACE_PROCEEDED, 0, str(thread_id))
+ except:
+ return self.makeErrorMessage(0, GetExceptionTracebackStr())
+
+ def makeSendConsoleMessage(self, seq, payload):
+ try:
+ return NetCommand(CMD_EVALUATE_CONSOLE_EXPRESSION, seq, payload)
+ except Exception:
+ return self.makeErrorMessage(seq, GetExceptionTracebackStr())
+
+ def makeCustomOperationMessage(self, seq, payload):
+ try:
+ return NetCommand(CMD_RUN_CUSTOM_OPERATION, seq, payload)
+ except Exception:
+ return self.makeErrorMessage(seq, GetExceptionTracebackStr())
+
def makeLoadSourceMessage(self, seq, source, dbg=None):
try:
net = NetCommand(CMD_LOAD_SOURCE, seq, '%s' % source)
@@ -698,7 +761,7 @@ class InternalThreadCommand:
def canBeExecutedBy(self, thread_id):
'''By default, it must be in the same thread to be executed
'''
- return self.thread_id == thread_id
+ return self.thread_id == thread_id or self.thread_id.endswith('|' + thread_id)
def doIt(self, dbg):
raise NotImplementedError("you have to override doIt")
@@ -929,7 +992,7 @@ class InternalEvaluateExpression(InternalThreadCommand):
try:
result = pydevd_vars.evaluateExpression(self.thread_id, self.frame_id, self.expression, self.doExec)
xml = "<xml>"
- xml += pydevd_vars.varToXML(result, "", self.doTrim)
+ xml += pydevd_vars.varToXML(result, self.expression, self.doTrim)
xml += "</xml>"
cmd = dbg.cmdFactory.makeEvaluateExpressionMessage(self.sequence, xml)
dbg.writer.addCommand(cmd)
@@ -961,7 +1024,6 @@ class InternalGetCompletions(InternalThreadCommand):
frame = pydevd_vars.findFrame(self.thread_id, self.frame_id)
if frame is not None:
-
msg = _pydev_completer.GenerateCompletionsAsXML(frame, self.act_tok)
cmd = dbg.cmdFactory.makeGetCompletionsMessage(self.sequence, msg)
@@ -981,6 +1043,182 @@ class InternalGetCompletions(InternalThreadCommand):
cmd = dbg.cmdFactory.makeErrorMessage(self.sequence, "Error evaluating expression " + exc)
dbg.writer.addCommand(cmd)
+#=======================================================================================================================
+# InternalGetBreakpointException
+#=======================================================================================================================
+class InternalGetBreakpointException(InternalThreadCommand):
+ """ Send details of exception raised while evaluating conditional breakpoint """
+ def __init__(self, thread_id, exc_type, stacktrace):
+ self.sequence = 0
+ self.thread_id = thread_id
+ self.stacktrace = stacktrace
+ self.exc_type = exc_type
+
+ def doIt(self, dbg):
+ try:
+ callstack = "<xml>"
+
+ makeValid = pydevd_vars.makeValidXmlValue
+
+ for filename, line, methodname, methodobj in self.stacktrace:
+ if file_system_encoding.lower() != "utf-8" and hasattr(filename, "decode"):
+ # filename is a byte string encoded using the file system encoding
+ # convert it to utf8
+ filename = filename.decode(file_system_encoding).encode("utf-8")
+
+ callstack += '<frame thread_id = "%s" file="%s" line="%s" name="%s" obj="%s" />' \
+ % (self.thread_id, makeValid(filename), line, makeValid(methodname), makeValid(methodobj))
+ callstack += "</xml>"
+
+ cmd = dbg.cmdFactory.makeSendBreakpointExceptionMessage(self.sequence, self.exc_type + "\t" + callstack)
+ dbg.writer.addCommand(cmd)
+ except:
+ exc = GetExceptionTracebackStr()
+ sys.stderr.write('%s\n' % (exc,))
+ cmd = dbg.cmdFactory.makeErrorMessage(self.sequence, "Error Sending Exception: " + exc)
+ dbg.writer.addCommand(cmd)
+
+
+#=======================================================================================================================
+# InternalSendCurrExceptionTrace
+#=======================================================================================================================
+class InternalSendCurrExceptionTrace(InternalThreadCommand):
+ """ Send details of the exception that was caught and where we've broken in.
+ """
+ def __init__(self, thread_id, arg, curr_frame_id):
+ '''
+ :param arg: exception type, description, traceback object
+ '''
+ self.sequence = 0
+ self.thread_id = thread_id
+ self.curr_frame_id = curr_frame_id
+ self.arg = arg
+
+ def doIt(self, dbg):
+ try:
+ cmd = dbg.cmdFactory.makeSendCurrExceptionTraceMessage(self.sequence, self.thread_id, self.curr_frame_id, *self.arg)
+ del self.arg
+ dbg.writer.addCommand(cmd)
+ except:
+ exc = GetExceptionTracebackStr()
+ sys.stderr.write('%s\n' % (exc,))
+ cmd = dbg.cmdFactory.makeErrorMessage(self.sequence, "Error Sending Current Exception Trace: " + exc)
+ dbg.writer.addCommand(cmd)
+
+#=======================================================================================================================
+# InternalSendCurrExceptionTraceProceeded
+#=======================================================================================================================
+class InternalSendCurrExceptionTraceProceeded(InternalThreadCommand):
+ """ Send details of the exception that was caught and where we've broken in.
+ """
+ def __init__(self, thread_id):
+ self.sequence = 0
+ self.thread_id = thread_id
+
+ def doIt(self, dbg):
+ try:
+ cmd = dbg.cmdFactory.makeSendCurrExceptionTraceProceededMessage(self.sequence, self.thread_id)
+ dbg.writer.addCommand(cmd)
+ except:
+ exc = GetExceptionTracebackStr()
+ sys.stderr.write('%s\n' % (exc,))
+ cmd = dbg.cmdFactory.makeErrorMessage(self.sequence, "Error Sending Current Exception Trace Proceeded: " + exc)
+ dbg.writer.addCommand(cmd)
+
+
+#=======================================================================================================================
+# InternalEvaluateConsoleExpression
+#=======================================================================================================================
+class InternalEvaluateConsoleExpression(InternalThreadCommand):
+ """ Execute the given command in the debug console """
+
+ def __init__(self, seq, thread_id, frame_id, line):
+ self.sequence = seq
+ self.thread_id = thread_id
+ self.frame_id = frame_id
+ self.line = line
+
+ def doIt(self, dbg):
+ """ Create an XML for console output, error and more (true/false)
+ <xml>
+ <output message=output_message></output>
+ <error message=error_message></error>
+ <more>true/false</more>
+ </xml>
+ """
+ try:
+ frame = pydevd_vars.findFrame(self.thread_id, self.frame_id)
+ if frame is not None:
+ console_message = pydevd_console.execute_console_command(frame, self.thread_id, self.frame_id, self.line)
+ cmd = dbg.cmdFactory.makeSendConsoleMessage(self.sequence, console_message.toXML())
+ else:
+ from pydevd_console import ConsoleMessage
+ console_message = ConsoleMessage()
+ console_message.add_console_message(
+ pydevd_console.CONSOLE_ERROR,
+ "Select the valid frame in the debug view (thread: %s, frame: %s invalid)" % (self.thread_id, self.frame_id),
+ )
+ cmd = dbg.cmdFactory.makeErrorMessage(self.sequence, console_message.toXML())
+ except:
+ exc = GetExceptionTracebackStr()
+ cmd = dbg.cmdFactory.makeErrorMessage(self.sequence, "Error evaluating expression " + exc)
+ dbg.writer.addCommand(cmd)
+
+
+#=======================================================================================================================
+# InternalRunCustomOperation
+#=======================================================================================================================
+class InternalRunCustomOperation(InternalThreadCommand):
+ """ Run a custom command on an expression
+ """
+ def __init__(self, seq, thread_id, frame_id, scope, attrs, style, encoded_code_or_file, fnname):
+ self.sequence = seq
+ self.thread_id = thread_id
+ self.frame_id = frame_id
+ self.scope = scope
+ self.attrs = attrs
+ self.style = style
+ self.code_or_file = unquote_plus(encoded_code_or_file)
+ self.fnname = fnname
+
+ def doIt(self, dbg):
+ try:
+ res = pydevd_vars.customOperation(self.thread_id, self.frame_id, self.scope, self.attrs,
+ self.style, self.code_or_file, self.fnname)
+ resEncoded = quote_plus(res)
+ cmd = dbg.cmdFactory.makeCustomOperationMessage(self.sequence, resEncoded)
+ dbg.writer.addCommand(cmd)
+ except:
+ exc = GetExceptionTracebackStr()
+ cmd = dbg.cmdFactory.makeErrorMessage(self.sequence, "Error in running custom operation" + exc)
+ dbg.writer.addCommand(cmd)
+
+
+#=======================================================================================================================
+# InternalConsoleGetCompletions
+#=======================================================================================================================
+class InternalConsoleGetCompletions(InternalThreadCommand):
+ """ Fetch the completions in the debug console
+ """
+ def __init__(self, seq, thread_id, frame_id, act_tok):
+ self.sequence = seq
+ self.thread_id = thread_id
+ self.frame_id = frame_id
+ self.act_tok = act_tok
+
+ def doIt(self, dbg):
+ """ Get completions and write back to the client
+ """
+ try:
+ frame = pydevd_vars.findFrame(self.thread_id, self.frame_id)
+ completions_xml = pydevd_console.get_completions(frame, self.act_tok)
+ cmd = dbg.cmdFactory.makeSendConsoleMessage(self.sequence, completions_xml)
+ dbg.writer.addCommand(cmd)
+ except:
+ exc = GetExceptionTracebackStr()
+ cmd = dbg.cmdFactory.makeErrorMessage(self.sequence, "Error in fetching completions" + exc)
+ dbg.writer.addCommand(cmd)
+
#=======================================================================================================================
# InternalConsoleExec
@@ -996,13 +1234,10 @@ class InternalConsoleExec(InternalThreadCommand):
def doIt(self, dbg):
""" Converts request into python variable """
- pydev_start_new_thread = None
try:
try:
- pydev_start_new_thread = thread.start_new_thread
-
- thread.start_new_thread = thread._original_start_new_thread #don't trace new threads created by console command
- thread.start_new = thread._original_start_new_thread
+ #don't trace new threads created by console command
+ disable_trace_thread_modules()
result = pydevconsole.consoleExec(self.thread_id, self.frame_id, self.expression)
xml = "<xml>"
@@ -1016,8 +1251,8 @@ class InternalConsoleExec(InternalThreadCommand):
cmd = dbg.cmdFactory.makeErrorMessage(self.sequence, "Error evaluating console expression " + exc)
dbg.writer.addCommand(cmd)
finally:
- thread.start_new_thread = pydev_start_new_thread
- thread.start_new = pydev_start_new_thread
+ enable_trace_thread_modules()
+
sys.stderr.flush()
sys.stdout.flush()
diff --git a/python/helpers/pydev/pydevd_console.py b/python/helpers/pydev/pydevd_console.py
new file mode 100644
index 000000000000..52b18bb29211
--- /dev/null
+++ b/python/helpers/pydev/pydevd_console.py
@@ -0,0 +1,212 @@
+'''An helper file for the pydev debugger (REPL) console
+'''
+from code import InteractiveConsole
+import sys
+import traceback
+
+import _pydev_completer
+from pydevd_tracing import GetExceptionTracebackStr
+from pydevd_vars import makeValidXmlValue
+from pydev_imports import Exec
+from pydevd_io import IOBuf
+from pydev_console_utils import BaseInterpreterInterface, BaseStdIn
+from pydev_override import overrides
+import pydevd_save_locals
+
+CONSOLE_OUTPUT = "output"
+CONSOLE_ERROR = "error"
+
+
+#=======================================================================================================================
+# ConsoleMessage
+#=======================================================================================================================
+class ConsoleMessage:
+ """Console Messages
+ """
+ def __init__(self):
+ self.more = False
+ # List of tuple [('error', 'error_message'), ('message_list', 'output_message')]
+ self.console_messages = []
+
+ def add_console_message(self, message_type, message):
+ """add messages in the console_messages list
+ """
+ for m in message.split("\n"):
+ if m.strip():
+ self.console_messages.append((message_type, m))
+
+ def update_more(self, more):
+ """more is set to true if further input is required from the user
+ else more is set to false
+ """
+ self.more = more
+
+ def toXML(self):
+ """Create an XML for console message_list, error and more (true/false)
+ <xml>
+ <message_list>console message_list</message_list>
+ <error>console error</error>
+ <more>true/false</more>
+ </xml>
+ """
+ makeValid = makeValidXmlValue
+
+ xml = '<xml><more>%s</more>' % (self.more)
+
+ for message_type, message in self.console_messages:
+ xml += '<%s message="%s"></%s>' % (message_type, makeValid(message), message_type)
+
+ xml += '</xml>'
+
+ return xml
+
+
+#=======================================================================================================================
+# DebugConsoleStdIn
+#=======================================================================================================================
+class DebugConsoleStdIn(BaseStdIn):
+
+ overrides(BaseStdIn.readline)
+ def readline(self, *args, **kwargs):
+ sys.stderr.write('Warning: Reading from stdin is still not supported in this console.\n')
+ return '\n'
+
+#=======================================================================================================================
+# DebugConsole
+#=======================================================================================================================
+class DebugConsole(InteractiveConsole, BaseInterpreterInterface):
+ """Wrapper around code.InteractiveConsole, in order to send
+ errors and outputs to the debug console
+ """
+
+ overrides(BaseInterpreterInterface.createStdIn)
+ def createStdIn(self):
+ return DebugConsoleStdIn() #For now, raw_input is not supported in this console.
+
+
+ overrides(InteractiveConsole.push)
+ def push(self, line, frame):
+ """Change built-in stdout and stderr methods by the
+ new custom StdMessage.
+ execute the InteractiveConsole.push.
+ Change the stdout and stderr back be the original built-ins
+
+ Return boolean (True if more input is required else False),
+ output_messages and input_messages
+ """
+ more = False
+ original_stdout = sys.stdout
+ original_stderr = sys.stderr
+ try:
+ try:
+ self.frame = frame
+ out = sys.stdout = IOBuf()
+ err = sys.stderr = IOBuf()
+ more = self.addExec(line)
+ except Exception:
+ exc = GetExceptionTracebackStr()
+ err.buflist.append("Internal Error: %s" % (exc,))
+ finally:
+ #Remove frame references.
+ self.frame = None
+ frame = None
+ sys.stdout = original_stdout
+ sys.stderr = original_stderr
+
+ return more, out.buflist, err.buflist
+
+
+ overrides(BaseInterpreterInterface.doAddExec)
+ def doAddExec(self, line):
+ return InteractiveConsole.push(self, line)
+
+
+ overrides(InteractiveConsole.runcode)
+ def runcode(self, code):
+ """Execute a code object.
+
+ When an exception occurs, self.showtraceback() is called to
+ display a traceback. All exceptions are caught except
+ SystemExit, which is reraised.
+
+ A note about KeyboardInterrupt: this exception may occur
+ elsewhere in this code, and may not always be caught. The
+ caller should be prepared to deal with it.
+
+ """
+ try:
+ Exec(code, self.frame.f_globals, self.frame.f_locals)
+ pydevd_save_locals.save_locals(self.frame)
+ except SystemExit:
+ raise
+ except:
+ self.showtraceback()
+
+
+#=======================================================================================================================
+# InteractiveConsoleCache
+#=======================================================================================================================
+class InteractiveConsoleCache:
+
+ thread_id = None
+ frame_id = None
+ interactive_console_instance = None
+
+
+#Note: On Jython 2.1 we can't use classmethod or staticmethod, so, just make the functions below free-functions.
+def get_interactive_console(thread_id, frame_id, frame, console_message):
+ """returns the global interactive console.
+ interactive console should have been initialized by this time
+ """
+ if InteractiveConsoleCache.thread_id == thread_id and InteractiveConsoleCache.frame_id == frame_id:
+ return InteractiveConsoleCache.interactive_console_instance
+
+ InteractiveConsoleCache.interactive_console_instance = DebugConsole()
+ InteractiveConsoleCache.thread_id = thread_id
+ InteractiveConsoleCache.frame_id = frame_id
+
+ console_stacktrace = traceback.extract_stack(frame, limit=1)
+ if console_stacktrace:
+ current_context = console_stacktrace[0] # top entry from stacktrace
+ context_message = 'File "%s", line %s, in %s' % (current_context[0], current_context[1], current_context[2])
+ console_message.add_console_message(CONSOLE_OUTPUT, "[Current context]: %s" % (context_message,))
+ return InteractiveConsoleCache.interactive_console_instance
+
+
+def clear_interactive_console():
+ InteractiveConsoleCache.thread_id = None
+ InteractiveConsoleCache.frame_id = None
+ InteractiveConsoleCache.interactive_console_instance = None
+
+
+def execute_console_command(frame, thread_id, frame_id, line):
+ """fetch an interactive console instance from the cache and
+ push the received command to the console.
+
+ create and return an instance of console_message
+ """
+ console_message = ConsoleMessage()
+
+ interpreter = get_interactive_console(thread_id, frame_id, frame, console_message)
+ more, output_messages, error_messages = interpreter.push(line, frame)
+ console_message.update_more(more)
+
+ for message in output_messages:
+ console_message.add_console_message(CONSOLE_OUTPUT, message)
+
+ for message in error_messages:
+ console_message.add_console_message(CONSOLE_ERROR, message)
+
+ return console_message
+
+
+def get_completions(frame, act_tok):
+ """ fetch all completions, create xml for the same
+ return the completions xml
+ """
+ return _pydev_completer.GenerateCompletionsAsXML(frame, act_tok)
+
+
+
+
+
diff --git a/python/helpers/pydev/pydevd_constants.py b/python/helpers/pydev/pydevd_constants.py
index 71fe4aed2505..74e897461458 100644
--- a/python/helpers/pydev/pydevd_constants.py
+++ b/python/helpers/pydev/pydevd_constants.py
@@ -1,7 +1,6 @@
'''
This module holds the constants used for specifying the states of the debugger.
'''
-
STATE_RUN = 1
STATE_SUSPEND = 2
@@ -17,13 +16,13 @@ except:
setattr(__builtin__, 'False', 0)
class DebugInfoHolder:
- #we have to put it here because it can be set through the command line (so, the
+ #we have to put it here because it can be set through the command line (so, the
#already imported references would not have it).
DEBUG_RECORD_SOCKET_READS = False
DEBUG_TRACE_LEVEL = -1
DEBUG_TRACE_BREAKPOINTS = -1
-#Optimize with psyco? This gave a 50% speedup in the debugger in tests
+#Optimize with psyco? This gave a 50% speedup in the debugger in tests
USE_PSYCO_OPTIMIZATION = True
#Hold a reference to the original _getframe (because psyco will change that as soon as it's imported)
@@ -111,11 +110,48 @@ except:
return default
+if IS_PY3K:
+ def DictKeys(d):
+ return list(d.keys())
+
+ def DictValues(d):
+ return list(d.values())
+
+ DictIterValues = dict.values
+
+ def DictIterItems(d):
+ return d.items()
+
+ def DictItems(d):
+ return list(d.items())
+
+else:
+ DictKeys = dict.keys
+ try:
+ DictIterValues = dict.itervalues
+ except:
+ DictIterValues = dict.values #Older versions don't have the itervalues
+
+ DictValues = dict.values
+
+ def DictIterItems(d):
+ return d.iteritems()
+
+ def DictItems(d):
+ return d.items()
+
+
try:
- xrange
+ xrange = xrange
except:
#Python 3k does not have it
xrange = range
+
+try:
+ import itertools
+ izip = itertools.izip
+except:
+ izip = zip
try:
object
@@ -128,10 +164,10 @@ try:
except:
def enumerate(lst):
ret = []
- i=0
+ i = 0
for element in lst:
ret.append((i, element))
- i+=1
+ i += 1
return ret
#=======================================================================================================================
@@ -174,8 +210,7 @@ def GetThreadId(thread):
except AttributeError:
try:
#Jython does not have it!
- import java.lang.management.ManagementFactory #@UnresolvedImport -- just for jython
-
+ import java.lang.management.ManagementFactory #@UnresolvedImport -- just for jython
pid = java.lang.management.ManagementFactory.getRuntimeMXBean().getName()
pid = pid.replace('@', '_')
except:
@@ -262,4 +297,4 @@ def call_only_once(func):
if __name__ == '__main__':
if Null():
sys.stdout.write('here\n')
-
+
diff --git a/python/helpers/pydev/pydevd_dont_trace.py b/python/helpers/pydev/pydevd_dont_trace.py
new file mode 100644
index 000000000000..2d5ad959f7b0
--- /dev/null
+++ b/python/helpers/pydev/pydevd_dont_trace.py
@@ -0,0 +1,127 @@
+'''
+Support for a tag that allows skipping over functions while debugging.
+'''
+import linecache
+import re
+from pydevd_constants import DictContains
+
+# To suppress tracing a method, add the tag @DontTrace
+# to a comment either preceding or on the same line as
+# the method definition
+#
+# E.g.:
+# #@DontTrace
+# def test1():
+# pass
+#
+# ... or ...
+#
+# def test2(): #@DontTrace
+# pass
+DONT_TRACE_TAG = '@DontTrace'
+
+# Regular expression to match a decorator (at the beginning
+# of a line).
+RE_DECORATOR = re.compile(r'^\s*@')
+
+# Mapping from code object to bool.
+# If the key exists, the value is the cached result of should_trace_hook
+_filename_to_ignored_lines = {}
+
+def default_should_trace_hook(frame, filename):
+ '''
+ Return True if this frame should be traced, False if tracing should be blocked.
+ '''
+ # First, check whether this code object has a cached value
+ ignored_lines = _filename_to_ignored_lines.get(filename)
+ if ignored_lines is None:
+ # Now, look up that line of code and check for a @DontTrace
+ # preceding or on the same line as the method.
+ # E.g.:
+ # #@DontTrace
+ # def test():
+ # pass
+ # ... or ...
+ # def test(): #@DontTrace
+ # pass
+ ignored_lines = {}
+ lines = linecache.getlines(filename)
+ i_line = 0 # Could use enumerate, but not there on all versions...
+ for line in lines:
+ j = line.find('#')
+ if j >= 0:
+ comment = line[j:]
+ if DONT_TRACE_TAG in comment:
+ ignored_lines[i_line] = 1
+
+ #Note: when it's found in the comment, mark it up and down for the decorator lines found.
+ k = i_line - 1
+ while k >= 0:
+ if RE_DECORATOR.match(lines[k]):
+ ignored_lines[k] = 1
+ k -= 1
+ else:
+ break
+
+ k = i_line + 1
+ while k <= len(lines):
+ if RE_DECORATOR.match(lines[k]):
+ ignored_lines[k] = 1
+ k += 1
+ else:
+ break
+
+ i_line += 1
+
+
+ _filename_to_ignored_lines[filename] = ignored_lines
+
+ func_line = frame.f_code.co_firstlineno - 1 # co_firstlineno is 1-based, so -1 is needed
+ return not (
+ DictContains(ignored_lines, func_line - 1) or #-1 to get line before method
+ DictContains(ignored_lines, func_line)) #method line
+
+
+should_trace_hook = None
+
+
+def clear_trace_filter_cache():
+ '''
+ Clear the trace filter cache.
+ Call this after reloading.
+ '''
+ global should_trace_hook
+ try:
+ # Need to temporarily disable a hook because otherwise
+ # _filename_to_ignored_lines.clear() will never complete.
+ old_hook = should_trace_hook
+ should_trace_hook = None
+
+ # Clear the linecache
+ linecache.clearcache()
+ _filename_to_ignored_lines.clear()
+
+ finally:
+ should_trace_hook = old_hook
+
+
+def trace_filter(mode):
+ '''
+ Set the trace filter mode.
+
+ mode: Whether to enable the trace hook.
+ True: Trace filtering on (skipping methods tagged @DontTrace)
+ False: Trace filtering off (trace methods tagged @DontTrace)
+ None/default: Toggle trace filtering.
+ '''
+ global should_trace_hook
+ if mode is None:
+ mode = should_trace_hook is None
+
+ if mode:
+ should_trace_hook = default_should_trace_hook
+ else:
+ should_trace_hook = None
+
+ return mode
+
diff --git a/python/helpers/pydev/pydevd_file_utils.py b/python/helpers/pydev/pydevd_file_utils.py
index b4f8d50d473a..c135c4bd5ad4 100644
--- a/python/helpers/pydev/pydevd_file_utils.py
+++ b/python/helpers/pydev/pydevd_file_utils.py
@@ -3,72 +3,91 @@
- The case of a file will match the actual file in the filesystem (otherwise breakpoints won't be hit).
- Providing means for the user to make path conversions when doing a remote debugging session in
one machine and debugging in another.
-
+
To do that, the PATHS_FROM_ECLIPSE_TO_PYTHON constant must be filled with the appropriate paths.
-
- @note:
- in this context, the server is where your python process is running
+
+ @note:
+ in this context, the server is where your python process is running
and the client is where eclipse is running.
-
- E.g.:
+
+ E.g.:
If the server (your python process) has the structure
- /user/projects/my_project/src/package/module1.py
-
- and the client has:
- c:\my_project\src\package\module1.py
-
+ /user/projects/my_project/src/package/module1.py
+
+ and the client has:
+ c:\my_project\src\package\module1.py
+
the PATHS_FROM_ECLIPSE_TO_PYTHON would have to be:
PATHS_FROM_ECLIPSE_TO_PYTHON = [(r'c:\my_project\src', r'/user/projects/my_project/src')]
-
+
@note: DEBUG_CLIENT_SERVER_TRANSLATION can be set to True to debug the result of those translations
-
+
@note: the case of the paths is important! Note that this can be tricky to get right when one machine
uses a case-independent filesystem and the other uses a case-dependent filesystem (if the system being
- debugged is case-independent, 'normcase()' should be used on the paths defined in PATHS_FROM_ECLIPSE_TO_PYTHON).
-
+ debugged is case-independent, 'normcase()' should be used on the paths defined in PATHS_FROM_ECLIPSE_TO_PYTHON).
+
@note: all the paths with breakpoints must be translated (otherwise they won't be found in the server)
-
+
@note: to enable remote debugging in the target machine (pydev extensions in the eclipse installation)
import pydevd;pydevd.settrace(host, stdoutToServer, stderrToServer, port, suspend)
-
+
see parameter docs on pydevd.py
-
- @note: for doing a remote debugging session, all the pydevd_ files must be on the server accessible
- through the PYTHONPATH (and the PATHS_FROM_ECLIPSE_TO_PYTHON only needs to be set on the target
+
+ @note: for doing a remote debugging session, all the pydevd_ files must be on the server accessible
+ through the PYTHONPATH (and the PATHS_FROM_ECLIPSE_TO_PYTHON only needs to be set on the target
machine for the paths that'll actually have breakpoints).
'''
-
-
-
-from pydevd_constants import * #@UnusedWildImport
import os.path
import sys
import traceback
-
-
+os_normcase = os.path.normcase
basename = os.path.basename
exists = os.path.exists
join = os.path.join
try:
- rPath = os.path.realpath #@UndefinedVariable
+ rPath = os.path.realpath #@UndefinedVariable
except:
# jython does not support os.path.realpath
# realpath is a no-op on systems without islink support
- rPath = os.path.abspath
-
+ rPath = os.path.abspath
+
#defined as a list of tuples where the 1st element of the tuple is the path in the client machine
#and the 2nd element is the path in the server machine.
#see module docstring for more details.
PATHS_FROM_ECLIPSE_TO_PYTHON = []
-
#example:
#PATHS_FROM_ECLIPSE_TO_PYTHON = [
-#(normcase(r'd:\temp\temp_workspace_2\test_python\src\yyy\yyy'),
-# normcase(r'd:\temp\temp_workspace_2\test_python\src\hhh\xxx'))]
+# (r'd:\temp\temp_workspace_2\test_python\src\yyy\yyy',
+# r'd:\temp\temp_workspace_2\test_python\src\hhh\xxx')
+#]
+
+
+normcase = os_normcase # May be rebound on set_ide_os
+
+def set_ide_os(os):
+ '''
+ We need to set the IDE os because the host where the code is running may be
+ actually different from the client (and the point is that we want the proper
+ paths to translate from the client to the server).
+ '''
+ global normcase
+ if os == 'UNIX':
+ normcase = lambda f:f #Change to no-op if the client side is on unix/mac.
+ else:
+ normcase = os_normcase
+
+ # After setting the ide OS, apply the normcase to the existing paths.
+
+ # Note: not using enumerate nor list comprehension because it may not be available in older python versions...
+ i = 0
+ for path in PATHS_FROM_ECLIPSE_TO_PYTHON[:]:
+ PATHS_FROM_ECLIPSE_TO_PYTHON[i] = (normcase(path[0]), normcase(path[1]))
+ i += 1
+
DEBUG_CLIENT_SERVER_TRANSLATION = False
@@ -79,14 +98,6 @@ NORM_FILENAME_TO_SERVER_CONTAINER = {}
NORM_FILENAME_TO_CLIENT_CONTAINER = {}
-pycharm_os = None
-
-def normcase(file):
- global pycharm_os
- if pycharm_os == 'UNIX':
- return file
- else:
- return os.path.normcase(file)
def _NormFile(filename):
@@ -147,7 +158,7 @@ def exists(file):
return None
return None
-
+
#Now, let's do a quick test to see if we're working with a version of python that has no problems
#related to the names generated...
try:
@@ -162,11 +173,11 @@ try:
sys.stderr.write('pydev debugger: Related bug: http://bugs.python.org/issue1666807\n')
sys.stderr.write('-------------------------------------------------------------------------------\n')
sys.stderr.flush()
-
+
NORM_SEARCH_CACHE = {}
-
+
initial_norm_file = _NormFile
- def _NormFile(filename): #Let's redefine _NormFile to work with paths that may be incorrect
+ def _NormFile(filename): #Let's redefine _NormFile to work with paths that may be incorrect
try:
return NORM_SEARCH_CACHE[filename]
except KeyError:
@@ -180,7 +191,7 @@ try:
else:
sys.stderr.write('pydev debugger: Unable to find real location for: %s\n' % (filename,))
ret = filename
-
+
NORM_SEARCH_CACHE[filename] = ret
return ret
except:
@@ -195,28 +206,28 @@ if PATHS_FROM_ECLIPSE_TO_PYTHON:
for eclipse_prefix, server_prefix in PATHS_FROM_ECLIPSE_TO_PYTHON:
if eclipse_sep is not None and python_sep is not None:
break
-
+
if eclipse_sep is None:
for c in eclipse_prefix:
if c in ('/', '\\'):
eclipse_sep = c
break
-
+
if python_sep is None:
for c in server_prefix:
if c in ('/', '\\'):
python_sep = c
break
-
+
#If they're the same or one of them cannot be determined, just make it all None.
if eclipse_sep == python_sep or eclipse_sep is None or python_sep is None:
eclipse_sep = python_sep = None
-
-
- #only setup translation functions if absolutely needed!
+
+
+ #only setup translation functions if absolutely needed!
def NormFileToServer(filename):
#Eclipse will send the passed filename to be translated to the python process
- #So, this would be 'NormFileFromEclipseToPython'
+ #So, this would be 'NormFileFromEclipseToPython'
try:
return NORM_FILENAME_TO_SERVER_CONTAINER[filename]
except KeyError:
@@ -234,17 +245,17 @@ if PATHS_FROM_ECLIPSE_TO_PYTHON:
if DEBUG_CLIENT_SERVER_TRANSLATION:
sys.stderr.write('pydev debugger: to server: unable to find matching prefix for: %s in %s\n' % \
(translated, [x[0] for x in PATHS_FROM_ECLIPSE_TO_PYTHON]))
-
+
#Note that when going to the server, we do the replace first and only later do the norm file.
if eclipse_sep is not None:
translated = translated.replace(eclipse_sep, python_sep)
translated = _NormFile(translated)
-
+
NORM_FILENAME_TO_SERVER_CONTAINER[filename] = translated
return translated
-
-
- def NormFileToClient(filename):
+
+
+ def NormFileToClient(filename):
#The result of this method will be passed to eclipse
#So, this would be 'NormFileFromPythonToEclipse'
try:
@@ -264,15 +275,15 @@ if PATHS_FROM_ECLIPSE_TO_PYTHON:
if DEBUG_CLIENT_SERVER_TRANSLATION:
sys.stderr.write('pydev debugger: to client: unable to find matching prefix for: %s in %s\n' % \
(translated, [x[1] for x in PATHS_FROM_ECLIPSE_TO_PYTHON]))
-
+
if eclipse_sep is not None:
translated = translated.replace(python_sep, eclipse_sep)
-
+
#The resulting path is not in the python process, so, we cannot do a _NormFile here,
#only at the beginning of this method.
NORM_FILENAME_TO_CLIENT_CONTAINER[filename] = translated
return translated
-
+
else:
#no translation step needed (just inline the calls)
NormFileToClient = _NormFile
@@ -299,6 +310,3 @@ def GetFilenameAndBase(frame):
f = f[:-1]
return GetFileNameAndBaseFromFile(f)
-def set_pycharm_os(os):
- global pycharm_os
- pycharm_os = os
diff --git a/python/helpers/pydev/pydevd_frame.py b/python/helpers/pydev/pydevd_frame.py
index 05faaeb77ff2..374d2818bf87 100644
--- a/python/helpers/pydev/pydevd_frame.py
+++ b/python/helpers/pydev/pydevd_frame.py
@@ -1,18 +1,29 @@
-from django_debug import is_django_render_call, get_template_file_name, get_template_line, is_django_suspended, suspend_django, is_django_resolve_call, is_django_context_get_call
+import linecache
+import os.path
+import re
+import traceback # @Reimport
+
from django_debug import find_django_render_frame
-from django_frame import just_raised
-from django_frame import is_django_exception_break_context
+from django_debug import is_django_render_call, is_django_suspended, suspend_django, is_django_resolve_call, is_django_context_get_call
from django_frame import DjangoTemplateFrame
-from pydevd_comm import * #@UnusedWildImport
-from pydevd_breakpoints import * #@UnusedWildImport
-import traceback #@Reimport
-import os.path
-import sys
+from django_frame import is_django_exception_break_context
+from django_frame import just_raised, get_template_file_name, get_template_line
import pydev_log
+from pydevd_breakpoints import get_exception_breakpoint, get_exception_name
+from pydevd_comm import CMD_ADD_DJANGO_EXCEPTION_BREAK, \
+ CMD_STEP_CAUGHT_EXCEPTION, CMD_STEP_RETURN, CMD_STEP_OVER, CMD_SET_BREAK, \
+ CMD_STEP_INTO, CMD_SMART_STEP_INTO, CMD_RUN_TO_LINE, CMD_SET_NEXT_STATEMENT
+from pydevd_constants import * # @UnusedWildImport
+from pydevd_file_utils import GetFilenameAndBase
from pydevd_signature import sendSignatureCallTrace
+import pydevd_vars
+import pydevd_dont_trace
basename = os.path.basename
+IGNORE_EXCEPTION_TAG = re.compile('[^#]*#.*@IgnoreException')
+
+
#=======================================================================================================================
# PyDBFrame
#=======================================================================================================================
@@ -22,6 +33,13 @@ class PyDBFrame:
is reused for the entire context.
'''
+ #Note: class (and not instance) attributes.
+
+ #Same thing in the main debugger but only considering the file contents, while the one in the main debugger
+ #considers the user input (so, the actual result must be a join of both).
+ filename_to_lines_where_exceptions_are_ignored = {}
+ filename_to_stat_info = {}
+
def __init__(self, args):
#args = mainDebugger, filename, base, info, t, frame
#yeap, much faster than putting in self and then getting it from self later on
@@ -33,84 +51,234 @@ class PyDBFrame:
def doWaitSuspend(self, *args, **kwargs):
self._args[0].doWaitSuspend(*args, **kwargs)
+ def _is_django_render_call(self, frame):
+ try:
+ return self._cached_is_django_render_call
+ except:
+ # Calculate lazily: note that a PyDBFrame always deals with the same
+ # frame over and over, so, we can cache this.
+ # -- although we can't cache things which change over time (such as
+ # the breakpoints for the file).
+ ret = self._cached_is_django_render_call = is_django_render_call(frame)
+ return ret
+
def trace_exception(self, frame, event, arg):
if event == 'exception':
- (flag, frame) = self.shouldStopOnException(frame, event, arg)
+ flag, frame = self.should_stop_on_exception(frame, event, arg)
if flag:
- self.handle_exception(frame, event, arg)
- return self.trace_dispatch
+ self.handle_exception(frame, event, arg)
+ return self.trace_dispatch
return self.trace_exception
- def shouldStopOnException(self, frame, event, arg):
- mainDebugger, filename, info, thread = self._args
- flag = False
-
- if info.pydev_state != STATE_SUSPEND: #and breakpoint is not None:
- (exception, value, trace) = arg
-
- if trace is not None: #on jython trace is None on the first event
- exception_breakpoint = get_exception_breakpoint(exception, dict(mainDebugger.exception_set), NOTIFY_ALWAYS)
- if exception_breakpoint is not None:
- if not exception_breakpoint.notify_on_first_raise_only or just_raised(trace):
- curr_func_name = frame.f_code.co_name
- add_exception_to_frame(frame, (exception, value, trace))
- self.setSuspend(thread, CMD_ADD_EXCEPTION_BREAK)
- thread.additionalInfo.message = exception_breakpoint.qname
- flag = True
- else:
- flag = False
- else:
- try:
- if mainDebugger.django_exception_break and get_exception_name(exception) in ['VariableDoesNotExist', 'TemplateDoesNotExist', 'TemplateSyntaxError'] and just_raised(trace) and is_django_exception_break_context(frame):
- render_frame = find_django_render_frame(frame)
- if render_frame:
- suspend_frame = suspend_django(self, mainDebugger, thread, render_frame, CMD_ADD_DJANGO_EXCEPTION_BREAK)
-
- if suspend_frame:
- add_exception_to_frame(suspend_frame, (exception, value, trace))
- flag = True
- thread.additionalInfo.message = 'VariableDoesNotExist'
- suspend_frame.f_back = frame
- frame = suspend_frame
- except :
- flag = False
-
- return (flag, frame)
+ def should_stop_on_exception(self, frame, event, arg):
+ mainDebugger, _filename, info, thread = self._args
+ flag = False
+
+ if info.pydev_state != STATE_SUSPEND: #and breakpoint is not None:
+ exception, value, trace = arg
+
+ if trace is not None: #on jython trace is None on the first event
+ exception_breakpoint = get_exception_breakpoint(
+ exception, mainDebugger.break_on_caught_exceptions)
+
+ if exception_breakpoint is not None:
+ if not exception_breakpoint.notify_on_first_raise_only or just_raised(trace):
+ # print frame.f_code.co_name
+ add_exception_to_frame(frame, (exception, value, trace))
+ thread.additionalInfo.message = exception_breakpoint.qname
+ flag = True
+ else:
+ flag = False
+ else:
+ try:
+ if mainDebugger.django_exception_break and get_exception_name(exception) in [
+ 'VariableDoesNotExist', 'TemplateDoesNotExist', 'TemplateSyntaxError'] \
+ and just_raised(trace) and is_django_exception_break_context(frame):
+
+ render_frame = find_django_render_frame(frame)
+ if render_frame:
+ suspend_frame = suspend_django(
+ self, mainDebugger, thread, render_frame, CMD_ADD_DJANGO_EXCEPTION_BREAK)
+
+ if suspend_frame:
+ add_exception_to_frame(suspend_frame, (exception, value, trace))
+ flag = True
+ thread.additionalInfo.message = 'VariableDoesNotExist'
+ suspend_frame.f_back = frame
+ frame = suspend_frame
+ except :
+ flag = False
+
+ return flag, frame
def handle_exception(self, frame, event, arg):
- mainDebugger = self._args[0]
- thread = self._args[3]
- self.doWaitSuspend(thread, frame, event, arg)
- mainDebugger.SetTraceForFrameAndParents(frame)
+ try:
+ # print 'handle_exception', frame.f_lineno, frame.f_code.co_name
+
+ # We have 3 things in arg: exception type, description, traceback object
+ trace_obj = arg[2]
+ mainDebugger = self._args[0]
+
+ if not hasattr(trace_obj, 'tb_next'):
+ return #Not always there on Jython...
+
+ initial_trace_obj = trace_obj
+ if trace_obj.tb_next is None and trace_obj.tb_frame is frame:
+ #I.e.: tb_next should be only None in the context it was thrown (trace_obj.tb_frame is frame is just a double check).
+
+ if mainDebugger.break_on_exceptions_thrown_in_same_context:
+ #Option: Don't break if an exception is caught in the same function from which it is thrown
+ return
+ else:
+ #Get the trace_obj from where the exception was raised...
+ while trace_obj.tb_next is not None:
+ trace_obj = trace_obj.tb_next
+
+
+ if mainDebugger.ignore_exceptions_thrown_in_lines_with_ignore_exception:
+ for check_trace_obj in (initial_trace_obj, trace_obj):
+ filename = GetFilenameAndBase(check_trace_obj.tb_frame)[0]
+
+
+ filename_to_lines_where_exceptions_are_ignored = self.filename_to_lines_where_exceptions_are_ignored
+
+
+ lines_ignored = filename_to_lines_where_exceptions_are_ignored.get(filename)
+ if lines_ignored is None:
+ lines_ignored = filename_to_lines_where_exceptions_are_ignored[filename] = {}
+
+ try:
+ curr_stat = os.stat(filename)
+ curr_stat = (curr_stat.st_size, curr_stat.st_mtime)
+ except:
+ curr_stat = None
+
+ last_stat = self.filename_to_stat_info.get(filename)
+ if last_stat != curr_stat:
+ self.filename_to_stat_info[filename] = curr_stat
+ lines_ignored.clear()
+ try:
+ linecache.checkcache(filename)
+ except:
+ #Jython 2.1
+ linecache.checkcache()
+
+ from_user_input = mainDebugger.filename_to_lines_where_exceptions_are_ignored.get(filename)
+ if from_user_input:
+ merged = {}
+ merged.update(lines_ignored)
+ #Override what we have with the related entries that the user entered
+ merged.update(from_user_input)
+ else:
+ merged = lines_ignored
+
+ exc_lineno = check_trace_obj.tb_lineno
+
+ # print ('lines ignored', lines_ignored)
+ # print ('user input', from_user_input)
+ # print ('merged', merged, 'curr', exc_lineno)
+
+ if not DictContains(merged, exc_lineno): #Note: check on merged but update lines_ignored.
+ try:
+ line = linecache.getline(filename, exc_lineno, check_trace_obj.tb_frame.f_globals)
+ except:
+ #Jython 2.1
+ line = linecache.getline(filename, exc_lineno)
+
+ if IGNORE_EXCEPTION_TAG.match(line) is not None:
+ lines_ignored[exc_lineno] = 1
+ return
+ else:
+ #Put in the cache saying not to ignore
+ lines_ignored[exc_lineno] = 0
+ else:
+ #Ok, dict has it already cached, so, let's check it...
+ if merged.get(exc_lineno, 0):
+ return
+
+
+ thread = self._args[3]
+
+ try:
+ frame_id_to_frame = {}
+ frame_id_to_frame[id(frame)] = frame
+ f = trace_obj.tb_frame
+ while f is not None:
+ frame_id_to_frame[id(f)] = f
+ f = f.f_back
+ f = None
+
+ thread_id = GetThreadId(thread)
+ pydevd_vars.addAdditionalFrameById(thread_id, frame_id_to_frame)
+ try:
+ mainDebugger.sendCaughtExceptionStack(thread, arg, id(frame))
+ self.setSuspend(thread, CMD_STEP_CAUGHT_EXCEPTION)
+ self.doWaitSuspend(thread, frame, event, arg)
+ mainDebugger.sendCaughtExceptionStackProceeded(thread)
+
+ finally:
+ pydevd_vars.removeAdditionalFrameById(thread_id)
+ except:
+ traceback.print_exc()
+
+ mainDebugger.SetTraceForFrameAndParents(frame)
+ finally:
+ #Clear some local variables...
+ trace_obj = None
+ initial_trace_obj = None
+ check_trace_obj = None
+ f = None
+ frame_id_to_frame = None
+ mainDebugger = None
+ thread = None
def trace_dispatch(self, frame, event, arg):
- mainDebugger, filename, info, thread = self._args
+ main_debugger, filename, info, thread = self._args
try:
info.is_tracing = True
- if mainDebugger._finishDebuggingSession:
+ if main_debugger._finishDebuggingSession:
return None
if getattr(thread, 'pydev_do_not_trace', None):
return None
- if event == 'call':
- sendSignatureCallTrace(mainDebugger, frame, filename)
+ if event == 'call' and main_debugger.signature_factory:
+ sendSignatureCallTrace(main_debugger, frame, filename)
+
+ is_exception_event = event == 'exception'
+ has_exception_breakpoints = main_debugger.break_on_caught_exceptions or main_debugger.django_exception_break
- if event not in ('line', 'call', 'return'):
- if event == 'exception':
- (flag, frame) = self.shouldStopOnException(frame, event, arg)
+ if is_exception_event:
+ if has_exception_breakpoints:
+ flag, frame = self.should_stop_on_exception(frame, event, arg)
if flag:
self.handle_exception(frame, event, arg)
return self.trace_dispatch
- else:
+
+ elif event not in ('line', 'call', 'return'):
#I believe this can only happen in jython on some frontiers on jython and java code, which we don't want to trace.
- return None
+ return None
- if event is not 'exception':
- breakpoints_for_file = mainDebugger.breakpoints.get(filename)
+ stop_frame = info.pydev_step_stop
+ step_cmd = info.pydev_step_cmd
+
+ if is_exception_event:
+ breakpoints_for_file = None
+ else:
+ # If we are in single step mode and something causes us to exit the current frame, we need to make sure we break
+ # eventually. Force the step mode to step into and the step stop frame to None.
+ # I.e.: F6 in the end of a function should stop in the next possible position (instead of forcing the user
+ # to make a step in or step over at that location).
+ # Note: this is especially troublesome when we're skipping code with the
+ # @DontTrace comment.
+ if stop_frame is frame and event in ('return', 'exception') and step_cmd in (CMD_STEP_RETURN, CMD_STEP_OVER):
+ info.pydev_step_cmd = CMD_STEP_INTO
+ info.pydev_step_stop = None
+
+ breakpoints_for_file = main_debugger.breakpoints.get(filename)
can_skip = False
@@ -118,10 +286,11 @@ class PyDBFrame:
#we can skip if:
#- we have no stop marked
#- we should make a step return/step over and we're not in the current frame
- can_skip = (info.pydev_step_cmd is None and info.pydev_step_stop is None)\
- or (info.pydev_step_cmd in (CMD_STEP_RETURN, CMD_STEP_OVER) and info.pydev_step_stop is not frame)
+ can_skip = (step_cmd is None and stop_frame is None)\
+ or (step_cmd in (CMD_STEP_RETURN, CMD_STEP_OVER) and stop_frame is not frame)
- if mainDebugger.django_breakpoints:
+ check_stop_on_django_render_call = main_debugger.django_breakpoints and self._is_django_render_call(frame)
+ if check_stop_on_django_render_call:
can_skip = False
# Let's check to see if we are in a function that has a breakpoint. If we don't have a breakpoint,
@@ -130,7 +299,7 @@ class PyDBFrame:
#so, that's why the additional checks are there.
if not breakpoints_for_file:
if can_skip:
- if mainDebugger.always_exception_set or mainDebugger.django_exception_break:
+ if has_exception_breakpoints:
return self.trace_exception
else:
return None
@@ -143,17 +312,18 @@ class PyDBFrame:
if curr_func_name in ('?', '<module>'):
curr_func_name = ''
- for breakpoint in breakpoints_for_file.values(): #jython does not support itervalues()
+ for breakpoint in DictIterValues(breakpoints_for_file): #jython does not support itervalues()
#will match either global or some function
if breakpoint.func_name in ('None', curr_func_name):
break
else: # if we had some break, it won't get here (so, that's a context that we want to skip)
if can_skip:
- #print 'skipping', frame.f_lineno, info.pydev_state, info.pydev_step_stop, info.pydev_step_cmd
- return None
- else:
- breakpoints_for_file = None
+ if has_exception_breakpoints:
+ return self.trace_exception
+ else:
+ return None
+
#We may have hit a breakpoint or we are already in step mode. Either way, let's check what we should do in this frame
#print 'NOT skipped', frame.f_lineno, frame.f_code.co_name, event
@@ -163,33 +333,63 @@ class PyDBFrame:
flag = False
- if event == 'call' and info.pydev_state != STATE_SUSPEND and mainDebugger.django_breakpoints \
- and is_django_render_call(frame):
- (flag, frame) = self.shouldStopOnDjangoBreak(frame, event, arg)
+ if event == 'call' and info.pydev_state != STATE_SUSPEND and check_stop_on_django_render_call:
+ flag, frame = self.should_stop_on_django_breakpoint(frame, event, arg)
#return is not taken into account for breakpoint hit because we'd have a double-hit in this case
#(one for the line and the other for the return).
if not flag and event != 'return' and info.pydev_state != STATE_SUSPEND and breakpoints_for_file is not None\
- and DictContains(breakpoints_for_file, line):
+ and DictContains(breakpoints_for_file, line):
#ok, hit breakpoint, now, we have to discover if it is a conditional breakpoint
# lets do the conditional stuff here
breakpoint = breakpoints_for_file[line]
stop = True
- if info.pydev_step_cmd == CMD_STEP_OVER and info.pydev_step_stop is frame and event in ('line', 'return'):
+ if step_cmd == CMD_STEP_OVER and stop_frame is frame and event in ('line', 'return'):
stop = False #we don't stop on breakpoint if we have to stop by step-over (it will be processed later)
else:
- if breakpoint.condition is not None:
+ condition = breakpoint.condition
+ if condition is not None:
try:
- val = eval(breakpoint.condition, frame.f_globals, frame.f_locals)
+ val = eval(condition, frame.f_globals, frame.f_locals)
if not val:
return self.trace_dispatch
except:
- pydev_log.info('Error while evaluating condition \'%s\': %s\n' % (breakpoint.condition, sys.exc_info()[1]))
-
- return self.trace_dispatch
+ if type(condition) != type(''):
+ if hasattr(condition, 'encode'):
+ condition = condition.encode('utf-8')
+
+ msg = 'Error while evaluating expression: %s\n' % (condition,)
+ sys.stderr.write(msg)
+ traceback.print_exc()
+ if not main_debugger.suspend_on_breakpoint_exception:
+ return self.trace_dispatch
+ else:
+ stop = True
+ try:
+ additional_info = None
+ try:
+ additional_info = thread.additionalInfo
+ except AttributeError:
+ pass #that's ok, no info currently set
+
+ if additional_info is not None:
+ # add exception_type and stacktrace into thread additional info
+ etype, value, tb = sys.exc_info()
+ try:
+ error = ''.join(traceback.format_exception_only(etype, value))
+ stack = traceback.extract_stack(f=tb.tb_frame.f_back)
+
+ # On self.setSuspend(thread, CMD_SET_BREAK) this info will be
+ # sent to the client.
+ additional_info.conditional_breakpoint_exception = \
+ ('Condition:\n' + condition + '\n\nError:\n' + error, stack)
+ finally:
+ etype, value, tb = None, None, None
+ except:
+ traceback.print_exc()
if breakpoint.expression is not None:
try:
@@ -216,30 +416,45 @@ class PyDBFrame:
#step handling. We stop when we hit the right frame
try:
django_stop = False
- if info.pydev_step_cmd == CMD_STEP_INTO:
+
+ should_skip = False
+ if pydevd_dont_trace.should_trace_hook is not None:
+ if not hasattr(self, 'should_skip'):
+ # I.e.: cache the result on self.should_skip (no need to evaluate the same frame multiple times).
+ # Note that on a code reload, we won't re-evaluate this because in practice, the frame.f_code
+ # Which will be handled by this frame is read-only, so, we can cache it safely.
+ should_skip = self.should_skip = not pydevd_dont_trace.should_trace_hook(frame, filename)
+ else:
+ should_skip = self.should_skip
+
+ if should_skip:
+ stop = False
+
+ elif step_cmd == CMD_STEP_INTO:
stop = event in ('line', 'return')
+
if is_django_suspended(thread):
#django_stop = event == 'call' and is_django_render_call(frame)
stop = stop and is_django_resolve_call(frame.f_back) and not is_django_context_get_call(frame)
if stop:
info.pydev_django_resolve_frame = 1 #we remember that we've go into python code from django rendering frame
- elif info.pydev_step_cmd == CMD_STEP_OVER:
+ elif step_cmd == CMD_STEP_OVER:
if is_django_suspended(thread):
- django_stop = event == 'call' and is_django_render_call(frame)
+ django_stop = event == 'call' and self._is_django_render_call(frame)
stop = False
else:
if event == 'return' and info.pydev_django_resolve_frame is not None and is_django_resolve_call(frame.f_back):
#we return to Django suspend mode and should not stop before django rendering frame
- info.pydev_step_stop = info.pydev_django_resolve_frame
+ stop_frame = info.pydev_step_stop = info.pydev_django_resolve_frame
info.pydev_django_resolve_frame = None
thread.additionalInfo.suspend_type = DJANGO_SUSPEND
- stop = info.pydev_step_stop is frame and event in ('line', 'return')
+ stop = stop_frame is frame and event in ('line', 'return')
- elif info.pydev_step_cmd == CMD_SMART_STEP_INTO:
+ elif step_cmd == CMD_SMART_STEP_INTO:
stop = False
if info.pydev_smart_step_stop is frame:
info.pydev_func_name = None
@@ -253,12 +468,12 @@ class PyDBFrame:
curr_func_name = ''
if curr_func_name == info.pydev_func_name:
- stop = True
+ stop = True
- elif info.pydev_step_cmd == CMD_STEP_RETURN:
- stop = event == 'return' and info.pydev_step_stop is frame
+ elif step_cmd == CMD_STEP_RETURN:
+ stop = event == 'return' and stop_frame is frame
- elif info.pydev_step_cmd == CMD_RUN_TO_LINE or info.pydev_step_cmd == CMD_SET_NEXT_STATEMENT:
+ elif step_cmd == CMD_RUN_TO_LINE or step_cmd == CMD_SET_NEXT_STATEMENT:
stop = False
if event == 'line' or event == 'exception':
@@ -286,13 +501,13 @@ class PyDBFrame:
stop = False
if django_stop:
- frame = suspend_django(self, mainDebugger, thread, frame)
+ frame = suspend_django(self, main_debugger, thread, frame)
if frame:
self.doWaitSuspend(thread, frame, event, arg)
elif stop:
#event is always == line or return at this point
if event == 'line':
- self.setSuspend(thread, info.pydev_step_cmd)
+ self.setSuspend(thread, step_cmd)
self.doWaitSuspend(thread, frame, event, arg)
else: #return event
back = frame.f_back
@@ -300,12 +515,18 @@ class PyDBFrame:
#When we get to the pydevd run function, the debugging has actually finished for the main thread
#(note that it can still go on for other threads, but for this one, we just make it finish)
#So, just setting it to None should be OK
- if basename(back.f_code.co_filename) == 'pydevd.py' and back.f_code.co_name == 'run':
+ base = basename(back.f_code.co_filename)
+ if base == 'pydevd.py' and back.f_code.co_name == 'run':
back = None
+ elif base == 'pydevd_traceproperty.py':
+ # We dont want to trace the return event of pydevd_traceproperty (custom property for debugging)
+ #if we're in a return, we want it to appear to the user in the previous frame!
+ return None
+
if back is not None:
#if we're in a return, we want it to appear to the user in the previous frame!
- self.setSuspend(thread, info.pydev_step_cmd)
+ self.setSuspend(thread, step_cmd)
self.doWaitSuspend(thread, back, event, arg)
else:
#in jython we may not have a back frame
@@ -320,7 +541,7 @@ class PyDBFrame:
#if we are quitting, let's stop the tracing
retVal = None
- if not mainDebugger.quitting:
+ if not main_debugger.quitting:
retVal = self.trace_dispatch
return retVal
@@ -339,24 +560,36 @@ class PyDBFrame:
sys.exc_clear() #don't keep the traceback
pass #ok, psyco not available
- def shouldStopOnDjangoBreak(self, frame, event, arg):
- mainDebugger, filename, info, thread = self._args
+ def should_stop_on_django_breakpoint(self, frame, event, arg):
+ mainDebugger = self._args[0]
+ thread = self._args[3]
flag = False
- filename = get_template_file_name(frame)
- pydev_log.debug("Django is rendering a template: %s\n" % filename)
- django_breakpoints_for_file = mainDebugger.django_breakpoints.get(filename)
+ template_frame_file = get_template_file_name(frame)
+
+ #pydev_log.debug("Django is rendering a template: %s\n" % template_frame_file)
+
+ django_breakpoints_for_file = mainDebugger.django_breakpoints.get(template_frame_file)
if django_breakpoints_for_file:
- pydev_log.debug("Breakpoints for that file: %s\n" % django_breakpoints_for_file)
- template_line = get_template_line(frame)
- pydev_log.debug("Tracing template line: %d\n" % template_line)
- if DictContains(django_breakpoints_for_file, template_line):
- django_breakpoint = django_breakpoints_for_file[template_line]
+ #pydev_log.debug("Breakpoints for that file: %s\n" % django_breakpoints_for_file)
+
+ template_frame_line = get_template_line(frame, template_frame_file)
+
+ #pydev_log.debug("Tracing template line: %d\n" % template_frame_line)
+
+ if DictContains(django_breakpoints_for_file, template_frame_line):
+ django_breakpoint = django_breakpoints_for_file[template_frame_line]
+
+ if django_breakpoint.is_triggered(template_frame_file, template_frame_line):
+
+ #pydev_log.debug("Breakpoint is triggered.\n")
- if django_breakpoint.is_triggered(frame):
- pydev_log.debug("Breakpoint is triggered.\n")
flag = True
- new_frame = DjangoTemplateFrame(frame)
+ new_frame = DjangoTemplateFrame(
+ frame,
+ template_frame_file=template_frame_file,
+ template_frame_line=template_frame_line,
+ )
if django_breakpoint.condition is not None:
try:
@@ -379,7 +612,7 @@ class PyDBFrame:
thread.additionalInfo.message = val
if flag:
frame = suspend_django(self, mainDebugger, thread, frame)
- return (flag, frame)
+ return flag, frame
def add_exception_to_frame(frame, exception_info):
frame.f_locals['__exception__'] = exception_info \ No newline at end of file
diff --git a/python/helpers/pydev/pydevd_io.py b/python/helpers/pydev/pydevd_io.py
index a83adc8de2b9..2e74154df667 100644
--- a/python/helpers/pydev/pydevd_io.py
+++ b/python/helpers/pydev/pydevd_io.py
@@ -24,10 +24,10 @@ class IORedirector:
r.flush()
def __getattr__(self, name):
- for r in self._redirectTo:
- if hasattr(r, name):
- return r.__getattribute__(name)
- raise AttributeError(name)
+ for r in self._redirectTo:
+ if hasattr(r, name):
+ return r.__getattribute__(name)
+ raise AttributeError(name)
class IOBuf:
'''This class works as a replacement for stdio and stderr.
diff --git a/python/helpers/pydev/pydevd_referrers.py b/python/helpers/pydev/pydevd_referrers.py
new file mode 100644
index 000000000000..66b1a0ef1df4
--- /dev/null
+++ b/python/helpers/pydev/pydevd_referrers.py
@@ -0,0 +1,238 @@
+from pydevd_constants import DictContains
+import sys
+import pydevd_vars
+from os.path import basename
+import traceback
+try:
+ from urllib import quote, quote_plus, unquote, unquote_plus
+except:
+ from urllib.parse import quote, quote_plus, unquote, unquote_plus #@Reimport @UnresolvedImport
+
+#===================================================================================================
+# print_var_node
+#===================================================================================================
+def print_var_node(xml_node, stream):
+ name = xml_node.getAttribute('name')
+ value = xml_node.getAttribute('value')
+ val_type = xml_node.getAttribute('type')
+
+ found_as = xml_node.getAttribute('found_as')
+ stream.write('Name: ')
+ stream.write(unquote_plus(name))
+ stream.write(', Value: ')
+ stream.write(unquote_plus(value))
+ stream.write(', Type: ')
+ stream.write(unquote_plus(val_type))
+ if found_as:
+ stream.write(', Found as: %s' % (unquote_plus(found_as),))
+ stream.write('\n')
+
+#===================================================================================================
+# print_referrers
+#===================================================================================================
+def print_referrers(obj, stream=None):
+ if stream is None:
+ stream = sys.stdout
+ result = get_referrer_info(obj)
+ from xml.dom.minidom import parseString
+ dom = parseString(result)
+
+ xml = dom.getElementsByTagName('xml')[0]
+ for node in xml.childNodes:
+ if node.nodeType == node.TEXT_NODE:
+ continue
+
+ if node.localName == 'for':
+ stream.write('Searching references for: ')
+ for child in node.childNodes:
+ if child.nodeType == node.TEXT_NODE:
+ continue
+ print_var_node(child, stream)
+
+ elif node.localName == 'var':
+ stream.write('Referrer found: ')
+ print_var_node(node, stream)
+
+ else:
+ sys.stderr.write('Unhandled node: %s\n' % (node,))
+
+ return result
+
+
+#===================================================================================================
+# get_referrer_info
+#===================================================================================================
+def get_referrer_info(searched_obj):
+ DEBUG = 0
+ if DEBUG:
+ sys.stderr.write('Getting referrers info.\n')
+ try:
+ try:
+ if searched_obj is None:
+ ret = ['<xml>\n']
+
+ ret.append('<for>\n')
+ ret.append(pydevd_vars.varToXML(
+ searched_obj,
+ 'Skipping getting referrers for None',
+ additionalInXml=' id="%s"' % (id(searched_obj),)))
+ ret.append('</for>\n')
+ ret.append('</xml>')
+ ret = ''.join(ret)
+ return ret
+
+ obj_id = id(searched_obj)
+
+ try:
+ if DEBUG:
+ sys.stderr.write('Getting referrers...\n')
+ import gc
+ referrers = gc.get_referrers(searched_obj)
+ except:
+ traceback.print_exc()
+ ret = ['<xml>\n']
+
+ ret.append('<for>\n')
+ ret.append(pydevd_vars.varToXML(
+ searched_obj,
+ 'Exception raised while trying to get_referrers.',
+ additionalInXml=' id="%s"' % (id(searched_obj),)))
+ ret.append('</for>\n')
+ ret.append('</xml>')
+ ret = ''.join(ret)
+ return ret
+
+ if DEBUG:
+ sys.stderr.write('Found %s referrers.\n' % (len(referrers),))
+
+ curr_frame = sys._getframe()
+ frame_type = type(curr_frame)
+
+ #Ignore this frame and any caller frame of this frame
+
+ ignore_frames = {} #Should be a set, but it's not available on all python versions.
+ while curr_frame is not None:
+ if basename(curr_frame.f_code.co_filename).startswith('pydev'):
+ ignore_frames[curr_frame] = 1
+ curr_frame = curr_frame.f_back
+
+
+ ret = ['<xml>\n']
+
+ ret.append('<for>\n')
+ if DEBUG:
+ sys.stderr.write('Searching Referrers of obj with id="%s"\n' % (obj_id,))
+
+ ret.append(pydevd_vars.varToXML(
+ searched_obj,
+ 'Referrers of obj with id="%s"' % (obj_id,)))
+ ret.append('</for>\n')
+
+ all_objects = None
+
+ for r in referrers:
+ try:
+ if DictContains(ignore_frames, r):
+ continue #Skip the references we may add ourselves
+ except:
+ pass #Ok: unhashable type checked...
+
+ if r is referrers:
+ continue
+
+ r_type = type(r)
+ r_id = str(id(r))
+
+ representation = str(r_type)
+
+ found_as = ''
+ if r_type == frame_type:
+ if DEBUG:
+ sys.stderr.write('Found frame referrer: %r\n' % (r,))
+ for key, val in r.f_locals.items():
+ if val is searched_obj:
+ found_as = key
+ break
+
+ elif r_type == dict:
+ if DEBUG:
+ sys.stderr.write('Found dict referrer: %r\n' % (r,))
+
+ # Try to check if it's a value in the dict (and under which key it was found)
+ for key, val in r.items():
+ if val is searched_obj:
+ found_as = key
+ if DEBUG:
+ sys.stderr.write(' Found as %r in dict\n' % (found_as,))
+ break
+
+ #Ok, there's one annoying thing: many times we find it in a dict from an instance,
+ #but with this we don't directly have the class, only the dict, so, to workaround that
+ #we iterate over all reachable objects ad check if one of those has the given dict.
+ if all_objects is None:
+ all_objects = gc.get_objects()
+
+ for x in all_objects:
+ try:
+ if getattr(x, '__dict__', None) is r:
+ r = x
+ r_type = type(x)
+ r_id = str(id(r))
+ representation = str(r_type)
+ break
+ except:
+ pass #Just ignore any error here (i.e.: ReferenceError, etc.)
+
+ elif r_type in (tuple, list):
+ if DEBUG:
+ sys.stderr.write('Found tuple referrer: %r\n' % (r,))
+
+ #Don't use enumerate() because not all Python versions have it.
+ i = 0
+ for x in r:
+ if x is searched_obj:
+ found_as = '%s[%s]' % (r_type.__name__, i)
+ if DEBUG:
+ sys.stderr.write(' Found as %s in tuple: \n' % (found_as,))
+ break
+ i += 1
+
+ if found_as:
+ found_as = ' found_as="%s"' % (pydevd_vars.makeValidXmlValue(found_as),)
+
+ ret.append(pydevd_vars.varToXML(
+ r,
+ representation,
+ additionalInXml=' id="%s"%s' % (r_id, found_as)))
+ finally:
+ if DEBUG:
+ sys.stderr.write('Done searching for references.\n')
+
+ #If we have any exceptions, don't keep dangling references from this frame to any of our objects.
+ all_objects = None
+ referrers = None
+ searched_obj = None
+ r = None
+ x = None
+ key = None
+ val = None
+ curr_frame = None
+ ignore_frames = None
+ except:
+ traceback.print_exc()
+ ret = ['<xml>\n']
+
+ ret.append('<for>\n')
+ ret.append(pydevd_vars.varToXML(
+ searched_obj,
+ 'Error getting referrers for:',
+ additionalInXml=' id="%s"' % (id(searched_obj),)))
+ ret.append('</for>\n')
+ ret.append('</xml>')
+ ret = ''.join(ret)
+ return ret
+
+ ret.append('</xml>')
+ ret = ''.join(ret)
+ return ret
+
diff --git a/python/helpers/pydev/pydevd_resolver.py b/python/helpers/pydev/pydevd_resolver.py
index 614549f74f37..3fe895c504a7 100644
--- a/python/helpers/pydev/pydevd_resolver.py
+++ b/python/helpers/pydev/pydevd_resolver.py
@@ -13,6 +13,7 @@ except:
setattr(__builtin__, 'False', 0)
import pydevd_constants
+from pydevd_constants import DictIterItems, xrange, izip
MAX_ITEMS_TO_HANDLE = 500
@@ -58,7 +59,7 @@ except:
class AbstractResolver:
'''
This class exists only for documentation purposes to explain how to create a resolver.
-
+
Some examples on how to resolve things:
- list: getDictionary could return a dict with index->item and use the index to resolve it later
- set: getDictionary could return a dict with id(object)->object and reiterate in that array to resolve it later
@@ -69,7 +70,7 @@ class AbstractResolver:
'''
In this method, we'll resolve some child item given the string representation of the item in the key
representing the previously asked dictionary.
-
+
@param var: this is the actual variable to be resolved.
@param attribute: this is the string representation of a key previously returned in getDictionary.
'''
@@ -78,7 +79,7 @@ class AbstractResolver:
def getDictionary(self, var):
'''
@param var: this is the variable that should have its children gotten.
-
+
@return: a dictionary where each pair key, value should be shown to the user as children items
in the variables view for the given var.
'''
@@ -128,12 +129,12 @@ class DefaultResolver:
declaredMethods = obj.getDeclaredMethods()
declaredFields = obj.getDeclaredFields()
- for i in range(len(declaredMethods)):
+ for i in xrange(len(declaredMethods)):
name = declaredMethods[i].getName()
ret[name] = declaredMethods[i].toString()
found.put(name, 1)
- for i in range(len(declaredFields)):
+ for i in xrange(len(declaredFields)):
name = declaredFields[i].getName()
found.put(name, 1)
#if declaredFields[i].isAccessible():
@@ -145,7 +146,7 @@ class DefaultResolver:
ret[name] = declaredFields[i].toString()
#this simple dir does not always get all the info, that's why we have the part before
- #(e.g.: if we do a dir on String, some methods that are from other interfaces such as
+ #(e.g.: if we do a dir on String, some methods that are from other interfaces such as
#charAt don't appear)
try:
d = dir(original)
@@ -169,8 +170,8 @@ class DefaultResolver:
names = var.__members__
d = {}
- #Be aware that the order in which the filters are applied attempts to
- #optimize the operation by removing as many items as possible in the
+ #Be aware that the order in which the filters are applied attempts to
+ #optimize the operation by removing as many items as possible in the
#first filters, leaving fewer items for later filters
if filterBuiltIn or filterFunction:
@@ -212,18 +213,18 @@ class DefaultResolver:
class DictResolver:
def resolve(self, dict, key):
- if key == '__len__':
+ if key in ('__len__', TOO_LARGE_ATTR):
return None
if '(' not in key:
#we have to treat that because the dict resolver is also used to directly resolve the global and local
- #scopes (which already have the items directly)
+ #scopes (which already have the items directly)
return dict[key]
#ok, we have to iterate over the items to find the one that matches the id, because that's the only way
#to actually find the reference from the string we have before.
expected_id = int(key.split('(')[-1][:-1])
- for key, val in dict.items():
+ for key, val in DictIterItems(dict):
if id(key) == expected_id:
return val
@@ -241,10 +242,15 @@ class DictResolver:
def getDictionary(self, dict):
ret = {}
- for key, val in dict.items():
+ i = 0
+ for key, val in DictIterItems(dict):
+ i += 1
#we need to add the id because otherwise we cannot find the real object to get its contents later on.
key = '%s (%s)' % (self.keyStr(key), id(key))
ret[key] = val
+ if i > MAX_ITEMS_TO_HANDLE:
+ ret[TOO_LARGE_ATTR] = TOO_LARGE_MSG
+ break
ret['__len__'] = len(dict)
return ret
@@ -261,7 +267,7 @@ class TupleResolver: #to enumerate tuples and lists
@param var: that's the original attribute
@param attribute: that's the key passed in the dict (as a string)
'''
- if attribute == '__len__' or attribute == TOO_LARGE_ATTR:
+ if attribute in ('__len__', TOO_LARGE_ATTR):
return None
return var[int(attribute)]
@@ -270,12 +276,12 @@ class TupleResolver: #to enumerate tuples and lists
# modified 'cause jython does not have enumerate support
l = len(var)
d = {}
-
+
if l < MAX_ITEMS_TO_HANDLE:
format = '%0' + str(int(len(str(l)))) + 'd'
-
-
- for i, item in zip(range(l), var):
+
+
+ for i, item in izip(xrange(l), var):
d[ format % i ] = item
else:
d[TOO_LARGE_ATTR] = TOO_LARGE_MSG
@@ -293,7 +299,7 @@ class SetResolver:
'''
def resolve(self, var, attribute):
- if attribute == '__len__':
+ if attribute in ('__len__', TOO_LARGE_ATTR):
return None
attribute = int(attribute)
@@ -305,8 +311,16 @@ class SetResolver:
def getDictionary(self, var):
d = {}
+ i = 0
for item in var:
- d[ id(item) ] = item
+ i+= 1
+ d[id(item)] = item
+
+ if i > MAX_ITEMS_TO_HANDLE:
+ d[TOO_LARGE_ATTR] = TOO_LARGE_MSG
+ break
+
+
d['__len__'] = len(var)
return d
@@ -325,7 +339,7 @@ class InstanceResolver:
ret = {}
declaredFields = obj.__class__.getDeclaredFields()
- for i in range(len(declaredFields)):
+ for i in xrange(len(declaredFields)):
name = declaredFields[i].getName()
try:
declaredFields[i].setAccessible(True)
@@ -352,7 +366,7 @@ class JyArrayResolver:
def getDictionary(self, obj):
ret = {}
- for i in range(len(obj)):
+ for i in xrange(len(obj)):
ret[ i ] = obj[i]
ret['__len__'] = len(obj)
diff --git a/python/helpers/pydev/pydevd_save_locals.py b/python/helpers/pydev/pydevd_save_locals.py
index 2808081a5866..15a7382968bf 100644
--- a/python/helpers/pydev/pydevd_save_locals.py
+++ b/python/helpers/pydev/pydevd_save_locals.py
@@ -2,6 +2,7 @@
Utility for saving locals.
"""
import sys
+import pydevd_vars
def is_save_locals_available():
try:
@@ -12,7 +13,7 @@ def is_save_locals_available():
except:
pass
-
+
try:
import ctypes
except:
@@ -22,7 +23,7 @@ def is_save_locals_available():
func = ctypes.pythonapi.PyFrame_LocalsToFast
except:
return False
-
+
return True
def save_locals(frame):
@@ -32,6 +33,10 @@ def save_locals(frame):
Note: the 'save_locals' branch had a different approach wrapping the frame (much more code, but it gives ideas
on how to save things partially, not the 'whole' locals).
"""
+ if not isinstance(frame, pydevd_vars.frame_type):
+ # Fix exception when changing Django variable (receiving DjangoTemplateFrame)
+ return
+
try:
if '__pypy__' in sys.builtin_module_names:
import __pypy__
@@ -40,7 +45,7 @@ def save_locals(frame):
return
except:
pass
-
+
try:
import ctypes
diff --git a/python/helpers/pydev/pydevd_signature.py b/python/helpers/pydev/pydevd_signature.py
index e11bb5dd446b..03dc0eb9c98b 100644
--- a/python/helpers/pydev/pydevd_signature.py
+++ b/python/helpers/pydev/pydevd_signature.py
@@ -6,6 +6,7 @@ trace._warn = lambda *args: None # workaround for http://bugs.python.org/issue
import gc
from pydevd_comm import CMD_SIGNATURE_CALL_TRACE, NetCommand
import pydevd_vars
+from pydevd_constants import xrange
class Signature(object):
def __init__(self, file, name):
@@ -43,7 +44,7 @@ class SignatureFactory(object):
locals = frame.f_locals
filename, modulename, funcname = self.file_module_function_of(frame)
res = Signature(filename, funcname)
- for i in range(0, code.co_argcount):
+ for i in xrange(0, code.co_argcount):
name = code.co_varnames[i]
tp = type(locals[name])
class_name = tp.__name__
@@ -123,9 +124,8 @@ def create_signature_message(signature):
return NetCommand(CMD_SIGNATURE_CALL_TRACE, 0, cmdText)
def sendSignatureCallTrace(dbg, frame, filename):
- if dbg.signature_factory:
- if dbg.signature_factory.is_in_scope(filename):
- dbg.writer.addCommand(create_signature_message(dbg.signature_factory.create_signature(frame)))
+ if dbg.signature_factory.is_in_scope(filename):
+ dbg.writer.addCommand(create_signature_message(dbg.signature_factory.create_signature(frame)))
diff --git a/python/helpers/pydev/pydevd_stackless.py b/python/helpers/pydev/pydevd_stackless.py
index bd3b306dad63..c2fd508e05d4 100644
--- a/python/helpers/pydev/pydevd_stackless.py
+++ b/python/helpers/pydev/pydevd_stackless.py
@@ -7,6 +7,7 @@ from pydevd_comm import GetGlobalDebugger
import weakref
from pydevd_file_utils import GetFilenameAndBase
from pydevd import DONT_TRACE
+from pydevd_constants import DictItems
# Used so that we don't loose the id (because we'll remove when it's not alive and would generate a new id for the
@@ -195,7 +196,7 @@ def _schedule_callback(prev, next):
register_tasklet_info(prev)
try:
- for tasklet_ref, tasklet_info in list(_weak_tasklet_registered_to_info.items()): # Make sure it's a copy!
+ for tasklet_ref, tasklet_info in DictItems(_weak_tasklet_registered_to_info): # Make sure it's a copy!
tasklet = tasklet_ref()
if tasklet is None or not tasklet.alive:
# Garbage-collected already!
@@ -269,7 +270,7 @@ if not hasattr(stackless.tasklet, "trace_function"):
register_tasklet_info(prev)
try:
- for tasklet_ref, tasklet_info in list(_weak_tasklet_registered_to_info.items()): # Make sure it's a copy!
+ for tasklet_ref, tasklet_info in DictItems(_weak_tasklet_registered_to_info): # Make sure it's a copy!
tasklet = tasklet_ref()
if tasklet is None or not tasklet.alive:
# Garbage-collected already!
@@ -388,7 +389,7 @@ def patch_stackless():
_application_set_schedule_callback = callable
return old
- def get_schedule_callback(callable):
+ def get_schedule_callback():
global _application_set_schedule_callback
return _application_set_schedule_callback
diff --git a/python/helpers/pydev/pydevd_traceproperty.py b/python/helpers/pydev/pydevd_traceproperty.py
new file mode 100644
index 000000000000..d8e7e5f9280f
--- /dev/null
+++ b/python/helpers/pydev/pydevd_traceproperty.py
@@ -0,0 +1,108 @@
+'''For debug purpose we are replacing actual builtin property by the debug property
+'''
+from pydevd_comm import GetGlobalDebugger
+from pydevd_constants import * #@UnusedWildImport
+import pydevd_tracing
+
+#=======================================================================================================================
+# replace_builtin_property
+#=======================================================================================================================
+def replace_builtin_property(new_property=None):
+ if new_property is None:
+ new_property = DebugProperty
+ original = property
+ if not IS_PY3K:
+ try:
+ import __builtin__
+ __builtin__.__dict__['property'] = new_property
+ except:
+ if DebugInfoHolder.DEBUG_TRACE_LEVEL:
+ import traceback;traceback.print_exc() #@Reimport
+ else:
+ try:
+ import builtins #Python 3.0 does not have the __builtin__ module @UnresolvedImport
+ builtins.__dict__['property'] = new_property
+ except:
+ if DebugInfoHolder.DEBUG_TRACE_LEVEL:
+ import traceback;traceback.print_exc() #@Reimport
+ return original
+
+
+#=======================================================================================================================
+# DebugProperty
+#=======================================================================================================================
+class DebugProperty(object):
+ """A custom property which allows python property to get
+ controlled by the debugger and selectively disable/re-enable
+ the tracing.
+ """
+
+
+ def __init__(self, fget=None, fset=None, fdel=None, doc=None):
+ self.fget = fget
+ self.fset = fset
+ self.fdel = fdel
+ self.__doc__ = doc
+
+
+ def __get__(self, obj, objtype=None):
+ if obj is None:
+ return self
+ global_debugger = GetGlobalDebugger()
+ try:
+ if global_debugger is not None and global_debugger.disable_property_getter_trace:
+ pydevd_tracing.SetTrace(None)
+ if self.fget is None:
+ raise AttributeError("unreadable attribute")
+ return self.fget(obj)
+ finally:
+ if global_debugger is not None:
+ pydevd_tracing.SetTrace(global_debugger.trace_dispatch)
+
+
+ def __set__(self, obj, value):
+ global_debugger = GetGlobalDebugger()
+ try:
+ if global_debugger is not None and global_debugger.disable_property_setter_trace:
+ pydevd_tracing.SetTrace(None)
+ if self.fset is None:
+ raise AttributeError("can't set attribute")
+ self.fset(obj, value)
+ finally:
+ if global_debugger is not None:
+ pydevd_tracing.SetTrace(global_debugger.trace_dispatch)
+
+
+ def __delete__(self, obj):
+ global_debugger = GetGlobalDebugger()
+ try:
+ if global_debugger is not None and global_debugger.disable_property_deleter_trace:
+ pydevd_tracing.SetTrace(None)
+ if self.fdel is None:
+ raise AttributeError("can't delete attribute")
+ self.fdel(obj)
+ finally:
+ if global_debugger is not None:
+ pydevd_tracing.SetTrace(global_debugger.trace_dispatch)
+
+
+ def getter(self, fget):
+ """Overriding getter decorator for the property
+ """
+ self.fget = fget
+ return self
+
+
+ def setter(self, fset):
+ """Overriding setter decorator for the property
+ """
+ self.fset = fset
+ return self
+
+
+ def deleter(self, fdel):
+ """Overriding deleter decorator for the property
+ """
+ self.fdel = fdel
+ return self
+
diff --git a/python/helpers/pydev/pydevd_tracing.py b/python/helpers/pydev/pydevd_tracing.py
index 1a5a833f6bd0..7bc1ba5c2c23 100644
--- a/python/helpers/pydev/pydevd_tracing.py
+++ b/python/helpers/pydev/pydevd_tracing.py
@@ -65,7 +65,7 @@ def _InternalSetTrace(tracing_func):
sys.stderr.flush()
if TracingFunctionHolder._original_tracing:
- TracingFunctionHolder._original_tracing(tracing_func)
+ TracingFunctionHolder._original_tracing(tracing_func)
def SetTrace(tracing_func):
if TracingFunctionHolder._original_tracing is None:
diff --git a/python/helpers/pydev/pydevd_vars.py b/python/helpers/pydev/pydevd_vars.py
index de8c2415fcae..0cc45f73710f 100644
--- a/python/helpers/pydev/pydevd_vars.py
+++ b/python/helpers/pydev/pydevd_vars.py
@@ -3,7 +3,6 @@
"""
import pickle
from django_frame import DjangoTemplateFrame
-from pydevd_constants import * #@UnusedWildImport
from types import * #@UnusedWildImport
from pydevd_custom_frames import getCustomFrame
@@ -19,16 +18,15 @@ if USE_LIB_COPY:
import _pydev_threading as threading
else:
import threading
-import pydevd_resolver
import traceback
import pydevd_save_locals
-from pydev_imports import Exec, quote, execfile
+from pydev_imports import Exec, execfile
try:
import types
frame_type = types.FrameType
except:
- frame_type = None
+ frame_type = type(sys._getframe())
#-------------------------------------------------------------------------- defining true and false for earlier versions
@@ -37,25 +35,14 @@ try:
__setFalse = False
except:
import __builtin__
-
setattr(__builtin__, 'True', 1)
setattr(__builtin__, 'False', 0)
#------------------------------------------------------------------------------------------------------ class for errors
-class VariableError(RuntimeError): pass
-
-class FrameNotFoundError(RuntimeError): pass
-
-
-if USE_PSYCO_OPTIMIZATION:
- try:
- import psyco
+class VariableError(RuntimeError):pass
- varToXML = psyco.proxy(varToXML)
- except ImportError:
- if hasattr(sys, 'exc_clear'): #jython does not have it
- sys.exc_clear() #don't keep the traceback -- clients don't want to see it
+class FrameNotFoundError(RuntimeError):pass
def iterFrames(initialFrame):
'''NO-YIELD VERSION: Iterates through all the frames starting at the specified frame (which will be the first returned item)'''
@@ -166,50 +153,127 @@ def findFrame(thread_id, frame_id):
traceback.print_exc()
return None
-def resolveCompoundVariable(thread_id, frame_id, scope, attrs):
- """ returns the value of the compound variable as a dictionary"""
+def getVariable(thread_id, frame_id, scope, attrs):
+ """
+ returns the value of a variable
+
+ :scope: can be BY_ID, EXPRESSION, GLOBAL, LOCAL, FRAME
+
+ BY_ID means we'll traverse the list of all objects alive to get the object.
+
+ :attrs: after reaching the proper scope, we have to get the attributes until we find
+ the proper location (i.e.: obj\tattr1\tattr2)
+
+ :note: when BY_ID is used, the frame_id is considered the id of the object to find and
+ not the frame (as we don't care about the frame in this case).
+ """
+ if scope == 'BY_ID':
+ if thread_id != GetThreadId(threading.currentThread()) :
+ raise VariableError("getVariable: must execute on same thread")
+
+ try:
+ import gc
+ objects = gc.get_objects()
+ except:
+ pass #Not all python variants have it.
+ else:
+ frame_id = int(frame_id)
+ for var in objects:
+ if id(var) == frame_id:
+ if attrs is not None:
+ attrList = attrs.split('\t')
+ for k in attrList:
+ _type, _typeName, resolver = getType(var)
+ var = resolver.resolve(var, k)
+
+ return var
+
+ #If it didn't return previously, we coudn't find it by id (i.e.: alrceady garbage collected).
+ sys.stderr.write('Unable to find object with id: %s\n' % (frame_id,))
+ return None
+
frame = findFrame(thread_id, frame_id)
if frame is None:
return {}
- attrList = attrs.split('\t')
-
- if scope == "GLOBAL":
- var = frame.f_globals
- del attrList[0] # globals are special, and they get a single dummy unused attribute
+ if attrs is not None:
+ attrList = attrs.split('\t')
else:
- var = frame.f_locals
- type, _typeName, resolver = getType(var)
- try:
- resolver.resolve(var, attrList[0])
- except:
+ attrList = []
+
+ if scope == 'EXPRESSION':
+ for count in xrange(len(attrList)):
+ if count == 0:
+ # An Expression can be in any scope (globals/locals), therefore it needs to evaluated as an expression
+ var = evaluateExpression(thread_id, frame_id, attrList[count], False)
+ else:
+ _type, _typeName, resolver = getType(var)
+ var = resolver.resolve(var, attrList[count])
+ else:
+ if scope == "GLOBAL":
var = frame.f_globals
+ del attrList[0] # globals are special, and they get a single dummy unused attribute
+ else:
+ var = frame.f_locals
+
+ for k in attrList:
+ _type, _typeName, resolver = getType(var)
+ var = resolver.resolve(var, k)
+
+ return var
- for k in attrList:
- type, _typeName, resolver = getType(var)
- var = resolver.resolve(var, k)
+
+def resolveCompoundVariable(thread_id, frame_id, scope, attrs):
+ """ returns the value of the compound variable as a dictionary"""
+
+ var = getVariable(thread_id, frame_id, scope, attrs)
try:
- type, _typeName, resolver = getType(var)
+ _type, _typeName, resolver = getType(var)
return resolver.getDictionary(var)
except:
+ sys.stderr.write('Error evaluating: thread_id: %s\nframe_id: %s\nscope: %s\nattrs: %s\n' % (
+ thread_id, frame_id, scope, attrs,))
traceback.print_exc()
-
-
+
+
def resolveVar(var, attrs):
attrList = attrs.split('\t')
-
+
for k in attrList:
type, _typeName, resolver = getType(var)
-
+
var = resolver.resolve(var, k)
-
+
try:
type, _typeName, resolver = getType(var)
return resolver.getDictionary(var)
except:
traceback.print_exc()
-
+
+
+def customOperation(thread_id, frame_id, scope, attrs, style, code_or_file, operation_fn_name):
+ """
+ We'll execute the code_or_file and then search in the namespace the operation_fn_name to execute with the given var.
+
+ code_or_file: either some code (i.e.: from pprint import pprint) or a file to be executed.
+ operation_fn_name: the name of the operation to execute after the exec (i.e.: pprint)
+ """
+ expressionValue = getVariable(thread_id, frame_id, scope, attrs)
+
+ try:
+ namespace = {'__name__': '<customOperation>'}
+ if style == "EXECFILE":
+ namespace['__file__'] = code_or_file
+ execfile(code_or_file, namespace, namespace)
+ else: # style == EXEC
+ namespace['__file__'] = '<customOperationCode>'
+ Exec(code_or_file, namespace, namespace)
+
+ return str(namespace[operation_fn_name](expressionValue))
+ except:
+ traceback.print_exc()
+
def evaluateExpression(thread_id, frame_id, expression, doExec):
'''returns the result of the evaluated expression
@@ -230,6 +294,7 @@ def evaluateExpression(thread_id, frame_id, expression, doExec):
updated_globals.update(frame.f_locals) #locals later because it has precedence over the actual globals
try:
+
if doExec:
try:
#try to make it an eval (if it is an eval we can print it, otherwise we'll exec it and
@@ -240,7 +305,7 @@ def evaluateExpression(thread_id, frame_id, expression, doExec):
pydevd_save_locals.save_locals(frame)
else:
result = eval(compiled, updated_globals, frame.f_locals)
- if result is not None: #Only print if it's not None (as python does)
+ if result is not None: #Only print if it's not None (as python does)
sys.stdout.write('%s\n' % (result,))
return
@@ -251,7 +316,6 @@ def evaluateExpression(thread_id, frame_id, expression, doExec):
except Exception:
s = StringIO()
traceback.print_exc(file=s)
-
result = s.getvalue()
try:
@@ -265,6 +329,22 @@ def evaluateExpression(thread_id, frame_id, expression, doExec):
result = ExceptionOnEvaluate(result)
+ # Ok, we have the initial error message, but let's see if we're dealing with a name mangling error...
+ try:
+ if '__' in expression:
+ # Try to handle '__' name mangling...
+ split = expression.split('.')
+ curr = frame.f_locals.get(split[0])
+ for entry in split[1:]:
+ if entry.startswith('__') and not hasattr(curr, entry):
+ entry = '_%s%s' % (curr.__class__.__name__, entry)
+ curr = getattr(curr, entry)
+
+ result = curr
+ except:
+ pass
+
+
return result
finally:
#Should not be kept alive if an exception happens and this frame is kept in the stack.
@@ -273,22 +353,18 @@ def evaluateExpression(thread_id, frame_id, expression, doExec):
def changeAttrExpression(thread_id, frame_id, attr, expression):
'''Changes some attribute in a given frame.
- @note: it will not (currently) work if we're not in the topmost frame (that's a python
- deficiency -- and it appears that there is no way of making it currently work --
- will probably need some change to the python internals)
'''
frame = findFrame(thread_id, frame_id)
if frame is None:
return
- if isinstance(frame, DjangoTemplateFrame):
- result = eval(expression, frame.f_globals, frame.f_locals)
- frame.changeVariable(attr, result)
-
try:
expression = expression.replace('@LINE@', '\n')
-
+ if isinstance(frame, DjangoTemplateFrame):
+ result = eval(expression, frame.f_globals, frame.f_locals)
+ frame.changeVariable(attr, result)
+ return
if attr[:7] == "Globals":
attr = attr[8:]
diff --git a/python/helpers/pydev/pydevd_xml.py b/python/helpers/pydev/pydevd_xml.py
index ac3f71cd9566..52bb186bc58e 100644
--- a/python/helpers/pydev/pydevd_xml.py
+++ b/python/helpers/pydev/pydevd_xml.py
@@ -1,6 +1,7 @@
import pydev_log
import traceback
import pydevd_resolver
+import sys
from pydevd_constants import * #@UnusedWildImport
from pydev_imports import quote
@@ -146,9 +147,9 @@ def frameVarsToXML(frame_f_locals):
pydev_log.error("Unexpected error, recovered safely.\n")
return xml
-
-
-def varToXML(val, name, doTrim=True):
+
+
+def varToXML(val, name, doTrim=True, additionalInXml=''):
""" single variable or dictionary to xml representation """
is_exception_on_eval = isinstance(val, ExceptionOnEvaluate)
@@ -162,19 +163,22 @@ def varToXML(val, name, doTrim=True):
try:
if hasattr(v, '__class__'):
- try:
- cName = str(v.__class__)
- if cName.find('.') != -1:
- cName = cName.split('.')[-1]
-
- elif cName.find("'") != -1: #does not have '.' (could be something like <type 'int'>)
- cName = cName[cName.index("'") + 1:]
-
- if cName.endswith("'>"):
- cName = cName[:-2]
- except:
- cName = str(v.__class__)
- value = '%s: %s' % (cName, v)
+ if v.__class__ == frame_type:
+ value = pydevd_resolver.frameResolver.getFrameName(v)
+ else:
+ try:
+ cName = str(v.__class__)
+ if cName.find('.') != -1:
+ cName = cName.split('.')[-1]
+
+ elif cName.find("'") != -1: #does not have '.' (could be something like <type 'int'>)
+ cName = cName[cName.index("'") + 1:]
+
+ if cName.endswith("'>"):
+ cName = cName[:-2]
+ except:
+ cName = str(v.__class__)
+ value = '%s: %s' % (cName, v)
else:
value = str(v)
except:
@@ -218,4 +222,13 @@ def varToXML(val, name, doTrim=True):
else:
xmlCont = ''
- return ''.join((xml, xmlValue, xmlCont, ' />\n'))
+ return ''.join((xml, xmlValue, xmlCont, additionalInXml, ' />\n'))
+
+if USE_PSYCO_OPTIMIZATION:
+ try:
+ import psyco
+
+ varToXML = psyco.proxy(varToXML)
+ except ImportError:
+ if hasattr(sys, 'exc_clear'): #jython does not have it
+ sys.exc_clear() #don't keep the traceback -- clients don't want to see it
diff --git a/python/helpers/pydev/runfiles.py b/python/helpers/pydev/runfiles.py
index 4a25469c1fec..67c88be4fe7c 100644
--- a/python/helpers/pydev/runfiles.py
+++ b/python/helpers/pydev/runfiles.py
@@ -1,530 +1,249 @@
-import fnmatch
-import os.path
-import re
-import sys
-import unittest
+import os
+def main():
+ import sys
+ #Separate the nose params and the pydev params.
+ pydev_params = []
+ other_test_framework_params = []
+ found_other_test_framework_param = None
+ NOSE_PARAMS = '--nose-params'
+ PY_TEST_PARAMS = '--py-test-params'
-try:
- __setFalse = False
-except:
- import __builtin__
- setattr(__builtin__, 'True', 1)
- setattr(__builtin__, 'False', 0)
+ for arg in sys.argv[1:]:
+ if not found_other_test_framework_param and arg != NOSE_PARAMS and arg != PY_TEST_PARAMS:
+ pydev_params.append(arg)
+ else:
+ if not found_other_test_framework_param:
+ found_other_test_framework_param = arg
+ else:
+ other_test_framework_params.append(arg)
+ #Here we'll run either with nose or with the pydev_runfiles.
+ import pydev_runfiles
+ import pydev_runfiles_xml_rpc
+ import pydevd_constants
+ from pydevd_file_utils import _NormFile
+
+ DEBUG = 0
+ if DEBUG:
+ sys.stdout.write('Received parameters: %s\n' % (sys.argv,))
+ sys.stdout.write('Params for pydev: %s\n' % (pydev_params,))
+ if found_other_test_framework_param:
+ sys.stdout.write('Params for test framework: %s, %s\n' % (found_other_test_framework_param, other_test_framework_params))
-#=======================================================================================================================
-# Jython?
-#=======================================================================================================================
-try:
- import org.python.core.PyDictionary #@UnresolvedImport @UnusedImport -- just to check if it could be valid
- def DictContains(d, key):
- return d.has_key(key)
-except:
try:
- #Py3k does not have has_key anymore, and older versions don't have __contains__
- DictContains = dict.__contains__
+ configuration = pydev_runfiles.parse_cmdline([sys.argv[0]] + pydev_params)
except:
- DictContains = dict.has_key
-
-try:
- xrange
-except:
- #Python 3k does not have it
- xrange = range
-
-try:
- enumerate
-except:
- def enumerate(lst):
- ret = []
- i=0
- for element in lst:
- ret.append((i, element))
- i+=1
- return ret
-
-
-
-#=======================================================================================================================
-# getopt code copied since gnu_getopt is not available on jython 2.1
-#=======================================================================================================================
-class GetoptError(Exception):
- opt = ''
- msg = ''
- def __init__(self, msg, opt=''):
- self.msg = msg
- self.opt = opt
- Exception.__init__(self, msg, opt)
-
- def __str__(self):
- return self.msg
-
-
-def gnu_getopt(args, shortopts, longopts=[]):
- """getopt(args, options[, long_options]) -> opts, args
-
- This function works like getopt(), except that GNU style scanning
- mode is used by default. This means that option and non-option
- arguments may be intermixed. The getopt() function stops
- processing options as soon as a non-option argument is
- encountered.
-
- If the first character of the option string is `+', or if the
- environment variable POSIXLY_CORRECT is set, then option
- processing stops as soon as a non-option argument is encountered.
- """
-
- opts = []
- prog_args = []
- if isinstance(longopts, ''.__class__):
- longopts = [longopts]
- else:
- longopts = list(longopts)
-
- # Allow options after non-option arguments?
- if shortopts.startswith('+'):
- shortopts = shortopts[1:]
- all_options_first = True
- elif os.environ.get("POSIXLY_CORRECT"):
- all_options_first = True
- else:
- all_options_first = False
-
- while args:
- if args[0] == '--':
- prog_args += args[1:]
- break
-
- if args[0][:2] == '--':
- opts, args = do_longs(opts, args[0][2:], longopts, args[1:])
- elif args[0][:1] == '-':
- opts, args = do_shorts(opts, args[0][1:], shortopts, args[1:])
- else:
- if all_options_first:
- prog_args += args
- break
- else:
- prog_args.append(args[0])
- args = args[1:]
-
- return opts, prog_args
+ sys.stderr.write('Command line received: %s\n' % (sys.argv,))
+ raise
+ pydev_runfiles_xml_rpc.InitializeServer(configuration.port) #Note that if the port is None, a Null server will be initialized.
-def do_longs(opts, opt, longopts, args):
+ NOSE_FRAMEWORK = 1
+ PY_TEST_FRAMEWORK = 2
try:
- i = opt.index('=')
- except ValueError:
- optarg = None
- else:
- opt, optarg = opt[:i], opt[i + 1:]
-
- has_arg, opt = long_has_args(opt, longopts)
- if has_arg:
- if optarg is None:
- if not args:
- raise GetoptError('option --%s requires argument' % opt, opt)
- optarg, args = args[0], args[1:]
- elif optarg:
- raise GetoptError('option --%s must not have an argument' % opt, opt)
- opts.append(('--' + opt, optarg or ''))
- return opts, args
-
-# Return:
-# has_arg?
-# full option name
-def long_has_args(opt, longopts):
- possibilities = [o for o in longopts if o.startswith(opt)]
- if not possibilities:
- raise GetoptError('option --%s not recognized' % opt, opt)
- # Is there an exact match?
- if opt in possibilities:
- return False, opt
- elif opt + '=' in possibilities:
- return True, opt
- # No exact match, so better be unique.
- if len(possibilities) > 1:
- # XXX since possibilities contains all valid continuations, might be
- # nice to work them into the error msg
- raise GetoptError('option --%s not a unique prefix' % opt, opt)
- assert len(possibilities) == 1
- unique_match = possibilities[0]
- has_arg = unique_match.endswith('=')
- if has_arg:
- unique_match = unique_match[:-1]
- return has_arg, unique_match
-
-def do_shorts(opts, optstring, shortopts, args):
- while optstring != '':
- opt, optstring = optstring[0], optstring[1:]
- if short_has_arg(opt, shortopts):
- if optstring == '':
- if not args:
- raise GetoptError('option -%s requires argument' % opt,
- opt)
- optstring, args = args[0], args[1:]
- optarg, optstring = optstring, ''
- else:
- optarg = ''
- opts.append(('-' + opt, optarg))
- return opts, args
+ if found_other_test_framework_param:
+ test_framework = 0 #Default (pydev)
+ if found_other_test_framework_param == NOSE_PARAMS:
+ import nose
+ test_framework = NOSE_FRAMEWORK
-def short_has_arg(opt, shortopts):
- for i in range(len(shortopts)):
- if opt == shortopts[i] != ':':
- return shortopts.startswith(':', i + 1)
- raise GetoptError('option -%s not recognized' % opt, opt)
-
-
-#=======================================================================================================================
-# End getopt code
-#=======================================================================================================================
+ elif found_other_test_framework_param == PY_TEST_PARAMS:
+ import pytest
+ test_framework = PY_TEST_FRAMEWORK
+ else:
+ raise ImportError()
+ else:
+ raise ImportError()
+ except ImportError:
+ if found_other_test_framework_param:
+ sys.stderr.write('Warning: Could not import the test runner: %s. Running with the default pydev unittest runner instead.\n' % (
+ found_other_test_framework_param,))
+ test_framework = 0
+ #Clear any exception that may be there so that clients don't see it.
+ #See: https://sourceforge.net/tracker/?func=detail&aid=3408057&group_id=85796&atid=577329
+ if hasattr(sys, 'exc_clear'):
+ sys.exc_clear()
+ if test_framework == 0:
+ pydev_runfiles.main(configuration)
+ else:
+ #We'll convert the parameters to what nose or py.test expects.
+ #The supported parameters are:
+ #runfiles.py --config-file|-t|--tests <Test.test1,Test2> dirs|files --nose-params xxx yyy zzz
+ #(all after --nose-params should be passed directly to nose)
+ #In java:
+ #--tests = Constants.ATTR_UNITTEST_TESTS
+ #--config-file = Constants.ATTR_UNITTEST_CONFIGURATION_FILE
-#=======================================================================================================================
-# parse_cmdline
-#=======================================================================================================================
-def parse_cmdline():
- """ parses command line and returns test directories, verbosity, test filter and test suites
- usage:
- runfiles.py -v|--verbosity <level> -f|--filter <regex> -t|--tests <Test.test1,Test2> dirs|files
- """
- verbosity = 2
- test_filter = None
- tests = None
- optlist, dirs = gnu_getopt(sys.argv[1:], "v:f:t:", ["verbosity=", "filter=", "tests="])
- for opt, value in optlist:
- if opt in ("-v", "--verbosity"):
- verbosity = value
+ #The only thing actually handled here are the tests that we want to run, which we'll
+ #handle and pass as what the test framework expects.
- elif opt in ("-f", "--filter"):
- test_filter = value.split(',')
+ py_test_accept_filter = {}
+ files_to_tests = configuration.files_to_tests
- elif opt in ("-t", "--tests"):
- tests = value.split(',')
+ if files_to_tests:
+ #Handling through the file contents (file where each line is a test)
+ files_or_dirs = []
+ for file, tests in files_to_tests.items():
+ if test_framework == NOSE_FRAMEWORK:
+ for test in tests:
+ files_or_dirs.append(file + ':' + test)
- if type([]) != type(dirs):
- dirs = [dirs]
+ elif test_framework == PY_TEST_FRAMEWORK:
+ file = _NormFile(file)
+ py_test_accept_filter[file] = tests
+ files_or_dirs.append(file)
- ret_dirs = []
- for d in dirs:
- if '|' in d:
- #paths may come from the ide separated by |
- ret_dirs.extend(d.split('|'))
- else:
- ret_dirs.append(d)
-
- return ret_dirs, int(verbosity), test_filter, tests
-
-
-#=======================================================================================================================
-# PydevTestRunner
-#=======================================================================================================================
-class PydevTestRunner:
- """ finds and runs a file or directory of files as a unit test """
-
- __py_extensions = ["*.py", "*.pyw"]
- __exclude_files = ["__init__.*"]
-
- def __init__(self, test_dir, test_filter=None, verbosity=2, tests=None):
- self.test_dir = test_dir
- self.__adjust_path()
- self.test_filter = self.__setup_test_filter(test_filter)
- self.verbosity = verbosity
- self.tests = tests
-
-
- def __adjust_path(self):
- """ add the current file or directory to the python path """
- path_to_append = None
- for n in xrange(len(self.test_dir)):
- dir_name = self.__unixify(self.test_dir[n])
- if os.path.isdir(dir_name):
- if not dir_name.endswith("/"):
- self.test_dir[n] = dir_name + "/"
- path_to_append = os.path.normpath(dir_name)
- elif os.path.isfile(dir_name):
- path_to_append = os.path.dirname(dir_name)
- else:
- msg = ("unknown type. \n%s\nshould be file or a directory.\n" % (dir_name))
- raise RuntimeError(msg)
- if path_to_append is not None:
- #Add it as the last one (so, first things are resolved against the default dirs and
- #if none resolves, then we try a relative import).
- sys.path.append(path_to_append)
- return
-
- def __setup_test_filter(self, test_filter):
- """ turn a filter string into a list of filter regexes """
- if test_filter is None or len(test_filter) == 0:
- return None
- return [re.compile("test%s" % f) for f in test_filter]
-
- def __is_valid_py_file(self, fname):
- """ tests that a particular file contains the proper file extension
- and is not in the list of files to exclude """
- is_valid_fname = 0
- for invalid_fname in self.__class__.__exclude_files:
- is_valid_fname += int(not fnmatch.fnmatch(fname, invalid_fname))
- if_valid_ext = 0
- for ext in self.__class__.__py_extensions:
- if_valid_ext += int(fnmatch.fnmatch(fname, ext))
- return is_valid_fname > 0 and if_valid_ext > 0
-
- def __unixify(self, s):
- """ stupid windows. converts the backslash to forwardslash for consistency """
- return os.path.normpath(s).replace(os.sep, "/")
-
- def __importify(self, s, dir=False):
- """ turns directory separators into dots and removes the ".py*" extension
- so the string can be used as import statement """
- if not dir:
- dirname, fname = os.path.split(s)
-
- if fname.count('.') > 1:
- #if there's a file named xxx.xx.py, it is not a valid module, so, let's not load it...
- return
-
- imp_stmt_pieces = [dirname.replace("\\", "/").replace("/", "."), os.path.splitext(fname)[0]]
-
- if len(imp_stmt_pieces[0]) == 0:
- imp_stmt_pieces = imp_stmt_pieces[1:]
-
- return ".".join(imp_stmt_pieces)
-
- else: #handle dir
- return s.replace("\\", "/").replace("/", ".")
-
- def __add_files(self, pyfiles, root, files):
- """ if files match, appends them to pyfiles. used by os.path.walk fcn """
- for fname in files:
- if self.__is_valid_py_file(fname):
- name_without_base_dir = self.__unixify(os.path.join(root, fname))
- pyfiles.append(name_without_base_dir)
- return
-
-
- def find_import_files(self):
- """ return a list of files to import """
- pyfiles = []
-
- for base_dir in self.test_dir:
- if os.path.isdir(base_dir):
- if hasattr(os, 'walk'):
- for root, dirs, files in os.walk(base_dir):
- self.__add_files(pyfiles, root, files)
else:
- # jython2.1 is too old for os.walk!
- os.path.walk(base_dir, self.__add_files, pyfiles)
-
- elif os.path.isfile(base_dir):
- pyfiles.append(base_dir)
-
- return pyfiles
-
- def __get_module_from_str(self, modname, print_exception):
- """ Import the module in the given import path.
- * Returns the "final" module, so importing "coilib40.subject.visu"
- returns the "visu" module, not the "coilib40" as returned by __import__ """
- try:
- mod = __import__(modname)
- for part in modname.split('.')[1:]:
- mod = getattr(mod, part)
- return mod
- except:
- if print_exception:
- import traceback;traceback.print_exc()
- sys.stderr.write('ERROR: Module: %s could not be imported.\n' % (modname,))
- return None
-
- def find_modules_from_files(self, pyfiles):
- """ returns a lisst of modules given a list of files """
- #let's make sure that the paths we want are in the pythonpath...
- imports = [self.__importify(s) for s in pyfiles]
-
- system_paths = []
- for s in sys.path:
- system_paths.append(self.__importify(s, True))
-
-
- ret = []
- for imp in imports:
- if imp is None:
- continue #can happen if a file is not a valid module
- choices = []
- for s in system_paths:
- if imp.startswith(s):
- add = imp[len(s) + 1:]
- if add:
- choices.append(add)
- #sys.stdout.write(' ' + add + ' ')
-
- if not choices:
- sys.stdout.write('PYTHONPATH not found for file: %s\n' % imp)
- else:
- for i, import_str in enumerate(choices):
- mod = self.__get_module_from_str(import_str, print_exception=i == len(choices) - 1)
- if mod is not None:
- ret.append(mod)
- break
-
-
- return ret
-
- def find_tests_from_modules(self, modules):
- """ returns the unittests given a list of modules """
- loader = unittest.TestLoader()
-
- ret = []
- if self.tests:
- accepted_classes = {}
- accepted_methods = {}
-
- for t in self.tests:
- splitted = t.split('.')
- if len(splitted) == 1:
- accepted_classes[t] = t
-
- elif len(splitted) == 2:
- accepted_methods[t] = t
-
- #===========================================================================================================
- # GetTestCaseNames
- #===========================================================================================================
- class GetTestCaseNames:
- """Yes, we need a class for that (cannot use outer context on jython 2.1)"""
+ raise AssertionError('Cannot handle test framework: %s at this point.' % (test_framework,))
- def __init__(self, accepted_classes, accepted_methods):
- self.accepted_classes = accepted_classes
- self.accepted_methods = accepted_methods
-
- def __call__(self, testCaseClass):
- """Return a sorted sequence of method names found within testCaseClass"""
- testFnNames = []
- className = testCaseClass.__name__
-
- if DictContains(self.accepted_classes, className):
- for attrname in dir(testCaseClass):
- #If a class is chosen, we select all the 'test' methods'
- if attrname.startswith('test') and hasattr(getattr(testCaseClass, attrname), '__call__'):
- testFnNames.append(attrname)
+ else:
+ if configuration.tests:
+ #Tests passed (works together with the files_or_dirs)
+ files_or_dirs = []
+ for file in configuration.files_or_dirs:
+ if test_framework == NOSE_FRAMEWORK:
+ for t in configuration.tests:
+ files_or_dirs.append(file + ':' + t)
+
+ elif test_framework == PY_TEST_FRAMEWORK:
+ file = _NormFile(file)
+ py_test_accept_filter[file] = configuration.tests
+ files_or_dirs.append(file)
else:
- for attrname in dir(testCaseClass):
- #If we have the class+method name, we must do a full check and have an exact match.
- if DictContains(self.accepted_methods, className + '.' + attrname):
- if hasattr(getattr(testCaseClass, attrname), '__call__'):
- testFnNames.append(attrname)
-
- #sorted() is not available in jython 2.1
- testFnNames.sort()
- return testFnNames
-
-
- loader.getTestCaseNames = GetTestCaseNames(accepted_classes, accepted_methods)
-
-
- ret.extend([loader.loadTestsFromModule(m) for m in modules])
-
- return ret
-
-
- def filter_tests(self, test_objs):
- """ based on a filter name, only return those tests that have
- the test case names that match """
- test_suite = []
- for test_obj in test_objs:
-
- if isinstance(test_obj, unittest.TestSuite):
- if test_obj._tests:
- test_obj._tests = self.filter_tests(test_obj._tests)
- if test_obj._tests:
- test_suite.append(test_obj)
-
- elif isinstance(test_obj, unittest.TestCase):
- test_cases = []
- for tc in test_objs:
- try:
- testMethodName = tc._TestCase__testMethodName
- except AttributeError:
- #changed in python 2.5
- testMethodName = tc._testMethodName
-
- if self.__match(self.test_filter, testMethodName) and self.__match_tests(self.tests, tc, testMethodName):
- test_cases.append(tc)
- return test_cases
- return test_suite
-
-
- def __match_tests(self, tests, test_case, test_method_name):
- if not tests:
- return 1
-
- for t in tests:
- class_and_method = t.split('.')
- if len(class_and_method) == 1:
- #only class name
- if class_and_method[0] == test_case.__class__.__name__:
- return 1
-
- elif len(class_and_method) == 2:
- if class_and_method[0] == test_case.__class__.__name__ and class_and_method[1] == test_method_name:
- return 1
-
- return 0
-
-
-
-
- def __match(self, filter_list, name):
- """ returns whether a test name matches the test filter """
- if filter_list is None:
- return 1
- for f in filter_list:
- if re.match(f, name):
- return 1
- return 0
-
-
- def run_tests(self):
- """ runs all tests """
- sys.stdout.write("Finding files...\n")
- files = self.find_import_files()
- sys.stdout.write('%s %s\n' % (self.test_dir, '... done'))
- sys.stdout.write("Importing test modules ... ")
- modules = self.find_modules_from_files(files)
- sys.stdout.write("done.\n")
- all_tests = self.find_tests_from_modules(modules)
- if self.test_filter or self.tests:
-
- if self.test_filter:
- sys.stdout.write('Test Filter: %s' % ([p.pattern for p in self.test_filter],))
-
- if self.tests:
- sys.stdout.write('Tests to run: %s' % (self.tests,))
+ raise AssertionError('Cannot handle test framework: %s at this point.' % (test_framework,))
+ else:
+ #Only files or dirs passed (let it do the test-loading based on those paths)
+ files_or_dirs = configuration.files_or_dirs
+
+ argv = other_test_framework_params + files_or_dirs
+
+
+ if test_framework == NOSE_FRAMEWORK:
+ #Nose usage: http://somethingaboutorange.com/mrl/projects/nose/0.11.2/usage.html
+ #show_stdout_option = ['-s']
+ #processes_option = ['--processes=2']
+ argv.insert(0, sys.argv[0])
+ if DEBUG:
+ sys.stdout.write('Final test framework args: %s\n' % (argv[1:],))
+
+ import pydev_runfiles_nose
+ PYDEV_NOSE_PLUGIN_SINGLETON = pydev_runfiles_nose.StartPydevNosePluginSingleton(configuration)
+ argv.append('--with-pydevplugin')
+ nose.run(argv=argv, addplugins=[PYDEV_NOSE_PLUGIN_SINGLETON])
+
+ elif test_framework == PY_TEST_FRAMEWORK:
+ if DEBUG:
+ sys.stdout.write('Final test framework args: %s\n' % (argv,))
+ sys.stdout.write('py_test_accept_filter: %s\n' % (py_test_accept_filter,))
+
+ import os
+
+ try:
+ xrange
+ except:
+ xrange = range
+
+ for i in xrange(len(argv)):
+ arg = argv[i]
+ #Workaround bug in py.test: if we pass the full path it ends up importing conftest
+ #more than once (so, always work with relative paths).
+ if os.path.isfile(arg) or os.path.isdir(arg):
+ from pydev_imports import relpath
+ arg = relpath(arg)
+ argv[i] = arg
+
+ d = os.path.dirname(__file__)
+ if d not in sys.path:
+ sys.path.insert(0, d)
+
+ import pickle, zlib, base64
+
+ # Update environment PYTHONPATH so that it finds our plugin if using xdist.
+ os.environ['PYTHONPATH'] = os.pathsep.join(sys.path)
+
+ # Set what should be skipped in the plugin through an environment variable
+ s = base64.b64encode(zlib.compress(pickle.dumps(py_test_accept_filter)))
+ if pydevd_constants.IS_PY3K:
+ s = s.decode('ascii') # Must be str in py3.
+ os.environ['PYDEV_PYTEST_SKIP'] = s
+
+ # Identifies the main pid (i.e.: if it's not the main pid it has to connect back to the
+ # main pid to give xml-rpc notifications).
+ os.environ['PYDEV_MAIN_PID'] = str(os.getpid())
+ os.environ['PYDEV_PYTEST_SERVER'] = str(configuration.port)
+
+ argv.append('-p')
+ argv.append('pydev_runfiles_pytest2')
+ pytest.main(argv)
- all_tests = self.filter_tests(all_tests)
+ else:
+ raise AssertionError('Cannot handle test framework: %s at this point.' % (test_framework,))
- sys.stdout.write('\n')
- runner = unittest.TextTestRunner(stream=sys.stdout, descriptions=1, verbosity=verbosity)
- runner.run(unittest.TestSuite(all_tests))
- return
-#=======================================================================================================================
-# main
-#=======================================================================================================================
if __name__ == '__main__':
- dirs, verbosity, test_filter, tests = parse_cmdline()
- PydevTestRunner(dirs, test_filter, verbosity, tests).run_tests()
+ try:
+ main()
+ finally:
+ try:
+ #The server is not a daemon thread, so, we have to ask for it to be killed!
+ import pydev_runfiles_xml_rpc
+ pydev_runfiles_xml_rpc.forceServerKill()
+ except:
+ pass #Ignore any errors here
+
+ import sys
+ import threading
+ if hasattr(sys, '_current_frames') and hasattr(threading, 'enumerate'):
+ import time
+ import traceback
+
+ class DumpThreads(threading.Thread):
+ def run(self):
+ time.sleep(10)
+
+ thread_id_to_name = {}
+ try:
+ for t in threading.enumerate():
+ thread_id_to_name[t.ident] = '%s (daemon: %s)' % (t.name, t.daemon)
+ except:
+ pass
+
+ stack_trace = [
+ '===============================================================================',
+ 'pydev pyunit runner: Threads still found running after tests finished',
+ '================================= Thread Dump =================================']
+
+ for thread_id, stack in sys._current_frames().items():
+ stack_trace.append('\n-------------------------------------------------------------------------------')
+ stack_trace.append(" Thread %s" % thread_id_to_name.get(thread_id, thread_id))
+ stack_trace.append('')
+
+ if 'self' in stack.f_locals:
+ sys.stderr.write(str(stack.f_locals['self'])+'\n')
+
+ for filename, lineno, name, line in traceback.extract_stack(stack):
+ stack_trace.append(' File "%s", line %d, in %s' % (filename, lineno, name))
+ if line:
+ stack_trace.append(" %s" % (line.strip()))
+ stack_trace.append('\n=============================== END Thread Dump ===============================')
+ sys.stderr.write('\n'.join(stack_trace))
+
+
+ dump_current_frames_thread = DumpThreads()
+ dump_current_frames_thread.setDaemon(True) # Daemon so that this thread doesn't halt it!
+ dump_current_frames_thread.start()
diff --git a/python/helpers/pydev/stubs/_django_manager_body.py b/python/helpers/pydev/stubs/_django_manager_body.py
new file mode 100644
index 000000000000..2bf47067ce3e
--- /dev/null
+++ b/python/helpers/pydev/stubs/_django_manager_body.py
@@ -0,0 +1,414 @@
+# This is a dummy for code-completion purposes.
+
+def __unicode__(self):
+ """
+ Return "app_label.model_label.manager_name".
+ """
+
+def _copy_to_model(self, model):
+ """
+ Makes a copy of the manager and assigns it to 'model', which should be
+ a child of the existing model (used when inheriting a manager from an
+ abstract base class).
+ """
+
+
+def _db(self):
+ """
+
+ """
+
+
+def _get_queryset_methods(cls, queryset_class):
+ """
+
+ """
+
+
+def _hints(self):
+ """
+ dict() -> new empty dictionary
+ dict(mapping) -> new dictionary initialized from a mapping object's
+ (key, value) pairs
+ dict(iterable) -> new dictionary initialized as if via:
+ d = {}
+ for k, v in iterable:
+ d[k] = v
+ dict(**kwargs) -> new dictionary initialized with the name=value pairs
+ in the keyword argument list. For example: dict(one=1, two=2)
+ """
+
+
+def _inherited(self):
+ """
+
+ """
+
+
+def _insert(self, *args, **kwargs):
+ """
+ Inserts a new record for the given model. This provides an interface to
+ the InsertQuery class and is how Model.save() is implemented.
+ """
+
+
+def _queryset_class(self):
+ """
+ Represents a lazy database lookup for a set of objects.
+ """
+
+
+def _set_creation_counter(self):
+ """
+ Sets the creation counter value for this instance and increments the
+ class-level copy.
+ """
+
+
+def _update(self, *args, **kwargs):
+ """
+ A version of update that accepts field objects instead of field names.
+ Used primarily for model saving and not intended for use by general
+ code (it requires too much poking around at model internals to be
+ useful at that level).
+ """
+
+
+def aggregate(self, *args, **kwargs):
+ """
+ Returns a dictionary containing the calculations (aggregation)
+ over the current queryset
+
+ If args is present the expression is passed as a kwarg using
+ the Aggregate object's default alias.
+ """
+
+
+def all(self):
+ """
+ @rtype: django.db.models.query.QuerySet
+ """
+
+
+def annotate(self, *args, **kwargs):
+ """
+ Return a query set in which the returned objects have been annotated
+ with data aggregated from related fields.
+ """
+
+
+def bulk_create(self, *args, **kwargs):
+ """
+ Inserts each of the instances into the database. This does *not* call
+ save() on each of the instances, does not send any pre/post save
+ signals, and does not set the primary key attribute if it is an
+ autoincrement field.
+ """
+
+
+def check(self, **kwargs):
+ """
+
+ """
+
+
+def complex_filter(self, *args, **kwargs):
+ """
+ Returns a new QuerySet instance with filter_obj added to the filters.
+
+ filter_obj can be a Q object (or anything with an add_to_query()
+ method) or a dictionary of keyword lookup arguments.
+
+ This exists to support framework features such as 'limit_choices_to',
+ and usually it will be more natural to use other methods.
+
+ @rtype: django.db.models.query.QuerySet
+ """
+
+
+def contribute_to_class(self, model, name):
+ """
+
+ """
+
+
+def count(self, *args, **kwargs):
+ """
+ Performs a SELECT COUNT() and returns the number of records as an
+ integer.
+
+ If the QuerySet is already fully cached this simply returns the length
+ of the cached results set to avoid multiple SELECT COUNT(*) calls.
+ """
+
+
+def create(self, *args, **kwargs):
+ """
+ Creates a new object with the given kwargs, saving it to the database
+ and returning the created object.
+ """
+
+
+def creation_counter(self):
+ """
+
+ """
+
+
+def dates(self, *args, **kwargs):
+ """
+ Returns a list of date objects representing all available dates for
+ the given field_name, scoped to 'kind'.
+ """
+
+
+def datetimes(self, *args, **kwargs):
+ """
+ Returns a list of datetime objects representing all available
+ datetimes for the given field_name, scoped to 'kind'.
+ """
+
+
+def db(self):
+ """
+
+ """
+
+
+def db_manager(self, using=None, hints=None):
+ """
+
+ """
+
+
+def defer(self, *args, **kwargs):
+ """
+ Defers the loading of data for certain fields until they are accessed.
+ The set of fields to defer is added to any existing set of deferred
+ fields. The only exception to this is if None is passed in as the only
+ parameter, in which case all deferrals are removed (None acts as a
+ reset option).
+ """
+
+
+def distinct(self, *args, **kwargs):
+ """
+ Returns a new QuerySet instance that will select only distinct results.
+
+ @rtype: django.db.models.query.QuerySet
+ """
+
+
+def earliest(self, *args, **kwargs):
+ """
+
+ """
+
+
+def exclude(self, *args, **kwargs):
+ """
+ Returns a new QuerySet instance with NOT (args) ANDed to the existing
+ set.
+
+ @rtype: django.db.models.query.QuerySet
+ """
+
+
+def exists(self, *args, **kwargs):
+ """
+
+ """
+
+
+def extra(self, *args, **kwargs):
+ """
+ Adds extra SQL fragments to the query.
+ """
+
+
+def filter(self, *args, **kwargs):
+ """
+ Returns a new QuerySet instance with the args ANDed to the existing
+ set.
+
+ @rtype: django.db.models.query.QuerySet
+ """
+
+
+def first(self, *args, **kwargs):
+ """
+ Returns the first object of a query, returns None if no match is found.
+ """
+
+
+def from_queryset(cls, queryset_class, class_name=None):
+ """
+
+ """
+
+
+def get(self, *args, **kwargs):
+ """
+ Performs the query and returns a single object matching the given
+ keyword arguments.
+ """
+
+
+def get_or_create(self, *args, **kwargs):
+ """
+ Looks up an object with the given kwargs, creating one if necessary.
+ Returns a tuple of (object, created), where created is a boolean
+ specifying whether an object was created.
+ """
+
+
+def get_queryset(self):
+ """
+ Returns a new QuerySet object. Subclasses can override this method to
+ easily customize the behavior of the Manager.
+
+ @rtype: django.db.models.query.QuerySet
+ """
+
+
+def in_bulk(self, *args, **kwargs):
+ """
+ Returns a dictionary mapping each of the given IDs to the object with
+ that ID.
+ """
+
+
+def iterator(self, *args, **kwargs):
+ """
+ An iterator over the results from applying this QuerySet to the
+ database.
+ """
+
+
+def last(self, *args, **kwargs):
+ """
+ Returns the last object of a query, returns None if no match is found.
+ """
+
+
+def latest(self, *args, **kwargs):
+ """
+
+ """
+
+
+def model(self):
+ """
+ MyModel(id)
+ """
+
+
+def none(self, *args, **kwargs):
+ """
+ Returns an empty QuerySet.
+
+ @rtype: django.db.models.query.QuerySet
+ """
+
+
+def only(self, *args, **kwargs):
+ """
+ Essentially, the opposite of defer. Only the fields passed into this
+ method and that are not already specified as deferred are loaded
+ immediately when the queryset is evaluated.
+ """
+
+
+def order_by(self, *args, **kwargs):
+ """
+ Returns a new QuerySet instance with the ordering changed.
+
+ @rtype: django.db.models.query.QuerySet
+ """
+
+
+def prefetch_related(self, *args, **kwargs):
+ """
+ Returns a new QuerySet instance that will prefetch the specified
+ Many-To-One and Many-To-Many related objects when the QuerySet is
+ evaluated.
+
+ When prefetch_related() is called more than once, the list of lookups to
+ prefetch is appended to. If prefetch_related(None) is called, the list
+ is cleared.
+
+ @rtype: django.db.models.query.QuerySet
+ """
+
+
+def raw(self, *args, **kwargs):
+ """
+
+ """
+
+
+def reverse(self, *args, **kwargs):
+ """
+ Reverses the ordering of the QuerySet.
+
+ @rtype: django.db.models.query.QuerySet
+ """
+
+
+def select_for_update(self, *args, **kwargs):
+ """
+ Returns a new QuerySet instance that will select objects with a
+ FOR UPDATE lock.
+
+ @rtype: django.db.models.query.QuerySet
+ """
+
+
+def select_related(self, *args, **kwargs):
+ """
+ Returns a new QuerySet instance that will select related objects.
+
+ If fields are specified, they must be ForeignKey fields and only those
+ related objects are included in the selection.
+
+ If select_related(None) is called, the list is cleared.
+
+ @rtype: django.db.models.query.QuerySet
+ """
+
+
+def update(self, *args, **kwargs):
+ """
+ Updates all elements in the current QuerySet, setting all the given
+ fields to the appropriate values.
+ """
+
+
+def update_or_create(self, *args, **kwargs):
+ """
+ Looks up an object with the given kwargs, updating one with defaults
+ if it exists, otherwise creates a new one.
+ Returns a tuple (object, created), where created is a boolean
+ specifying whether an object was created.
+ """
+
+
+def using(self, *args, **kwargs):
+ """
+ Selects which database this QuerySet should execute its query against.
+
+ @rtype: django.db.models.query.QuerySet
+ """
+
+
+def values(self, *args, **kwargs):
+ """
+
+ """
+
+
+def values_list(self, *args, **kwargs):
+ """
+
+ """
+
diff --git a/python/helpers/pydev/stubs/_get_tips.py b/python/helpers/pydev/stubs/_get_tips.py
new file mode 100644
index 000000000000..b98e1c536cea
--- /dev/null
+++ b/python/helpers/pydev/stubs/_get_tips.py
@@ -0,0 +1,280 @@
+import os.path
+import inspect
+import sys
+
+# completion types.
+TYPE_IMPORT = '0'
+TYPE_CLASS = '1'
+TYPE_FUNCTION = '2'
+TYPE_ATTR = '3'
+TYPE_BUILTIN = '4'
+TYPE_PARAM = '5'
+
+def _imp(name, log=None):
+ try:
+ return __import__(name)
+ except:
+ if '.' in name:
+ sub = name[0:name.rfind('.')]
+
+ if log is not None:
+ log.AddContent('Unable to import', name, 'trying with', sub)
+ # log.AddContent('PYTHONPATH:')
+ # log.AddContent('\n'.join(sorted(sys.path)))
+ log.AddException()
+
+ return _imp(sub, log)
+ else:
+ s = 'Unable to import module: %s - sys.path: %s' % (str(name), sys.path)
+ if log is not None:
+ log.AddContent(s)
+ log.AddException()
+
+ raise ImportError(s)
+
+
+IS_IPY = False
+if sys.platform == 'cli':
+ IS_IPY = True
+ _old_imp = _imp
+ def _imp(name, log=None):
+ # We must add a reference in clr for .Net
+ import clr # @UnresolvedImport
+ initial_name = name
+ while '.' in name:
+ try:
+ clr.AddReference(name)
+ break # If it worked, that's OK.
+ except:
+ name = name[0:name.rfind('.')]
+ else:
+ try:
+ clr.AddReference(name)
+ except:
+ pass # That's OK (not dot net module).
+
+ return _old_imp(initial_name, log)
+
+
+
+def GetFile(mod):
+ f = None
+ try:
+ f = inspect.getsourcefile(mod) or inspect.getfile(mod)
+ except:
+ if hasattr(mod, '__file__'):
+ f = mod.__file__
+ if f.lower(f[-4:]) in ['.pyc', '.pyo']:
+ filename = f[:-4] + '.py'
+ if os.path.exists(filename):
+ f = filename
+
+ return f
+
+def Find(name, log=None):
+ f = None
+
+ mod = _imp(name, log)
+ parent = mod
+ foundAs = ''
+
+ if inspect.ismodule(mod):
+ f = GetFile(mod)
+
+ components = name.split('.')
+
+ old_comp = None
+ for comp in components[1:]:
+ try:
+ # this happens in the following case:
+ # we have mx.DateTime.mxDateTime.mxDateTime.pyd
+ # but after importing it, mx.DateTime.mxDateTime shadows access to mxDateTime.pyd
+ mod = getattr(mod, comp)
+ except AttributeError:
+ if old_comp != comp:
+ raise
+
+ if inspect.ismodule(mod):
+ f = GetFile(mod)
+ else:
+ if len(foundAs) > 0:
+ foundAs = foundAs + '.'
+ foundAs = foundAs + comp
+
+ old_comp = comp
+
+ return f, mod, parent, foundAs
+
+
+def GenerateTip(data, log=None):
+ data = data.replace('\n', '')
+ if data.endswith('.'):
+ data = data.rstrip('.')
+
+ f, mod, parent, foundAs = Find(data, log)
+ # print_ >> open('temp.txt', 'w'), f
+ tips = GenerateImportsTipForModule(mod)
+ return f, tips
+
+
+def CheckChar(c):
+ if c == '-' or c == '.':
+ return '_'
+ return c
+
+def GenerateImportsTipForModule(obj_to_complete, dirComps=None, getattr=getattr, filter=lambda name:True):
+ '''
+ @param obj_to_complete: the object from where we should get the completions
+ @param dirComps: if passed, we should not 'dir' the object and should just iterate those passed as a parameter
+ @param getattr: the way to get a given object from the obj_to_complete (used for the completer)
+ @param filter: a callable that receives the name and decides if it should be appended or not to the results
+ @return: list of tuples, so that each tuple represents a completion with:
+ name, doc, args, type (from the TYPE_* constants)
+ '''
+ ret = []
+
+ if dirComps is None:
+ dirComps = dir(obj_to_complete)
+ if hasattr(obj_to_complete, '__dict__'):
+ dirComps.append('__dict__')
+ if hasattr(obj_to_complete, '__class__'):
+ dirComps.append('__class__')
+
+ getCompleteInfo = True
+
+ if len(dirComps) > 1000:
+ # ok, we don't want to let our users wait forever...
+ # no complete info for you...
+
+ getCompleteInfo = False
+
+ dontGetDocsOn = (float, int, str, tuple, list)
+ for d in dirComps:
+
+ if d is None:
+ continue
+
+ if not filter(d):
+ continue
+
+ args = ''
+
+ try:
+ obj = getattr(obj_to_complete, d)
+ except: # just ignore and get it without aditional info
+ ret.append((d, '', args, TYPE_BUILTIN))
+ else:
+
+ if getCompleteInfo:
+ retType = TYPE_BUILTIN
+
+ # check if we have to get docs
+ getDoc = True
+ for class_ in dontGetDocsOn:
+
+ if isinstance(obj, class_):
+ getDoc = False
+ break
+
+ doc = ''
+ if getDoc:
+ # no need to get this info... too many constants are defined and
+ # makes things much slower (passing all that through sockets takes quite some time)
+ try:
+ doc = inspect.getdoc(obj)
+ if doc is None:
+ doc = ''
+ except: # may happen on jython when checking java classes (so, just ignore it)
+ doc = ''
+
+
+ if inspect.ismethod(obj) or inspect.isbuiltin(obj) or inspect.isfunction(obj) or inspect.isroutine(obj):
+ try:
+ args, vargs, kwargs, defaults = inspect.getargspec(obj)
+ except:
+ args, vargs, kwargs, defaults = (('self',), None, None, None)
+ if defaults is not None:
+ start_defaults_at = len(args) - len(defaults)
+
+
+ r = ''
+ for i, a in enumerate(args):
+
+ if len(r) > 0:
+ r = r + ', '
+
+ r = r + str(a)
+
+ if defaults is not None and i >= start_defaults_at:
+ default = defaults[i - start_defaults_at]
+ r += '=' +str(default)
+
+
+ others = ''
+ if vargs:
+ others += '*' + vargs
+
+ if kwargs:
+ if others:
+ others+= ', '
+ others += '**' + kwargs
+
+ if others:
+ r+= ', '
+
+
+ args = '(%s%s)' % (r, others)
+ retType = TYPE_FUNCTION
+
+ elif inspect.isclass(obj):
+ retType = TYPE_CLASS
+
+ elif inspect.ismodule(obj):
+ retType = TYPE_IMPORT
+
+ else:
+ retType = TYPE_ATTR
+
+
+ # add token and doc to return - assure only strings.
+ ret.append((d, doc, args, retType))
+
+
+ else: # getCompleteInfo == False
+ if inspect.ismethod(obj) or inspect.isbuiltin(obj) or inspect.isfunction(obj) or inspect.isroutine(obj):
+ retType = TYPE_FUNCTION
+
+ elif inspect.isclass(obj):
+ retType = TYPE_CLASS
+
+ elif inspect.ismodule(obj):
+ retType = TYPE_IMPORT
+
+ else:
+ retType = TYPE_ATTR
+ # ok, no complete info, let's try to do this as fast and clean as possible
+ # so, no docs for this kind of information, only the signatures
+ ret.append((d, '', str(args), retType))
+
+ return ret
+
+
+
+
+if __name__ == '__main__':
+ # To use when we have some object: i.e.: obj_to_complete=MyModel.objects
+ temp = '''
+def %(method_name)s%(args)s:
+ """
+%(doc)s
+ """
+'''
+
+ for entry in GenerateImportsTipForModule(obj_to_complete):
+ import textwrap
+ doc = textwrap.dedent(entry[1])
+ lines = []
+ for line in doc.splitlines():
+ lines.append(' ' + line)
+ doc = '\n'.join(lines)
+ print temp % dict(method_name=entry[0], args=entry[2] or '(self)', doc=doc)
diff --git a/python/helpers/pydev/test_debug.py b/python/helpers/pydev/test_debug.py
index bc55de16907d..2196ca6f9540 100644
--- a/python/helpers/pydev/test_debug.py
+++ b/python/helpers/pydev/test_debug.py
@@ -3,7 +3,7 @@ __author__ = 'Dmitry.Trofimov'
import unittest
import os
-test_data_path = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__)), '..', '..', '..', '..', 'python', 'testData', 'debug'))
+test_data_path = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__)), '..', '..', 'testData', 'debug'))
class PyDevTestCase(unittest.TestCase):
def testZipFileExits(self):
diff --git a/python/helpers/pydev/test_pydevd_reload/test_pydevd_reload.py b/python/helpers/pydev/test_pydevd_reload/test_pydevd_reload.py
new file mode 100644
index 000000000000..062ead2b5ff8
--- /dev/null
+++ b/python/helpers/pydev/test_pydevd_reload/test_pydevd_reload.py
@@ -0,0 +1,516 @@
+import os # @NoMove
+import sys # @NoMove
+sys.path.insert(0, os.path.realpath(os.path.abspath('..')))
+
+import pydevd_reload
+import tempfile
+import unittest
+
+
+SAMPLE_CODE = """
+class C:
+ def foo(self):
+ return 0
+
+ @classmethod
+ def bar(cls):
+ return (0, 0)
+
+ @staticmethod
+ def stomp():
+ return (0, 0, 0)
+
+ def unchanged(self):
+ return 'unchanged'
+"""
+
+
+
+class Test(unittest.TestCase):
+
+
+ def setUp(self):
+ unittest.TestCase.setUp(self)
+ self.tempdir = None
+ self.save_path = None
+ self.tempdir = tempfile.mkdtemp()
+ self.save_path = list(sys.path)
+ sys.path.append(self.tempdir)
+ try:
+ del sys.modules['x']
+ except:
+ pass
+
+
+ def tearDown(self):
+ unittest.TestCase.tearDown(self)
+ sys.path = self.save_path
+ try:
+ del sys.modules['x']
+ except:
+ pass
+
+ def make_mod(self, name="x", repl=None, subst=None, sample=SAMPLE_CODE):
+ fn = os.path.join(self.tempdir, name + ".py")
+ f = open(fn, "w")
+ if repl is not None and subst is not None:
+ sample = sample.replace(repl, subst)
+ try:
+ f.write(sample)
+ finally:
+ f.close()
+
+
+ def test_pydevd_reload(self):
+
+ self.make_mod()
+ import x
+
+ C = x.C
+ COut = C
+ Cfoo = C.foo
+ Cbar = C.bar
+ Cstomp = C.stomp
+
+ def check2(expected):
+ C = x.C
+ Cfoo = C.foo
+ Cbar = C.bar
+ Cstomp = C.stomp
+ b = C()
+ bfoo = b.foo
+ self.assertEqual(expected, b.foo())
+ self.assertEqual(expected, bfoo())
+ self.assertEqual(expected, Cfoo(b))
+
+ def check(expected):
+ b = COut()
+ bfoo = b.foo
+ self.assertEqual(expected, b.foo())
+ self.assertEqual(expected, bfoo())
+ self.assertEqual(expected, Cfoo(b))
+ self.assertEqual((expected, expected), Cbar())
+ self.assertEqual((expected, expected, expected), Cstomp())
+ check2(expected)
+
+ check(0)
+
+ # modify mod and reload
+ count = 0
+ while count < 1:
+ count += 1
+ self.make_mod(repl="0", subst=str(count))
+ pydevd_reload.xreload(x)
+ check(count)
+
+
+ def test_pydevd_reload2(self):
+
+ self.make_mod()
+ import x
+
+ c = x.C()
+ cfoo = c.foo
+ self.assertEqual(0, c.foo())
+ self.assertEqual(0, cfoo())
+
+ self.make_mod(repl="0", subst='1')
+ pydevd_reload.xreload(x)
+ self.assertEqual(1, c.foo())
+ self.assertEqual(1, cfoo())
+
+ def test_pydevd_reload3(self):
+ class F:
+ def m1(self):
+ return 1
+ class G:
+ def m1(self):
+ return 2
+
+ self.assertEqual(F().m1(), 1)
+ pydevd_reload.Reload(None)._update(None, None, F, G)
+ self.assertEqual(F().m1(), 2)
+
+
+ def test_pydevd_reload4(self):
+ class F:
+ pass
+ F.m1 = lambda a:None
+ class G:
+ pass
+ G.m1 = lambda a:10
+
+ self.assertEqual(F().m1(), None)
+ pydevd_reload.Reload(None)._update(None, None, F, G)
+ self.assertEqual(F().m1(), 10)
+
+
+
+ def test_if_code_obj_equals(self):
+ class F:
+ def m1(self):
+ return 1
+ class G:
+ def m1(self):
+ return 1
+ class H:
+ def m1(self):
+ return 2
+
+ if hasattr(F.m1, 'func_code'):
+ self.assertTrue(pydevd_reload.code_objects_equal(F.m1.func_code, G.m1.func_code))
+ self.assertFalse(pydevd_reload.code_objects_equal(F.m1.func_code, H.m1.func_code))
+ else:
+ self.assertTrue(pydevd_reload.code_objects_equal(F.m1.__code__, G.m1.__code__))
+ self.assertFalse(pydevd_reload.code_objects_equal(F.m1.__code__, H.m1.__code__))
+
+
+
+ def test_metaclass(self):
+
+ class Meta(type):
+ def __init__(cls, name, bases, attrs):
+ super(Meta, cls).__init__(name, bases, attrs)
+
+ class F:
+ __metaclass__ = Meta
+
+ def m1(self):
+ return 1
+
+
+ class G:
+ __metaclass__ = Meta
+
+ def m1(self):
+ return 2
+
+ self.assertEqual(F().m1(), 1)
+ pydevd_reload.Reload(None)._update(None, None, F, G)
+ self.assertEqual(F().m1(), 2)
+
+
+
+ def test_change_hierarchy(self):
+
+ class F(object):
+
+ def m1(self):
+ return 1
+
+
+ class B(object):
+ def super_call(self):
+ return 2
+
+ class G(B):
+
+ def m1(self):
+ return self.super_call()
+
+ self.assertEqual(F().m1(), 1)
+ old = pydevd_reload.notify_error
+ self._called = False
+ def on_error(*args):
+ self._called = True
+ try:
+ pydevd_reload.notify_error = on_error
+ pydevd_reload.Reload(None)._update(None, None, F, G)
+ self.assertTrue(self._called)
+ finally:
+ pydevd_reload.notify_error = old
+
+
+ def test_change_hierarchy_old_style(self):
+
+ class F:
+
+ def m1(self):
+ return 1
+
+
+ class B:
+ def super_call(self):
+ return 2
+
+ class G(B):
+
+ def m1(self):
+ return self.super_call()
+
+
+ self.assertEqual(F().m1(), 1)
+ old = pydevd_reload.notify_error
+ self._called = False
+ def on_error(*args):
+ self._called = True
+ try:
+ pydevd_reload.notify_error = on_error
+ pydevd_reload.Reload(None)._update(None, None, F, G)
+ self.assertTrue(self._called)
+ finally:
+ pydevd_reload.notify_error = old
+
+
+ def test_create_class(self):
+ SAMPLE_CODE1 = """
+class C:
+ def foo(self):
+ return 0
+"""
+ # Creating a new class and using it from old class
+ SAMPLE_CODE2 = """
+class B:
+ pass
+
+class C:
+ def foo(self):
+ return B
+"""
+
+ self.make_mod(sample=SAMPLE_CODE1)
+ import x
+ foo = x.C().foo
+ self.assertEqual(foo(), 0)
+ self.make_mod(sample=SAMPLE_CODE2)
+ pydevd_reload.xreload(x)
+ self.assertEqual(foo().__name__, 'B')
+
+ def test_create_class2(self):
+ SAMPLE_CODE1 = """
+class C(object):
+ def foo(self):
+ return 0
+"""
+ # Creating a new class and using it from old class
+ SAMPLE_CODE2 = """
+class B(object):
+ pass
+
+class C(object):
+ def foo(self):
+ return B
+"""
+
+ self.make_mod(sample=SAMPLE_CODE1)
+ import x
+ foo = x.C().foo
+ self.assertEqual(foo(), 0)
+ self.make_mod(sample=SAMPLE_CODE2)
+ pydevd_reload.xreload(x)
+ self.assertEqual(foo().__name__, 'B')
+
+ def test_parent_function(self):
+ SAMPLE_CODE1 = """
+class B(object):
+ def foo(self):
+ return 0
+
+class C(B):
+ def call(self):
+ return self.foo()
+"""
+ # Creating a new class and using it from old class
+ SAMPLE_CODE2 = """
+class B(object):
+ def foo(self):
+ return 0
+ def bar(self):
+ return 'bar'
+
+class C(B):
+ def call(self):
+ return self.bar()
+"""
+
+ self.make_mod(sample=SAMPLE_CODE1)
+ import x
+ call = x.C().call
+ self.assertEqual(call(), 0)
+ self.make_mod(sample=SAMPLE_CODE2)
+ pydevd_reload.xreload(x)
+ self.assertEqual(call(), 'bar')
+
+
+ def test_update_constant(self):
+ SAMPLE_CODE1 = """
+CONSTANT = 1
+
+class B(object):
+ def foo(self):
+ return CONSTANT
+"""
+ SAMPLE_CODE2 = """
+CONSTANT = 2
+
+class B(object):
+ def foo(self):
+ return CONSTANT
+"""
+
+ self.make_mod(sample=SAMPLE_CODE1)
+ import x
+ foo = x.B().foo
+ self.assertEqual(foo(), 1)
+ self.make_mod(sample=SAMPLE_CODE2)
+ pydevd_reload.xreload(x)
+ self.assertEqual(foo(), 1) #Just making it explicit we don't reload constants.
+
+
+ def test_update_constant_with_custom_code(self):
+ SAMPLE_CODE1 = """
+CONSTANT = 1
+
+class B(object):
+ def foo(self):
+ return CONSTANT
+"""
+ SAMPLE_CODE2 = """
+CONSTANT = 2
+
+def __xreload_old_new__(namespace, name, old, new):
+ if name == 'CONSTANT':
+ namespace[name] = new
+
+class B(object):
+ def foo(self):
+ return CONSTANT
+"""
+
+ self.make_mod(sample=SAMPLE_CODE1)
+ import x
+ foo = x.B().foo
+ self.assertEqual(foo(), 1)
+ self.make_mod(sample=SAMPLE_CODE2)
+ pydevd_reload.xreload(x)
+ self.assertEqual(foo(), 2) #Actually updated it now!
+
+
+ def test_reload_custom_code_after_changes(self):
+ SAMPLE_CODE1 = """
+CONSTANT = 1
+
+class B(object):
+ def foo(self):
+ return CONSTANT
+"""
+ SAMPLE_CODE2 = """
+CONSTANT = 1
+
+def __xreload_after_reload_update__(namespace):
+ namespace['CONSTANT'] = 2
+
+class B(object):
+ def foo(self):
+ return CONSTANT
+"""
+
+ self.make_mod(sample=SAMPLE_CODE1)
+ import x
+ foo = x.B().foo
+ self.assertEqual(foo(), 1)
+ self.make_mod(sample=SAMPLE_CODE2)
+ pydevd_reload.xreload(x)
+ self.assertEqual(foo(), 2) #Actually updated it now!
+
+
+ def test_reload_custom_code_after_changes_in_class(self):
+ SAMPLE_CODE1 = """
+
+class B(object):
+ CONSTANT = 1
+
+ def foo(self):
+ return self.CONSTANT
+"""
+ SAMPLE_CODE2 = """
+
+
+class B(object):
+ CONSTANT = 1
+
+ @classmethod
+ def __xreload_after_reload_update__(cls):
+ cls.CONSTANT = 2
+
+ def foo(self):
+ return self.CONSTANT
+"""
+
+ self.make_mod(sample=SAMPLE_CODE1)
+ import x
+ foo = x.B().foo
+ self.assertEqual(foo(), 1)
+ self.make_mod(sample=SAMPLE_CODE2)
+ pydevd_reload.xreload(x)
+ self.assertEqual(foo(), 2) #Actually updated it now!
+
+
+ def test_update_constant_with_custom_code(self):
+ SAMPLE_CODE1 = """
+
+class B(object):
+ CONSTANT = 1
+
+ def foo(self):
+ return self.CONSTANT
+"""
+ SAMPLE_CODE2 = """
+
+
+class B(object):
+
+ CONSTANT = 2
+
+ def __xreload_old_new__(cls, name, old, new):
+ if name == 'CONSTANT':
+ cls.CONSTANT = new
+ __xreload_old_new__ = classmethod(__xreload_old_new__)
+
+ def foo(self):
+ return self.CONSTANT
+"""
+
+ self.make_mod(sample=SAMPLE_CODE1)
+ import x
+ foo = x.B().foo
+ self.assertEqual(foo(), 1)
+ self.make_mod(sample=SAMPLE_CODE2)
+ pydevd_reload.xreload(x)
+ self.assertEqual(foo(), 2) #Actually updated it now!
+
+
+ def test_update_with_slots(self):
+ SAMPLE_CODE1 = """
+class B(object):
+
+ __slots__ = ['bar']
+
+"""
+ SAMPLE_CODE2 = """
+class B(object):
+
+ __slots__ = ['bar', 'foo']
+
+ def m1(self):
+ self.bar = 10
+ return 1
+
+"""
+
+ self.make_mod(sample=SAMPLE_CODE1)
+ import x
+ B = x.B
+ self.make_mod(sample=SAMPLE_CODE2)
+ pydevd_reload.xreload(x)
+ b = B()
+ self.assertEqual(1, b.m1())
+ self.assertEqual(10, b.bar)
+ self.assertRaises(Exception, setattr, b, 'foo', 20) #__slots__ can't be updated
+
+
+
+
+if __name__ == "__main__":
+# import sys;sys.argv = ['', 'Test.test_reload_custom_code_after_changes_in_class']
+ unittest.main()
diff --git a/python/helpers/pydev/tests/__not_in_default_pythonpath.txt b/python/helpers/pydev/tests/__not_in_default_pythonpath.txt
new file mode 100644
index 000000000000..29cdc5bc1078
--- /dev/null
+++ b/python/helpers/pydev/tests/__not_in_default_pythonpath.txt
@@ -0,0 +1 @@
+(no __init__.py file) \ No newline at end of file
diff --git a/python/helpers/pydev/tests/check_pydevconsole.py b/python/helpers/pydev/tests/check_pydevconsole.py
new file mode 100644
index 000000000000..7d1b7eed4e0b
--- /dev/null
+++ b/python/helpers/pydev/tests/check_pydevconsole.py
@@ -0,0 +1,105 @@
+import sys
+import os
+
+#Put pydevconsole in the path.
+sys.argv[0] = os.path.dirname(sys.argv[0])
+sys.path.insert(1, os.path.join(os.path.dirname(sys.argv[0])))
+
+print('Running tests with:', sys.executable)
+print('PYTHONPATH:')
+print('\n'.join(sorted(sys.path)))
+
+import threading
+import unittest
+
+import pydevconsole
+from pydev_imports import xmlrpclib, SimpleXMLRPCServer
+
+try:
+ raw_input
+ raw_input_name = 'raw_input'
+except NameError:
+ raw_input_name = 'input'
+
+#=======================================================================================================================
+# Test
+#=======================================================================================================================
+class Test(unittest.TestCase):
+
+
+ def startClientThread(self, client_port):
+ class ClientThread(threading.Thread):
+ def __init__(self, client_port):
+ threading.Thread.__init__(self)
+ self.client_port = client_port
+
+ def run(self):
+ class HandleRequestInput:
+ def RequestInput(self):
+ return 'RequestInput: OK'
+
+ handle_request_input = HandleRequestInput()
+
+ import pydev_localhost
+ print('Starting client with:', pydev_localhost.get_localhost(), self.client_port)
+ client_server = SimpleXMLRPCServer((pydev_localhost.get_localhost(), self.client_port), logRequests=False)
+ client_server.register_function(handle_request_input.RequestInput)
+ client_server.serve_forever()
+
+ client_thread = ClientThread(client_port)
+ client_thread.setDaemon(True)
+ client_thread.start()
+ return client_thread
+
+
+ def getFreeAddresses(self):
+ import socket
+ s = socket.socket()
+ s.bind(('', 0))
+ port0 = s.getsockname()[1]
+
+ s1 = socket.socket()
+ s1.bind(('', 0))
+ port1 = s1.getsockname()[1]
+ s.close()
+ s1.close()
+ return port0, port1
+
+
+ def testServer(self):
+ client_port, server_port = self.getFreeAddresses()
+ class ServerThread(threading.Thread):
+ def __init__(self, client_port, server_port):
+ threading.Thread.__init__(self)
+ self.client_port = client_port
+ self.server_port = server_port
+
+ def run(self):
+ import pydev_localhost
+ print('Starting server with:', pydev_localhost.get_localhost(), self.server_port, self.client_port)
+ pydevconsole.StartServer(pydev_localhost.get_localhost(), self.server_port, self.client_port)
+ server_thread = ServerThread(client_port, server_port)
+ server_thread.setDaemon(True)
+ server_thread.start()
+
+ client_thread = self.startClientThread(client_port) #@UnusedVariable
+
+ import time
+ time.sleep(.3) #let's give it some time to start the threads
+
+ import pydev_localhost
+ server = xmlrpclib.Server('http://%s:%s' % (pydev_localhost.get_localhost(), server_port))
+ server.addExec("import sys; print('Running with: %s %s' % (sys.executable or sys.platform, sys.version))")
+ server.addExec('class Foo:')
+ server.addExec(' pass')
+ server.addExec('')
+ server.addExec('foo = Foo()')
+ server.addExec('a = %s()' % raw_input_name)
+ server.addExec('print (a)')
+
+#=======================================================================================================================
+# main
+#=======================================================================================================================
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/python/helpers/pydev/tests/test_get_referrers.py b/python/helpers/pydev/tests/test_get_referrers.py
new file mode 100644
index 000000000000..7fc85142b02e
--- /dev/null
+++ b/python/helpers/pydev/tests/test_get_referrers.py
@@ -0,0 +1,139 @@
+import os.path
+import sys
+import threading
+import time
+
+IS_JYTHON = sys.platform.find('java') != -1
+
+try:
+ this_file_name = __file__
+except NameError:
+ # stupid jython. plain old __file__ isnt working for some reason
+ import test_runfiles #@UnresolvedImport - importing the module itself
+ this_file_name = test_runfiles.__file__
+
+
+desired_runfiles_path = os.path.normpath(os.path.dirname(this_file_name) + "/..")
+sys.path.insert(0, desired_runfiles_path)
+
+import unittest
+import pydevd_referrers
+from pydev_imports import StringIO
+
+#=======================================================================================================================
+# Test
+#=======================================================================================================================
+class Test(unittest.TestCase):
+
+
+ def testGetReferrers1(self):
+
+ container = []
+ contained = [1, 2]
+ container.append(0)
+ container.append(contained)
+
+ # Ok, we have the contained in this frame and inside the given list (which on turn is in this frame too).
+ # we should skip temporary references inside the get_referrer_info.
+ result = pydevd_referrers.get_referrer_info(contained)
+ assert 'list[1]' in result
+ pydevd_referrers.print_referrers(contained, stream=StringIO())
+
+ def testGetReferrers2(self):
+
+ class MyClass(object):
+ def __init__(self):
+ pass
+
+ contained = [1, 2]
+ obj = MyClass()
+ obj.contained = contained
+ del contained
+
+ # Ok, we have the contained in this frame and inside the given list (which on turn is in this frame too).
+ # we should skip temporary references inside the get_referrer_info.
+ result = pydevd_referrers.get_referrer_info(obj.contained)
+ assert 'found_as="contained"' in result
+ assert 'MyClass' in result
+
+
+ def testGetReferrers3(self):
+
+ class MyClass(object):
+ def __init__(self):
+ pass
+
+ contained = [1, 2]
+ obj = MyClass()
+ obj.contained = contained
+ del contained
+
+ # Ok, we have the contained in this frame and inside the given list (which on turn is in this frame too).
+ # we should skip temporary references inside the get_referrer_info.
+ result = pydevd_referrers.get_referrer_info(obj.contained)
+ assert 'found_as="contained"' in result
+ assert 'MyClass' in result
+
+
+ def testGetReferrers4(self):
+
+ class MyClass(object):
+ def __init__(self):
+ pass
+
+ obj = MyClass()
+ obj.me = obj
+
+ # Let's see if we detect the cycle...
+ result = pydevd_referrers.get_referrer_info(obj)
+ assert 'found_as="me"' in result #Cyclic ref
+
+
+ def testGetReferrers5(self):
+ container = dict(a=[1])
+
+ # Let's see if we detect the cycle...
+ result = pydevd_referrers.get_referrer_info(container['a'])
+ assert 'testGetReferrers5' not in result #I.e.: NOT in the current method
+ assert 'found_as="a"' in result
+ assert 'dict' in result
+ assert str(id(container)) in result
+
+
+ def testGetReferrers6(self):
+ container = dict(a=[1])
+
+ def should_appear(obj):
+ # Let's see if we detect the cycle...
+ return pydevd_referrers.get_referrer_info(obj)
+
+ result = should_appear(container['a'])
+ assert 'should_appear' in result
+
+
+ def testGetReferrers7(self):
+
+ class MyThread(threading.Thread):
+ def run(self):
+ #Note: we do that because if we do
+ self.frame = sys._getframe()
+
+ t = MyThread()
+ t.start()
+ while not hasattr(t, 'frame'):
+ time.sleep(0.01)
+
+ result = pydevd_referrers.get_referrer_info(t.frame)
+ assert 'MyThread' in result
+
+
+if __name__ == "__main__":
+ #this is so that we can run it frem the jython tests -- because we don't actually have an __main__ module
+ #(so, it won't try importing the __main__ module)
+ try:
+ import gc
+ gc.get_referrers(unittest)
+ except:
+ pass
+ else:
+ unittest.TextTestRunner().run(unittest.makeSuite(Test))
diff --git a/python/helpers/pydev/tests/test_jyserver.py b/python/helpers/pydev/tests/test_jyserver.py
new file mode 100644
index 000000000000..8765400ae39d
--- /dev/null
+++ b/python/helpers/pydev/tests/test_jyserver.py
@@ -0,0 +1,165 @@
+'''
+@author Fabio Zadrozny
+'''
+import sys
+import unittest
+import socket
+import urllib
+
+
+IS_JYTHON = sys.platform.find('java') != -1
+
+if IS_JYTHON:
+ import os
+
+ #make it as if we were executing from the directory above this one (so that we can use jycompletionserver
+ #without the need for it being in the pythonpath)
+ sys.argv[0] = os.path.dirname(sys.argv[0])
+ #twice the dirname to get the previous level from this file.
+ sys.path.insert(1, os.path.join(os.path.dirname(sys.argv[0])))
+
+ import pycompletionserver as jycompletionserver
+
+
+ DEBUG = 0
+
+def dbg(s):
+ if DEBUG:
+ sys.stdout.write('TEST %s\n' % s)
+
+class Test(unittest.TestCase):
+
+ def setUp(self):
+ unittest.TestCase.setUp(self)
+
+ def tearDown(self):
+ unittest.TestCase.tearDown(self)
+
+ def testIt(self):
+ dbg('ok')
+
+ def testMessage(self):
+ t = jycompletionserver.T(0)
+
+ l = []
+ l.append(('Def', 'description' , 'args'))
+ l.append(('Def1', 'description1', 'args1'))
+ l.append(('Def2', 'description2', 'args2'))
+
+ msg = t.processor.formatCompletionMessage('test_jyserver.py', l)
+
+ self.assertEquals('@@COMPLETIONS(test_jyserver.py,(Def,description,args),(Def1,description1,args1),(Def2,description2,args2))END@@', msg)
+
+ l = []
+ l.append(('Def', 'desc,,r,,i()ption', ''))
+ l.append(('Def(1', 'descriptio(n1', ''))
+ l.append(('De,f)2', 'de,s,c,ription2', ''))
+ msg = t.processor.formatCompletionMessage(None, l)
+ expected = '@@COMPLETIONS(None,(Def,desc%2C%2Cr%2C%2Ci%28%29ption, ),(Def%281,descriptio%28n1, ),(De%2Cf%292,de%2Cs%2Cc%2Cription2, ))END@@'
+
+ self.assertEquals(expected, msg)
+
+
+
+
+
+
+ def testCompletionSocketsAndMessages(self):
+ dbg('testCompletionSocketsAndMessages')
+ t, socket = self.createConnections()
+ self.socket = socket
+ dbg('connections created')
+
+ try:
+ #now that we have the connections all set up, check the code completion messages.
+ msg = urllib.quote_plus('math')
+
+ toWrite = '@@IMPORTS:%sEND@@' % msg
+ dbg('writing' + str(toWrite))
+ socket.send(toWrite) #math completions
+ completions = self.readMsg()
+ dbg(urllib.unquote_plus(completions))
+
+ start = '@@COMPLETIONS('
+ self.assert_(completions.startswith(start), '%s DOESNT START WITH %s' % (completions, start))
+ self.assert_(completions.find('@@COMPLETIONS') != -1)
+ self.assert_(completions.find('END@@') != -1)
+
+
+ msg = urllib.quote_plus('__builtin__.str')
+ toWrite = '@@IMPORTS:%sEND@@' % msg
+ dbg('writing' + str(toWrite))
+ socket.send(toWrite) #math completions
+ completions = self.readMsg()
+ dbg(urllib.unquote_plus(completions))
+
+ start = '@@COMPLETIONS('
+ self.assert_(completions.startswith(start), '%s DOESNT START WITH %s' % (completions, start))
+ self.assert_(completions.find('@@COMPLETIONS') != -1)
+ self.assert_(completions.find('END@@') != -1)
+
+
+
+ finally:
+ try:
+ self.sendKillMsg(socket)
+
+
+ while not t.ended:
+ pass #wait until it receives the message and quits.
+
+
+ socket.close()
+ except:
+ pass
+
+
+
+
+ def createConnections(self, p1=50001):
+ '''
+ Creates the connections needed for testing.
+ '''
+ t = jycompletionserver.T(p1)
+
+ t.start()
+
+ server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ server.bind((jycompletionserver.HOST, p1))
+ server.listen(1)
+
+ sock, _addr = server.accept()
+
+ return t, sock
+
+
+ def readMsg(self):
+ msg = '@@PROCESSING_END@@'
+ while msg.startswith('@@PROCESSING'):
+ msg = self.socket.recv(1024)
+ if msg.startswith('@@PROCESSING:'):
+ dbg('Status msg:' + str(msg))
+
+ while msg.find('END@@') == -1:
+ msg += self.socket.recv(1024)
+
+ return msg
+
+ def sendKillMsg(self, socket):
+ socket.send(jycompletionserver.MSG_KILL_SERVER)
+
+
+
+
+#"C:\Program Files\Java\jdk1.5.0_04\bin\java.exe" -Dpython.path="C:\bin\jython21\Lib";"C:\bin\jython21";"C:\Program Files\Java\jdk1.5.0_04\jre\lib\rt.jar" -classpath C:/bin/jython21/jython.jar org.python.util.jython D:\eclipse_workspace\org.python.pydev\pysrc\pycompletionserver.py 53795 58659
+#
+#"C:\Program Files\Java\jdk1.5.0_04\bin\java.exe" -Dpython.path="C:\bin\jython21\Lib";"C:\bin\jython21";"C:\Program Files\Java\jdk1.5.0_04\jre\lib\rt.jar" -classpath C:/bin/jython21/jython.jar org.python.util.jython D:\eclipse_workspace\org.python.pydev\pysrc\tests\test_jyserver.py
+#
+#"C:\Program Files\Java\jdk1.5.0_04\bin\java.exe" -Dpython.path="C:\bin\jython21\Lib";"C:\bin\jython21";"C:\Program Files\Java\jdk1.5.0_04\jre\lib\rt.jar" -classpath C:/bin/jython21/jython.jar org.python.util.jython d:\runtime-workbench-workspace\jython_test\src\test.py
+if __name__ == '__main__':
+ if IS_JYTHON:
+ suite = unittest.makeSuite(Test)
+ unittest.TextTestRunner(verbosity=1).run(suite)
+ else:
+ sys.stdout.write('Not running jython tests for non-java platform: %s' % sys.platform)
+
diff --git a/python/helpers/pydev/tests/test_jysimpleTipper.py b/python/helpers/pydev/tests/test_jysimpleTipper.py
new file mode 100644
index 000000000000..4a755634bdc7
--- /dev/null
+++ b/python/helpers/pydev/tests/test_jysimpleTipper.py
@@ -0,0 +1,255 @@
+#line to run:
+#java -classpath D:\bin\jython-2.1\jython.jar;D:\bin\eclipse331_1\plugins\org.junit_3.8.2.v200706111738\junit.jar;D:\bin\eclipse331_1\plugins\org.apache.ant_1.7.0.v200706080842\lib\ant.jar org.python.util.jython w:\org.python.pydev\pysrc\tests\test_jysimpleTipper.py
+
+import unittest
+import os
+import sys
+#make it as if we were executing from the directory above this one (so that we can use pycompletionserver
+#without the need for it being in the pythonpath)
+sys.argv[0] = os.path.dirname(sys.argv[0])
+#twice the dirname to get the previous level from this file.
+sys.path.insert(1, os.path.join(os.path.dirname(sys.argv[0])))
+
+#this does not work (they must be in the system pythonpath)
+#sys.path.insert(1, r"D:\bin\eclipse321\plugins\org.junit_3.8.1\junit.jar" ) #some late loading jar tests
+#sys.path.insert(1, r"D:\bin\eclipse331_1\plugins\org.apache.ant_1.7.0.v200706080842\lib\ant.jar" ) #some late loading jar tests
+
+if sys.platform.find('java') != -1:
+ from _pydev_jy_imports_tipper import ismethod
+ from _pydev_jy_imports_tipper import isclass
+ from _pydev_jy_imports_tipper import dirObj
+ import _pydev_jy_imports_tipper
+ from java.lang.reflect import Method #@UnresolvedImport
+ from java.lang import System #@UnresolvedImport
+ from java.lang import String #@UnresolvedImport
+ from java.lang.System import arraycopy #@UnresolvedImport
+ from java.lang.System import out #@UnresolvedImport
+ import java.lang.String #@UnresolvedImport
+
+__DBG = 0
+def dbg(s):
+ if __DBG:
+ sys.stdout.write('%s\n' % (s,))
+
+
+
+class TestMod(unittest.TestCase):
+
+ def assertArgs(self, tok, args, tips):
+ for a in tips:
+ if tok == a[0]:
+ self.assertEquals(args, a[2])
+ return
+ raise AssertionError('%s not in %s', tok, tips)
+
+ def assertIn(self, tok, tips):
+ self.assertEquals(4, len(tips[0]))
+ for a in tips:
+ if tok == a[0]:
+ return a
+ s = ''
+ for a in tips:
+ s += str(a)
+ s += '\n'
+ raise AssertionError('%s not in %s' % (tok, s))
+
+ def testImports1a(self):
+ f, tip = _pydev_jy_imports_tipper.GenerateTip('java.util.HashMap')
+ assert f.endswith('rt.jar')
+
+ def testImports1c(self):
+ f, tip = _pydev_jy_imports_tipper.GenerateTip('java.lang.Class')
+ assert f.endswith('rt.jar')
+
+ def testImports1b(self):
+ try:
+ f, tip = _pydev_jy_imports_tipper.GenerateTip('__builtin__.m')
+ self.fail('err')
+ except:
+ pass
+
+ def testImports1(self):
+ f, tip = _pydev_jy_imports_tipper.GenerateTip('junit.framework.TestCase')
+ assert f.endswith('junit.jar')
+ ret = self.assertIn('assertEquals', tip)
+# self.assertEquals('', ret[2])
+
+ def testImports2(self):
+ f, tip = _pydev_jy_imports_tipper.GenerateTip('junit.framework')
+ assert f.endswith('junit.jar')
+ ret = self.assertIn('TestCase', tip)
+ self.assertEquals('', ret[2])
+
+ def testImports2a(self):
+ f, tip = _pydev_jy_imports_tipper.GenerateTip('org.apache.tools.ant')
+ assert f.endswith('ant.jar')
+ ret = self.assertIn('Task', tip)
+ self.assertEquals('', ret[2])
+
+ def testImports3(self):
+ f, tip = _pydev_jy_imports_tipper.GenerateTip('os')
+ assert f.endswith('os.py')
+ ret = self.assertIn('path', tip)
+ self.assertEquals('', ret[2])
+
+ def testTipOnString(self):
+ f, tip = _pydev_jy_imports_tipper.GenerateTip('string')
+ self.assertIn('join', tip)
+ self.assertIn('uppercase', tip)
+
+ def testImports(self):
+ tip = _pydev_jy_imports_tipper.GenerateTip('__builtin__')[1]
+ self.assertIn('tuple' , tip)
+ self.assertIn('RuntimeError' , tip)
+ self.assertIn('RuntimeWarning' , tip)
+
+ def testImports5(self):
+ f, tip = _pydev_jy_imports_tipper.GenerateTip('java.lang')
+ assert f.endswith('rt.jar')
+ tup = self.assertIn('String' , tip)
+ self.assertEquals(str(_pydev_jy_imports_tipper.TYPE_CLASS), tup[3])
+
+ tip = _pydev_jy_imports_tipper.GenerateTip('java')[1]
+ tup = self.assertIn('lang' , tip)
+ self.assertEquals(str(_pydev_jy_imports_tipper.TYPE_IMPORT), tup[3])
+
+ tip = _pydev_jy_imports_tipper.GenerateTip('java.lang.String')[1]
+ tup = self.assertIn('indexOf' , tip)
+ self.assertEquals(str(_pydev_jy_imports_tipper.TYPE_FUNCTION), tup[3])
+
+ tip = _pydev_jy_imports_tipper.GenerateTip('java.lang.String')[1]
+ tup = self.assertIn('charAt' , tip)
+ self.assertEquals(str(_pydev_jy_imports_tipper.TYPE_FUNCTION), tup[3])
+ self.assertEquals('(int)', tup[2])
+
+ tup = self.assertIn('format' , tip)
+ self.assertEquals(str(_pydev_jy_imports_tipper.TYPE_FUNCTION), tup[3])
+ self.assertEquals('(string, objectArray)', tup[2])
+ self.assert_(tup[1].find('[Ljava.lang.Object;') == -1)
+
+ tup = self.assertIn('getBytes' , tip)
+ self.assertEquals(str(_pydev_jy_imports_tipper.TYPE_FUNCTION), tup[3])
+ self.assert_(tup[1].find('[B') == -1)
+ self.assert_(tup[1].find('byte[]') != -1)
+
+ f, tip = _pydev_jy_imports_tipper.GenerateTip('__builtin__.str')
+ assert f.endswith('jython.jar')
+ self.assertIn('find' , tip)
+
+ f, tip = _pydev_jy_imports_tipper.GenerateTip('__builtin__.dict')
+ assert f.endswith('jython.jar')
+ self.assertIn('get' , tip)
+
+
+class TestSearch(unittest.TestCase):
+
+ def testSearchOnJython(self):
+ self.assertEqual('javaos.py', _pydev_jy_imports_tipper.Search('os')[0][0].split(os.sep)[-1])
+ self.assertEqual(0, _pydev_jy_imports_tipper.Search('os')[0][1])
+
+ self.assertEqual('javaos.py', _pydev_jy_imports_tipper.Search('os.makedirs')[0][0].split(os.sep)[-1])
+ self.assertNotEqual(0, _pydev_jy_imports_tipper.Search('os.makedirs')[0][1])
+
+ #print _pydev_jy_imports_tipper.Search('os.makedirs')
+
+class TestCompl(unittest.TestCase):
+
+ def setUp(self):
+ unittest.TestCase.setUp(self)
+
+ def tearDown(self):
+ unittest.TestCase.tearDown(self)
+
+ def testGettingInfoOnJython(self):
+
+ dbg('\n\n--------------------------- java')
+ assert not ismethod(java)[0]
+ assert not isclass(java)
+ assert _pydev_jy_imports_tipper.ismodule(java)
+
+ dbg('\n\n--------------------------- java.lang')
+ assert not ismethod(java.lang)[0]
+ assert not isclass(java.lang)
+ assert _pydev_jy_imports_tipper.ismodule(java.lang)
+
+ dbg('\n\n--------------------------- Method')
+ assert not ismethod(Method)[0]
+ assert isclass(Method)
+
+ dbg('\n\n--------------------------- System')
+ assert not ismethod(System)[0]
+ assert isclass(System)
+
+ dbg('\n\n--------------------------- String')
+ assert not ismethod(System)[0]
+ assert isclass(String)
+ assert len(dirObj(String)) > 10
+
+ dbg('\n\n--------------------------- arraycopy')
+ isMet = ismethod(arraycopy)
+ assert isMet[0]
+ assert isMet[1][0].basicAsStr() == "function:arraycopy args=['java.lang.Object', 'int', 'java.lang.Object', 'int', 'int'], varargs=None, kwargs=None, docs:None"
+ assert not isclass(arraycopy)
+
+ dbg('\n\n--------------------------- out')
+ isMet = ismethod(out)
+ assert not isMet[0]
+ assert not isclass(out)
+
+ dbg('\n\n--------------------------- out.println')
+ isMet = ismethod(out.println) #@UndefinedVariable
+ assert isMet[0]
+ assert len(isMet[1]) == 10
+ self.assertEquals(isMet[1][0].basicAsStr(), "function:println args=[], varargs=None, kwargs=None, docs:None")
+ assert isMet[1][1].basicAsStr() == "function:println args=['long'], varargs=None, kwargs=None, docs:None"
+ assert not isclass(out.println) #@UndefinedVariable
+
+ dbg('\n\n--------------------------- str')
+ isMet = ismethod(str)
+ #the code below should work, but is failing on jython 22a1
+ #assert isMet[0]
+ #assert isMet[1][0].basicAsStr() == "function:str args=['org.python.core.PyObject'], varargs=None, kwargs=None, docs:None"
+ assert not isclass(str)
+
+
+ def met1():
+ a = 3
+ return a
+
+ dbg('\n\n--------------------------- met1')
+ isMet = ismethod(met1)
+ assert isMet[0]
+ assert isMet[1][0].basicAsStr() == "function:met1 args=[], varargs=None, kwargs=None, docs:None"
+ assert not isclass(met1)
+
+ def met2(arg1, arg2, *vararg, **kwarg):
+ '''docmet2'''
+
+ a = 1
+ return a
+
+ dbg('\n\n--------------------------- met2')
+ isMet = ismethod(met2)
+ assert isMet[0]
+ assert isMet[1][0].basicAsStr() == "function:met2 args=['arg1', 'arg2'], varargs=vararg, kwargs=kwarg, docs:docmet2"
+ assert not isclass(met2)
+
+
+
+if __name__ == '__main__':
+ if sys.platform.find('java') != -1:
+ #Only run if jython
+ suite = unittest.makeSuite(TestCompl)
+ suite2 = unittest.makeSuite(TestMod)
+ suite3 = unittest.makeSuite(TestSearch)
+
+ unittest.TextTestRunner(verbosity=1).run(suite)
+ unittest.TextTestRunner(verbosity=1).run(suite2)
+ unittest.TextTestRunner(verbosity=1).run(suite3)
+
+# suite.addTest(Test('testCase12'))
+# suite = unittest.TestSuite()
+# unittest.TextTestRunner(verbosity=1).run(suite)
+
+ else:
+ sys.stdout.write('Not running jython tests for non-java platform: %s' % sys.platform)
diff --git a/python/helpers/pydev/tests/test_pydev_ipython_010.py b/python/helpers/pydev/tests/test_pydev_ipython_010.py
new file mode 100644
index 000000000000..5ce1dc32c34a
--- /dev/null
+++ b/python/helpers/pydev/tests/test_pydev_ipython_010.py
@@ -0,0 +1,80 @@
+#TODO: This test no longer works (check if it should be fixed or removed altogether).
+
+#import unittest
+#import sys
+#import os
+##make it as if we were executing from the directory above this one
+#sys.argv[0] = os.path.dirname(sys.argv[0])
+##twice the dirname to get the previous level from this file.
+#sys.path.insert(1, os.path.join(os.path.dirname(sys.argv[0])))
+#
+#from pydev_localhost import get_localhost
+#
+#
+#IS_JYTHON = sys.platform.find('java') != -1
+#
+##=======================================================================================================================
+## TestCase
+##=======================================================================================================================
+#class TestCase(unittest.TestCase):
+#
+# def setUp(self):
+# unittest.TestCase.setUp(self)
+#
+# def tearDown(self):
+# unittest.TestCase.tearDown(self)
+#
+# def testIPython(self):
+# try:
+# from pydev_ipython_console import PyDevFrontEnd
+# except:
+# if IS_JYTHON:
+# return
+# front_end = PyDevFrontEnd(get_localhost(), 0)
+#
+# front_end.input_buffer = 'if True:'
+# self.assert_(not front_end._on_enter())
+#
+# front_end.input_buffer = 'if True:\n' + \
+# front_end.continuation_prompt() + ' a = 10\n'
+# self.assert_(not front_end._on_enter())
+#
+#
+# front_end.input_buffer = 'if True:\n' + \
+# front_end.continuation_prompt() + ' a = 10\n\n'
+# self.assert_(front_end._on_enter())
+#
+#
+## front_end.input_buffer = ' print a'
+## self.assert_(not front_end._on_enter())
+## front_end.input_buffer = ''
+## self.assert_(front_end._on_enter())
+#
+#
+## front_end.input_buffer = 'a.'
+## front_end.complete_current_input()
+## front_end.input_buffer = 'if True:'
+## front_end._on_enter()
+# front_end.input_buffer = 'a = 30'
+# front_end._on_enter()
+# front_end.input_buffer = 'print a'
+# front_end._on_enter()
+# front_end.input_buffer = 'a?'
+# front_end._on_enter()
+# print front_end.complete('%')
+# print front_end.complete('%e')
+# print front_end.complete('cd c:/t')
+# print front_end.complete('cd c:/temp/')
+## front_end.input_buffer = 'print raw_input("press enter\\n")'
+## front_end._on_enter()
+##
+#
+##=======================================================================================================================
+## main
+##=======================================================================================================================
+#if __name__ == '__main__':
+# if sys.platform.find('java') == -1:
+# #IPython not available for Jython
+# unittest.main()
+# else:
+# print('not supported on Jython')
diff --git a/python/helpers/pydev/tests/test_pydev_ipython_011.py b/python/helpers/pydev/tests/test_pydev_ipython_011.py
new file mode 100644
index 000000000000..3cfa70fd0112
--- /dev/null
+++ b/python/helpers/pydev/tests/test_pydev_ipython_011.py
@@ -0,0 +1,193 @@
+import sys
+import unittest
+import threading
+import os
+from nose.tools import eq_
+from pydev_imports import StringIO, SimpleXMLRPCServer
+from pydev_localhost import get_localhost
+from pydev_console_utils import StdIn
+import socket
+
+# make it as if we were executing from the directory above this one
+sys.argv[0] = os.path.dirname(sys.argv[0])
+# twice the dirname to get the previous level from this file.
+sys.path.insert(1, os.path.join(os.path.dirname(sys.argv[0])))
+
+# PyDevFrontEnd depends on singleton in IPython, so you
+# can't make multiple versions. So we reuse front_end for
+# all the tests
+
+orig_stdout = sys.stdout
+orig_stderr = sys.stderr
+
+stdout = sys.stdout = StringIO()
+stderr = sys.stderr = StringIO()
+
+from pydev_ipython_console_011 import PyDevFrontEnd
+s = socket.socket()
+s.bind(('', 0))
+client_port = s.getsockname()[1]
+s.close()
+front_end = PyDevFrontEnd(get_localhost(), client_port)
+
+
+def addExec(code, expected_more=False):
+ more = front_end.addExec(code)
+ eq_(expected_more, more)
+
+class TestBase(unittest.TestCase):
+ def setUp(self):
+ front_end.input_splitter.reset()
+ stdout.truncate(0)
+ stdout.seek(0)
+ stderr.truncate(0)
+ stderr.seek(0)
+ def tearDown(self):
+ pass
+
+
+class TestPyDevFrontEnd(TestBase):
+ def testAddExec_1(self):
+ addExec('if True:', True)
+ def testAddExec_2(self):
+ addExec('if True:\n testAddExec_a = 10\n', True)
+ def testAddExec_3(self):
+ assert 'testAddExec_a' not in front_end.getNamespace()
+ addExec('if True:\n testAddExec_a = 10\n\n')
+ assert 'testAddExec_a' in front_end.getNamespace()
+ eq_(front_end.getNamespace()['testAddExec_a'], 10)
+
+ def testGetNamespace(self):
+ assert 'testGetNamespace_a' not in front_end.getNamespace()
+ addExec('testGetNamespace_a = 10')
+ assert 'testGetNamespace_a' in front_end.getNamespace()
+ eq_(front_end.getNamespace()['testGetNamespace_a'], 10)
+
+ def testComplete(self):
+ unused_text, matches = front_end.complete('%')
+ assert len(matches) > 1, 'at least one magic should appear in completions'
+
+ def testCompleteDoesNotDoPythonMatches(self):
+ # Test that IPython's completions do not do the things that
+ # PyDev's completions will handle
+ addExec('testComplete_a = 5')
+ addExec('testComplete_b = 10')
+ addExec('testComplete_c = 15')
+ unused_text, matches = front_end.complete('testComplete_')
+ assert len(matches) == 0
+
+ def testGetCompletions_1(self):
+ # Test the merged completions include the standard completions
+ addExec('testComplete_a = 5')
+ addExec('testComplete_b = 10')
+ addExec('testComplete_c = 15')
+ res = front_end.getCompletions('testComplete_', 'testComplete_')
+ matches = [f[0] for f in res]
+ assert len(matches) == 3
+ eq_(set(['testComplete_a', 'testComplete_b', 'testComplete_c']), set(matches))
+
+ def testGetCompletions_2(self):
+ # Test that we get IPython completions in results
+ # we do this by checking kw completion which PyDev does
+ # not do by default
+ addExec('def ccc(ABC=123): pass')
+ res = front_end.getCompletions('ccc(', '')
+ matches = [f[0] for f in res]
+ assert 'ABC=' in matches
+
+ def testGetCompletions_3(self):
+ # Test that magics return IPYTHON magic as type
+ res = front_end.getCompletions('%cd', '%cd')
+ assert len(res) == 1
+ eq_(res[0][3], '12') # '12' == IToken.TYPE_IPYTHON_MAGIC
+ assert len(res[0][1]) > 100, 'docstring for %cd should be a reasonably long string'
+
+class TestRunningCode(TestBase):
+ def testPrint(self):
+ addExec('print("output")')
+ eq_(stdout.getvalue(), 'output\n')
+
+ def testQuestionMark_1(self):
+ addExec('?')
+ assert len(stdout.getvalue()) > 1000, 'IPython help should be pretty big'
+
+ def testQuestionMark_2(self):
+ addExec('int?')
+ assert stdout.getvalue().find('Convert') != -1
+
+
+ def testGui(self):
+ from pydev_ipython.inputhook import get_inputhook, set_stdin_file
+ set_stdin_file(sys.stdin)
+ assert get_inputhook() is None
+ addExec('%gui tk')
+ # we can't test the GUI works here because we aren't connected to XML-RPC so
+ # nowhere for hook to run
+ assert get_inputhook() is not None
+ addExec('%gui none')
+ assert get_inputhook() is None
+
+ def testHistory(self):
+ ''' Make sure commands are added to IPython's history '''
+ addExec('a=1')
+ addExec('b=2')
+ _ih = front_end.getNamespace()['_ih']
+ eq_(_ih[-1], 'b=2')
+ eq_(_ih[-2], 'a=1')
+
+ addExec('history')
+ hist = stdout.getvalue().split('\n')
+ eq_(hist[-1], '')
+ eq_(hist[-2], 'history')
+ eq_(hist[-3], 'b=2')
+ eq_(hist[-4], 'a=1')
+
+ def testEdit(self):
+ ''' Make sure we can issue an edit command '''
+ called_RequestInput = [False]
+ called_IPythonEditor = [False]
+ def startClientThread(client_port):
+ class ClientThread(threading.Thread):
+ def __init__(self, client_port):
+ threading.Thread.__init__(self)
+ self.client_port = client_port
+ def run(self):
+ class HandleRequestInput:
+ def RequestInput(self):
+ called_RequestInput[0] = True
+ return '\n'
+ def IPythonEditor(self, name, line):
+ called_IPythonEditor[0] = (name, line)
+ return True
+
+ handle_request_input = HandleRequestInput()
+
+ import pydev_localhost
+ client_server = SimpleXMLRPCServer((pydev_localhost.get_localhost(), self.client_port), logRequests=False)
+ client_server.register_function(handle_request_input.RequestInput)
+ client_server.register_function(handle_request_input.IPythonEditor)
+ client_server.serve_forever()
+
+ client_thread = ClientThread(client_port)
+ client_thread.setDaemon(True)
+ client_thread.start()
+ return client_thread
+
+ startClientThread(client_port)
+ orig_stdin = sys.stdin
+ sys.stdin = StdIn(self, get_localhost(), client_port)
+ try:
+ filename = 'made_up_file.py'
+ addExec('%edit ' + filename)
+ eq_(called_IPythonEditor[0], (os.path.abspath(filename), 0))
+ assert called_RequestInput[0], "Make sure the 'wait' parameter has been respected"
+ finally:
+ sys.stdin = orig_stdin
+
+if __name__ == '__main__':
+
+ #Just doing: unittest.main() was not working for me when run directly (not sure why)
+ #And doing it the way below the test with the import: from pydev_ipython.inputhook import get_inputhook, set_stdin_file
+ #is failing (but if I do a Ctrl+F9 in PyDev to run it, it works properly, so, I'm a bit puzzled here).
+ unittest.TextTestRunner(verbosity=1).run(unittest.makeSuite(TestRunningCode))
+ unittest.TextTestRunner(verbosity=1).run(unittest.makeSuite(TestPyDevFrontEnd))
diff --git a/python/helpers/pydev/tests/test_pydevconsole.py b/python/helpers/pydev/tests/test_pydevconsole.py
new file mode 100644
index 000000000000..9a9e3edaf124
--- /dev/null
+++ b/python/helpers/pydev/tests/test_pydevconsole.py
@@ -0,0 +1,231 @@
+import threading
+import unittest
+import sys
+import os
+
+sys.argv[0] = os.path.dirname(sys.argv[0])
+sys.path.insert(1, os.path.join(os.path.dirname(sys.argv[0])))
+import pydevconsole
+from pydev_imports import xmlrpclib, SimpleXMLRPCServer, StringIO
+
+try:
+ raw_input
+ raw_input_name = 'raw_input'
+except NameError:
+ raw_input_name = 'input'
+
+#=======================================================================================================================
+# Test
+#=======================================================================================================================
+class Test(unittest.TestCase):
+
+ def setUp(self):
+ self.original_stdout = sys.stdout
+ sys.stdout = StringIO()
+
+
+ def tearDown(self):
+ ret = sys.stdout #@UnusedVariable
+ sys.stdout = self.original_stdout
+ #print_ ret.getvalue() -- use to see test output
+
+ def testConsoleHello(self):
+ client_port, _server_port = self.getFreeAddresses()
+ client_thread = self.startClientThread(client_port) #@UnusedVariable
+ import time
+ time.sleep(.3) #let's give it some time to start the threads
+
+ import pydev_localhost
+ interpreter = pydevconsole.InterpreterInterface(pydev_localhost.get_localhost(), client_port, server=None)
+
+ (result,) = interpreter.hello("Hello pydevconsole")
+ self.assertEqual(result, "Hello eclipse")
+
+
+ def testConsoleRequests(self):
+ client_port, _server_port = self.getFreeAddresses()
+ client_thread = self.startClientThread(client_port) #@UnusedVariable
+ import time
+ time.sleep(.3) #let's give it some time to start the threads
+
+ import pydev_localhost
+ interpreter = pydevconsole.InterpreterInterface(pydev_localhost.get_localhost(), client_port, server=None)
+ interpreter.addExec('class Foo:')
+ interpreter.addExec(' CONSTANT=1')
+ interpreter.addExec('')
+ interpreter.addExec('foo=Foo()')
+ interpreter.addExec('foo.__doc__=None')
+ interpreter.addExec('val = %s()' % (raw_input_name,))
+ interpreter.addExec('50')
+ interpreter.addExec('print (val)')
+ found = sys.stdout.getvalue().split()
+ try:
+ self.assertEqual(['50', 'input_request'], found)
+ except:
+ self.assertEqual(['input_request'], found) #IPython
+
+ comps = interpreter.getCompletions('foo.', 'foo.')
+ self.assert_(
+ ('CONSTANT', '', '', '3') in comps or ('CONSTANT', '', '', '4') in comps, \
+ 'Found: %s' % comps
+ )
+
+ comps = interpreter.getCompletions('"".', '"".')
+ self.assert_(
+ ('__add__', 'x.__add__(y) <==> x+y', '', '3') in comps or
+ ('__add__', '', '', '4') in comps or
+ ('__add__', 'x.__add__(y) <==> x+y\r\nx.__add__(y) <==> x+y', '()', '2') in comps or
+ ('__add__', 'x.\n__add__(y) <==> x+yx.\n__add__(y) <==> x+y', '()', '2'),
+ 'Did not find __add__ in : %s' % (comps,)
+ )
+
+
+ completions = interpreter.getCompletions('', '')
+ for c in completions:
+ if c[0] == 'AssertionError':
+ break
+ else:
+ self.fail('Could not find AssertionError')
+
+ completions = interpreter.getCompletions('Assert', 'Assert')
+ for c in completions:
+ if c[0] == 'RuntimeError':
+ self.fail('Did not expect to find RuntimeError there')
+
+ self.assert_(('__doc__', None, '', '3') not in interpreter.getCompletions('foo.CO', 'foo.'))
+
+ comps = interpreter.getCompletions('va', 'va')
+ self.assert_(('val', '', '', '3') in comps or ('val', '', '', '4') in comps)
+
+ interpreter.addExec('s = "mystring"')
+
+ desc = interpreter.getDescription('val')
+ self.assert_(desc.find('str(object) -> string') >= 0 or
+ desc == "'input_request'" or
+ desc.find('str(string[, encoding[, errors]]) -> str') >= 0 or
+ desc.find('str(Char* value)') >= 0 or
+ desc.find('str(value: Char*)') >= 0,
+ 'Could not find what was needed in %s' % desc)
+
+ desc = interpreter.getDescription('val.join')
+ self.assert_(desc.find('S.join(sequence) -> string') >= 0 or
+ desc.find('S.join(sequence) -> str') >= 0 or
+ desc.find('S.join(iterable) -> string') >= 0 or
+ desc == "<builtin method 'join'>" or
+ desc == "<built-in method join of str object>" or
+ desc.find('str join(str self, list sequence)') >= 0 or
+ desc.find('S.join(iterable) -> str') >= 0 or
+ desc.find('join(self: str, sequence: list) -> str') >= 0,
+ "Could not recognize: %s" % (desc,))
+
+
+ def startClientThread(self, client_port):
+ class ClientThread(threading.Thread):
+ def __init__(self, client_port):
+ threading.Thread.__init__(self)
+ self.client_port = client_port
+ def run(self):
+ class HandleRequestInput:
+ def RequestInput(self):
+ return 'input_request'
+
+ handle_request_input = HandleRequestInput()
+
+ import pydev_localhost
+ client_server = SimpleXMLRPCServer((pydev_localhost.get_localhost(), self.client_port), logRequests=False)
+ client_server.register_function(handle_request_input.RequestInput)
+ client_server.serve_forever()
+
+ client_thread = ClientThread(client_port)
+ client_thread.setDaemon(True)
+ client_thread.start()
+ return client_thread
+
+
+ def startDebuggerServerThread(self, debugger_port, socket_code):
+ class DebuggerServerThread(threading.Thread):
+ def __init__(self, debugger_port, socket_code):
+ threading.Thread.__init__(self)
+ self.debugger_port = debugger_port
+ self.socket_code = socket_code
+ def run(self):
+ import socket
+ s = socket.socket()
+ s.bind(('', debugger_port))
+ s.listen(1)
+ socket, unused_addr = s.accept()
+ socket_code(socket)
+
+ debugger_thread = DebuggerServerThread(debugger_port, socket_code)
+ debugger_thread.setDaemon(True)
+ debugger_thread.start()
+ return debugger_thread
+
+
+ def getFreeAddresses(self):
+ import socket
+ s = socket.socket()
+ s.bind(('', 0))
+ port0 = s.getsockname()[1]
+
+ s1 = socket.socket()
+ s1.bind(('', 0))
+ port1 = s1.getsockname()[1]
+ s.close()
+ s1.close()
+
+ if port0 <= 0 or port1 <= 0:
+ #This happens in Jython...
+ from java.net import ServerSocket
+ s0 = ServerSocket(0)
+ port0 = s0.getLocalPort()
+
+ s1 = ServerSocket(0)
+ port1 = s1.getLocalPort()
+
+ s0.close()
+ s1.close()
+
+ assert port0 != port1
+ assert port0 > 0
+ assert port1 > 0
+
+ return port0, port1
+
+
+ def testServer(self):
+ client_port, server_port = self.getFreeAddresses()
+ class ServerThread(threading.Thread):
+ def __init__(self, client_port, server_port):
+ threading.Thread.__init__(self)
+ self.client_port = client_port
+ self.server_port = server_port
+
+ def run(self):
+ import pydev_localhost
+ pydevconsole.StartServer(pydev_localhost.get_localhost(), self.server_port, self.client_port)
+ server_thread = ServerThread(client_port, server_port)
+ server_thread.setDaemon(True)
+ server_thread.start()
+
+ client_thread = self.startClientThread(client_port) #@UnusedVariable
+
+ import time
+ time.sleep(.3) #let's give it some time to start the threads
+
+ import pydev_localhost
+ server = xmlrpclib.Server('http://%s:%s' % (pydev_localhost.get_localhost(), server_port))
+ server.addExec('class Foo:')
+ server.addExec(' pass')
+ server.addExec('')
+ server.addExec('foo = Foo()')
+ server.addExec('a = %s()' % (raw_input_name,))
+ server.addExec('print (a)')
+ self.assertEqual(['input_request'], sys.stdout.getvalue().split())
+
+#=======================================================================================================================
+# main
+#=======================================================================================================================
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/python/helpers/pydev/tests/test_pyserver.py b/python/helpers/pydev/tests/test_pyserver.py
new file mode 100644
index 000000000000..a74876b8c8b9
--- /dev/null
+++ b/python/helpers/pydev/tests/test_pyserver.py
@@ -0,0 +1,173 @@
+'''
+@author Fabio Zadrozny
+'''
+import sys
+import os
+
+#make it as if we were executing from the directory above this one (so that we can use pycompletionserver
+#without the need for it being in the pythonpath)
+sys.argv[0] = os.path.dirname(sys.argv[0])
+#twice the dirname to get the previous level from this file.
+sys.path.insert(1, os.path.join(os.path.dirname(sys.argv[0])))
+
+IS_PYTHON_3K = 0
+if sys.platform.find('java') == -1:
+
+
+ try:
+ import inspect
+ import pycompletionserver
+ import socket
+ try:
+ from urllib import quote_plus, unquote_plus
+ def send(s, msg):
+ s.send(msg)
+ except ImportError:
+ IS_PYTHON_3K = 1
+ from urllib.parse import quote_plus, unquote_plus #Python 3.0
+ def send(s, msg):
+ s.send(bytearray(msg, 'utf-8'))
+ except ImportError:
+ pass #Not available in jython
+
+ import unittest
+
+ class Test(unittest.TestCase):
+
+ def setUp(self):
+ unittest.TestCase.setUp(self)
+
+ def tearDown(self):
+ unittest.TestCase.tearDown(self)
+
+ def testMessage(self):
+ t = pycompletionserver.T(0)
+
+ l = []
+ l.append(('Def', 'description' , 'args'))
+ l.append(('Def1', 'description1', 'args1'))
+ l.append(('Def2', 'description2', 'args2'))
+
+ msg = t.processor.formatCompletionMessage(None, l)
+ self.assertEquals('@@COMPLETIONS(None,(Def,description,args),(Def1,description1,args1),(Def2,description2,args2))END@@', msg)
+
+ l = []
+ l.append(('Def', 'desc,,r,,i()ption', ''))
+ l.append(('Def(1', 'descriptio(n1', ''))
+ l.append(('De,f)2', 'de,s,c,ription2', ''))
+ msg = t.processor.formatCompletionMessage(None, l)
+ self.assertEquals('@@COMPLETIONS(None,(Def,desc%2C%2Cr%2C%2Ci%28%29ption, ),(Def%281,descriptio%28n1, ),(De%2Cf%292,de%2Cs%2Cc%2Cription2, ))END@@', msg)
+
+ def createConnections(self, p1=50002):
+ '''
+ Creates the connections needed for testing.
+ '''
+ t = pycompletionserver.T(p1)
+
+ t.start()
+
+ server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ server.bind((pycompletionserver.HOST, p1))
+ server.listen(1) #socket to receive messages.
+
+ s, addr = server.accept()
+
+ return t, s
+
+
+ def readMsg(self):
+ finish = False
+ msg = ''
+ while finish == False:
+ m = self.socket.recv(1024 * 4)
+ if IS_PYTHON_3K:
+ m = m.decode('utf-8')
+ if m.startswith('@@PROCESSING'):
+ sys.stdout.write('Status msg: %s\n' % (msg,))
+ else:
+ msg += m
+
+ if msg.find('END@@') != -1:
+ finish = True
+
+ return msg
+
+ def testCompletionSocketsAndMessages(self):
+ t, socket = self.createConnections()
+ self.socket = socket
+
+ try:
+ #now that we have the connections all set up, check the code completion messages.
+ msg = quote_plus('math')
+ send(socket, '@@IMPORTS:%sEND@@' % msg) #math completions
+ completions = self.readMsg()
+ #print_ unquote_plus(completions)
+
+ #math is a builtin and because of that, it starts with None as a file
+ start = '@@COMPLETIONS(None,(__doc__,'
+ start_2 = '@@COMPLETIONS(None,(__name__,'
+ self.assert_(completions.startswith(start) or completions.startswith(start_2), '%s DOESNT START WITH %s' % (completions, (start, start_2)))
+
+ self.assert_('@@COMPLETIONS' in completions)
+ self.assert_('END@@' in completions)
+
+
+ #now, test i
+ msg = quote_plus('__builtin__.list')
+ send(socket, "@@IMPORTS:%s\nEND@@" % msg)
+ found = self.readMsg()
+ self.assert_('sort' in found, 'Could not find sort in: %s' % (found,))
+
+ #now, test search
+ msg = quote_plus('inspect.ismodule')
+ send(socket, '@@SEARCH%sEND@@' % msg) #math completions
+ found = self.readMsg()
+ self.assert_('inspect.py' in found)
+ self.assert_('33' in found or '34' in found or '51' in found or '50' in found, 'Could not find 33, 34, 50 or 51 in %s' % found)
+
+ #now, test search
+ msg = quote_plus('inspect.CO_NEWLOCALS')
+ send(socket, '@@SEARCH%sEND@@' % msg) #math completions
+ found = self.readMsg()
+ self.assert_('inspect.py' in found)
+ self.assert_('CO_NEWLOCALS' in found)
+
+ #now, test search
+ msg = quote_plus('inspect.BlockFinder.tokeneater')
+ send(socket, '@@SEARCH%sEND@@' % msg)
+ found = self.readMsg()
+ self.assert_('inspect.py' in found)
+ # self.assert_('CO_NEWLOCALS' in found)
+
+ #reload modules test
+ # send(socket, '@@RELOAD_MODULES_END@@')
+ # ok = self.readMsg()
+ # self.assertEquals('@@MSG_OK_END@@' , ok)
+ # this test is not executed because it breaks our current enviroment.
+
+
+ finally:
+ try:
+ sys.stdout.write('succedded...sending kill msg\n')
+ self.sendKillMsg(socket)
+
+
+ # while not hasattr(t, 'ended'):
+ # pass #wait until it receives the message and quits.
+
+
+ socket.close()
+ self.socket.close()
+ except:
+ pass
+
+ def sendKillMsg(self, socket):
+ socket.send(pycompletionserver.MSG_KILL_SERVER)
+
+
+if __name__ == '__main__':
+ if sys.platform.find('java') == -1:
+ unittest.main()
+ else:
+ sys.stdout.write('Not running python tests in platform: %s\n' % (sys.platform,))
+
diff --git a/python/helpers/pydev/tests/test_simpleTipper.py b/python/helpers/pydev/tests/test_simpleTipper.py
new file mode 100644
index 000000000000..f759ad60f678
--- /dev/null
+++ b/python/helpers/pydev/tests/test_simpleTipper.py
@@ -0,0 +1,209 @@
+'''
+@author Fabio Zadrozny
+'''
+import os
+import sys
+#make it as if we were executing from the directory above this one (so that we can use pycompletionserver
+#without the need for it being in the pythonpath)
+#twice the dirname to get the previous level from this file.
+sys.path.insert(1, os.path.split(os.path.split(__file__)[0])[0])
+
+try:
+ import __builtin__ #@UnusedImport
+ BUILTIN_MOD = '__builtin__'
+except ImportError:
+ BUILTIN_MOD = 'builtins'
+
+
+if sys.platform.find('java') == -1:
+
+ HAS_WX = False
+
+ import unittest
+ import _pydev_imports_tipper
+ import inspect
+
+ class Test(unittest.TestCase):
+
+ def p(self, t):
+ for a in t:
+ sys.stdout.write('%s\n' % (a,))
+
+ def testImports3(self):
+ tip = _pydev_imports_tipper.GenerateTip('os')
+ ret = self.assertIn('path', tip)
+ self.assertEquals('', ret[2])
+
+ def testImports2(self):
+ try:
+ tip = _pydev_imports_tipper.GenerateTip('OpenGL.GLUT')
+ self.assertIn('glutDisplayFunc', tip)
+ self.assertIn('glutInitDisplayMode', tip)
+ except ImportError:
+ pass
+
+ def testImports4(self):
+ try:
+ tip = _pydev_imports_tipper.GenerateTip('mx.DateTime.mxDateTime.mxDateTime')
+ self.assertIn('now', tip)
+ except ImportError:
+ pass
+
+ def testImports5(self):
+ tip = _pydev_imports_tipper.GenerateTip('__builtin__.list')
+ s = self.assertIn('sort', tip)
+ self.CheckArgs(
+ s,
+ '(cmp=None, key=None, reverse=False)',
+ '(self, object cmp, object key, bool reverse)',
+ '(self, cmp: object, key: object, reverse: bool)'
+ )
+
+ def testImports2a(self):
+ tips = _pydev_imports_tipper.GenerateTip('%s.RuntimeError' % BUILTIN_MOD)
+ self.assertIn('__doc__', tips)
+
+ def testImports2b(self):
+ tips = _pydev_imports_tipper.GenerateTip('%s' % BUILTIN_MOD)
+ t = self.assertIn('file' , tips)
+ self.assert_('->' in t[1].strip() or 'file' in t[1])
+
+ def testImports2c(self):
+ tips = _pydev_imports_tipper.GenerateTip('%s.file' % BUILTIN_MOD)
+ t = self.assertIn('readlines' , tips)
+ self.assert_('->' in t[1] or 'sizehint' in t[1])
+
+ def testImports(self):
+ '''
+ You can print_ the results to check...
+ '''
+ if HAS_WX:
+ tip = _pydev_imports_tipper.GenerateTip('wxPython.wx')
+ self.assertIn('wxApp' , tip)
+
+ tip = _pydev_imports_tipper.GenerateTip('wxPython.wx.wxApp')
+
+ try:
+ tip = _pydev_imports_tipper.GenerateTip('qt')
+ self.assertIn('QWidget' , tip)
+ self.assertIn('QDialog' , tip)
+
+ tip = _pydev_imports_tipper.GenerateTip('qt.QWidget')
+ self.assertIn('rect' , tip)
+ self.assertIn('rect' , tip)
+ self.assertIn('AltButton' , tip)
+
+ tip = _pydev_imports_tipper.GenerateTip('qt.QWidget.AltButton')
+ self.assertIn('__xor__' , tip)
+
+ tip = _pydev_imports_tipper.GenerateTip('qt.QWidget.AltButton.__xor__')
+ self.assertIn('__class__' , tip)
+ except ImportError:
+ pass
+
+ tip = _pydev_imports_tipper.GenerateTip(BUILTIN_MOD)
+ # for t in tip[1]:
+ # print_ t
+ self.assertIn('object' , tip)
+ self.assertIn('tuple' , tip)
+ self.assertIn('list' , tip)
+ self.assertIn('RuntimeError' , tip)
+ self.assertIn('RuntimeWarning' , tip)
+
+ t = self.assertIn('cmp' , tip)
+
+ self.CheckArgs(t, '(x, y)', '(object x, object y)', '(x: object, y: object)') #args
+
+ t = self.assertIn('isinstance' , tip)
+ self.CheckArgs(t, '(object, class_or_type_or_tuple)', '(object o, type typeinfo)', '(o: object, typeinfo: type)') #args
+
+ t = self.assertIn('compile' , tip)
+ self.CheckArgs(t, '(source, filename, mode)', '()', '(o: object, name: str, val: object)') #args
+
+ t = self.assertIn('setattr' , tip)
+ self.CheckArgs(t, '(object, name, value)', '(object o, str name, object val)', '(o: object, name: str, val: object)') #args
+
+ try:
+ import compiler
+ compiler_module = 'compiler'
+ except ImportError:
+ try:
+ import ast
+ compiler_module = 'ast'
+ except ImportError:
+ compiler_module = None
+
+ if compiler_module is not None: #Not available in iron python
+ tip = _pydev_imports_tipper.GenerateTip(compiler_module)
+ if compiler_module == 'compiler':
+ self.assertArgs('parse', '(buf, mode)', tip)
+ self.assertArgs('walk', '(tree, visitor, walker, verbose)', tip)
+ self.assertIn('parseFile' , tip)
+ else:
+ self.assertArgs('parse', '(source, filename, mode)', tip)
+ self.assertArgs('walk', '(node)', tip)
+ self.assertIn('parse' , tip)
+
+
+ def CheckArgs(self, t, *expected):
+ for x in expected:
+ if x == t[2]:
+ return
+ self.fail('Found: %s. Expected: %s' % (t[2], expected))
+
+
+ def assertArgs(self, tok, args, tips):
+ for a in tips[1]:
+ if tok == a[0]:
+ self.assertEquals(args, a[2])
+ return
+ raise AssertionError('%s not in %s', tok, tips)
+
+ def assertIn(self, tok, tips):
+ for a in tips[1]:
+ if tok == a[0]:
+ return a
+ raise AssertionError('%s not in %s' % (tok, tips))
+
+
+ def testSearch(self):
+ s = _pydev_imports_tipper.Search('inspect.ismodule')
+ (f, line, col), foundAs = s
+ self.assert_(line > 0)
+
+
+ def testDotNetLibraries(self):
+ if sys.platform == 'cli':
+ tip = _pydev_imports_tipper.GenerateTip('System.Drawing')
+ self.assertIn('Brushes' , tip)
+
+ tip = _pydev_imports_tipper.GenerateTip('System.Drawing.Brushes')
+ self.assertIn('Aqua' , tip)
+
+
+ def testInspect(self):
+
+ class C(object):
+ def metA(self, a, b):
+ pass
+
+ obj = C.metA
+ if inspect.ismethod (obj):
+ pass
+ # print_ obj.im_func
+ # print_ inspect.getargspec(obj.im_func)
+
+
+ def suite():
+ s = unittest.TestSuite()
+ s.addTest(Test("testImports5"))
+ unittest.TextTestRunner(verbosity=2).run(s)
+
+
+if __name__ == '__main__':
+ if sys.platform.find('java') == -1:
+# suite()
+ unittest.main()
+ else:
+ sys.stdout.write('Not running python tests in platform: %s\n' % (sys.platform,))
+
diff --git a/python/helpers/pydev/tests_mainloop/README b/python/helpers/pydev/tests_mainloop/README
new file mode 100644
index 000000000000..65e699b98e55
--- /dev/null
+++ b/python/helpers/pydev/tests_mainloop/README
@@ -0,0 +1,4 @@
+# Parts of IPython, files from: https://github.com/ipython/ipython/tree/rel-1.0.0/examples/lib
+# The files in this folder are manual tests for main loop integration
+
+# These tests have been modified to work in the PyDev Console context
diff --git a/python/helpers/pydev/tests_mainloop/__not_in_default_pythonpath.txt b/python/helpers/pydev/tests_mainloop/__not_in_default_pythonpath.txt
new file mode 100644
index 000000000000..29cdc5bc1078
--- /dev/null
+++ b/python/helpers/pydev/tests_mainloop/__not_in_default_pythonpath.txt
@@ -0,0 +1 @@
+(no __init__.py file) \ No newline at end of file
diff --git a/python/helpers/pydev/tests_mainloop/gui-glut.py b/python/helpers/pydev/tests_mainloop/gui-glut.py
new file mode 100644
index 000000000000..f05a4bc0beaf
--- /dev/null
+++ b/python/helpers/pydev/tests_mainloop/gui-glut.py
@@ -0,0 +1,50 @@
+#!/usr/bin/env python
+"""Simple GLUT example to manually test event loop integration.
+
+To run this:
+1) Enable the PyDev GUI event loop integration for glut
+2) do an execfile on this script
+3) ensure you have a working GUI simultaneously with an
+ interactive console
+4) run: gl.glClearColor(1,1,1,1)
+"""
+
+#!/usr/bin/env python
+import sys
+import OpenGL.GL as gl
+import OpenGL.GLUT as glut
+
+def close():
+ glut.glutDestroyWindow(glut.glutGetWindow())
+
+def display():
+ gl.glClear (gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)
+ glut.glutSwapBuffers()
+
+def resize(width,height):
+ gl.glViewport(0, 0, width, height+4)
+ gl.glMatrixMode(gl.GL_PROJECTION)
+ gl.glLoadIdentity()
+ gl.glOrtho(0, width, 0, height+4, -1, 1)
+ gl.glMatrixMode(gl.GL_MODELVIEW)
+
+if glut.glutGetWindow() > 0:
+ interactive = True
+ glut.glutInit(sys.argv)
+ glut.glutInitDisplayMode(glut.GLUT_DOUBLE |
+ glut.GLUT_RGBA |
+ glut.GLUT_DEPTH)
+else:
+ interactive = False
+
+glut.glutCreateWindow('gui-glut')
+glut.glutDisplayFunc(display)
+glut.glutReshapeFunc(resize)
+# This is necessary on osx to be able to close the window
+# (else the close button is disabled)
+if sys.platform == 'darwin' and not bool(glut.HAVE_FREEGLUT):
+ glut.glutWMCloseFunc(close)
+gl.glClearColor(0,0,0,1)
+
+if not interactive:
+ glut.glutMainLoop()
diff --git a/python/helpers/pydev/tests_mainloop/gui-gtk.py b/python/helpers/pydev/tests_mainloop/gui-gtk.py
new file mode 100644
index 000000000000..978f8f9a25f3
--- /dev/null
+++ b/python/helpers/pydev/tests_mainloop/gui-gtk.py
@@ -0,0 +1,34 @@
+#!/usr/bin/env python
+"""Simple GTK example to manually test event loop integration.
+
+To run this:
+1) Enable the PyDev GUI event loop integration for gtk
+2) do an execfile on this script
+3) ensure you have a working GUI simultaneously with an
+ interactive console
+"""
+
+import pygtk
+pygtk.require('2.0')
+import gtk
+
+
+def hello_world(wigdet, data=None):
+ print("Hello World")
+
+def delete_event(widget, event, data=None):
+ return False
+
+def destroy(widget, data=None):
+ gtk.main_quit()
+
+window = gtk.Window(gtk.WINDOW_TOPLEVEL)
+window.connect("delete_event", delete_event)
+window.connect("destroy", destroy)
+button = gtk.Button("Hello World")
+button.connect("clicked", hello_world, None)
+
+window.add(button)
+button.show()
+window.show()
+
diff --git a/python/helpers/pydev/tests_mainloop/gui-gtk3.py b/python/helpers/pydev/tests_mainloop/gui-gtk3.py
new file mode 100644
index 000000000000..a787f7ee9e65
--- /dev/null
+++ b/python/helpers/pydev/tests_mainloop/gui-gtk3.py
@@ -0,0 +1,32 @@
+#!/usr/bin/env python
+"""Simple Gtk example to manually test event loop integration.
+
+To run this:
+1) Enable the PyDev GUI event loop integration for gtk3
+2) do an execfile on this script
+3) ensure you have a working GUI simultaneously with an
+ interactive console
+"""
+
+from gi.repository import Gtk
+
+
+def hello_world(wigdet, data=None):
+ print("Hello World")
+
+def delete_event(widget, event, data=None):
+ return False
+
+def destroy(widget, data=None):
+ Gtk.main_quit()
+
+window = Gtk.Window(Gtk.WindowType.TOPLEVEL)
+window.connect("delete_event", delete_event)
+window.connect("destroy", destroy)
+button = Gtk.Button("Hello World")
+button.connect("clicked", hello_world, None)
+
+window.add(button)
+button.show()
+window.show()
+
diff --git a/python/helpers/pydev/tests_mainloop/gui-pyglet.py b/python/helpers/pydev/tests_mainloop/gui-pyglet.py
new file mode 100644
index 000000000000..b646093e0967
--- /dev/null
+++ b/python/helpers/pydev/tests_mainloop/gui-pyglet.py
@@ -0,0 +1,27 @@
+#!/usr/bin/env python
+"""Simple pyglet example to manually test event loop integration.
+
+To run this:
+1) Enable the PyDev GUI event loop integration for pyglet
+2) do an execfile on this script
+3) ensure you have a working GUI simultaneously with an
+ interactive console
+"""
+
+import pyglet
+
+
+window = pyglet.window.Window()
+label = pyglet.text.Label('Hello, world',
+ font_name='Times New Roman',
+ font_size=36,
+ x=window.width//2, y=window.height//2,
+ anchor_x='center', anchor_y='center')
+@window.event
+def on_close():
+ window.close()
+
+@window.event
+def on_draw():
+ window.clear()
+ label.draw()
diff --git a/python/helpers/pydev/tests_mainloop/gui-qt.py b/python/helpers/pydev/tests_mainloop/gui-qt.py
new file mode 100644
index 000000000000..c27cbd6ff1e6
--- /dev/null
+++ b/python/helpers/pydev/tests_mainloop/gui-qt.py
@@ -0,0 +1,35 @@
+#!/usr/bin/env python
+"""Simple Qt4 example to manually test event loop integration.
+
+To run this:
+1) Enable the PyDev GUI event loop integration for qt
+2) do an execfile on this script
+3) ensure you have a working GUI simultaneously with an
+ interactive console
+
+Ref: Modified from http://zetcode.com/tutorials/pyqt4/firstprograms/
+"""
+
+import sys
+from PyQt4 import QtGui, QtCore
+
+class SimpleWindow(QtGui.QWidget):
+ def __init__(self, parent=None):
+ QtGui.QWidget.__init__(self, parent)
+
+ self.setGeometry(300, 300, 200, 80)
+ self.setWindowTitle('Hello World')
+
+ quit = QtGui.QPushButton('Close', self)
+ quit.setGeometry(10, 10, 60, 35)
+
+ self.connect(quit, QtCore.SIGNAL('clicked()'),
+ self, QtCore.SLOT('close()'))
+
+if __name__ == '__main__':
+ app = QtCore.QCoreApplication.instance()
+ if app is None:
+ app = QtGui.QApplication([])
+
+ sw = SimpleWindow()
+ sw.show()
diff --git a/python/helpers/pydev/tests_mainloop/gui-tk.py b/python/helpers/pydev/tests_mainloop/gui-tk.py
new file mode 100644
index 000000000000..69ceb0b9f053
--- /dev/null
+++ b/python/helpers/pydev/tests_mainloop/gui-tk.py
@@ -0,0 +1,31 @@
+#!/usr/bin/env python
+"""Simple Tk example to manually test event loop integration.
+
+To run this:
+1) Enable the PyDev GUI event loop integration for tk
+2) do an execfile on this script
+3) ensure you have a working GUI simultaneously with an
+ interactive console
+"""
+
+try:
+ from Tkinter import *
+except:
+ # Python 3
+ from tkinter import *
+
+class MyApp:
+
+ def __init__(self, root):
+ frame = Frame(root)
+ frame.pack()
+
+ self.button = Button(frame, text="Hello", command=self.hello_world)
+ self.button.pack(side=LEFT)
+
+ def hello_world(self):
+ print("Hello World!")
+
+root = Tk()
+
+app = MyApp(root)
diff --git a/python/helpers/pydev/tests_mainloop/gui-wx.py b/python/helpers/pydev/tests_mainloop/gui-wx.py
new file mode 100644
index 000000000000..2101e7f214d4
--- /dev/null
+++ b/python/helpers/pydev/tests_mainloop/gui-wx.py
@@ -0,0 +1,101 @@
+#!/usr/bin/env python
+"""
+A Simple wx example to test PyDev's event loop integration.
+
+To run this:
+1) Enable the PyDev GUI event loop integration for wx
+2) do an execfile on this script
+3) ensure you have a working GUI simultaneously with an
+ interactive console
+
+Ref: Modified from wxPython source code wxPython/samples/simple/simple.py
+"""
+
+import wx
+
+
+class MyFrame(wx.Frame):
+ """
+ This is MyFrame. It just shows a few controls on a wxPanel,
+ and has a simple menu.
+ """
+ def __init__(self, parent, title):
+ wx.Frame.__init__(self, parent, -1, title,
+ pos=(150, 150), size=(350, 200))
+
+ # Create the menubar
+ menuBar = wx.MenuBar()
+
+ # and a menu
+ menu = wx.Menu()
+
+ # add an item to the menu, using \tKeyName automatically
+ # creates an accelerator, the third param is some help text
+ # that will show up in the statusbar
+ menu.Append(wx.ID_EXIT, "E&xit\tAlt-X", "Exit this simple sample")
+
+ # bind the menu event to an event handler
+ self.Bind(wx.EVT_MENU, self.OnTimeToClose, id=wx.ID_EXIT)
+
+ # and put the menu on the menubar
+ menuBar.Append(menu, "&File")
+ self.SetMenuBar(menuBar)
+
+ self.CreateStatusBar()
+
+ # Now create the Panel to put the other controls on.
+ panel = wx.Panel(self)
+
+ # and a few controls
+ text = wx.StaticText(panel, -1, "Hello World!")
+ text.SetFont(wx.Font(14, wx.SWISS, wx.NORMAL, wx.BOLD))
+ text.SetSize(text.GetBestSize())
+ btn = wx.Button(panel, -1, "Close")
+ funbtn = wx.Button(panel, -1, "Just for fun...")
+
+ # bind the button events to handlers
+ self.Bind(wx.EVT_BUTTON, self.OnTimeToClose, btn)
+ self.Bind(wx.EVT_BUTTON, self.OnFunButton, funbtn)
+
+ # Use a sizer to layout the controls, stacked vertically and with
+ # a 10 pixel border around each
+ sizer = wx.BoxSizer(wx.VERTICAL)
+ sizer.Add(text, 0, wx.ALL, 10)
+ sizer.Add(btn, 0, wx.ALL, 10)
+ sizer.Add(funbtn, 0, wx.ALL, 10)
+ panel.SetSizer(sizer)
+ panel.Layout()
+
+
+ def OnTimeToClose(self, evt):
+ """Event handler for the button click."""
+ print("See ya later!")
+ self.Close()
+
+ def OnFunButton(self, evt):
+ """Event handler for the button click."""
+ print("Having fun yet?")
+
+
+class MyApp(wx.App):
+ def OnInit(self):
+ frame = MyFrame(None, "Simple wxPython App")
+ self.SetTopWindow(frame)
+
+ print("Print statements go to this stdout window by default.")
+
+ frame.Show(True)
+ return True
+
+
+if __name__ == '__main__':
+
+ app = wx.GetApp()
+ if app is None:
+ app = MyApp(redirect=False, clearSigInt=False)
+ else:
+ frame = MyFrame(None, "Simple wxPython App")
+ app.SetTopWindow(frame)
+ print("Print statements go to this stdout window by default.")
+ frame.Show(True)
+
diff --git a/python/helpers/pydev/tests_python/__not_in_default_pythonpath.txt b/python/helpers/pydev/tests_python/__not_in_default_pythonpath.txt
new file mode 100644
index 000000000000..29cdc5bc1078
--- /dev/null
+++ b/python/helpers/pydev/tests_python/__not_in_default_pythonpath.txt
@@ -0,0 +1 @@
+(no __init__.py file) \ No newline at end of file
diff --git a/python/helpers/pydev/tests_python/_debugger_case1.py b/python/helpers/pydev/tests_python/_debugger_case1.py
new file mode 100644
index 000000000000..964d951f382f
--- /dev/null
+++ b/python/helpers/pydev/tests_python/_debugger_case1.py
@@ -0,0 +1,61 @@
+import sys
+import weakref
+
+def SetUp():
+ observable = Observable()
+ observer = Observer()
+ observable.AddObserver(observer)
+ return observable
+
+
+class Observable(object):
+ def __init__(self):
+ self.observers = []
+
+ def AddObserver(self, observer):
+ sys.stdout.write( 'observer %s\n' % (observer,))
+ ref = weakref.ref(observer)
+ self.observers.append(ref)
+ sys.stdout.write('weakref: %s\n' % (ref(),))
+
+ def Notify(self):
+ for o in self.observers:
+ o = o()
+
+
+ try:
+ import gc
+ except ImportError:
+ o = None #some jython does not have gc, so, there's no sense testing this in it
+ else:
+ try:
+ gc.get_referrers(o)
+ except:
+ o = None #jython and ironpython do not have get_referrers
+
+ if o is not None:
+ sys.stdout.write('still observing %s\n' % (o,))
+ sys.stdout.write('number of referrers: %s\n' % len(gc.get_referrers(o)))
+ frame = gc.get_referrers(o)[0]
+ frame_referrers = gc.get_referrers(frame)
+ sys.stdout.write('frame referrer %s\n' % (frame_referrers,))
+ referrers1 = gc.get_referrers(frame_referrers[1])
+ sys.stdout.write('%s\n' % (referrers1,))
+ sys.stderr.write('TEST FAILED: The observer should have died, even when running in debug\n')
+ else:
+ sys.stdout.write('TEST SUCEEDED: observer died\n')
+
+ sys.stdout.flush()
+ sys.stderr.flush()
+
+class Observer(object):
+ pass
+
+
+def main():
+ observable = SetUp()
+ observable.Notify()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/python/helpers/pydev/tests_python/_debugger_case10.py b/python/helpers/pydev/tests_python/_debugger_case10.py
new file mode 100644
index 000000000000..323dedaafbad
--- /dev/null
+++ b/python/helpers/pydev/tests_python/_debugger_case10.py
@@ -0,0 +1,18 @@
+def Method1():
+ print('m1')
+ print('m1')
+
+def Method1a():
+ print('m1a')
+ print('m1a')
+
+def Method2():
+ print('m2 before')
+ Method1()
+ Method1a()
+ print('m2 after')
+
+
+if __name__ == '__main__':
+ Method2()
+ print('TEST SUCEEDED!')
diff --git a/python/helpers/pydev/tests_python/_debugger_case13.py b/python/helpers/pydev/tests_python/_debugger_case13.py
new file mode 100644
index 000000000000..dbdbbd4c573b
--- /dev/null
+++ b/python/helpers/pydev/tests_python/_debugger_case13.py
@@ -0,0 +1,43 @@
+
+class TestProperty(object):
+ def __init__(self, name = "Default"):
+ self._x = None
+ self.name = name
+
+ def get_name(self):
+ return self.__name
+
+
+ def set_name(self, value):
+ self.__name = value
+
+
+ def del_name(self):
+ del self.__name
+ name = property(get_name, set_name, del_name, "name's docstring")
+
+ @property
+ def x(self):
+ return self._x
+
+ @x.setter
+ def x(self, value):
+ self._x = value
+
+ @x.deleter
+ def x(self):
+ del self._x
+
+def main():
+ """
+ """
+ testObj = TestProperty()
+ testObj.x = 10
+ val = testObj.x
+
+ testObj.name = "Pydev"
+ debugType = testObj.name
+ print('TEST SUCEEDED!')
+
+if __name__ == '__main__':
+ main() \ No newline at end of file
diff --git a/python/helpers/pydev/tests_python/_debugger_case14.py b/python/helpers/pydev/tests_python/_debugger_case14.py
new file mode 100644
index 000000000000..2a5e181b041f
--- /dev/null
+++ b/python/helpers/pydev/tests_python/_debugger_case14.py
@@ -0,0 +1,29 @@
+
+class Car(object):
+ """A car class"""
+ def __init__(self, model, make, color):
+ self.model = model
+ self.make = make
+ self.color = color
+ self.price = None
+
+ def get_price(self):
+ return self.price
+
+ def set_price(self, value):
+ self.price = value
+
+availableCars = []
+def main():
+ global availableCars
+
+ #Create a new car obj
+ carObj = Car("Maruti SX4", "2011", "Black")
+ carObj.set_price(950000) # Set price
+ # Add this to available cars
+ availableCars.append(carObj)
+
+ print('TEST SUCEEDED')
+
+if __name__ == '__main__':
+ main()
diff --git a/python/helpers/pydev/tests_python/_debugger_case15.py b/python/helpers/pydev/tests_python/_debugger_case15.py
new file mode 100644
index 000000000000..2a5e181b041f
--- /dev/null
+++ b/python/helpers/pydev/tests_python/_debugger_case15.py
@@ -0,0 +1,29 @@
+
+class Car(object):
+ """A car class"""
+ def __init__(self, model, make, color):
+ self.model = model
+ self.make = make
+ self.color = color
+ self.price = None
+
+ def get_price(self):
+ return self.price
+
+ def set_price(self, value):
+ self.price = value
+
+availableCars = []
+def main():
+ global availableCars
+
+ #Create a new car obj
+ carObj = Car("Maruti SX4", "2011", "Black")
+ carObj.set_price(950000) # Set price
+ # Add this to available cars
+ availableCars.append(carObj)
+
+ print('TEST SUCEEDED')
+
+if __name__ == '__main__':
+ main()
diff --git a/python/helpers/pydev/tests_python/_debugger_case15_execfile.py b/python/helpers/pydev/tests_python/_debugger_case15_execfile.py
new file mode 100644
index 000000000000..7123209ae714
--- /dev/null
+++ b/python/helpers/pydev/tests_python/_debugger_case15_execfile.py
@@ -0,0 +1 @@
+f=lambda x: 'val=%s' % x
diff --git a/python/helpers/pydev/tests_python/_debugger_case16.py b/python/helpers/pydev/tests_python/_debugger_case16.py
new file mode 100644
index 000000000000..5622813acd0a
--- /dev/null
+++ b/python/helpers/pydev/tests_python/_debugger_case16.py
@@ -0,0 +1,12 @@
+# this test requires numpy to be installed
+import numpy
+
+def main():
+ smallarray = numpy.arange(100) * 1 + 1j
+ bigarray = numpy.arange(100000).reshape((10,10000)) # 100 thousand
+ hugearray = numpy.arange(10000000) # 10 million
+
+ pass # location of breakpoint after all arrays defined
+
+main()
+print('TEST SUCEEDED')
diff --git a/python/helpers/pydev/tests_python/_debugger_case17.py b/python/helpers/pydev/tests_python/_debugger_case17.py
new file mode 100644
index 000000000000..0177683c654a
--- /dev/null
+++ b/python/helpers/pydev/tests_python/_debugger_case17.py
@@ -0,0 +1,38 @@
+def get_here():
+ a = 10
+
+def foo(func):
+ return func
+
+def m1(): # @DontTrace
+ get_here()
+
+# @DontTrace
+def m2():
+ get_here()
+
+# @DontTrace
+@foo
+def m3():
+ get_here()
+
+@foo
+@foo
+def m4(): # @DontTrace
+ get_here()
+
+
+def main():
+
+ m1()
+
+ m2()
+
+ m3()
+
+ m4()
+
+if __name__ == '__main__':
+ main()
+
+ print('TEST SUCEEDED')
diff --git a/python/helpers/pydev/tests_python/_debugger_case18.py b/python/helpers/pydev/tests_python/_debugger_case18.py
new file mode 100644
index 000000000000..69717b2411ee
--- /dev/null
+++ b/python/helpers/pydev/tests_python/_debugger_case18.py
@@ -0,0 +1,23 @@
+
+
+def m2(a):
+ a = 10
+ b = 20 #Break here and set a = 40
+ c = 30
+
+ def function2():
+ print a
+
+ return a
+
+
+def m1(a):
+ return m2(a)
+
+
+if __name__ == '__main__':
+ found = m1(10)
+ if found == 40:
+ print('TEST SUCEEDED')
+ else:
+ raise AssertionError('Expected variable to be changed to 40. Found: %s' % (found,))
diff --git a/python/helpers/pydev/tests_python/_debugger_case19.py b/python/helpers/pydev/tests_python/_debugger_case19.py
new file mode 100644
index 000000000000..aaf380c8a3f5
--- /dev/null
+++ b/python/helpers/pydev/tests_python/_debugger_case19.py
@@ -0,0 +1,10 @@
+class A:
+
+ def __init__(self):
+ self.__var = 10
+
+if __name__ == '__main__':
+ a = A()
+ print a._A__var
+ # Evaluate 'a.__var' should give a._A__var_
+ print('TEST SUCEEDED')
diff --git a/python/helpers/pydev/tests_python/_debugger_case2.py b/python/helpers/pydev/tests_python/_debugger_case2.py
new file mode 100644
index 000000000000..e47a5e21a0eb
--- /dev/null
+++ b/python/helpers/pydev/tests_python/_debugger_case2.py
@@ -0,0 +1,24 @@
+
+def Call4():
+ print('Start Call4')
+ print('End Call4')
+
+def Call3():
+ print('Start Call3')
+ Call4()
+ print('End Call3')
+
+def Call2():
+ print('Start Call2')
+ Call3()
+ print('End Call2 - a')
+ print('End Call2 - b')
+
+def Call1():
+ print('Start Call1')
+ Call2()
+ print('End Call1')
+
+if __name__ == '__main__':
+ Call1()
+ print('TEST SUCEEDED!')
diff --git a/python/helpers/pydev/tests_python/_debugger_case3.py b/python/helpers/pydev/tests_python/_debugger_case3.py
new file mode 100644
index 000000000000..aa05032fc408
--- /dev/null
+++ b/python/helpers/pydev/tests_python/_debugger_case3.py
@@ -0,0 +1,8 @@
+import time
+if __name__ == '__main__':
+ for i in range(15):
+ print('here')
+ time.sleep(.2)
+
+ print('TEST SUCEEDED')
+
diff --git a/python/helpers/pydev/tests_python/_debugger_case4.py b/python/helpers/pydev/tests_python/_debugger_case4.py
new file mode 100644
index 000000000000..009da4a6bef2
--- /dev/null
+++ b/python/helpers/pydev/tests_python/_debugger_case4.py
@@ -0,0 +1,8 @@
+import time
+if __name__ == '__main__':
+ for i in range(10):
+ print('here %s' % i)
+ time.sleep(1)
+
+ print('TEST SUCEEDED')
+
diff --git a/python/helpers/pydev/tests_python/_debugger_case56.py b/python/helpers/pydev/tests_python/_debugger_case56.py
new file mode 100644
index 000000000000..e5de28d9e834
--- /dev/null
+++ b/python/helpers/pydev/tests_python/_debugger_case56.py
@@ -0,0 +1,9 @@
+def Call2():
+ print('Call2')
+
+def Call1(a):
+ print('Call1')
+
+if __name__ == '__main__':
+ Call1(Call2())
+ print('TEST SUCEEDED!')
diff --git a/python/helpers/pydev/tests_python/_debugger_case7.py b/python/helpers/pydev/tests_python/_debugger_case7.py
new file mode 100644
index 000000000000..263110b1e990
--- /dev/null
+++ b/python/helpers/pydev/tests_python/_debugger_case7.py
@@ -0,0 +1,8 @@
+def Call():
+ variable_for_test_1 = 10
+ variable_for_test_2 = 20
+ variable_for_test_3 = 30
+
+if __name__ == '__main__':
+ Call()
+ print 'TEST SUCEEDED!'
diff --git a/python/helpers/pydev/tests_python/_debugger_case89.py b/python/helpers/pydev/tests_python/_debugger_case89.py
new file mode 100644
index 000000000000..e6f32dd522bb
--- /dev/null
+++ b/python/helpers/pydev/tests_python/_debugger_case89.py
@@ -0,0 +1,16 @@
+def Method1():
+ print 'm1'
+
+def Method2():
+ print 'm2 before'
+ Method1()
+ print 'm2 after'
+
+def Method3():
+ print 'm3 before'
+ Method2()
+ print 'm3 after'
+
+if __name__ == '__main__':
+ Method3()
+ print 'TEST SUCEEDED!'
diff --git a/python/helpers/pydev/tests_python/test_additional_thread_info.py b/python/helpers/pydev/tests_python/test_additional_thread_info.py
new file mode 100644
index 000000000000..6ae260d6a658
--- /dev/null
+++ b/python/helpers/pydev/tests_python/test_additional_thread_info.py
@@ -0,0 +1,111 @@
+import sys
+import os
+sys.path.insert(0, os.path.split(os.path.split(__file__)[0])[0])
+
+from pydevd_constants import Null
+import unittest
+
+#=======================================================================================================================
+# TestCase
+#=======================================================================================================================
+class TestCase(unittest.TestCase):
+ '''
+ Used for profiling the PyDBAdditionalThreadInfoWithoutCurrentFramesSupport version
+ '''
+
+ def testMetNoFramesSupport(self):
+ from pydevd_additional_thread_info import PyDBAdditionalThreadInfoWithoutCurrentFramesSupport
+ info = PyDBAdditionalThreadInfoWithoutCurrentFramesSupport()
+
+ mainDebugger = Null()
+ filename = ''
+ base = ''
+ additionalInfo = Null()
+ t = Null()
+ frame = Null()
+
+ times = 10
+ for i in range(times):
+ info.CreateDbFrame((mainDebugger, filename, additionalInfo, t, frame))
+
+ #we haven't kept any reference, so, they must have been garbage-collected already!
+ self.assertEqual(0, len(info.IterFrames()))
+
+ kept_frames = []
+ for i in range(times):
+ kept_frames.append(info.CreateDbFrame((mainDebugger, filename, additionalInfo, t, frame)))
+
+ for i in range(times):
+ self.assertEqual(times, len(info.IterFrames()))
+
+
+ def testStartNewThread(self):
+ import pydevd
+ import thread
+ original = thread.start_new_thread
+ thread.start_new_thread = pydevd.pydev_start_new_thread
+ try:
+ found = {}
+ def function(a, b, *args, **kwargs):
+ found['a'] = a
+ found['b'] = b
+ found['args'] = args
+ found['kwargs'] = kwargs
+ thread.start_new_thread(function, (1,2,3,4), {'d':1, 'e':2})
+ import time
+ for _i in xrange(20):
+ if len(found) == 4:
+ break
+ time.sleep(.1)
+ else:
+ raise AssertionError('Could not get to condition before 2 seconds')
+
+ self.assertEqual({'a': 1, 'b': 2, 'args': (3, 4), 'kwargs': {'e': 2, 'd': 1}}, found)
+ finally:
+ thread.start_new_thread = original
+
+
+ def testStartNewThread2(self):
+ import pydevd
+ import thread
+
+ original = thread.start_new_thread
+ thread.start_new_thread = pydevd.pydev_start_new_thread
+ try:
+ found = {}
+
+ class F(object):
+ start_new_thread = thread.start_new_thread
+
+ def start_it(self):
+ try:
+ self.start_new_thread(self.function, (1,2,3,4), {'d':1, 'e':2})
+ except:
+ import traceback;traceback.print_exc()
+
+ def function(self, a, b, *args, **kwargs):
+ found['a'] = a
+ found['b'] = b
+ found['args'] = args
+ found['kwargs'] = kwargs
+
+ f = F()
+ f.start_it()
+ import time
+ for _i in xrange(20):
+ if len(found) == 4:
+ break
+ time.sleep(.1)
+ else:
+ raise AssertionError('Could not get to condition before 2 seconds')
+
+ self.assertEqual({'a': 1, 'b': 2, 'args': (3, 4), 'kwargs': {'e': 2, 'd': 1}}, found)
+ finally:
+ thread.start_new_thread = original
+
+
+#=======================================================================================================================
+# main
+#=======================================================================================================================
+if __name__ == '__main__':
+ unittest.main()
diff --git a/python/helpers/pydev/tests_python/test_debugger.py b/python/helpers/pydev/tests_python/test_debugger.py
new file mode 100644
index 000000000000..3a216cb64079
--- /dev/null
+++ b/python/helpers/pydev/tests_python/test_debugger.py
@@ -0,0 +1,1205 @@
+'''
+ The idea is that we record the commands sent to the debugger and reproduce them from this script
+ (so, this works as the client, which spawns the debugger as a separate process and communicates
+ to it as if it was run from the outside)
+
+ Note that it's a python script but it'll spawn a process to run as jython, ironpython and as python.
+'''
+CMD_SET_PROPERTY_TRACE, CMD_EVALUATE_CONSOLE_EXPRESSION, CMD_RUN_CUSTOM_OPERATION, CMD_ENABLE_DONT_TRACE = 133, 134, 135, 141
+PYTHON_EXE = None
+IRONPYTHON_EXE = None
+JYTHON_JAR_LOCATION = None
+JAVA_LOCATION = None
+
+
+import unittest
+import pydev_localhost
+
+port = None
+
+def UpdatePort():
+ global port
+ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ s.bind((pydev_localhost.get_localhost(), 0))
+ _, port = s.getsockname()
+ s.close()
+
+import os
+def NormFile(filename):
+ try:
+ rPath = os.path.realpath # @UndefinedVariable
+ except:
+ # jython does not support os.path.realpath
+ # realpath is a no-op on systems without islink support
+ rPath = os.path.abspath
+ return os.path.normcase(rPath(filename))
+
+PYDEVD_FILE = NormFile('../pydevd.py')
+import sys
+sys.path.append(os.path.dirname(PYDEVD_FILE))
+
+SHOW_WRITES_AND_READS = False
+SHOW_RESULT_STR = False
+SHOW_OTHER_DEBUG_INFO = False
+
+
+import subprocess
+import socket
+import threading
+import time
+from urllib import quote_plus, quote, unquote_plus
+
+
+#=======================================================================================================================
+# ReaderThread
+#=======================================================================================================================
+class ReaderThread(threading.Thread):
+
+ def __init__(self, sock):
+ threading.Thread.__init__(self)
+ self.setDaemon(True)
+ self.sock = sock
+ self.lastReceived = None
+
+ def run(self):
+ try:
+ buf = ''
+ while True:
+ l = self.sock.recv(1024)
+ buf += l
+
+ if '\n' in buf:
+ self.lastReceived = buf
+ buf = ''
+
+ if SHOW_WRITES_AND_READS:
+ print 'Test Reader Thread Received %s' % self.lastReceived.strip()
+ except:
+ pass # ok, finished it
+
+ def DoKill(self):
+ self.sock.close()
+
+#=======================================================================================================================
+# AbstractWriterThread
+#=======================================================================================================================
+class AbstractWriterThread(threading.Thread):
+
+ def __init__(self):
+ threading.Thread.__init__(self)
+ self.setDaemon(True)
+ self.finishedOk = False
+ self._next_breakpoint_id = 0
+
+ def DoKill(self):
+ if hasattr(self, 'readerThread'):
+ # if it's not created, it's not there...
+ self.readerThread.DoKill()
+ self.sock.close()
+
+ def Write(self, s):
+ last = self.readerThread.lastReceived
+ if SHOW_WRITES_AND_READS:
+ print 'Test Writer Thread Written %s' % (s,)
+ self.sock.send(s + '\n')
+ time.sleep(0.2)
+
+ i = 0
+ while last == self.readerThread.lastReceived and i < 10:
+ i += 1
+ time.sleep(0.1)
+
+
+ def StartSocket(self):
+ if SHOW_WRITES_AND_READS:
+ print 'StartSocket'
+
+ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ s.bind(('', port))
+ s.listen(1)
+ if SHOW_WRITES_AND_READS:
+ print 'Waiting in socket.accept()'
+ newSock, addr = s.accept()
+ if SHOW_WRITES_AND_READS:
+ print 'Test Writer Thread Socket:', newSock, addr
+
+ readerThread = self.readerThread = ReaderThread(newSock)
+ readerThread.start()
+ self.sock = newSock
+
+ self._sequence = -1
+ # initial command is always the version
+ self.WriteVersion()
+
+ def NextBreakpointId(self):
+ self._next_breakpoint_id += 1
+ return self._next_breakpoint_id
+
+ def NextSeq(self):
+ self._sequence += 2
+ return self._sequence
+
+
+ def WaitForNewThread(self):
+ i = 0
+ # wait for hit breakpoint
+ while not '<xml><thread name="' in self.readerThread.lastReceived or '<xml><thread name="pydevd.' in self.readerThread.lastReceived:
+ i += 1
+ time.sleep(1)
+ if i >= 15:
+ raise AssertionError('After %s seconds, a thread was not created.' % i)
+
+ # we have something like <xml><thread name="MainThread" id="12103472" /></xml>
+ splitted = self.readerThread.lastReceived.split('"')
+ threadId = splitted[3]
+ return threadId
+
+ def WaitForBreakpointHit(self, reason='111', get_line=False):
+ '''
+ 108 is over
+ 109 is return
+ 111 is breakpoint
+ '''
+ i = 0
+ # wait for hit breakpoint
+ while not ('stop_reason="%s"' % reason) in self.readerThread.lastReceived:
+ i += 1
+ time.sleep(1)
+ if i >= 10:
+ raise AssertionError('After %s seconds, a break with reason: %s was not hit. Found: %s' % \
+ (i, reason, self.readerThread.lastReceived))
+
+ # we have something like <xml><thread id="12152656" stop_reason="111"><frame id="12453120" ...
+ splitted = self.readerThread.lastReceived.split('"')
+ threadId = splitted[1]
+ frameId = splitted[7]
+ if get_line:
+ return threadId, frameId, int(splitted[13])
+
+ return threadId, frameId
+
+ def WaitForCustomOperation(self, expected):
+ i = 0
+ # wait for custom operation response, the response is double encoded
+ expectedEncoded = quote(quote_plus(expected))
+ while not expectedEncoded in self.readerThread.lastReceived:
+ i += 1
+ time.sleep(1)
+ if i >= 10:
+ raise AssertionError('After %s seconds, the custom operation not received. Last found:\n%s\nExpected (encoded)\n%s' %
+ (i, self.readerThread.lastReceived, expectedEncoded))
+
+ return True
+
+ def WaitForEvaluation(self, expected):
+ return self._WaitFor(expected, 'the expected evaluation was not found')
+
+
+ def WaitForVars(self, expected):
+ i = 0
+ # wait for hit breakpoint
+ while not expected in self.readerThread.lastReceived:
+ i += 1
+ time.sleep(1)
+ if i >= 10:
+ raise AssertionError('After %s seconds, the vars were not found. Last found:\n%s' %
+ (i, self.readerThread.lastReceived))
+
+ return True
+
+ def WaitForVar(self, expected):
+ self._WaitFor(expected, 'the var was not found')
+
+ def _WaitFor(self, expected, error_msg):
+ '''
+ :param expected:
+ If a list we'll work with any of the choices.
+ '''
+ if not isinstance(expected, (list, tuple)):
+ expected = [expected]
+
+ i = 0
+ found = False
+ while not found:
+ last = self.readerThread.lastReceived
+ for e in expected:
+ if e in last:
+ found = True
+ break
+
+ last = unquote_plus(last)
+ for e in expected:
+ if e in last:
+ found = True
+ break
+
+ if found:
+ break
+
+ i += 1
+ time.sleep(1)
+ if i >= 10:
+ raise AssertionError('After %s seconds, %s. Last found:\n%s' %
+ (i, error_msg, last))
+
+ return True
+
+ def WaitForMultipleVars(self, expected_vars):
+ i = 0
+ # wait for hit breakpoint
+ while True:
+ for expected in expected_vars:
+ if expected not in self.readerThread.lastReceived:
+ break # Break out of loop (and don't get to else)
+ else:
+ return True
+
+ i += 1
+ time.sleep(1)
+ if i >= 10:
+ raise AssertionError('After %s seconds, the vars were not found. Last found:\n%s' %
+ (i, self.readerThread.lastReceived))
+
+ return True
+
+ def WriteMakeInitialRun(self):
+ self.Write("101\t%s\t" % self.NextSeq())
+
+ def WriteVersion(self):
+ self.Write("501\t%s\t1.0\tWINDOWS\tID" % self.NextSeq())
+
+ def WriteAddBreakpoint(self, line, func):
+ '''
+ @param line: starts at 1
+ '''
+ breakpoint_id = self.NextBreakpointId()
+ self.Write("111\t%s\t%s\t%s\t%s\t%s\t%s\tNone\tNone" % (self.NextSeq(), breakpoint_id, 'python-line', self.TEST_FILE, line, func))
+ return breakpoint_id
+
+ def WriteRemoveBreakpoint(self, breakpoint_id):
+ self.Write("112\t%s\t%s\t%s\t%s" % (self.NextSeq(), 'python-line', self.TEST_FILE, breakpoint_id))
+
+ def WriteChangeVariable(self, thread_id, frame_id, varname, value):
+ self.Write("117\t%s\t%s\t%s\t%s\t%s\t%s" % (self.NextSeq(), thread_id, frame_id, 'FRAME', varname, value))
+
+ def WriteGetFrame(self, threadId, frameId):
+ self.Write("114\t%s\t%s\t%s\tFRAME" % (self.NextSeq(), threadId, frameId))
+
+ def WriteGetVariable(self, threadId, frameId, var_attrs):
+ self.Write("110\t%s\t%s\t%s\tFRAME\t%s" % (self.NextSeq(), threadId, frameId, var_attrs))
+
+ def WriteStepOver(self, threadId):
+ self.Write("108\t%s\t%s" % (self.NextSeq(), threadId,))
+
+ def WriteStepIn(self, threadId):
+ self.Write("107\t%s\t%s" % (self.NextSeq(), threadId,))
+
+ def WriteStepReturn(self, threadId):
+ self.Write("109\t%s\t%s" % (self.NextSeq(), threadId,))
+
+ def WriteSuspendThread(self, threadId):
+ self.Write("105\t%s\t%s" % (self.NextSeq(), threadId,))
+
+ def WriteRunThread(self, threadId):
+ self.Write("106\t%s\t%s" % (self.NextSeq(), threadId,))
+
+ def WriteKillThread(self, threadId):
+ self.Write("104\t%s\t%s" % (self.NextSeq(), threadId,))
+
+ def WriteDebugConsoleExpression(self, locator):
+ self.Write("%s\t%s\t%s" % (CMD_EVALUATE_CONSOLE_EXPRESSION, self.NextSeq(), locator))
+
+ def WriteCustomOperation(self, locator, style, codeOrFile, operation_fn_name):
+ self.Write("%s\t%s\t%s||%s\t%s\t%s" % (CMD_RUN_CUSTOM_OPERATION, self.NextSeq(), locator, style, codeOrFile, operation_fn_name))
+
+ def WriteEvaluateExpression(self, locator, expression):
+ self.Write("113\t%s\t%s\t%s\t1" % (self.NextSeq(), locator, expression))
+
+ def WriteEnableDontTrace(self, enable):
+ if enable:
+ enable = 'true'
+ else:
+ enable = 'false'
+ self.Write("%s\t%s\t%s" % (CMD_ENABLE_DONT_TRACE, self.NextSeq(), enable))
+
+
+#=======================================================================================================================
+# WriterThreadCase19 - [Test Case]: Evaluate '__' attributes
+#======================================================================================================================
+class WriterThreadCase19(AbstractWriterThread):
+
+ TEST_FILE = NormFile('_debugger_case19.py')
+
+ def run(self):
+ self.StartSocket()
+ self.WriteAddBreakpoint(8, None)
+ self.WriteMakeInitialRun()
+
+ threadId, frameId, line = self.WaitForBreakpointHit('111', True)
+
+ assert line == 8, 'Expected return to be in line 8, was: %s' % line
+
+ self.WriteEvaluateExpression('%s\t%s\t%s' % (threadId, frameId, 'LOCAL'), 'a.__var')
+ self.WaitForEvaluation('<var name="a.__var" type="int" value="int')
+ self.WriteRunThread(threadId)
+
+
+ self.finishedOk = True
+
+
+#=======================================================================================================================
+# WriterThreadCase18 - [Test Case]: change local variable
+#======================================================================================================================
+class WriterThreadCase18(AbstractWriterThread):
+
+ TEST_FILE = NormFile('_debugger_case18.py')
+
+ def run(self):
+ self.StartSocket()
+ self.WriteAddBreakpoint(5, 'm2')
+ self.WriteMakeInitialRun()
+
+ thread_id, frame_id, line = self.WaitForBreakpointHit('111', True)
+ assert line == 5, 'Expected return to be in line 2, was: %s' % line
+
+ self.WriteChangeVariable(thread_id, frame_id, 'a', '40')
+ self.WriteRunThread(thread_id)
+
+ self.finishedOk = True
+
+#=======================================================================================================================
+# WriterThreadCase17 - [Test Case]: dont trace
+#======================================================================================================================
+class WriterThreadCase17(AbstractWriterThread):
+
+ TEST_FILE = NormFile('_debugger_case17.py')
+
+ def run(self):
+ self.StartSocket()
+ self.WriteEnableDontTrace(True)
+ self.WriteAddBreakpoint(27, 'main')
+ self.WriteAddBreakpoint(29, 'main')
+ self.WriteAddBreakpoint(31, 'main')
+ self.WriteAddBreakpoint(33, 'main')
+ self.WriteMakeInitialRun()
+
+ for i in range(4):
+ threadId, frameId, line = self.WaitForBreakpointHit('111', True)
+
+ self.WriteStepIn(threadId)
+ threadId, frameId, line = self.WaitForBreakpointHit('107', True)
+ # Should Skip step into properties setter
+ assert line == 2, 'Expected return to be in line 2, was: %s' % line
+ self.WriteRunThread(threadId)
+
+
+ self.finishedOk = True
+
+#=======================================================================================================================
+# WriterThreadCase16 - [Test Case]: numpy.ndarray resolver
+#======================================================================================================================
+class WriterThreadCase16(AbstractWriterThread):
+
+ TEST_FILE = NormFile('_debugger_case16.py')
+
+ def run(self):
+ self.StartSocket()
+ self.WriteAddBreakpoint(9, 'main')
+ self.WriteMakeInitialRun()
+
+ threadId, frameId, line = self.WaitForBreakpointHit('111', True)
+
+ # In this test we check that the three arrays of different shapes, sizes and types
+ # are all resolved properly as ndarrays.
+
+ # First pass check is that we have all three expected variables defined
+ self.WriteGetFrame(threadId, frameId)
+ self.WaitForVars('<var name="smallarray" type="ndarray" value="ndarray%253A %255B 0.%252B1.j 1.%252B1.j 2.%252B1.j 3.%252B1.j 4.%252B1.j 5.%252B1.j 6.%252B1.j 7.%252B1.j%250A 8.%252B1.j 9.%252B1.j 10.%252B1.j 11.%252B1.j 12.%252B1.j 13.%252B1.j 14.%252B1.j 15.%252B1.j%250A 16.%252B1.j 17.%252B1.j 18.%252B1.j 19.%252B1.j 20.%252B1.j 21.%252B1.j 22.%252B1.j 23.%252B1.j%250A 24.%252B1.j 25.%252B1.j 26.%252B1.j 27.%252B1.j 28.%252B1.j 29.%252B1.j 30.%252B1.j 31.%252B1.j%250A 32.%252B1.j 33.%252B1.j 34.%252B1.j 35.%252B1.j 36.%252B1.j 37.%252B1.j 38.%252B1.j 39.%252B1.j%250A 40.%252B1.j 41.%252B1.j 42.%252B1.j 43.%252B1.j 44.%252B1.j 45.%252B1.j 46.%252B1.j 47.%252B1.j%250A 48.%252B1.j 49.%252B1.j 50.%252B1.j 51.%252B1.j 52.%252B1.j 53.%252B1.j 54.%252B1.j 55.%252B1.j%250A 56.%252B1.j 57.%252B1.j 58.%252B1.j 59.%252B1.j 60.%252B1.j 61.%252B1.j 62.%252B1.j 63.%252B1.j%250A 64.%252B1.j 65.%252B1.j 66.%252B1.j 67.%252B1.j 68.%252B1.j 69.%252B1.j 70.%252B1.j 71.%252B1.j%250A 72.%252B1.j 73.%252B1.j 74.%252B1.j 75.%252B1.j 76.%252B1.j 77.%252B1.j 78.%252B1.j 79.%252B1.j%250A 80.%252B1.j 81.%252B1.j 82.%252B1.j 83.%252B1.j 84.%252B1.j 85.%252B1.j 86.%252B1.j 87.%252B1.j%250A 88.%252B1.j 89.%252B1.j 90.%252B1.j 91.%252B1.j 92.%252B1.j 93.%252B1.j 94.%252B1.j 95.%252B1.j%250A 96.%252B1.j 97.%252B1.j 98.%252B1.j 99.%252B1.j%255D" isContainer="True" />')
+ self.WaitForVars('<var name="bigarray" type="ndarray" value="ndarray%253A %255B%255B 0 1 2 ...%252C 9997 9998 9999%255D%250A %255B10000 10001 10002 ...%252C 19997 19998 19999%255D%250A %255B20000 20001 20002 ...%252C 29997 29998 29999%255D%250A ...%252C %250A %255B70000 70001 70002 ...%252C 79997 79998 79999%255D%250A %255B80000 80001 80002 ...%252C 89997 89998 89999%255D%250A %255B90000 90001 90002 ...%252C 99997 99998 99999%255D%255D" isContainer="True" />')
+ self.WaitForVars('<var name="hugearray" type="ndarray" value="ndarray%253A %255B 0 1 2 ...%252C 9999997 9999998 9999999%255D" isContainer="True" />')
+
+ # For each variable, check each of the resolved (meta data) attributes...
+ self.WriteGetVariable(threadId, frameId, 'smallarray')
+ self.WaitForVar('<var name="min" type="complex128"')
+ self.WaitForVar('<var name="max" type="complex128"')
+ self.WaitForVar('<var name="shape" type="tuple"')
+ self.WaitForVar('<var name="dtype" type="dtype"')
+ self.WaitForVar('<var name="size" type="int"')
+ # ...and check that the internals are resolved properly
+ self.WriteGetVariable(threadId, frameId, 'smallarray\t__internals__')
+ self.WaitForVar('<var name="%27size%27')
+
+ self.WriteGetVariable(threadId, frameId, 'bigarray')
+ self.WaitForVar(['<var name="min" type="int64" value="int64%253A 0" />', '<var name="size" type="int" value="int%3A 100000" />']) # TODO: When on a 32 bit python we get an int32 (which makes this test fail).
+ self.WaitForVar(['<var name="max" type="int64" value="int64%253A 99999" />', '<var name="max" type="int32" value="int32%253A 99999" />'])
+ self.WaitForVar('<var name="shape" type="tuple"')
+ self.WaitForVar('<var name="dtype" type="dtype"')
+ self.WaitForVar('<var name="size" type="int"')
+ self.WriteGetVariable(threadId, frameId, 'bigarray\t__internals__')
+ self.WaitForVar('<var name="%27size%27')
+
+ # this one is different because it crosses the magic threshold where we don't calculate
+ # the min/max
+ self.WriteGetVariable(threadId, frameId, 'hugearray')
+ self.WaitForVar('<var name="min" type="str" value="str%253A ndarray too big%252C calculating min would slow down debugging" />')
+ self.WaitForVar('<var name="max" type="str" value="str%253A ndarray too big%252C calculating max would slow down debugging" />')
+ self.WaitForVar('<var name="shape" type="tuple"')
+ self.WaitForVar('<var name="dtype" type="dtype"')
+ self.WaitForVar('<var name="size" type="int"')
+ self.WriteGetVariable(threadId, frameId, 'hugearray\t__internals__')
+ self.WaitForVar('<var name="%27size%27')
+
+ self.WriteRunThread(threadId)
+ self.finishedOk = True
+
+
+#=======================================================================================================================
+# WriterThreadCase15 - [Test Case]: Custom Commands
+#======================================================================================================================
+class WriterThreadCase15(AbstractWriterThread):
+
+ TEST_FILE = NormFile('_debugger_case15.py')
+
+ def run(self):
+ self.StartSocket()
+ self.WriteAddBreakpoint(22, 'main')
+ self.WriteMakeInitialRun()
+
+ threadId, frameId, line = self.WaitForBreakpointHit('111', True)
+
+ # Access some variable
+ self.WriteCustomOperation("%s\t%s\tEXPRESSION\tcarObj.color" % (threadId, frameId), "EXEC", "f=lambda x: 'val=%s' % x", "f")
+ self.WaitForCustomOperation('val=Black')
+ assert 7 == self._sequence, 'Expected 7. Had: %s' % self._sequence
+
+ self.WriteCustomOperation("%s\t%s\tEXPRESSION\tcarObj.color" % (threadId, frameId), "EXECFILE", NormFile('_debugger_case15_execfile.py'), "f")
+ self.WaitForCustomOperation('val=Black')
+ assert 9 == self._sequence, 'Expected 9. Had: %s' % self._sequence
+
+ self.WriteRunThread(threadId)
+ self.finishedOk = True
+
+
+
+#=======================================================================================================================
+# WriterThreadCase14 - [Test Case]: Interactive Debug Console
+#======================================================================================================================
+class WriterThreadCase14(AbstractWriterThread):
+
+ TEST_FILE = NormFile('_debugger_case14.py')
+
+ def run(self):
+ self.StartSocket()
+ self.WriteAddBreakpoint(22, 'main')
+ self.WriteMakeInitialRun()
+
+ threadId, frameId, line = self.WaitForBreakpointHit('111', True)
+ assert threadId, '%s not valid.' % threadId
+ assert frameId, '%s not valid.' % frameId
+
+ # Access some variable
+ self.WriteDebugConsoleExpression("%s\t%s\tEVALUATE\tcarObj.color" % (threadId, frameId))
+ self.WaitForMultipleVars(['<more>False</more>', '%27Black%27'])
+ assert 7 == self._sequence, 'Expected 9. Had: %s' % self._sequence
+
+ # Change some variable
+ self.WriteDebugConsoleExpression("%s\t%s\tEVALUATE\tcarObj.color='Red'" % (threadId, frameId))
+ self.WriteDebugConsoleExpression("%s\t%s\tEVALUATE\tcarObj.color" % (threadId, frameId))
+ self.WaitForMultipleVars(['<more>False</more>', '%27Red%27'])
+ assert 11 == self._sequence, 'Expected 13. Had: %s' % self._sequence
+
+ # Iterate some loop
+ self.WriteDebugConsoleExpression("%s\t%s\tEVALUATE\tfor i in range(3):" % (threadId, frameId))
+ self.WaitForVars('<xml><more>True</more></xml>')
+ self.WriteDebugConsoleExpression("%s\t%s\tEVALUATE\t print i" % (threadId, frameId))
+ self.WriteDebugConsoleExpression("%s\t%s\tEVALUATE\t" % (threadId, frameId))
+ self.WaitForVars('<xml><more>False</more><output message="0"></output><output message="1"></output><output message="2"></output></xml>')
+ assert 17 == self._sequence, 'Expected 19. Had: %s' % self._sequence
+
+ self.WriteRunThread(threadId)
+ self.finishedOk = True
+
+
+#=======================================================================================================================
+# WriterThreadCase13
+#======================================================================================================================
+class WriterThreadCase13(AbstractWriterThread):
+
+ TEST_FILE = NormFile('_debugger_case13.py')
+
+ def run(self):
+ self.StartSocket()
+ self.WriteAddBreakpoint(35, 'main')
+ self.Write("%s\t%s\t%s" % (CMD_SET_PROPERTY_TRACE, self.NextSeq(), "true;false;false;true"))
+ self.WriteMakeInitialRun()
+ threadId, frameId, line = self.WaitForBreakpointHit('111', True)
+
+ self.WriteGetFrame(threadId, frameId)
+
+ self.WriteStepIn(threadId)
+ threadId, frameId, line = self.WaitForBreakpointHit('107', True)
+ # Should go inside setter method
+ assert line == 25, 'Expected return to be in line 25, was: %s' % line
+
+ self.WriteStepIn(threadId)
+ threadId, frameId, line = self.WaitForBreakpointHit('107', True)
+
+ self.WriteStepIn(threadId)
+ threadId, frameId, line = self.WaitForBreakpointHit('107', True)
+ # Should go inside getter method
+ assert line == 21, 'Expected return to be in line 21, was: %s' % line
+
+ self.WriteStepIn(threadId)
+ threadId, frameId, line = self.WaitForBreakpointHit('107', True)
+
+ # Disable property tracing
+ self.Write("%s\t%s\t%s" % (CMD_SET_PROPERTY_TRACE, self.NextSeq(), "true;true;true;true"))
+ self.WriteStepIn(threadId)
+ threadId, frameId, line = self.WaitForBreakpointHit('107', True)
+ # Should Skip step into properties setter
+ assert line == 39, 'Expected return to be in line 39, was: %s' % line
+
+ # Enable property tracing
+ self.Write("%s\t%s\t%s" % (CMD_SET_PROPERTY_TRACE, self.NextSeq(), "true;false;false;true"))
+ self.WriteStepIn(threadId)
+ threadId, frameId, line = self.WaitForBreakpointHit('107', True)
+ # Should go inside getter method
+ assert line == 8, 'Expected return to be in line 8, was: %s' % line
+
+ self.WriteRunThread(threadId)
+
+ self.finishedOk = True
+
+#=======================================================================================================================
+# WriterThreadCase12
+#======================================================================================================================
+class WriterThreadCase12(AbstractWriterThread):
+
+ TEST_FILE = NormFile('_debugger_case10.py')
+
+ def run(self):
+ self.StartSocket()
+ self.WriteAddBreakpoint(2, '') # Should not be hit: setting empty function (not None) should only hit global.
+ self.WriteAddBreakpoint(6, 'Method1a')
+ self.WriteAddBreakpoint(11, 'Method2')
+ self.WriteMakeInitialRun()
+
+ threadId, frameId, line = self.WaitForBreakpointHit('111', True)
+
+ assert line == 11, 'Expected return to be in line 11, was: %s' % line
+
+ self.WriteStepReturn(threadId)
+
+ threadId, frameId, line = self.WaitForBreakpointHit('111', True) # not a return (it stopped in the other breakpoint)
+
+ assert line == 6, 'Expected return to be in line 6, was: %s' % line
+
+ self.WriteRunThread(threadId)
+
+ assert 13 == self._sequence, 'Expected 13. Had: %s' % self._sequence
+
+ self.finishedOk = True
+
+
+
+#=======================================================================================================================
+# WriterThreadCase11
+#======================================================================================================================
+class WriterThreadCase11(AbstractWriterThread):
+
+ TEST_FILE = NormFile('_debugger_case10.py')
+
+ def run(self):
+ self.StartSocket()
+ self.WriteAddBreakpoint(2, 'Method1')
+ self.WriteMakeInitialRun()
+
+ threadId, frameId = self.WaitForBreakpointHit('111')
+
+ self.WriteStepOver(threadId)
+
+ threadId, frameId, line = self.WaitForBreakpointHit('108', True)
+
+ assert line == 3, 'Expected return to be in line 3, was: %s' % line
+
+ self.WriteStepOver(threadId)
+
+ threadId, frameId, line = self.WaitForBreakpointHit('108', True)
+
+ assert line == 11, 'Expected return to be in line 11, was: %s' % line
+
+ self.WriteStepOver(threadId)
+
+ threadId, frameId, line = self.WaitForBreakpointHit('108', True)
+
+ assert line == 12, 'Expected return to be in line 12, was: %s' % line
+
+ self.WriteRunThread(threadId)
+
+ assert 13 == self._sequence, 'Expected 13. Had: %s' % self._sequence
+
+ self.finishedOk = True
+
+
+
+
+#=======================================================================================================================
+# WriterThreadCase10
+#======================================================================================================================
+class WriterThreadCase10(AbstractWriterThread):
+
+ TEST_FILE = NormFile('_debugger_case10.py')
+
+ def run(self):
+ self.StartSocket()
+ self.WriteAddBreakpoint(2, 'None') # None or Method should make hit.
+ self.WriteMakeInitialRun()
+
+ threadId, frameId = self.WaitForBreakpointHit('111')
+
+ self.WriteStepReturn(threadId)
+
+ threadId, frameId, line = self.WaitForBreakpointHit('109', True)
+
+ assert line == 11, 'Expected return to be in line 11, was: %s' % line
+
+ self.WriteStepOver(threadId)
+
+ threadId, frameId, line = self.WaitForBreakpointHit('108', True)
+
+ assert line == 12, 'Expected return to be in line 12, was: %s' % line
+
+ self.WriteRunThread(threadId)
+
+ assert 11 == self._sequence, 'Expected 11. Had: %s' % self._sequence
+
+ self.finishedOk = True
+
+
+
+#=======================================================================================================================
+# WriterThreadCase9
+#======================================================================================================================
+class WriterThreadCase9(AbstractWriterThread):
+
+ TEST_FILE = NormFile('_debugger_case89.py')
+
+ def run(self):
+ self.StartSocket()
+ self.WriteAddBreakpoint(10, 'Method3')
+ self.WriteMakeInitialRun()
+
+ threadId, frameId = self.WaitForBreakpointHit('111')
+
+ self.WriteStepOver(threadId)
+
+ threadId, frameId, line = self.WaitForBreakpointHit('108', True)
+
+ assert line == 11, 'Expected return to be in line 11, was: %s' % line
+
+ self.WriteStepOver(threadId)
+
+ threadId, frameId, line = self.WaitForBreakpointHit('108', True)
+
+ assert line == 12, 'Expected return to be in line 12, was: %s' % line
+
+ self.WriteRunThread(threadId)
+
+ assert 11 == self._sequence, 'Expected 11. Had: %s' % self._sequence
+
+ self.finishedOk = True
+
+
+#=======================================================================================================================
+# WriterThreadCase8
+#======================================================================================================================
+class WriterThreadCase8(AbstractWriterThread):
+
+ TEST_FILE = NormFile('_debugger_case89.py')
+
+ def run(self):
+ self.StartSocket()
+ self.WriteAddBreakpoint(10, 'Method3')
+ self.WriteMakeInitialRun()
+
+ threadId, frameId = self.WaitForBreakpointHit('111')
+
+ self.WriteStepReturn(threadId)
+
+ threadId, frameId, line = self.WaitForBreakpointHit('109', True)
+
+ assert line == 15, 'Expected return to be in line 15, was: %s' % line
+
+ self.WriteRunThread(threadId)
+
+ assert 9 == self._sequence, 'Expected 9. Had: %s' % self._sequence
+
+ self.finishedOk = True
+
+
+
+
+#=======================================================================================================================
+# WriterThreadCase7
+#======================================================================================================================
+class WriterThreadCase7(AbstractWriterThread):
+
+ TEST_FILE = NormFile('_debugger_case7.py')
+
+ def run(self):
+ self.StartSocket()
+ self.WriteAddBreakpoint(2, 'Call')
+ self.WriteMakeInitialRun()
+
+ threadId, frameId = self.WaitForBreakpointHit('111')
+
+ self.WriteGetFrame(threadId, frameId)
+
+ self.WaitForVars('<xml></xml>') # no vars at this point
+
+ self.WriteStepOver(threadId)
+
+ self.WriteGetFrame(threadId, frameId)
+
+ self.WaitForVars('<xml><var name="variable_for_test_1" type="int" value="int%253A 10" />%0A</xml>')
+
+ self.WriteStepOver(threadId)
+
+ self.WriteGetFrame(threadId, frameId)
+
+ self.WaitForVars('<xml><var name="variable_for_test_1" type="int" value="int%253A 10" />%0A<var name="variable_for_test_2" type="int" value="int%253A 20" />%0A</xml>')
+
+ self.WriteRunThread(threadId)
+
+ assert 17 == self._sequence, 'Expected 17. Had: %s' % self._sequence
+
+ self.finishedOk = True
+
+
+
+#=======================================================================================================================
+# WriterThreadCase6
+#=======================================================================================================================
+class WriterThreadCase6(AbstractWriterThread):
+
+ TEST_FILE = NormFile('_debugger_case56.py')
+
+ def run(self):
+ self.StartSocket()
+ self.WriteAddBreakpoint(2, 'Call2')
+ self.WriteMakeInitialRun()
+
+ threadId, frameId = self.WaitForBreakpointHit()
+
+ self.WriteGetFrame(threadId, frameId)
+
+ self.WriteStepReturn(threadId)
+
+ threadId, frameId, line = self.WaitForBreakpointHit('109', True)
+
+ assert line == 8, 'Expecting it to go to line 8. Went to: %s' % line
+
+ self.WriteStepIn(threadId)
+
+ threadId, frameId, line = self.WaitForBreakpointHit('107', True)
+
+ # goes to line 4 in jython (function declaration line)
+ assert line in (4, 5), 'Expecting it to go to line 4 or 5. Went to: %s' % line
+
+ self.WriteRunThread(threadId)
+
+ assert 13 == self._sequence, 'Expected 15. Had: %s' % self._sequence
+
+ self.finishedOk = True
+
+#=======================================================================================================================
+# WriterThreadCase5
+#=======================================================================================================================
+class WriterThreadCase5(AbstractWriterThread):
+
+ TEST_FILE = NormFile('_debugger_case56.py')
+
+ def run(self):
+ self.StartSocket()
+ breakpoint_id = self.WriteAddBreakpoint(2, 'Call2')
+ self.WriteMakeInitialRun()
+
+ threadId, frameId = self.WaitForBreakpointHit()
+
+ self.WriteGetFrame(threadId, frameId)
+
+ self.WriteRemoveBreakpoint(breakpoint_id)
+
+ self.WriteStepReturn(threadId)
+
+ threadId, frameId, line = self.WaitForBreakpointHit('109', True)
+
+ assert line == 8, 'Expecting it to go to line 8. Went to: %s' % line
+
+ self.WriteStepIn(threadId)
+
+ threadId, frameId, line = self.WaitForBreakpointHit('107', True)
+
+ # goes to line 4 in jython (function declaration line)
+ assert line in (4, 5), 'Expecting it to go to line 4 or 5. Went to: %s' % line
+
+ self.WriteRunThread(threadId)
+
+ assert 15 == self._sequence, 'Expected 15. Had: %s' % self._sequence
+
+ self.finishedOk = True
+
+
+#=======================================================================================================================
+# WriterThreadCase4
+#=======================================================================================================================
+class WriterThreadCase4(AbstractWriterThread):
+
+ TEST_FILE = NormFile('_debugger_case4.py')
+
+ def run(self):
+ self.StartSocket()
+ self.WriteMakeInitialRun()
+
+ threadId = self.WaitForNewThread()
+
+ self.WriteSuspendThread(threadId)
+
+ time.sleep(4) # wait for time enough for the test to finish if it wasn't suspended
+
+ self.WriteRunThread(threadId)
+
+ self.finishedOk = True
+
+
+#=======================================================================================================================
+# WriterThreadCase3
+#=======================================================================================================================
+class WriterThreadCase3(AbstractWriterThread):
+
+ TEST_FILE = NormFile('_debugger_case3.py')
+
+ def run(self):
+ self.StartSocket()
+ self.WriteMakeInitialRun()
+ time.sleep(1)
+ breakpoint_id = self.WriteAddBreakpoint(4, '')
+ self.WriteAddBreakpoint(5, 'FuncNotAvailable') # Check that it doesn't get hit in the global when a function is available
+
+ threadId, frameId = self.WaitForBreakpointHit()
+
+ self.WriteGetFrame(threadId, frameId)
+
+ self.WriteRunThread(threadId)
+
+ threadId, frameId = self.WaitForBreakpointHit()
+
+ self.WriteGetFrame(threadId, frameId)
+
+ self.WriteRemoveBreakpoint(breakpoint_id)
+
+ self.WriteRunThread(threadId)
+
+ assert 17 == self._sequence, 'Expected 17. Had: %s' % self._sequence
+
+ self.finishedOk = True
+
+#=======================================================================================================================
+# WriterThreadCase2
+#=======================================================================================================================
+class WriterThreadCase2(AbstractWriterThread):
+
+ TEST_FILE = NormFile('_debugger_case2.py')
+
+ def run(self):
+ self.StartSocket()
+ self.WriteAddBreakpoint(3, 'Call4') # seq = 3
+ self.WriteMakeInitialRun()
+
+ threadId, frameId = self.WaitForBreakpointHit()
+
+ self.WriteGetFrame(threadId, frameId)
+
+ self.WriteAddBreakpoint(14, 'Call2')
+
+ self.WriteRunThread(threadId)
+
+ threadId, frameId = self.WaitForBreakpointHit()
+
+ self.WriteGetFrame(threadId, frameId)
+
+ self.WriteRunThread(threadId)
+
+ assert 15 == self._sequence, 'Expected 15. Had: %s' % self._sequence
+
+ self.finishedOk = True
+
+#=======================================================================================================================
+# WriterThreadCase1
+#=======================================================================================================================
+class WriterThreadCase1(AbstractWriterThread):
+
+ TEST_FILE = NormFile('_debugger_case1.py')
+
+ def run(self):
+ self.StartSocket()
+ self.WriteAddBreakpoint(6, 'SetUp')
+ self.WriteMakeInitialRun()
+
+ threadId, frameId = self.WaitForBreakpointHit()
+
+ self.WriteGetFrame(threadId, frameId)
+
+ self.WriteStepOver(threadId)
+
+ self.WriteGetFrame(threadId, frameId)
+
+ self.WriteRunThread(threadId)
+
+ assert 13 == self._sequence, 'Expected 13. Had: %s' % self._sequence
+
+ self.finishedOk = True
+
+#=======================================================================================================================
+# DebuggerBase
+#=======================================================================================================================
+class DebuggerBase(object):
+
+ def getCommandLine(self):
+ raise NotImplementedError
+
+ def CheckCase(self, writerThreadClass):
+ UpdatePort()
+ writerThread = writerThreadClass()
+ writerThread.start()
+
+ localhost = pydev_localhost.get_localhost()
+ args = self.getCommandLine()
+ args += [
+ PYDEVD_FILE,
+ '--DEBUG_RECORD_SOCKET_READS',
+ '--client',
+ localhost,
+ '--port',
+ str(port),
+ '--file',
+ writerThread.TEST_FILE,
+ ]
+
+ if SHOW_OTHER_DEBUG_INFO:
+ print 'executing', ' '.join(args)
+
+# process = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=os.path.dirname(PYDEVD_FILE))
+ process = subprocess.Popen(args, stdout=subprocess.PIPE, cwd=os.path.dirname(PYDEVD_FILE))
+ class ProcessReadThread(threading.Thread):
+ def run(self):
+ self.resultStr = None
+ self.resultStr = process.stdout.read()
+ process.stdout.close()
+
+ def DoKill(self):
+ process.stdout.close()
+
+ processReadThread = ProcessReadThread()
+ processReadThread.setDaemon(True)
+ processReadThread.start()
+ if SHOW_OTHER_DEBUG_INFO:
+ print 'Both processes started'
+
+ # polls can fail (because the process may finish and the thread still not -- so, we give it some more chances to
+ # finish successfully).
+ pools_failed = 0
+ while writerThread.isAlive():
+ if process.poll() is not None:
+ pools_failed += 1
+ time.sleep(.2)
+ if pools_failed == 10:
+ break
+
+ if process.poll() is None:
+ for i in range(10):
+ if processReadThread.resultStr is None:
+ time.sleep(.5)
+ else:
+ break
+ else:
+ writerThread.DoKill()
+
+ else:
+ if process.poll() < 0:
+ self.fail("The other process exited with error code: " + str(process.poll()) + " result:" + processReadThread.resultStr)
+
+
+ if SHOW_RESULT_STR:
+ print processReadThread.resultStr
+
+ if processReadThread.resultStr is None:
+ self.fail("The other process may still be running -- and didn't give any output")
+
+ if 'TEST SUCEEDED' not in processReadThread.resultStr:
+ self.fail(processReadThread.resultStr)
+
+ if not writerThread.finishedOk:
+ self.fail("The thread that was doing the tests didn't finish successfully. Output: %s" % processReadThread.resultStr)
+
+ def testCase1(self):
+ self.CheckCase(WriterThreadCase1)
+
+ def testCase2(self):
+ self.CheckCase(WriterThreadCase2)
+
+ def testCase3(self):
+ self.CheckCase(WriterThreadCase3)
+
+ def testCase4(self):
+ self.CheckCase(WriterThreadCase4)
+
+ def testCase5(self):
+ self.CheckCase(WriterThreadCase5)
+
+ def testCase6(self):
+ self.CheckCase(WriterThreadCase6)
+
+ def testCase7(self):
+ self.CheckCase(WriterThreadCase7)
+
+ def testCase8(self):
+ self.CheckCase(WriterThreadCase8)
+
+ def testCase9(self):
+ self.CheckCase(WriterThreadCase9)
+
+ def testCase10(self):
+ self.CheckCase(WriterThreadCase10)
+
+ def testCase11(self):
+ self.CheckCase(WriterThreadCase11)
+
+ def testCase12(self):
+ self.CheckCase(WriterThreadCase12)
+
+ def testCase13(self):
+ self.CheckCase(WriterThreadCase13)
+
+ def testCase14(self):
+ self.CheckCase(WriterThreadCase14)
+
+ def testCase15(self):
+ self.CheckCase(WriterThreadCase15)
+
+ def testCase16(self):
+ self.CheckCase(WriterThreadCase16)
+
+ def testCase17(self):
+ self.CheckCase(WriterThreadCase17)
+
+ def testCase18(self):
+ self.CheckCase(WriterThreadCase18)
+
+ def testCase19(self):
+ self.CheckCase(WriterThreadCase19)
+
+
+class TestPython(unittest.TestCase, DebuggerBase):
+ def getCommandLine(self):
+ return [PYTHON_EXE]
+
+class TestJython(unittest.TestCase, DebuggerBase):
+ def getCommandLine(self):
+ return [
+ JAVA_LOCATION,
+ '-classpath',
+ JYTHON_JAR_LOCATION,
+ 'org.python.util.jython'
+ ]
+
+ # This case requires decorators to work (which are not present on Jython 2.1), so, this test is just removed from the jython run.
+ def testCase13(self):
+ self.skipTest("Unsupported Decorators")
+
+ def testCase16(self):
+ self.skipTest("Unsupported numpy")
+
+ # This case requires decorators to work (which are not present on Jython 2.1), so, this test is just removed from the jython run.
+ def testCase17(self):
+ self.skipTest("Unsupported Decorators")
+
+ def testCase18(self):
+ self.skipTest("Unsupported assign to local")
+
+class TestIronPython(unittest.TestCase, DebuggerBase):
+ def getCommandLine(self):
+ return [
+ IRONPYTHON_EXE,
+ '-X:Frames'
+ ]
+
+ def testCase16(self):
+ self.skipTest("Unsupported numpy")
+
+
+def GetLocationFromLine(line):
+ loc = line.split('=')[1].strip()
+ if loc.endswith(';'):
+ loc = loc[:-1]
+ if loc.endswith('"'):
+ loc = loc[:-1]
+ if loc.startswith('"'):
+ loc = loc[1:]
+ return loc
+
+
+def SplitLine(line):
+ if '=' not in line:
+ return None, None
+ var = line.split('=')[0].strip()
+ return var, GetLocationFromLine(line)
+
+
+
+import platform
+sysname = platform.system().lower()
+test_dependent = os.path.join('../../../', 'org.python.pydev.core', 'tests', 'org', 'python', 'pydev', 'core', 'TestDependent.' + sysname + '.properties')
+f = open(test_dependent)
+try:
+ for line in f.readlines():
+ var, loc = SplitLine(line)
+ if 'PYTHON_EXE' == var:
+ PYTHON_EXE = loc
+
+ if 'IRONPYTHON_EXE' == var:
+ IRONPYTHON_EXE = loc
+
+ if 'JYTHON_JAR_LOCATION' == var:
+ JYTHON_JAR_LOCATION = loc
+
+ if 'JAVA_LOCATION' == var:
+ JAVA_LOCATION = loc
+finally:
+ f.close()
+
+assert PYTHON_EXE, 'PYTHON_EXE not found in %s' % (test_dependent,)
+assert IRONPYTHON_EXE, 'IRONPYTHON_EXE not found in %s' % (test_dependent,)
+assert JYTHON_JAR_LOCATION, 'JYTHON_JAR_LOCATION not found in %s' % (test_dependent,)
+assert JAVA_LOCATION, 'JAVA_LOCATION not found in %s' % (test_dependent,)
+assert os.path.exists(PYTHON_EXE), 'The location: %s is not valid' % (PYTHON_EXE,)
+assert os.path.exists(IRONPYTHON_EXE), 'The location: %s is not valid' % (IRONPYTHON_EXE,)
+assert os.path.exists(JYTHON_JAR_LOCATION), 'The location: %s is not valid' % (JYTHON_JAR_LOCATION,)
+assert os.path.exists(JAVA_LOCATION), 'The location: %s is not valid' % (JAVA_LOCATION,)
+
+if False:
+ suite = unittest.TestSuite()
+ #PYTHON_EXE = r'C:\bin\Anaconda\python.exe'
+# suite.addTest(TestPython('testCase10'))
+# suite.addTest(TestPython('testCase3'))
+# suite.addTest(TestPython('testCase16'))
+# suite.addTest(TestPython('testCase17'))
+# suite.addTest(TestPython('testCase18'))
+# suite.addTest(TestPython('testCase19'))
+ suite = unittest.makeSuite(TestPython)
+ unittest.TextTestRunner(verbosity=3).run(suite)
+
+# unittest.TextTestRunner(verbosity=3).run(suite)
+#
+# suite = unittest.makeSuite(TestJython)
+# unittest.TextTestRunner(verbosity=3).run(suite)
diff --git a/python/helpers/pydev/tests_python/test_pydev_monkey.py b/python/helpers/pydev/tests_python/test_pydev_monkey.py
new file mode 100644
index 000000000000..3eb7930b73ae
--- /dev/null
+++ b/python/helpers/pydev/tests_python/test_pydev_monkey.py
@@ -0,0 +1,21 @@
+import unittest
+import pydev_monkey
+import sys
+
+
+
+class TestCase(unittest.TestCase):
+
+ def test_monkey(self):
+ check='''C:\\bin\\python.exe -u -c "
+connect(\\"127.0.0.1\\")
+"'''
+ sys.original_argv = []
+ self.assertEqual('"-u" "-c" "\nconnect(\\"127.0.0.1\\")\n"', pydev_monkey.patch_arg_str_win(check))
+
+ def test_str_to_args_windows(self):
+
+ self.assertEqual(['a', 'b'], pydev_monkey.str_to_args_windows('a "b"'))
+
+if __name__ == '__main__':
+ unittest.main() \ No newline at end of file
diff --git a/python/helpers/pydev/tests_python/test_save_locals.py b/python/helpers/pydev/tests_python/test_save_locals.py
new file mode 100644
index 000000000000..fe65d4d438d1
--- /dev/null
+++ b/python/helpers/pydev/tests_python/test_save_locals.py
@@ -0,0 +1,99 @@
+import inspect
+import sys
+import unittest
+
+from pydevd_save_locals import save_locals
+
+
+def use_save_locals(name, value):
+ """
+ Attempt to set the local of the given name to value, using locals_to_fast.
+ """
+ frame = inspect.currentframe().f_back
+ locals_dict = frame.f_locals
+ locals_dict[name] = value
+
+ save_locals(frame)
+
+
+def test_method(fn):
+ """
+ A harness for testing methods that attempt to modify the values of locals on the stack.
+ """
+ x = 1
+
+ # The method 'fn' should attempt to set x = 2 in the current frame.
+ fn('x', 2)
+
+ return x
+
+
+
+class TestSetLocals(unittest.TestCase):
+ """
+ Test setting locals in one function from another function using several approaches.
+ """
+
+
+ def test_set_locals_using_save_locals(self):
+ x = test_method(use_save_locals)
+ self.assertEqual(x, 2) # Expected to succeed
+
+
+ def test_frame_simple_change(self):
+ frame = sys._getframe()
+ a = 20
+ frame.f_locals['a'] = 50
+ save_locals(frame)
+ self.assertEquals(50, a)
+
+
+ def test_frame_co_freevars(self):
+
+ outer_var = 20
+
+ def func():
+ frame = sys._getframe()
+ frame.f_locals['outer_var'] = 50
+ save_locals(frame)
+ self.assertEquals(50, outer_var)
+
+ func()
+
+ def test_frame_co_cellvars(self):
+
+ def check_co_vars(a):
+ frame = sys._getframe()
+ def function2():
+ print a
+
+ assert 'a' in frame.f_code.co_cellvars
+ frame = sys._getframe()
+ frame.f_locals['a'] = 50
+ save_locals(frame)
+ self.assertEquals(50, a)
+
+ check_co_vars(1)
+
+
+ def test_frame_change_in_inner_frame(self):
+ def change(f):
+ self.assert_(f is not sys._getframe())
+ f.f_locals['a']= 50
+ save_locals(f)
+
+
+ frame = sys._getframe()
+ a = 20
+ change(frame)
+ self.assertEquals(50, a)
+
+
+if __name__ == '__main__':
+ suite = unittest.TestSuite()
+# suite.addTest(TestSetLocals('test_set_locals_using_dict'))
+# #suite.addTest(Test('testCase10a'))
+# unittest.TextTestRunner(verbosity=3).run(suite)
+
+ suite = unittest.makeSuite(TestSetLocals)
+ unittest.TextTestRunner(verbosity=3).run(suite)
diff --git a/python/helpers/pydev/tests_runfiles/not_in_default_pythonpath.txt b/python/helpers/pydev/tests_runfiles/not_in_default_pythonpath.txt
new file mode 100644
index 000000000000..29cdc5bc1078
--- /dev/null
+++ b/python/helpers/pydev/tests_runfiles/not_in_default_pythonpath.txt
@@ -0,0 +1 @@
+(no __init__.py file) \ No newline at end of file
diff --git a/python/helpers/pydev/tests_runfiles/samples/.cvsignore b/python/helpers/pydev/tests_runfiles/samples/.cvsignore
new file mode 100644
index 000000000000..d1c899510a28
--- /dev/null
+++ b/python/helpers/pydev/tests_runfiles/samples/.cvsignore
@@ -0,0 +1,2 @@
+*.class
+*.pyc
diff --git a/python/helpers/pydev/tests_runfiles/samples/__init__.py b/python/helpers/pydev/tests_runfiles/samples/__init__.py
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/python/helpers/pydev/tests_runfiles/samples/__init__.py
diff --git a/python/helpers/pydev/tests_runfiles/samples/nested_dir/__init__.py b/python/helpers/pydev/tests_runfiles/samples/nested_dir/__init__.py
new file mode 100644
index 000000000000..8b137891791f
--- /dev/null
+++ b/python/helpers/pydev/tests_runfiles/samples/nested_dir/__init__.py
@@ -0,0 +1 @@
+
diff --git a/python/helpers/pydev/tests_runfiles/samples/nested_dir/nested2/__init__.py b/python/helpers/pydev/tests_runfiles/samples/nested_dir/nested2/__init__.py
new file mode 100644
index 000000000000..8b137891791f
--- /dev/null
+++ b/python/helpers/pydev/tests_runfiles/samples/nested_dir/nested2/__init__.py
@@ -0,0 +1 @@
+
diff --git a/python/helpers/pydev/tests_runfiles/samples/nested_dir/nested2/deep_nest_test.py b/python/helpers/pydev/tests_runfiles/samples/nested_dir/nested2/deep_nest_test.py
new file mode 100644
index 000000000000..7b1972b89c8a
--- /dev/null
+++ b/python/helpers/pydev/tests_runfiles/samples/nested_dir/nested2/deep_nest_test.py
@@ -0,0 +1,22 @@
+import unittest
+
+class SampleTest(unittest.TestCase):
+
+ def setUp(self):
+ return
+
+ def tearDown(self):
+ return
+
+ def test_non_unique_name(self):
+ pass
+
+ def test_asdf2(self):
+ pass
+
+ def test_i_am_a_unique_test_name(self):
+ pass
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/python/helpers/pydev/tests_runfiles/samples/nested_dir/nested2/non_test_file.py b/python/helpers/pydev/tests_runfiles/samples/nested_dir/nested2/non_test_file.py
new file mode 100644
index 000000000000..470c65046922
--- /dev/null
+++ b/python/helpers/pydev/tests_runfiles/samples/nested_dir/nested2/non_test_file.py
@@ -0,0 +1,3 @@
+
+""" i am a python file with no tests """
+pass
diff --git a/python/helpers/pydev/tests_runfiles/samples/nested_dir/nested3/__init__.py b/python/helpers/pydev/tests_runfiles/samples/nested_dir/nested3/__init__.py
new file mode 100644
index 000000000000..8b137891791f
--- /dev/null
+++ b/python/helpers/pydev/tests_runfiles/samples/nested_dir/nested3/__init__.py
@@ -0,0 +1 @@
+
diff --git a/python/helpers/pydev/tests_runfiles/samples/nested_dir/nested3/junk.txt b/python/helpers/pydev/tests_runfiles/samples/nested_dir/nested3/junk.txt
new file mode 100644
index 000000000000..14dd4ddda145
--- /dev/null
+++ b/python/helpers/pydev/tests_runfiles/samples/nested_dir/nested3/junk.txt
@@ -0,0 +1 @@
+im a junk file
diff --git a/python/helpers/pydev/tests_runfiles/samples/nested_dir/nested3/non_test_file.py b/python/helpers/pydev/tests_runfiles/samples/nested_dir/nested3/non_test_file.py
new file mode 100644
index 000000000000..470c65046922
--- /dev/null
+++ b/python/helpers/pydev/tests_runfiles/samples/nested_dir/nested3/non_test_file.py
@@ -0,0 +1,3 @@
+
+""" i am a python file with no tests """
+pass
diff --git a/python/helpers/pydev/tests_runfiles/samples/nested_dir/non_test_file.py b/python/helpers/pydev/tests_runfiles/samples/nested_dir/non_test_file.py
new file mode 100644
index 000000000000..470c65046922
--- /dev/null
+++ b/python/helpers/pydev/tests_runfiles/samples/nested_dir/non_test_file.py
@@ -0,0 +1,3 @@
+
+""" i am a python file with no tests """
+pass
diff --git a/python/helpers/pydev/tests_runfiles/samples/nested_dir/simple4_test.py b/python/helpers/pydev/tests_runfiles/samples/nested_dir/simple4_test.py
new file mode 100644
index 000000000000..ba5d45f1a1e2
--- /dev/null
+++ b/python/helpers/pydev/tests_runfiles/samples/nested_dir/simple4_test.py
@@ -0,0 +1,16 @@
+import unittest
+
+class NestedSampleTest(unittest.TestCase):
+
+ def setUp(self):
+ return
+
+ def tearDown(self):
+ return
+
+ def test_non_unique_name(self):
+ pass
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/python/helpers/pydev/tests_runfiles/samples/non_test_file.py b/python/helpers/pydev/tests_runfiles/samples/non_test_file.py
new file mode 100644
index 000000000000..470c65046922
--- /dev/null
+++ b/python/helpers/pydev/tests_runfiles/samples/non_test_file.py
@@ -0,0 +1,3 @@
+
+""" i am a python file with no tests """
+pass
diff --git a/python/helpers/pydev/tests_runfiles/samples/simple2_test.py b/python/helpers/pydev/tests_runfiles/samples/simple2_test.py
new file mode 100644
index 000000000000..d46468ede256
--- /dev/null
+++ b/python/helpers/pydev/tests_runfiles/samples/simple2_test.py
@@ -0,0 +1,16 @@
+import unittest
+
+class YetAnotherSampleTest(unittest.TestCase):
+
+ def setUp(self):
+ return
+
+ def tearDown(self):
+ return
+
+ def test_abc(self):
+ pass
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/python/helpers/pydev/tests_runfiles/samples/simple3_test.py b/python/helpers/pydev/tests_runfiles/samples/simple3_test.py
new file mode 100644
index 000000000000..da1ccbfba1e0
--- /dev/null
+++ b/python/helpers/pydev/tests_runfiles/samples/simple3_test.py
@@ -0,0 +1,16 @@
+import unittest
+
+class StillYetAnotherSampleTest(unittest.TestCase):
+
+ def setUp(self):
+ return
+
+ def tearDown(self):
+ return
+
+ def test_non_unique_name(self):
+ pass
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/python/helpers/pydev/tests_runfiles/samples/simpleClass_test.py b/python/helpers/pydev/tests_runfiles/samples/simpleClass_test.py
new file mode 100644
index 000000000000..3a9c900e2c2b
--- /dev/null
+++ b/python/helpers/pydev/tests_runfiles/samples/simpleClass_test.py
@@ -0,0 +1,14 @@
+import unittest
+
+class SetUpClassTest(unittest.TestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ raise ValueError("This is an INTENTIONAL value error in setUpClass.")
+
+ def test_blank(self):
+ pass
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/python/helpers/pydev/tests_runfiles/samples/simpleModule_test.py b/python/helpers/pydev/tests_runfiles/samples/simpleModule_test.py
new file mode 100644
index 000000000000..fdde67e4aec4
--- /dev/null
+++ b/python/helpers/pydev/tests_runfiles/samples/simpleModule_test.py
@@ -0,0 +1,16 @@
+import unittest
+
+def setUpModule():
+ raise ValueError("This is an INTENTIONAL value error in setUpModule.")
+
+class SetUpModuleTest(unittest.TestCase):
+
+ def setUp(cls):
+ pass
+
+ def test_blank(self):
+ pass
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/python/helpers/pydev/tests_runfiles/samples/simple_test.py b/python/helpers/pydev/tests_runfiles/samples/simple_test.py
new file mode 100644
index 000000000000..619df7c821e2
--- /dev/null
+++ b/python/helpers/pydev/tests_runfiles/samples/simple_test.py
@@ -0,0 +1,45 @@
+import unittest
+
+class SampleTest(unittest.TestCase):
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def test_xxxxxx1(self):
+ self.fail('Fail test 2')
+ def test_xxxxxx2(self):
+ pass
+ def test_xxxxxx3(self):
+ pass
+ def test_xxxxxx4(self):
+ pass
+ def test_non_unique_name(self):
+ print('non unique name ran')
+
+
+class AnotherSampleTest(unittest.TestCase):
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def test_1(self):
+ pass
+ def test_2(self):
+ """ im a doc string"""
+ pass
+ def todo_not_tested(self):
+ '''
+ Not there by default!
+ '''
+
+
+if __name__ == '__main__':
+# suite = unittest.makeSuite(SampleTest, 'test')
+# runner = unittest.TextTestRunner( verbosity=3 )
+# runner.run(suite)
+ unittest.main()
diff --git a/python/helpers/pydev/tests_runfiles/test_pydevd_property.py b/python/helpers/pydev/tests_runfiles/test_pydevd_property.py
new file mode 100644
index 000000000000..64fa9b65efc3
--- /dev/null
+++ b/python/helpers/pydev/tests_runfiles/test_pydevd_property.py
@@ -0,0 +1,134 @@
+'''
+Created on Aug 22, 2011
+
+@author: hussain.bohra
+@author: fabioz
+'''
+
+import os
+import sys
+import unittest
+
+#=======================================================================================================================
+# Test
+#=======================================================================================================================
+class Test(unittest.TestCase):
+ """Test cases to validate custom property implementation in pydevd
+ """
+
+ def setUp(self, nused=None):
+ self.tempdir = os.path.join(os.path.dirname(os.path.dirname(__file__)))
+ sys.path.insert(0, self.tempdir)
+ import pydevd_traceproperty
+ self.old = pydevd_traceproperty.replace_builtin_property()
+
+
+ def tearDown(self, unused=None):
+ import pydevd_traceproperty
+ pydevd_traceproperty.replace_builtin_property(self.old)
+ sys.path.remove(self.tempdir)
+
+
+ def testProperty(self):
+ """Test case to validate custom property
+ """
+
+ import pydevd_traceproperty
+ class TestProperty(object):
+
+ def __init__(self):
+ self._get = 0
+ self._set = 0
+ self._del = 0
+
+ def get_name(self):
+ self._get += 1
+ return self.__name
+
+ def set_name(self, value):
+ self._set += 1
+ self.__name = value
+
+ def del_name(self):
+ self._del += 1
+ del self.__name
+ name = property(get_name, set_name, del_name, "name's docstring")
+ self.assertEqual(name.__class__, pydevd_traceproperty.DebugProperty)
+
+ testObj = TestProperty()
+ self._check(testObj)
+
+
+ def testProperty2(self):
+ """Test case to validate custom property
+ """
+
+ class TestProperty(object):
+
+ def __init__(self):
+ self._get = 0
+ self._set = 0
+ self._del = 0
+
+ def name(self):
+ self._get += 1
+ return self.__name
+ name = property(name)
+
+ def set_name(self, value):
+ self._set += 1
+ self.__name = value
+ name.setter(set_name)
+
+ def del_name(self):
+ self._del += 1
+ del self.__name
+ name.deleter(del_name)
+
+ testObj = TestProperty()
+ self._check(testObj)
+
+
+ def testProperty3(self):
+ """Test case to validate custom property
+ """
+
+ class TestProperty(object):
+
+ def __init__(self):
+ self._name = 'foo'
+
+ def name(self):
+ return self._name
+ name = property(name)
+
+ testObj = TestProperty()
+ self.assertRaises(AttributeError, setattr, testObj, 'name', 'bar')
+ self.assertRaises(AttributeError, delattr, testObj, 'name')
+
+
+ def _check(self, testObj):
+ testObj.name = "Custom"
+ self.assertEqual(1, testObj._set)
+
+ self.assertEqual(testObj.name, "Custom")
+ self.assertEqual(1, testObj._get)
+
+ self.assert_(hasattr(testObj, 'name'))
+ del testObj.name
+ self.assertEqual(1, testObj._del)
+
+ self.assert_(not hasattr(testObj, 'name'))
+ testObj.name = "Custom2"
+ self.assertEqual(testObj.name, "Custom2")
+
+
+
+#=======================================================================================================================
+# main
+#=======================================================================================================================
+if __name__ == '__main__':
+ #this is so that we can run it from the jython tests -- because we don't actually have an __main__ module
+ #(so, it won't try importing the __main__ module)
+ unittest.TextTestRunner().run(unittest.makeSuite(Test))
+
diff --git a/python/helpers/pydev/tests_runfiles/test_pydevdio.py b/python/helpers/pydev/tests_runfiles/test_pydevdio.py
new file mode 100644
index 000000000000..7a48a63bd6d4
--- /dev/null
+++ b/python/helpers/pydev/tests_runfiles/test_pydevdio.py
@@ -0,0 +1,40 @@
+import sys
+import os
+
+
+import unittest
+
+class Test(unittest.TestCase):
+
+ def testIt(self):
+ #make it as if we were executing from the directory above this one (so that we can use jycompletionserver
+ #without the need for it being in the pythonpath)
+ #(twice the dirname to get the previous level from this file.)
+ import test_pydevdio #@UnresolvedImport - importing itself
+ ADD_TO_PYTHONPATH = os.path.join(os.path.dirname(os.path.dirname(test_pydevdio.__file__)))
+ sys.path.insert(0, ADD_TO_PYTHONPATH)
+
+ try:
+ import pydevd_io
+ original = sys.stdout
+
+ try:
+ sys.stdout = pydevd_io.IOBuf()
+ print('foo')
+ print('bar')
+
+ self.assertEquals('foo\nbar\n', sys.stdout.getvalue()) #@UndefinedVariable
+
+ print('ww')
+ print('xx')
+ self.assertEquals('ww\nxx\n', sys.stdout.getvalue()) #@UndefinedVariable
+ finally:
+ sys.stdout = original
+ finally:
+ #remove it to leave it ok for other tests
+ sys.path.remove(ADD_TO_PYTHONPATH)
+
+if __name__ == '__main__':
+ #this is so that we can run it frem the jython tests -- because we don't actually have an __main__ module
+ #(so, it won't try importing the __main__ module)
+ unittest.TextTestRunner().run(unittest.makeSuite(Test))
diff --git a/python/helpers/pydev/tests_runfiles/test_runfiles.py b/python/helpers/pydev/tests_runfiles/test_runfiles.py
new file mode 100644
index 000000000000..0c04764e99fc
--- /dev/null
+++ b/python/helpers/pydev/tests_runfiles/test_runfiles.py
@@ -0,0 +1,393 @@
+import os.path
+import sys
+
+IS_JYTHON = sys.platform.find('java') != -1
+
+try:
+ this_file_name = __file__
+except NameError:
+ # stupid jython. plain old __file__ isnt working for some reason
+ import test_runfiles #@UnresolvedImport - importing the module itself
+ this_file_name = test_runfiles.__file__
+
+
+desired_runfiles_path = os.path.normpath(os.path.dirname(this_file_name) + "/..")
+sys.path.insert(0, desired_runfiles_path)
+
+import pydev_runfiles_unittest
+import pydev_runfiles_xml_rpc
+import pydevd_io
+
+#remove existing pydev_runfiles from modules (if any), so that we can be sure we have the correct version
+if 'pydev_runfiles' in sys.modules:
+ del sys.modules['pydev_runfiles']
+
+
+import pydev_runfiles
+import unittest
+import tempfile
+
+try:
+ set
+except:
+ from sets import Set as set
+
+#this is an early test because it requires the sys.path changed
+orig_syspath = sys.path
+a_file = pydev_runfiles.__file__
+pydev_runfiles.PydevTestRunner(pydev_runfiles.Configuration(files_or_dirs=[a_file]))
+file_dir = os.path.dirname(a_file)
+assert file_dir in sys.path
+sys.path = orig_syspath[:]
+
+#remove it so that we leave it ok for other tests
+sys.path.remove(desired_runfiles_path)
+
+class RunfilesTest(unittest.TestCase):
+
+ def _setup_scenario(
+ self,
+ path,
+ include_tests=None,
+ tests=None,
+ files_to_tests=None,
+ exclude_files=None,
+ exclude_tests=None,
+ include_files=None,
+ ):
+ self.MyTestRunner = pydev_runfiles.PydevTestRunner(
+ pydev_runfiles.Configuration(
+ files_or_dirs=path,
+ include_tests=include_tests,
+ verbosity=1,
+ tests=tests,
+ files_to_tests=files_to_tests,
+ exclude_files=exclude_files,
+ exclude_tests=exclude_tests,
+ include_files=include_files,
+ )
+ )
+ self.files = self.MyTestRunner.find_import_files()
+ self.modules = self.MyTestRunner.find_modules_from_files(self.files)
+ self.all_tests = self.MyTestRunner.find_tests_from_modules(self.modules)
+ self.filtered_tests = self.MyTestRunner.filter_tests(self.all_tests)
+
+ def setUp(self):
+ self.file_dir = [os.path.abspath(os.path.join(desired_runfiles_path, 'tests_runfiles/samples'))]
+ self._setup_scenario(self.file_dir, None)
+
+
+ def test_suite_used(self):
+ for suite in self.all_tests + self.filtered_tests:
+ self.assert_(isinstance(suite, pydev_runfiles_unittest.PydevTestSuite))
+
+ def test_parse_cmdline(self):
+ sys.argv = "pydev_runfiles.py ./".split()
+ configuration = pydev_runfiles.parse_cmdline()
+ self.assertEquals([sys.argv[1]], configuration.files_or_dirs)
+ self.assertEquals(2, configuration.verbosity) # default value
+ self.assertEquals(None, configuration.include_tests) # default value
+
+ sys.argv = "pydev_runfiles.py ../images c:/temp".split()
+ configuration = pydev_runfiles.parse_cmdline()
+ self.assertEquals(sys.argv[1:3], configuration.files_or_dirs)
+ self.assertEquals(2, configuration.verbosity)
+
+ sys.argv = "pydev_runfiles.py --verbosity 3 ../junk c:/asdf ".split()
+ configuration = pydev_runfiles.parse_cmdline()
+ self.assertEquals(sys.argv[3:], configuration.files_or_dirs)
+ self.assertEquals(int(sys.argv[2]), configuration.verbosity)
+
+ sys.argv = "pydev_runfiles.py --include_tests test_def ./".split()
+ configuration = pydev_runfiles.parse_cmdline()
+ self.assertEquals([sys.argv[-1]], configuration.files_or_dirs)
+ self.assertEquals([sys.argv[2]], configuration.include_tests)
+
+ sys.argv = "pydev_runfiles.py --include_tests Abc.test_def,Mod.test_abc c:/junk/".split()
+ configuration = pydev_runfiles.parse_cmdline()
+ self.assertEquals([sys.argv[-1]], configuration.files_or_dirs)
+ self.assertEquals(sys.argv[2].split(','), configuration.include_tests)
+
+ sys.argv = ('C:\\eclipse-SDK-3.2-win32\\eclipse\\plugins\\org.python.pydev.debug_1.2.2\\pysrc\\pydev_runfiles.py ' +
+ '--verbosity 1 ' +
+ 'C:\\workspace_eclipse\\fronttpa\\tests\\gui_tests\\calendar_popup_control_test.py ').split()
+ configuration = pydev_runfiles.parse_cmdline()
+ self.assertEquals([sys.argv[-1]], configuration.files_or_dirs)
+ self.assertEquals(1, configuration.verbosity)
+
+ sys.argv = "pydev_runfiles.py --verbosity 1 --include_tests Mod.test_abc c:/junk/ ./".split()
+ configuration = pydev_runfiles.parse_cmdline()
+ self.assertEquals(sys.argv[5:], configuration.files_or_dirs)
+ self.assertEquals(int(sys.argv[2]), configuration.verbosity)
+ self.assertEquals([sys.argv[4]], configuration.include_tests)
+
+ sys.argv = "pydev_runfiles.py --exclude_files=*.txt,a*.py".split()
+ configuration = pydev_runfiles.parse_cmdline()
+ self.assertEquals(['*.txt', 'a*.py'], configuration.exclude_files)
+
+ sys.argv = "pydev_runfiles.py --exclude_tests=*__todo,test*bar".split()
+ configuration = pydev_runfiles.parse_cmdline()
+ self.assertEquals(['*__todo', 'test*bar'], configuration.exclude_tests)
+
+
+ def test___adjust_python_path_works_for_directories(self):
+ orig_syspath = sys.path
+ tempdir = tempfile.gettempdir()
+ pydev_runfiles.PydevTestRunner(pydev_runfiles.Configuration(files_or_dirs=[tempdir]))
+ self.assertEquals(1, tempdir in sys.path)
+ sys.path = orig_syspath[:]
+
+
+ def test___is_valid_py_file(self):
+ isvalid = self.MyTestRunner._PydevTestRunner__is_valid_py_file
+ self.assertEquals(1, isvalid("test.py"))
+ self.assertEquals(0, isvalid("asdf.pyc"))
+ self.assertEquals(0, isvalid("__init__.py"))
+ self.assertEquals(0, isvalid("__init__.pyc"))
+ self.assertEquals(1, isvalid("asdf asdf.pyw"))
+
+ def test___unixify(self):
+ unixify = self.MyTestRunner._PydevTestRunner__unixify
+ self.assertEquals("c:/temp/junk/asdf.py", unixify("c:SEPtempSEPjunkSEPasdf.py".replace('SEP', os.sep)))
+
+ def test___importify(self):
+ importify = self.MyTestRunner._PydevTestRunner__importify
+ self.assertEquals("temp.junk.asdf", importify("temp/junk/asdf.py"))
+ self.assertEquals("asdf", importify("asdf.py"))
+ self.assertEquals("abc.def.hgi", importify("abc/def/hgi"))
+
+ def test_finding_a_file_from_file_system(self):
+ test_file = "simple_test.py"
+ self.MyTestRunner.files_or_dirs = [self.file_dir[0] + test_file]
+ files = self.MyTestRunner.find_import_files()
+ self.assertEquals(1, len(files))
+ self.assertEquals(files[0], self.file_dir[0] + test_file)
+
+ def test_finding_files_in_dir_from_file_system(self):
+ self.assertEquals(1, len(self.files) > 0)
+ for import_file in self.files:
+ self.assertEquals(-1, import_file.find(".pyc"))
+ self.assertEquals(-1, import_file.find("__init__.py"))
+ self.assertEquals(-1, import_file.find("\\"))
+ self.assertEquals(-1, import_file.find(".txt"))
+
+ def test___get_module_from_str(self):
+ my_importer = self.MyTestRunner._PydevTestRunner__get_module_from_str
+ my_os_path = my_importer("os.path", True, 'unused')
+ from os import path
+ import os.path as path2
+ self.assertEquals(path, my_os_path)
+ self.assertEquals(path2, my_os_path)
+ self.assertNotEquals(__import__("os.path"), my_os_path)
+ self.assertNotEquals(__import__("os"), my_os_path)
+
+ def test_finding_modules_from_import_strings(self):
+ self.assertEquals(1, len(self.modules) > 0)
+
+ def test_finding_tests_when_no_filter(self):
+ # unittest.py will create a TestCase with 0 tests in it
+ # since it just imports what is given
+ self.assertEquals(1, len(self.all_tests) > 0)
+ files_with_tests = [1 for t in self.all_tests if len(t._tests) > 0]
+ self.assertNotEquals(len(self.files), len(files_with_tests))
+
+ def count_tests(self, tests):
+ total = 0
+ for t in tests:
+ total += t.countTestCases()
+ return total
+
+ def test___match(self):
+ matcher = self.MyTestRunner._PydevTestRunner__match
+ self.assertEquals(1, matcher(None, "aname"))
+ self.assertEquals(1, matcher([".*"], "aname"))
+ self.assertEquals(0, matcher(["^x$"], "aname"))
+ self.assertEquals(0, matcher(["abc"], "aname"))
+ self.assertEquals(1, matcher(["abc", "123"], "123"))
+
+ def test_finding_tests_from_modules_with_bad_filter_returns_0_tests(self):
+ self._setup_scenario(self.file_dir, ["NO_TESTS_ARE_SURE_TO_HAVE_THIS_NAME"])
+ self.assertEquals(0, self.count_tests(self.all_tests))
+
+ def test_finding_test_with_unique_name_returns_1_test(self):
+ self._setup_scenario(self.file_dir, include_tests=["test_i_am_a_unique_test_name"])
+ filtered_tests = self.MyTestRunner.filter_tests(self.all_tests)
+ self.assertEquals(1, self.count_tests(filtered_tests))
+
+ def test_finding_test_with_non_unique_name(self):
+ self._setup_scenario(self.file_dir, include_tests=["test_non_unique_name"])
+ filtered_tests = self.MyTestRunner.filter_tests(self.all_tests)
+ self.assertEquals(1, self.count_tests(filtered_tests) > 2)
+
+ def test_finding_tests_with_regex_filters(self):
+ self._setup_scenario(self.file_dir, include_tests=["test_non*"])
+ filtered_tests = self.MyTestRunner.filter_tests(self.all_tests)
+ self.assertEquals(1, self.count_tests(filtered_tests) > 2)
+
+ self._setup_scenario(self.file_dir, ["^$"])
+ filtered_tests = self.MyTestRunner.filter_tests(self.all_tests)
+ self.assertEquals(0, self.count_tests(filtered_tests))
+
+ self._setup_scenario(self.file_dir, None, exclude_tests=["*"])
+ filtered_tests = self.MyTestRunner.filter_tests(self.all_tests)
+ self.assertEquals(0, self.count_tests(filtered_tests))
+
+ def test_matching_tests(self):
+ self._setup_scenario(self.file_dir, None, ['StillYetAnotherSampleTest'])
+ filtered_tests = self.MyTestRunner.filter_tests(self.all_tests)
+ self.assertEqual(1, self.count_tests(filtered_tests))
+
+ self._setup_scenario(self.file_dir, None, ['SampleTest.test_xxxxxx1'])
+ filtered_tests = self.MyTestRunner.filter_tests(self.all_tests)
+ self.assertEqual(1, self.count_tests(filtered_tests))
+
+ self._setup_scenario(self.file_dir, None, ['SampleTest'])
+ filtered_tests = self.MyTestRunner.filter_tests(self.all_tests)
+ self.assertEqual(8, self.count_tests(filtered_tests))
+
+ self._setup_scenario(self.file_dir, None, ['AnotherSampleTest.todo_not_tested'])
+ filtered_tests = self.MyTestRunner.filter_tests(self.all_tests)
+ self.assertEqual(1, self.count_tests(filtered_tests))
+
+ self._setup_scenario(self.file_dir, None, ['StillYetAnotherSampleTest', 'SampleTest.test_xxxxxx1'])
+ filtered_tests = self.MyTestRunner.filter_tests(self.all_tests)
+ self.assertEqual(2, self.count_tests(filtered_tests))
+
+ self._setup_scenario(self.file_dir, None, exclude_tests=['*'])
+ filtered_tests = self.MyTestRunner.filter_tests(self.all_tests)
+ self.assertEqual(self.count_tests(filtered_tests), 0)
+
+
+ self._setup_scenario(self.file_dir, None, exclude_tests=['*a*'])
+ filtered_tests = self.MyTestRunner.filter_tests(self.all_tests)
+ self.assertEqual(self.count_tests(filtered_tests), 6)
+
+ self.assertEqual(
+ set(self.MyTestRunner.list_test_names(filtered_tests)),
+ set(['test_1', 'test_2', 'test_xxxxxx1', 'test_xxxxxx2', 'test_xxxxxx3', 'test_xxxxxx4'])
+ )
+
+ self._setup_scenario(self.file_dir, None, exclude_tests=['*a*', '*x*'])
+ filtered_tests = self.MyTestRunner.filter_tests(self.all_tests)
+ self.assertEqual(self.count_tests(filtered_tests), 2)
+
+ self.assertEqual(
+ set(self.MyTestRunner.list_test_names(filtered_tests)),
+ set(['test_1', 'test_2'])
+ )
+
+ self._setup_scenario(self.file_dir, None, exclude_files=['simple_test.py'])
+ filtered_tests = self.MyTestRunner.filter_tests(self.all_tests)
+ names = self.MyTestRunner.list_test_names(filtered_tests)
+ self.assert_('test_xxxxxx1' not in names, 'Found: %s' % (names,))
+
+ self.assertEqual(
+ set(['test_abc', 'test_non_unique_name', 'test_non_unique_name', 'test_asdf2', 'test_i_am_a_unique_test_name', 'test_non_unique_name', 'test_blank']),
+ set(names)
+ )
+
+ self._setup_scenario(self.file_dir, None, include_files=['simple3_test.py'])
+ filtered_tests = self.MyTestRunner.filter_tests(self.all_tests)
+ names = self.MyTestRunner.list_test_names(filtered_tests)
+ self.assert_('test_xxxxxx1' not in names, 'Found: %s' % (names,))
+
+ self.assertEqual(
+ set(['test_non_unique_name']),
+ set(names)
+ )
+
+ def test_xml_rpc_communication(self):
+ notifications = []
+ class Server:
+
+ def __init__(self, notifications):
+ self.notifications = notifications
+
+ def notifyConnected(self):
+ #This method is called at the very start (in runfiles.py), and we do not check this here
+ raise AssertionError('Should not be called from the run tests.')
+
+
+ def notifyTestsCollected(self, number_of_tests):
+ self.notifications.append(('notifyTestsCollected', number_of_tests))
+
+
+ def notifyStartTest(self, file, test):
+ pass
+
+ def notifyTest(self, cond, captured_output, error_contents, file, test, time):
+ try:
+ #I.e.: when marked as Binary in xml-rpc
+ captured_output = captured_output.data
+ except:
+ pass
+ try:
+ #I.e.: when marked as Binary in xml-rpc
+ error_contents = error_contents.data
+ except:
+ pass
+ if error_contents:
+ error_contents = error_contents.splitlines()[-1].strip()
+ self.notifications.append(('notifyTest', cond, captured_output.strip(), error_contents, file, test))
+
+ def notifyTestRunFinished(self, total_time):
+ self.notifications.append(('notifyTestRunFinished',))
+
+ server = Server(notifications)
+ pydev_runfiles_xml_rpc.SetServer(server)
+ simple_test = os.path.join(self.file_dir[0], 'simple_test.py')
+ simple_test2 = os.path.join(self.file_dir[0], 'simple2_test.py')
+ simpleClass_test = os.path.join(self.file_dir[0], 'simpleClass_test.py')
+ simpleModule_test = os.path.join(self.file_dir[0], 'simpleModule_test.py')
+
+ files_to_tests = {}
+ files_to_tests.setdefault(simple_test , []).append('SampleTest.test_xxxxxx1')
+ files_to_tests.setdefault(simple_test , []).append('SampleTest.test_xxxxxx2')
+ files_to_tests.setdefault(simple_test , []).append('SampleTest.test_non_unique_name')
+ files_to_tests.setdefault(simple_test2, []).append('YetAnotherSampleTest.test_abc')
+ files_to_tests.setdefault(simpleClass_test, []).append('SetUpClassTest.test_blank')
+ files_to_tests.setdefault(simpleModule_test, []).append('SetUpModuleTest.test_blank')
+
+ self._setup_scenario(None, files_to_tests=files_to_tests)
+ self.MyTestRunner.verbosity = 2
+
+ buf = pydevd_io.StartRedirect(keep_original_redirection=False)
+ try:
+ self.MyTestRunner.run_tests()
+ self.assertEqual(8, len(notifications))
+ expected = [
+ ('notifyTestsCollected', 6),
+ ('notifyTest', 'ok', 'non unique name ran', '', simple_test, 'SampleTest.test_non_unique_name'),
+ ('notifyTest', 'fail', '', 'AssertionError: Fail test 2', simple_test, 'SampleTest.test_xxxxxx1'),
+ ('notifyTest', 'ok', '', '', simple_test, 'SampleTest.test_xxxxxx2'),
+ ('notifyTest', 'ok', '', '', simple_test2, 'YetAnotherSampleTest.test_abc'),
+ ]
+ if not IS_JYTHON:
+ expected.append(('notifyTest', 'error', '', 'ValueError: This is an INTENTIONAL value error in setUpClass.',
+ simpleClass_test.replace('/', os.path.sep), 'samples.simpleClass_test.SetUpClassTest <setUpClass>'))
+ expected.append(('notifyTest', 'error', '', 'ValueError: This is an INTENTIONAL value error in setUpModule.',
+ simpleModule_test.replace('/', os.path.sep), 'samples.simpleModule_test <setUpModule>'))
+ else:
+ expected.append(('notifyTest', 'ok', '', '', simpleClass_test, 'SetUpClassTest.test_blank'))
+ expected.append(('notifyTest', 'ok', '', '', simpleModule_test, 'SetUpModuleTest.test_blank'))
+
+ expected.append(('notifyTestRunFinished',))
+ expected.sort()
+ notifications.sort()
+ self.assertEqual(
+ expected,
+ notifications
+ )
+ finally:
+ pydevd_io.EndRedirect()
+ b = buf.getvalue()
+ if not IS_JYTHON:
+ self.assert_(b.find('Ran 4 tests in ') != -1, 'Found: ' + b)
+ else:
+ self.assert_(b.find('Ran 6 tests in ') != -1, 'Found: ' + b)
+
+
+if __name__ == "__main__":
+ #this is so that we can run it frem the jython tests -- because we don't actually have an __main__ module
+ #(so, it won't try importing the __main__ module)
+ unittest.TextTestRunner().run(unittest.makeSuite(RunfilesTest))
diff --git a/python/ide/src/com/jetbrains/python/PythonSdkChooserCombo.java b/python/ide/src/com/jetbrains/python/PythonSdkChooserCombo.java
index 3010b74486fa..69a98ded43f5 100644
--- a/python/ide/src/com/jetbrains/python/PythonSdkChooserCombo.java
+++ b/python/ide/src/com/jetbrains/python/PythonSdkChooserCombo.java
@@ -64,8 +64,15 @@ public class PythonSdkChooserCombo extends ComboboxWithBrowseButton {
comboBox.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
notifyChanged(e);
+ updateTooltip();
}
});
+ updateTooltip();
+ }
+
+ private void updateTooltip() {
+ final Object item = getComboBox().getSelectedItem();
+ getComboBox().setToolTipText(item instanceof Sdk ? ((Sdk)item).getHomePath() : null);
}
private void showOptions(final Project project) {
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 6ba283caf199..dd68cdb6ed2f 100644
--- a/python/ide/src/com/jetbrains/python/newProject/actions/AbstractProjectSettingsStep.java
+++ b/python/ide/src/com/jetbrains/python/newProject/actions/AbstractProjectSettingsStep.java
@@ -205,7 +205,19 @@ abstract public class AbstractProjectSettingsStep extends AbstractActionWithPane
final Project project = ProjectManager.getInstance().getDefaultProject();
final List<Sdk> sdks = PyConfigurableInterpreterList.getInstance(project).getAllPythonSdks();
VirtualEnvProjectFilter.removeAllAssociated(sdks);
- final Sdk preferred = sdks.isEmpty() ? null : sdks.iterator().next();
+ Sdk compatibleSdk = sdks.isEmpty() ? null : sdks.iterator().next();
+ DirectoryProjectGenerator generator = getProjectGenerator();
+ if (generator instanceof PyFrameworkProjectGenerator && !((PyFrameworkProjectGenerator)generator).supportsPython3()) {
+ if (compatibleSdk != null && PythonSdkType.getLanguageLevelForSdk(compatibleSdk).isPy3K()) {
+ Sdk python2Sdk = PythonSdkType.findPython2Sdk(sdks);
+ if (python2Sdk != null) {
+ compatibleSdk = python2Sdk;
+
+ }
+ }
+ }
+
+ final Sdk preferred = compatibleSdk;
mySdkCombo = new PythonSdkChooserCombo(project, sdks, new Condition<Sdk>() {
@Override
public boolean value(Sdk sdk) {
@@ -231,6 +243,8 @@ abstract public class AbstractProjectSettingsStep extends AbstractActionWithPane
@Nullable
protected JPanel extendBasePanel() {
+ if (myProjectGenerator instanceof PythonProjectGenerator)
+ return ((PythonProjectGenerator)myProjectGenerator).extendBasePanel();
return null;
}
@@ -354,17 +368,19 @@ abstract public class AbstractProjectSettingsStep extends AbstractActionWithPane
}
public void selectCompatiblePython() {
- DirectoryProjectGenerator generator = getProjectGenerator();
- if (generator instanceof PyFrameworkProjectGenerator && !((PyFrameworkProjectGenerator)generator).supportsPython3()) {
- Sdk sdk = getSdk();
- if (sdk != null && PythonSdkType.getLanguageLevelForSdk(sdk).isPy3K()) {
- Sdk python2Sdk = PythonSdkType.findPython2Sdk(null);
- if (python2Sdk != null) {
- mySdkCombo.getComboBox().setSelectedItem(python2Sdk);
- mySdkCombo.getComboBox().repaint();
- }
- }
- }
+ //DirectoryProjectGenerator generator = getProjectGenerator();
+ //if (generator instanceof PyFrameworkProjectGenerator && !((PyFrameworkProjectGenerator)generator).supportsPython3()) {
+ // Sdk sdk = getSdk();
+ // if (sdk != null && PythonSdkType.getLanguageLevelForSdk(sdk).isPy3K()) {
+ // Sdk python2Sdk = PythonSdkType.findPython2Sdk(null);
+ // if (python2Sdk != null) {
+ // mySdkCombo.getComboBox().setSelectedItem(python2Sdk);
+ // mySdkCombo.getComboBox().revalidate();
+ // mySdkCombo.getComboBox().repaint();
+ //
+ // }
+ // }
+ //}
}
private static boolean acceptsRemoteSdk(DirectoryProjectGenerator generator) {
diff --git a/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificAction.java b/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificAction.java
index 950e11e0beca..4397a090b253 100644
--- a/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificAction.java
+++ b/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificAction.java
@@ -42,6 +42,5 @@ public class ProjectSpecificAction extends DefaultActionGroup implements DumbAwa
@Override
public void actionPerformed(AnActionEvent e) {
super.actionPerformed(e);
- mySettings.selectCompatiblePython();
}
}
diff --git a/python/openapi/src/com/jetbrains/python/newProject/PythonProjectGenerator.java b/python/openapi/src/com/jetbrains/python/newProject/PythonProjectGenerator.java
index 1432e468f3e8..3216bfc20f53 100644
--- a/python/openapi/src/com/jetbrains/python/newProject/PythonProjectGenerator.java
+++ b/python/openapi/src/com/jetbrains/python/newProject/PythonProjectGenerator.java
@@ -19,6 +19,11 @@ public abstract class PythonProjectGenerator {
return null;
}
+ @Nullable
+ public JPanel extendBasePanel() throws ProcessCanceledException {
+ return null;
+ }
+
public Object getProjectSettings() {
return new PyNewProjectSettings();
}
diff --git a/python/openapi/src/com/jetbrains/python/templateLanguages/TemplateLanguagePanel.java b/python/openapi/src/com/jetbrains/python/templateLanguages/TemplateLanguagePanel.java
index d2c453e785d2..6196b54c9465 100644
--- a/python/openapi/src/com/jetbrains/python/templateLanguages/TemplateLanguagePanel.java
+++ b/python/openapi/src/com/jetbrains/python/templateLanguages/TemplateLanguagePanel.java
@@ -10,6 +10,9 @@ import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.io.File;
import java.util.List;
public class TemplateLanguagePanel extends JPanel {
@@ -17,7 +20,7 @@ public class TemplateLanguagePanel extends JPanel {
private JPanel myMainPanel;
private JLabel myTemplatesFolderLabel;
private JComboBox myTemplateLanguage;
-
+ private boolean myTemplateFolderModified = false;
private static final String DEFAULT_TEMPLATES_FOLDER = "templates";
public TemplateLanguagePanel() {
@@ -33,6 +36,15 @@ public class TemplateLanguagePanel extends JPanel {
myTemplateLanguage.addItem(configuration);
}
myTemplatesFolder.setText(DEFAULT_TEMPLATES_FOLDER);
+ myTemplatesFolder.addKeyListener(new KeyAdapter() {
+ @Override
+ public void keyTyped(KeyEvent e) {
+ final int dot = myTemplatesFolder.getCaret().getDot();
+ final int index = myTemplatesFolder.getText().indexOf(File.separator);
+ if (index >= dot)
+ myTemplateFolderModified = true;
+ }
+ });
}
public String getTemplatesFolder() {
@@ -58,6 +70,19 @@ public class TemplateLanguagePanel extends JPanel {
myTemplatesFolder.setText(folder);
}
+ public void locationChanged(@NotNull final String baseLocation) {
+ final String templatesFolder = myTemplatesFolder.getText();
+ final int index = templatesFolder.indexOf(File.separator);
+ final String templateFolderName = index >= 0 ? templatesFolder.substring(index) : File.separator + "templates";
+ final String oldBase = index >= 0 ? templatesFolder.substring(0, index) : "";
+ if (oldBase.equals(baseLocation)) {
+ myTemplateFolderModified = false;
+ }
+ if (!myTemplateFolderModified) {
+ myTemplatesFolder.setText(baseLocation + templateFolderName);
+ }
+ }
+
public Dimension getLabelSize() {
return new JBLabel("Template language:").getPreferredSize();
}
diff --git a/python/pluginResources/META-INF/plugin.xml b/python/pluginResources/META-INF/plugin.xml
index 31f714c875a8..4539edaa107b 100644
--- a/python/pluginResources/META-INF/plugin.xml
+++ b/python/pluginResources/META-INF/plugin.xml
@@ -22,4 +22,11 @@ The Python plug-in provides smart editing for Python scripts. The feature set of
<vendor url="http://www.jetbrains.com/pycharm/" logo="/com/jetbrains/python/python.png">JetBrains</vendor>
<xi:include href="/META-INF/python-core.xml" xpointer="xpointer(/idea-plugin/*)"/>
<xi:include href="/META-INF/python-plugin-core.xml" xpointer="xpointer(/idea-plugin/*)"/>
+
+ <application-components>
+ <component>
+ <interface-class>com.jetbrains.python.console.PythonConsoleRunnerFactory</interface-class>
+ <implementation-class>com.jetbrains.python.console.PydevConsoleRunnerFactory</implementation-class>
+ </component>
+ </application-components>
</idea-plugin>
diff --git a/python/pluginSrc/META-INF/python-plugin-core.xml b/python/pluginSrc/META-INF/python-plugin-core.xml
index f3deb12da9c0..d797dc8138d2 100644
--- a/python/pluginSrc/META-INF/python-plugin-core.xml
+++ b/python/pluginSrc/META-INF/python-plugin-core.xml
@@ -39,6 +39,13 @@
<action id="PyManagePackages" class="com.jetbrains.python.packaging.PyManagePackagesAction" text="Manage Python Packages...">
<add-to-group group-id="ToolsMenu" anchor="last"/>
</action>
+
+ <!-- Console -->
+ <action id="com.jetbrains.python.run.RunPythonConsoleAction"
+ class="com.jetbrains.python.run.RunPythonConsoleAction"
+ text="Run Python Console..." description="Allows to quickly run Python console">
+ <add-to-group group-id="ToolsMenu" anchor="last"/>
+ </action>
</actions>
</idea-plugin> \ No newline at end of file
diff --git a/python/pluginSrc/com/jetbrains/python/run/RunPythonConsoleAction.java b/python/pluginSrc/com/jetbrains/python/run/RunPythonConsoleAction.java
new file mode 100644
index 000000000000..6b9e631a83f8
--- /dev/null
+++ b/python/pluginSrc/com/jetbrains/python/run/RunPythonConsoleAction.java
@@ -0,0 +1,58 @@
+/*
+ * 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.run;
+
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.actionSystem.CommonDataKeys;
+import com.intellij.openapi.actionSystem.LangDataKeys;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.project.DumbAware;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.projectRoots.Sdk;
+import com.intellij.openapi.util.Pair;
+import com.jetbrains.python.console.PydevConsoleRunner;
+import com.jetbrains.python.console.PythonConsoleRunnerFactory;
+import icons.PythonIcons;
+
+/**
+ * @author oleg
+ */
+public class RunPythonConsoleAction extends AnAction implements DumbAware {
+
+ public RunPythonConsoleAction() {
+ super();
+ getTemplatePresentation().setIcon(PythonIcons.Python.PythonConsole);
+ }
+
+ @Override
+ public void update(final AnActionEvent e) {
+ e.getPresentation().setVisible(true);
+ e.getPresentation().setEnabled(false);
+ final Project project = e.getData(CommonDataKeys.PROJECT);
+ if (project != null) {
+ Pair<Sdk, Module> sdkAndModule = PydevConsoleRunner.findPythonSdkAndModule(project, e.getData(LangDataKeys.MODULE));
+ if (sdkAndModule.first != null) {
+ e.getPresentation().setEnabled(true);
+ }
+ }
+ }
+
+ public void actionPerformed(final AnActionEvent e) {
+ PydevConsoleRunner runner = PythonConsoleRunnerFactory.getInstance().createConsoleRunner(e.getData(CommonDataKeys.PROJECT), e.getData(LangDataKeys.MODULE));
+ runner.run();
+ }
+}
diff --git a/python/psi-api/src/com/jetbrains/python/PyNames.java b/python/psi-api/src/com/jetbrains/python/PyNames.java
index 94e35f711c29..bd927c5d49bf 100644
--- a/python/psi-api/src/com/jetbrains/python/PyNames.java
+++ b/python/psi-api/src/com/jetbrains/python/PyNames.java
@@ -60,6 +60,7 @@ public class PyNames {
public static final String FAKE_OLD_BASE = "___Classobj";
public static final String FAKE_GENERATOR = "__generator";
public static final String FAKE_FUNCTION = "__function";
+ public static final String FAKE_METHOD = "__method";
public static final String FAKE_NAMEDTUPLE = "__namedtuple";
public static final String FUTURE_MODULE = "__future__";
@@ -471,4 +472,33 @@ public class PyNames {
public static boolean isRightOperatorName(@Nullable String name) {
return name != null && name.matches("__r[a-z]+__");
}
+
+ /**
+ * Available in Python 3 and Python 2 starting from 2.6.
+ * <p/>
+ * Attributes {@code __doc__}, {@code __dict__} and {@code __module__} should be inherited from object.
+ */
+ public static final ImmutableSet<String> FUNCTION_SPECIAL_ATTRIBUTES = ImmutableSet.of(
+ "__defaults__",
+ "__globals__",
+ "__closure__",
+ "__code__",
+ "__name__"
+ );
+
+ public static final ImmutableSet<String> LEGACY_FUNCTION_SPECIAL_ATTRIBUTES = ImmutableSet.of(
+ "func_defaults",
+ "func_globals",
+ "func_closure",
+ "func_code",
+ "func_name",
+ "func_doc",
+ "func_dict"
+ );
+
+ public static final ImmutableSet<String> PY3_ONLY_FUNCTION_SPECIAL_ATTRIBUTES = ImmutableSet.of("__annotations__", "__kwdefaults__");
+
+ public static final ImmutableSet<String> METHOD_SPECIAL_ATTRIBUTES = ImmutableSet.of("__func__", "__self__");
+
+ public static final ImmutableSet<String> LEGACY_METHOD_SPECIAL_ATTRIBUTES = ImmutableSet.of("im_func", "im_self", "im_class");
}
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 daa8b3063014..539d3ab8df2e 100644
--- a/python/psi-api/src/com/jetbrains/python/psi/PyElementGenerator.java
+++ b/python/psi-api/src/com/jetbrains/python/psi/PyElementGenerator.java
@@ -90,8 +90,6 @@ public abstract class PyElementGenerator {
@NotNull
public abstract PyCallExpression createCallExpression(final LanguageLevel langLevel, String functionName);
- public abstract PyImportStatement createImportStatementFromText(final LanguageLevel languageLevel, String text);
-
public abstract PyImportElement createImportElement(final LanguageLevel languageLevel, String name);
public abstract PyFunction createProperty(final LanguageLevel languageLevel,
@@ -139,4 +137,32 @@ public abstract class PyElementGenerator {
*/
@NotNull
public abstract PsiElement createNewLine();
+
+ /**
+ * Creates import statement of form {@code from qualifier import name as alias}.
+ *
+ * @param languageLevel language level for created element
+ * @param qualifier from where {@code name} will be imported (module name)
+ * @param name text of the reference in import element
+ * @param alias optional alias for {@code as alias} part
+ * @return created {@link com.jetbrains.python.psi.PyFromImportStatement}
+ */
+ @NotNull
+ public abstract PyFromImportStatement createFromImportStatement(@NotNull LanguageLevel languageLevel,
+ @NotNull String qualifier,
+ @NotNull String name,
+ @Nullable String alias);
+
+ /**
+ * Creates import statement of form {@code import name as alias}.
+ *
+ * @param languageLevel language level for created element
+ * @param name text of the reference in import element (module name)
+ * @param alias optional alias for {@code as alias} part
+ * @return created {@link com.jetbrains.python.psi.PyImportStatement}
+ */
+ @NotNull
+ public abstract PyImportStatement createImportStatement(@NotNull LanguageLevel languageLevel,
+ @NotNull String name,
+ @Nullable String alias);
}
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 a14a91ef9f9c..90ef99cec362 100644
--- a/python/psi-api/src/com/jetbrains/python/psi/PyStatementPart.java
+++ b/python/psi-api/src/com/jetbrains/python/psi/PyStatementPart.java
@@ -15,8 +15,6 @@
*/
package com.jetbrains.python.psi;
-import org.jetbrains.annotations.NotNull;
-
/**
* Abstract part of a multipart statement.
* User: dcheryasov
@@ -24,10 +22,4 @@ import org.jetbrains.annotations.NotNull;
*/
public interface PyStatementPart extends PyElement, PyStatementListContainer {
PyStatementPart[] EMPTY_ARRAY = new PyStatementPart[0];
-
- /**
- * @return the body of the part.
- */
- @NotNull
- PyStatementList getStatementList();
}
diff --git a/python/pydevSrc/com/jetbrains/python/debugger/pydev/RemoteDebugger.java b/python/pydevSrc/com/jetbrains/python/debugger/pydev/RemoteDebugger.java
index 9e347e0e5d7b..5f962b259142 100644
--- a/python/pydevSrc/com/jetbrains/python/debugger/pydev/RemoteDebugger.java
+++ b/python/pydevSrc/com/jetbrains/python/debugger/pydev/RemoteDebugger.java
@@ -5,9 +5,11 @@
*/
package com.jetbrains.python.debugger.pydev;
+import com.google.common.collect.Maps;
import com.intellij.execution.ui.ConsoleViewContentType;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.TimeoutUtil;
@@ -54,6 +56,8 @@ public class RemoteDebugger implements ProcessDebugger {
private final Map<Integer, ProtocolFrame> myResponseQueue = new HashMap<Integer, ProtocolFrame>();
private final TempVarsHolder myTempVars = new TempVarsHolder();
+ private Map<Pair<String, Integer>, String> myTempBreakpoints = Maps.newHashMap();
+
private final List<RemoteDebuggerCloseListener> myCloseListeners = ContainerUtil.createLockFreeCopyOnWriteList();
private DebuggerReader myDebuggerReader;
@@ -383,12 +387,18 @@ public class RemoteDebugger implements ProcessDebugger {
final SetBreakpointCommand command =
new SetBreakpointCommand(this, type, file, line);
execute(command); // set temp. breakpoint
+ myTempBreakpoints.put(Pair.create(file, line), type);
}
@Override
public void removeTempBreakpoint(String file, int line) {
- final RemoveBreakpointCommand command = new RemoveBreakpointCommand(this, "all", file, line);
- execute(command); // remove temp. breakpoint
+ String type = myTempBreakpoints.get(Pair.create(file, line));
+ if (type != null) {
+ final RemoveBreakpointCommand command = new RemoveBreakpointCommand(this, type, file, line);
+ execute(command); // remove temp. breakpoint
+ } else {
+ LOG.error("Temp breakpoint not found for " + file + ":" + line);
+ }
}
@Override
diff --git a/python/resources/icons/com/jetbrains/python/pythonConsole.png b/python/resources/icons/com/jetbrains/python/pythonConsole.png
new file mode 100644
index 000000000000..74231f29e9f0
--- /dev/null
+++ b/python/resources/icons/com/jetbrains/python/pythonConsole.png
Binary files differ
diff --git a/python/resources/icons/com/jetbrains/python/pythonConsole@2x.png b/python/resources/icons/com/jetbrains/python/pythonConsole@2x.png
new file mode 100644
index 000000000000..77922c75f74b
--- /dev/null
+++ b/python/resources/icons/com/jetbrains/python/pythonConsole@2x.png
Binary files differ
diff --git a/python/resources/icons/com/jetbrains/python/pythonConsole@2x_dark.png b/python/resources/icons/com/jetbrains/python/pythonConsole@2x_dark.png
new file mode 100644
index 000000000000..24167e371084
--- /dev/null
+++ b/python/resources/icons/com/jetbrains/python/pythonConsole@2x_dark.png
Binary files differ
diff --git a/python/resources/icons/com/jetbrains/python/pythonConsoleToolWindow.png b/python/resources/icons/com/jetbrains/python/pythonConsoleToolWindow.png
new file mode 100644
index 000000000000..dc6ee5f355ef
--- /dev/null
+++ b/python/resources/icons/com/jetbrains/python/pythonConsoleToolWindow.png
Binary files differ
diff --git a/python/resources/icons/com/jetbrains/python/pythonConsoleToolWindow@2x.png b/python/resources/icons/com/jetbrains/python/pythonConsoleToolWindow@2x.png
new file mode 100644
index 000000000000..5355d7b5c1a3
--- /dev/null
+++ b/python/resources/icons/com/jetbrains/python/pythonConsoleToolWindow@2x.png
Binary files differ
diff --git a/python/resources/icons/com/jetbrains/python/pythonConsoleToolWindow@2x_dark.png b/python/resources/icons/com/jetbrains/python/pythonConsoleToolWindow@2x_dark.png
new file mode 100644
index 000000000000..a034e001dc93
--- /dev/null
+++ b/python/resources/icons/com/jetbrains/python/pythonConsoleToolWindow@2x_dark.png
Binary files differ
diff --git a/python/resources/icons/com/jetbrains/python/pythonConsoleToolWindow_dark.png b/python/resources/icons/com/jetbrains/python/pythonConsoleToolWindow_dark.png
new file mode 100644
index 000000000000..e6aed97cec7a
--- /dev/null
+++ b/python/resources/icons/com/jetbrains/python/pythonConsoleToolWindow_dark.png
Binary files differ
diff --git a/python/resources/icons/com/jetbrains/python/pythonConsole_dark.png b/python/resources/icons/com/jetbrains/python/pythonConsole_dark.png
new file mode 100644
index 000000000000..9cdc3ac5e25f
--- /dev/null
+++ b/python/resources/icons/com/jetbrains/python/pythonConsole_dark.png
Binary files differ
diff --git a/python/resources/idea/PyCharmCoreApplicationInfo.xml b/python/resources/idea/PyCharmCoreApplicationInfo.xml
index ef906b054297..41c0c3e8608c 100644
--- a/python/resources/idea/PyCharmCoreApplicationInfo.xml
+++ b/python/resources/idea/PyCharmCoreApplicationInfo.xml
@@ -1,6 +1,6 @@
<component>
<company name="JetBrains s.r.o." url="http://www.jetbrains.com/?fromIDE"/>
- <version major="3" minor="0" eap="true"/>
+ <version major="4" 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"/>
diff --git a/python/resources/pycharm_core_logo.png b/python/resources/pycharm_core_logo.png
index 3daabbaa1470..9bc912b49bdf 100644
--- a/python/resources/pycharm_core_logo.png
+++ b/python/resources/pycharm_core_logo.png
Binary files differ
diff --git a/python/resources/pycharm_core_logo@2x.png b/python/resources/pycharm_core_logo@2x.png
index 83bf65b55e3b..0f4595c230f7 100644
--- a/python/resources/pycharm_core_logo@2x.png
+++ b/python/resources/pycharm_core_logo@2x.png
Binary files differ
diff --git a/python/src/META-INF/PyCharmCorePlugin.xml b/python/src/META-INF/PyCharmCorePlugin.xml
index a250bdc539d7..99a39a1d0cc7 100644
--- a/python/src/META-INF/PyCharmCorePlugin.xml
+++ b/python/src/META-INF/PyCharmCorePlugin.xml
@@ -1,4 +1,4 @@
<idea-plugin version="2" xmlns:xi="http://www.w3.org/2001/XInclude">
- <xi:include href="/META-INF/pycharm-core.xml" xpointer="xpointer(/idea-plugin/*)"/>
+ <xi:include href="/META-INF/pycharm-community.xml" xpointer="xpointer(/idea-plugin/*)"/>
<xi:include href="/META-INF/python-core.xml" xpointer="xpointer(/idea-plugin/*)"/>
</idea-plugin>
diff --git a/python/src/META-INF/pycharm-community.xml b/python/src/META-INF/pycharm-community.xml
new file mode 100644
index 000000000000..68518574169d
--- /dev/null
+++ b/python/src/META-INF/pycharm-community.xml
@@ -0,0 +1,11 @@
+<idea-plugin version="2" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <!-- Components and extensions declared in this file work ONLY in PyCharm, not in Python plugin. -->
+ <xi:include href="/META-INF/pycharm-core.xml" xpointer="xpointer(/idea-plugin/*)"/>
+
+ <application-components>
+ <component>
+ <interface-class>com.jetbrains.python.console.PythonConsoleRunnerFactory</interface-class>
+ <implementation-class>com.jetbrains.python.console.PythonToolWindowConsoleRunnerFactory</implementation-class>
+ </component>
+ </application-components>
+</idea-plugin>
diff --git a/python/src/META-INF/pycharm-core.xml b/python/src/META-INF/pycharm-core.xml
index 13ba05db63f0..4732ad084b32 100644
--- a/python/src/META-INF/pycharm-core.xml
+++ b/python/src/META-INF/pycharm-core.xml
@@ -24,6 +24,12 @@
</component>
</project-components>
+ <project-components>
+ <component>
+ <implementation-class>com.jetbrains.python.console.PythonConsoleToolWindow</implementation-class>
+ </component>
+ </project-components>
+
<module value="com.intellij.modules.xml"/>
<extensions defaultExtensionNs="com.intellij">
@@ -75,6 +81,10 @@
<renameHandler implementation="com.intellij.platform.renameProject.RenameProjectHandler"/>
<renameHandler implementation="com.intellij.platform.renameProject.ProjectFolderRenameHandler"/>
+
+ <!-- Console -->
+ <toolWindow id="Python Console" anchor="bottom" icon="PythonIcons.Python.PythonConsoleToolWindow"
+ factoryClass="com.jetbrains.python.console.PythonConsoleToolWindowFactory" secondary="false"/>
</extensions>
<actions>
diff --git a/python/src/META-INF/python-core.xml b/python/src/META-INF/python-core.xml
index a27eb44ae3af..292237aac6ac 100644
--- a/python/src/META-INF/python-core.xml
+++ b/python/src/META-INF/python-core.xml
@@ -529,11 +529,6 @@
<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>
@@ -621,12 +616,6 @@
</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"/>
@@ -655,11 +644,7 @@
<reference ref="CompareFileWithEditor"/>
</group>
- <action id="com.jetbrains.python.console.RunPythonConsoleAction"
- class="com.jetbrains.python.console.RunPythonConsoleAction"
- text="Run Python Console..." description="Allows to quickly run Python console">
- <add-to-group group-id="ToolsMenu" anchor="last"/>
- </action>
+
<action id="com.jetbrains.python.console.PyOpenDebugConsoleAction"
class="com.jetbrains.python.console.PyOpenDebugConsoleAction"
@@ -669,7 +654,7 @@
<action id="ExecuteInPyConsoleAction"
- class="com.jetbrains.python.actions.ExecuteInConsoleAction"
+ class="com.jetbrains.python.actions.PyExecuteSelectionAction"
text="Execute selection in console"
description="Executes selected code fragment in Python/Django console">
<add-to-group group-id="EditorPopupMenu" anchor="before" relative-to-action="CompareClipboardWithSelection"/>
diff --git a/python/src/com/jetbrains/python/actions/ExecuteInConsoleAction.java b/python/src/com/jetbrains/python/actions/PyExecuteSelectionAction.java
index cb90d498e663..4aea63a8a196 100644
--- a/python/src/com/jetbrains/python/actions/ExecuteInConsoleAction.java
+++ b/python/src/com/jetbrains/python/actions/PyExecuteSelectionAction.java
@@ -32,18 +32,20 @@ import com.intellij.util.Consumer;
import com.intellij.util.NotNullFunction;
import com.jetbrains.python.console.PyCodeExecutor;
import com.jetbrains.python.console.PydevConsoleRunner;
-import com.jetbrains.python.console.RunPythonConsoleAction;
+import com.jetbrains.python.console.PythonConsoleRunnerFactory;
+import com.jetbrains.python.console.PythonConsoleToolWindow;
import com.jetbrains.python.psi.PyFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
+import java.util.List;
-public class ExecuteInConsoleAction extends AnAction {
+public class PyExecuteSelectionAction extends AnAction {
public static final String EXECUTE_SELECTION_IN_CONSOLE = "Execute Selection in Console";
- public ExecuteInConsoleAction() {
+ public PyExecuteSelectionAction() {
super(EXECUTE_SELECTION_IN_CONSOLE);
}
@@ -186,6 +188,12 @@ public class ExecuteInConsoleAction extends AnAction {
}
private static Collection<RunContentDescriptor> getConsoles(Project project) {
+ PythonConsoleToolWindow toolWindow = PythonConsoleToolWindow.getInstance(project);
+
+ if (toolWindow != null) {
+ return toolWindow.getConsoleContentDescriptors();
+ }
+
return ExecutionHelper.findRunningConsole(project, new NotNullFunction<RunContentDescriptor, Boolean>() {
@NotNull
@Override
@@ -214,15 +222,34 @@ public class ExecuteInConsoleAction extends AnAction {
private static void startConsole(final Project project,
final Consumer<PyCodeExecutor> consumer,
Module context) {
- PydevConsoleRunner runner = RunPythonConsoleAction.runPythonConsole(project, context, null);
- runner.addConsoleListener(new PydevConsoleRunner.ConsoleListener() {
- @Override
- public void handleConsoleInitialized(LanguageConsoleView consoleView) {
- if (consoleView instanceof PyCodeExecutor) {
- consumer.consume((PyCodeExecutor)consoleView);
+ final PythonConsoleToolWindow toolWindow = PythonConsoleToolWindow.getInstance(project);
+
+ if (toolWindow != null) {
+ toolWindow.activate(new Runnable() {
+ @Override
+ public void run() {
+ List<RunContentDescriptor> descs = toolWindow.getConsoleContentDescriptors();
+
+ RunContentDescriptor descriptor = descs.get(0);
+ if (descriptor != null && descriptor.getExecutionConsole() instanceof PyCodeExecutor) {
+ consumer.consume((PyCodeExecutor)descriptor.getExecutionConsole());
+ }
}
- }
- });
+ });
+ }
+ else {
+ PythonConsoleRunnerFactory consoleRunnerFactory = PythonConsoleRunnerFactory.getInstance();
+ PydevConsoleRunner runner = consoleRunnerFactory.createConsoleRunner(project, null);
+ runner.addConsoleListener(new PydevConsoleRunner.ConsoleListener() {
+ @Override
+ public void handleConsoleInitialized(LanguageConsoleView consoleView) {
+ if (consoleView instanceof PyCodeExecutor) {
+ consumer.consume((PyCodeExecutor)consoleView);
+ }
+ }
+ });
+ runner.run();
+ }
}
private static boolean canFindConsole(AnActionEvent e) {
diff --git a/python/src/com/jetbrains/python/buildout/BuildoutConfigPanel.java b/python/src/com/jetbrains/python/buildout/BuildoutConfigPanel.java
index 394de6160cbc..eceedeb00050 100644
--- a/python/src/com/jetbrains/python/buildout/BuildoutConfigPanel.java
+++ b/python/src/com/jetbrains/python/buildout/BuildoutConfigPanel.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.
@@ -81,6 +81,7 @@ public class BuildoutConfigPanel extends JPanel {
myErrorPanel.add(facetErrorPanel.getComponent(), BorderLayout.CENTER);
facetErrorPanel.getValidatorsManager().registerValidator(new FacetEditorValidator() {
+ @NotNull
@Override
public ValidationResult check() {
if (!myFacetEnabled) {
diff --git a/python/src/com/jetbrains/python/codeInsight/imports/AddImportHelper.java b/python/src/com/jetbrains/python/codeInsight/imports/AddImportHelper.java
index 1c09ee24f7dd..d33e97c1e7f9 100644
--- a/python/src/com/jetbrains/python/codeInsight/imports/AddImportHelper.java
+++ b/python/src/com/jetbrains/python/codeInsight/imports/AddImportHelper.java
@@ -21,14 +21,14 @@ import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.ProjectRootManager;
-import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.util.QualifiedName;
import com.intellij.util.IncorrectOperationException;
import com.jetbrains.python.codeInsight.PyCodeInsightSettings;
import com.jetbrains.python.documentation.DocStringUtil;
import com.jetbrains.python.psi.*;
-import com.intellij.psi.util.QualifiedName;
import com.jetbrains.python.psi.resolve.QualifiedNameFinder;
import com.jetbrains.python.sdk.PythonSdkType;
import org.jetbrains.annotations.NotNull;
@@ -36,6 +36,8 @@ import org.jetbrains.annotations.Nullable;
import java.util.List;
+import static com.jetbrains.python.psi.PyUtil.sure;
+
/**
* Does the actual job of adding an import statement into a file.
* User: dcheryasov
@@ -47,6 +49,34 @@ public class AddImportHelper {
private AddImportHelper() {
}
+ public static void addLocalImportStatement(@NotNull PyElement element, @NotNull String name) {
+ final PyElementGenerator generator = PyElementGenerator.getInstance(element.getProject());
+ final LanguageLevel languageLevel = LanguageLevel.forElement(element);
+
+ final PsiElement anchor = getLocalInsertPosition(element);
+ final PsiElement parentElement = sure(anchor).getParent();
+ if (parentElement != null) {
+ parentElement.addBefore(generator.createImportStatement(languageLevel, name, null), anchor);
+ }
+ }
+
+ public static void addLocalFromImportStatement(@NotNull PyElement element, @NotNull String qualifier, @NotNull String name) {
+ final PyElementGenerator generator = PyElementGenerator.getInstance(element.getProject());
+ final LanguageLevel languageLevel = LanguageLevel.forElement(element);
+
+ final PsiElement anchor = getLocalInsertPosition(element);
+ final PsiElement parentElement = sure(anchor).getParent();
+ if (parentElement != null) {
+ parentElement.addBefore(generator.createFromImportStatement(languageLevel, qualifier, name, null), anchor);
+ }
+
+ }
+
+ @Nullable
+ public static PsiElement getLocalInsertPosition(@NotNull PyElement anchor) {
+ return PsiTreeUtil.getParentOfType(anchor, PyStatement.class, false);
+ }
+
public enum ImportPriority {
BUILTIN, THIRD_PARTY, PROJECT
}
@@ -81,7 +111,8 @@ public class AddImportHelper {
// maybe we arrived at the doc comment stmt; skip over it, too
else if (!skippedOverImports && !skippedOverDoc && file instanceof PyFile) {
PsiElement doc_elt =
- DocStringUtil.findDocStringExpression((PyElement)file); // this gives the literal; its parent is the expr seeker may have encountered
+ DocStringUtil
+ .findDocStringExpression((PyElement)file); // this gives the literal; its parent is the expr seeker may have encountered
if (doc_elt != null && doc_elt.getParent() == feeler) {
feeler = feeler.getNextSibling();
seeker = feeler; // skip over doc even if there's nothing below it
@@ -147,19 +178,13 @@ public class AddImportHelper {
* @param file where to operate
* @param name which to import (qualified is OK)
* @param asName optional name for 'as' clause
+ * @return whether import statement was actually added
*/
public static boolean addImportStatement(PsiFile file, String name, @Nullable String asName, ImportPriority priority) {
- String as_clause;
- if (asName == null) {
- as_clause = "";
- }
- else {
- as_clause = " as " + asName;
- }
if (!(file instanceof PyFile)) {
return false;
}
- List<PyImportElement> existingImports = ((PyFile)file).getImportTargets();
+ final List<PyImportElement> existingImports = ((PyFile)file).getImportTargets();
for (PyImportElement element : existingImports) {
final QualifiedName qName = element.getImportedQName();
if (qName != null && name.equals(qName.toString())) {
@@ -171,7 +196,7 @@ public class AddImportHelper {
final PyElementGenerator generator = PyElementGenerator.getInstance(file.getProject());
final LanguageLevel languageLevel = LanguageLevel.forElement(file);
- final PyImportStatement importNodeToInsert = generator.createImportStatementFromText(languageLevel, "import " + name + as_clause);
+ final PyImportStatement importNodeToInsert = generator.createImportStatement(languageLevel, name, asName);
try {
file.addBefore(importNodeToInsert, getInsertPosition(file, name, priority));
}
@@ -180,6 +205,7 @@ public class AddImportHelper {
}
return true;
}
+
/**
* Adds an "import ... from ..." statement below other top-level imports.
*
@@ -189,20 +215,20 @@ public class AddImportHelper {
* @param asName optional name for 'as' clause
*/
public static void addImportFromStatement(PsiFile file, String from, String name, @Nullable String asName, ImportPriority priority) {
- String asClause = asName == null ? "" : " as " + asName;
-
- final PyFromImportStatement importNodeToInsert = PyElementGenerator.getInstance(file.getProject()).createFromText(
- LanguageLevel.forElement(file), PyFromImportStatement.class, "from " + from + " import " + name + asClause);
+ final PyElementGenerator generator = PyElementGenerator.getInstance(file.getProject());
+ final LanguageLevel languageLevel = LanguageLevel.forElement(file);
+ final PyFromImportStatement nodeToInsert = generator.createFromImportStatement(languageLevel, from, name, asName);
try {
if (InjectedLanguageManager.getInstance(file.getProject()).isInjectedFragment(file)) {
- final PsiElement element = file.addBefore(importNodeToInsert, getInsertPosition(file, from, priority));
+ final PsiElement element = file.addBefore(nodeToInsert, getInsertPosition(file, from, priority));
PsiElement whitespace = element.getNextSibling();
- if (!(whitespace instanceof PsiWhiteSpace))
+ if (!(whitespace instanceof PsiWhiteSpace)) {
whitespace = PsiParserFacade.SERVICE.getInstance(file.getProject()).createWhiteSpaceFromText(" >>> ");
+ }
file.addBefore(whitespace, element);
}
else {
- file.addBefore(importNodeToInsert, getInsertPosition(file, from, priority));
+ file.addBefore(nodeToInsert, getInsertPosition(file, from, priority));
}
}
catch (IncorrectOperationException e) {
@@ -228,7 +254,7 @@ public class AddImportHelper {
}
}
final PyElementGenerator generator = PyElementGenerator.getInstance(file.getProject());
- PyImportElement importElement = generator.createImportElement(LanguageLevel.forElement(file), name);
+ final PyImportElement importElement = generator.createImportElement(LanguageLevel.forElement(file), name);
existingImport.add(importElement);
return true;
}
@@ -239,7 +265,8 @@ public class AddImportHelper {
public static void addImport(final PsiNamedElement target, final PsiFile file, final PyElement element) {
final boolean useQualified = !PyCodeInsightSettings.getInstance().PREFER_FROM_IMPORT;
- final PsiFileSystemItem toImport = target instanceof PsiFileSystemItem ? ((PsiFileSystemItem)target).getParent() : target.getContainingFile();
+ final PsiFileSystemItem toImport =
+ target instanceof PsiFileSystemItem ? ((PsiFileSystemItem)target).getParent() : target.getContainingFile();
final ImportPriority priority = getImportPriority(file, toImport);
final QualifiedName qName = QualifiedNameFinder.findCanonicalImportPath(target, element);
if (qName == null) return;
diff --git a/python/src/com/jetbrains/python/codeInsight/imports/AutoImportQuickFix.java b/python/src/com/jetbrains/python/codeInsight/imports/AutoImportQuickFix.java
index 47c9ca9f8ee5..ce3c07932eb4 100644
--- a/python/src/com/jetbrains/python/codeInsight/imports/AutoImportQuickFix.java
+++ b/python/src/com/jetbrains/python/codeInsight/imports/AutoImportQuickFix.java
@@ -29,6 +29,7 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiFileSystemItem;
import com.intellij.psi.PsiReference;
+import com.intellij.psi.util.QualifiedName;
import com.intellij.util.IncorrectOperationException;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.codeInsight.PyCodeInsightSettings;
@@ -36,7 +37,6 @@ import com.jetbrains.python.psi.PyElement;
import com.jetbrains.python.psi.PyFunction;
import com.jetbrains.python.psi.PyImportElement;
import com.jetbrains.python.psi.PyQualifiedExpression;
-import com.intellij.psi.util.QualifiedName;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -138,7 +138,7 @@ public class AutoImportQuickFix implements LocalQuickFix, HighPriorityAction {
myImports.size() > 1,
ImportCandidateHolder.getQualifiedName(name, myImports.get(0).getPath(), myImports.get(0).getImportElement())
);
- final ImportFromExistingAction action = new ImportFromExistingAction(myNode, myImports, name, myUseQualifiedImport);
+ final ImportFromExistingAction action = new ImportFromExistingAction(myNode, myImports, name, myUseQualifiedImport, false);
action.onDone(new Runnable() {
public void run() {
myExpended = true;
@@ -166,11 +166,16 @@ public class AutoImportQuickFix implements LocalQuickFix, HighPriorityAction {
if (!FileModificationService.getInstance().prepareFileForWrite(file)) return;
if (ImportFromExistingAction.isResolved(myReference)) return;
// act
- ImportFromExistingAction action = new ImportFromExistingAction(myNode, myImports, getNameToImport(), myUseQualifiedImport);
+ ImportFromExistingAction action = createAction();
action.execute(); // assume that action runs in WriteAction on its own behalf
myExpended = true;
}
+ @NotNull
+ protected ImportFromExistingAction createAction() {
+ return new ImportFromExistingAction(myNode, myImports, getNameToImport(), myUseQualifiedImport, false);
+ }
+
public void sortCandidates() {
Collections.sort(myImports);
}
@@ -203,4 +208,27 @@ public class AutoImportQuickFix implements LocalQuickFix, HighPriorityAction {
}
return false;
}
+
+ @NotNull
+ public AutoImportQuickFix forLocalImport() {
+ return new AutoImportQuickFix(myNode, myReference, myUseQualifiedImport) {
+ @NotNull
+ @Override
+ public String getName() {
+ return super.getName() + " locally";
+ }
+
+ @NotNull
+ @Override
+ public String getFamilyName() {
+ return "import locally";
+ }
+
+ @NotNull
+ @Override
+ protected ImportFromExistingAction createAction() {
+ return new ImportFromExistingAction(myNode, myImports, getNameToImport(), myUseQualifiedImport, true);
+ }
+ };
+ }
}
diff --git a/python/src/com/jetbrains/python/codeInsight/imports/ImportCandidateHolder.java b/python/src/com/jetbrains/python/codeInsight/imports/ImportCandidateHolder.java
index b60348d34938..e75df5b9a0d0 100644
--- a/python/src/com/jetbrains/python/codeInsight/imports/ImportCandidateHolder.java
+++ b/python/src/com/jetbrains/python/codeInsight/imports/ImportCandidateHolder.java
@@ -24,18 +24,25 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiFileSystemItem;
-import com.jetbrains.python.psi.*;
import com.intellij.psi.util.QualifiedName;
+import com.jetbrains.python.psi.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* An immutable holder of information for one auto-import candidate.
- * User: dcheryasov
- * Date: Apr 23, 2009 4:17:50 PM
+ * <p/>
+ * There can be do different flavors of such candidates:
+ * <ul>
+ * <li>Candidates based on existing imports in module. In this case {@link #getImportElement()} must return not {@code null}.</li>
+ * <li>Candidates not yet imported. In this case {@link #getPath()} must return not {@code null}.</li>
+ * </ul>
+ * <p/>
+ *
+ * @author dcheryasov
*/
// visibility is intentionally package-level
-class ImportCandidateHolder implements Comparable {
+class ImportCandidateHolder implements Comparable<ImportCandidateHolder> {
private final PsiElement myImportable;
private final PyImportElement myImportElement;
private final PsiFileSystemItem myFile;
@@ -43,15 +50,19 @@ class ImportCandidateHolder implements Comparable {
/**
* Creates new instance.
- * @param importable an element that could be imported either from import element or from file.
- * @param file the file which is the source of the importable
+ *
+ * @param importable an element that could be imported either from import element or from file.
+ * @param file the file which is the source of the importable (module for symbols, containing directory for modules and packages)
* @param importElement an existing import element that can be a source for the importable.
- * @param path import path for the file, as a qualified name (a.b.c)
+ * @param path import path for the file, as a qualified name (a.b.c)
+ * For top-level imported symbols it's <em>qualified name of containing module</em> (or package for __init__.py).
+ * For modules and packages it should be <em>qualified name of their parental package</em>
+ * (empty for modules and packages located at source roots).
+ *
+ * @see com.jetbrains.python.codeInsight.imports.PythonReferenceImporter#proposeImportFix
*/
- public ImportCandidateHolder(
- @NotNull PsiElement importable, @NotNull PsiFileSystemItem file,
- @Nullable PyImportElement importElement, @Nullable QualifiedName path
- ) {
+ public ImportCandidateHolder(@NotNull PsiElement importable, @NotNull PsiFileSystemItem file,
+ @Nullable PyImportElement importElement, @Nullable QualifiedName path) {
myFile = file;
myImportable = importable;
myImportElement = importElement;
@@ -59,18 +70,22 @@ class ImportCandidateHolder implements Comparable {
assert importElement != null || path != null; // one of these must be present
}
+ @NotNull
public PsiElement getImportable() {
return myImportable;
}
+ @Nullable
public PyImportElement getImportElement() {
return myImportElement;
}
+ @NotNull
public PsiFileSystemItem getFile() {
return myFile;
}
+ @Nullable
public QualifiedName getPath() {
return myPath;
}
@@ -78,15 +93,17 @@ class ImportCandidateHolder implements Comparable {
/**
* Helper method that builds an import path, handling all these "import foo", "import foo as bar", "from bar import foo", etc.
* Either importPath or importSource must be not null.
- * @param name what is ultimately imported.
+ *
+ * @param name what is ultimately imported.
* @param importPath known path to import the name.
- * @param source known ImportElement to import the name; its 'as' clause is used if present.
+ * @param source known ImportElement to import the name; its 'as' clause is used if present.
* @return a properly qualified name.
*/
- public static String getQualifiedName(String name, QualifiedName importPath, PyImportElement source) {
- StringBuilder sb = new StringBuilder();
+ @NotNull
+ public static String getQualifiedName(@NotNull String name, @Nullable QualifiedName importPath, @Nullable PyImportElement source) {
+ final StringBuilder sb = new StringBuilder();
if (source != null) {
- PsiElement parent = source.getParent();
+ final PsiElement parent = source.getParent();
if (parent instanceof PyFromImportStatement) {
sb.append(name);
}
@@ -95,7 +112,7 @@ class ImportCandidateHolder implements Comparable {
}
}
else {
- if (importPath.getComponentCount() > 0) {
+ if (importPath != null && importPath.getComponentCount() > 0) {
sb.append(importPath).append(".");
}
sb.append(name);
@@ -103,8 +120,9 @@ class ImportCandidateHolder implements Comparable {
return sb.toString();
}
- public String getPresentableText(String myName) {
- StringBuilder sb = new StringBuilder(getQualifiedName(myName, myPath, myImportElement));
+ @NotNull
+ public String getPresentableText(@NotNull String myName) {
+ final StringBuilder sb = new StringBuilder(getQualifiedName(myName, myPath, myImportElement));
PsiElement parent = null;
if (myImportElement != null) {
parent = myImportElement.getParent();
@@ -113,13 +131,15 @@ class ImportCandidateHolder implements Comparable {
sb.append(((PyFunction)myImportable).getParameterList().getPresentableText(false));
}
else if (myImportable instanceof PyClass) {
- PyClass[] supers = ((PyClass)myImportable).getSuperClasses();
+ final PyClass[] supers = ((PyClass)myImportable).getSuperClasses();
if (supers.length > 0) {
sb.append("(");
// ", ".join(x.getName() for x in getSuperClasses())
- String[] super_names = new String[supers.length];
- for (int i=0; i < supers.length; i += 1) super_names[i] = supers[i].getName();
- sb.append(StringUtil.join(super_names, ", "));
+ final String[] superNames = new String[supers.length];
+ for (int i = 0; i < supers.length; i += 1) {
+ superNames[i] = supers[i].getName();
+ }
+ sb.append(StringUtil.join(superNames, ", "));
sb.append(")");
}
}
@@ -135,10 +155,9 @@ class ImportCandidateHolder implements Comparable {
return sb.toString();
}
- public int compareTo(Object o) {
- ImportCandidateHolder rhs = (ImportCandidateHolder) o;
- int lRelevance = getRelevance();
- int rRelevance = rhs.getRelevance();
+ public int compareTo(@NotNull ImportCandidateHolder rhs) {
+ final int lRelevance = getRelevance();
+ final int rRelevance = rhs.getRelevance();
if (rRelevance != lRelevance) {
return rRelevance - lRelevance;
}
@@ -150,7 +169,7 @@ class ImportCandidateHolder implements Comparable {
}
int getRelevance() {
- Project project = myImportable.getProject();
+ final Project project = myImportable.getProject();
final PsiFile psiFile = myImportable.getContainingFile();
final VirtualFile vFile = psiFile == null ? null : psiFile.getVirtualFile();
if (vFile == null) return 0;
diff --git a/python/src/com/jetbrains/python/codeInsight/imports/ImportFromExistingAction.java b/python/src/com/jetbrains/python/codeInsight/imports/ImportFromExistingAction.java
index 58254d999a90..e7a8151bf52d 100644
--- a/python/src/com/jetbrains/python/codeInsight/imports/ImportFromExistingAction.java
+++ b/python/src/com/jetbrains/python/codeInsight/imports/ImportFromExistingAction.java
@@ -53,6 +53,7 @@ public class ImportFromExistingAction implements QuestionAction {
String myName;
boolean myUseQualifiedImport;
private Runnable myOnDoneCallback;
+ private final boolean myImportLocally;
/**
* @param target element to become qualified as imported.
@@ -60,12 +61,13 @@ public class ImportFromExistingAction implements QuestionAction {
* @param name relevant name ot the target element (e.g. of identifier in an expression).
* @param useQualified if True, use qualified "import modulename" instead of "from modulename import ...".
*/
- public ImportFromExistingAction(@NotNull PyElement target, @NotNull List<ImportCandidateHolder> sources, String name,
- boolean useQualified) {
+ public ImportFromExistingAction(@NotNull PyElement target, @NotNull List<ImportCandidateHolder> sources, @NotNull String name,
+ boolean useQualified, boolean importLocally) {
myTarget = target;
mySources = sources;
myName = name;
myUseQualifiedImport = useQualified;
+ myImportLocally = importLocally;
}
public void onDone(Runnable callback) {
@@ -151,25 +153,41 @@ public class ImportFromExistingAction implements QuestionAction {
if (manager.isInjectedFragment(file)) {
file = manager.getTopLevelFile(myTarget);
}
+ // We are trying to import top-level module or package which thus cannot be qualified
if (isRoot(item.getFile())) {
- AddImportHelper.addImportStatement(file, myName, null, priority);
+ if (myImportLocally) {
+ AddImportHelper.addLocalImportStatement(myTarget, myName);
+ } else {
+ AddImportHelper.addImportStatement(file, myName, null, priority);
+ }
}
else {
- String qualifiedName = item.getPath().toString();
+ final String qualifiedName = item.getPath().toString();
if (myUseQualifiedImport) {
String nameToImport = qualifiedName;
if (item.getImportable() instanceof PsiFileSystemItem) {
nameToImport += "." + myName;
}
- AddImportHelper.addImportStatement(file, nameToImport, null, priority);
+ if (myImportLocally) {
+ AddImportHelper.addLocalImportStatement(myTarget, nameToImport);
+ }
+ else {
+ AddImportHelper.addImportStatement(file, nameToImport, null, priority);
+ }
myTarget.replace(gen.createExpressionFromText(LanguageLevel.forElement(myTarget), qualifiedName + "." + myName));
}
else {
- AddImportHelper.addImportFrom(file, myTarget, qualifiedName, myName, null, priority);
+ if (myImportLocally) {
+ AddImportHelper.addLocalFromImportStatement(myTarget, qualifiedName, myName);
+ }
+ else {
+ AddImportHelper.addImportFromStatement(file, qualifiedName, myName, null, priority);
+ }
}
}
}
+
private void addToExistingImport(PyImportElement src) {
final PyElementGenerator gen = PyElementGenerator.getInstance(myTarget.getProject());
// did user choose 'import' or 'from import'?
diff --git a/python/src/com/jetbrains/python/codeInsight/imports/PyImportOptimizer.java b/python/src/com/jetbrains/python/codeInsight/imports/PyImportOptimizer.java
index 5d24e3b89332..d5fd5a64495e 100644
--- a/python/src/com/jetbrains/python/codeInsight/imports/PyImportOptimizer.java
+++ b/python/src/com/jetbrains/python/codeInsight/imports/PyImportOptimizer.java
@@ -92,7 +92,7 @@ public class PyImportOptimizer implements ImportOptimizer {
for (PyImportElement importElement : importStatement.getImportElements()) {
myMissorted = true;
PsiElement toImport = importElement.resolve();
- final PyImportStatement splitImport = myGenerator.createImportStatementFromText(langLevel, "import " + importElement.getText());
+ final PyImportStatement splitImport = myGenerator.createImportStatement(langLevel, importElement.getText(), null);
prioritize(splitImport, toImport);
}
}
diff --git a/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibTypeProvider.java b/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibTypeProvider.java
index 346d40f3273e..c28bc29455c9 100644
--- a/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibTypeProvider.java
+++ b/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibTypeProvider.java
@@ -36,6 +36,8 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
+import static com.jetbrains.python.psi.PyUtil.as;
+
/**
* @author yole
*/
@@ -132,6 +134,23 @@ public class PyStdlibTypeProvider extends PyTypeProviderBase {
}
}
}
+ else if ("__builtin__.tuple.__add__".equals(qname) && callSite instanceof PyBinaryExpression) {
+ final PyBinaryExpression expression = (PyBinaryExpression)callSite;
+ final PyTupleType leftTupleType = as(context.getType(expression.getLeftExpression()), PyTupleType.class);
+ if (expression.getRightExpression() != null) {
+ final PyTupleType rightTupleType = as(context.getType(expression.getRightExpression()), PyTupleType.class);
+ if (leftTupleType != null && rightTupleType != null) {
+ final PyType[] elementTypes = new PyType[leftTupleType.getElementCount() + rightTupleType.getElementCount()];
+ for (int i = 0; i < leftTupleType.getElementCount(); i++) {
+ elementTypes[i] = leftTupleType.getElementType(i);
+ }
+ for (int i = 0; i < rightTupleType.getElementCount(); i++) {
+ elementTypes[i + leftTupleType.getElementCount()] = rightTupleType.getElementType(i);
+ }
+ return PyTupleType.create(function, elementTypes);
+ }
+ }
+ }
}
return null;
}
diff --git a/python/src/com/jetbrains/python/configuration/PyIntegratedToolsConfigurable.java b/python/src/com/jetbrains/python/configuration/PyIntegratedToolsConfigurable.java
index 8afd9cc4e674..fa869bfca359 100644
--- a/python/src/com/jetbrains/python/configuration/PyIntegratedToolsConfigurable.java
+++ b/python/src/com/jetbrains/python/configuration/PyIntegratedToolsConfigurable.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.
@@ -120,6 +120,7 @@ public class PyIntegratedToolsConfigurable implements SearchableConfigurable, No
myErrorPanel.add(facetErrorPanel.getComponent(), BorderLayout.CENTER);
facetErrorPanel.getValidatorsManager().registerValidator(new FacetEditorValidator() {
+ @NotNull
@Override
public ValidationResult check() {
final Sdk sdk = PythonSdkType.findPythonSdk(myModule);
diff --git a/python/src/com/jetbrains/python/console/PyConsoleOptions.java b/python/src/com/jetbrains/python/console/PyConsoleOptions.java
index e76c2ae576b0..59ae6875d1e9 100644
--- a/python/src/com/jetbrains/python/console/PyConsoleOptions.java
+++ b/python/src/com/jetbrains/python/console/PyConsoleOptions.java
@@ -95,7 +95,7 @@ public class PyConsoleOptions implements PersistentStateComponent<PyConsoleOptio
@Tag("console-settings")
public static class PyConsoleSettings {
- public String myCustomStartScript = RunPythonConsoleAction.CONSOLE_START_COMMAND;
+ public String myCustomStartScript = PydevConsoleRunner.CONSOLE_START_COMMAND;
public String mySdkHome = null;
public String myInterpreterOptions = "";
public boolean myUseModuleSdk;
diff --git a/python/src/com/jetbrains/python/console/PydevConsoleRunner.java b/python/src/com/jetbrains/python/console/PydevConsoleRunner.java
index 848818b95e27..b3ebacd83ae3 100644
--- a/python/src/com/jetbrains/python/console/PydevConsoleRunner.java
+++ b/python/src/com/jetbrains/python/console/PydevConsoleRunner.java
@@ -17,9 +17,8 @@ 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.base.Joiner;
+import com.google.common.collect.Collections2;
import com.google.common.collect.Maps;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.ExecutionHelper;
@@ -48,6 +47,8 @@ import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler;
import com.intellij.openapi.editor.actions.SplitLineAction;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
@@ -58,19 +59,17 @@ import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Couple;
import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.io.FileUtil;
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;
@@ -94,6 +93,7 @@ import com.jetbrains.python.run.ProcessRunner;
import com.jetbrains.python.run.PythonCommandLineState;
import com.jetbrains.python.run.PythonTracebackFilter;
import com.jetbrains.python.sdk.PySdkUtil;
+import com.jetbrains.python.sdk.PythonSdkType;
import com.jetbrains.python.sdk.flavors.PythonSdkFlavor;
import icons.PythonIcons;
import org.apache.xmlrpc.XmlRpcException;
@@ -115,6 +115,9 @@ import static com.jetbrains.python.sdk.PythonEnvUtil.setPythonUnbuffered;
* @author oleg
*/
public class PydevConsoleRunner extends AbstractConsoleRunnerWithHistory<PythonConsoleView> {
+ public static final String WORKING_DIR_ENV = "WORKING_DIR_AND_PYTHON_PATHS";
+ public static final String CONSOLE_START_COMMAND = "import sys; print('Python %s on %s' % (sys.version, sys.platform))\n" +
+ "sys.path.extend([" + WORKING_DIR_ENV + "])\n";
private static final Logger LOG = Logger.getInstance(PydevConsoleRunner.class.getName());
@SuppressWarnings("SpellCheckingInspection")
public static final String PYDEV_PYDEVCONSOLE_PY = "pydev/pydevconsole.py";
@@ -139,18 +142,100 @@ 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,
+ public PydevConsoleRunner(@NotNull final Project project,
@NotNull Sdk sdk, @NotNull final PyConsoleType consoleType,
@Nullable final String workingDir,
- Map<String, String> environmentVariables) {
+ Map<String, String> environmentVariables, String ... statementsToExecute) {
super(project, consoleType.getTitle(), workingDir);
mySdk = sdk;
myConsoleType = consoleType;
myEnvironmentVariables = environmentVariables;
+ myStatementsToExecute = statementsToExecute;
+ }
+
+ public static PathMappingSettings getMappings(Project project, Sdk sdk) {
+ PathMappingSettings mappingSettings = null;
+ if (PySdkUtil.isRemote(sdk)) {
+ PythonRemoteInterpreterManager instance = PythonRemoteInterpreterManager.getInstance();
+ if (instance != null) {
+ //noinspection ConstantConditions
+ mappingSettings =
+ instance.setupMappings(project, (PyRemoteSdkAdditionalDataBase)sdk.getSdkAdditionalData(), null);
+ }
+ }
+ return mappingSettings;
+ }
+
+ @NotNull
+ public static Pair<Sdk, Module> findPythonSdkAndModule(@NotNull Project project, @Nullable Module contextModule) {
+ Sdk sdk = null;
+ Module module = null;
+ PyConsoleOptions.PyConsoleSettings settings = PyConsoleOptions.getInstance(project).getPythonConsoleSettings();
+ String sdkHome = settings.getSdkHome();
+ if (sdkHome != null) {
+ sdk = PythonSdkType.findSdkByPath(sdkHome);
+ if (settings.getModuleName() != null) {
+ module = ModuleManager.getInstance(project).findModuleByName(settings.getModuleName());
+ }
+ else {
+ module = contextModule;
+ if (module == null && ModuleManager.getInstance(project).getModules().length > 0) {
+ module = ModuleManager.getInstance(project).getModules()[0];
+ }
+ }
+ }
+ if (sdk == null && settings.isUseModuleSdk()) {
+ if (contextModule != null) {
+ module = contextModule;
+ }
+ else if (settings.getModuleName() != null) {
+ module = ModuleManager.getInstance(project).findModuleByName(settings.getModuleName());
+ }
+ if (module != null) {
+ if (PythonSdkType.findPythonSdk(module) != null) {
+ sdk = PythonSdkType.findPythonSdk(module);
+ }
+ }
+ }
+ else if (contextModule != null) {
+ if (module == null) {
+ module = contextModule;
+ }
+ if (sdk == null) {
+ sdk = PythonSdkType.findPythonSdk(module);
+ }
+ }
+
+ if (sdk == null) {
+ for (Module m : ModuleManager.getInstance(project).getModules()) {
+ if (PythonSdkType.findPythonSdk(m) != null) {
+ sdk = PythonSdkType.findPythonSdk(m);
+ module = m;
+ break;
+ }
+ }
+ }
+ if (sdk == null) {
+ if (PythonSdkType.getAllSdks().size() > 0) {
+ //noinspection UnusedAssignment
+ sdk = PythonSdkType.getAllSdks().get(0); //take any python sdk
+ }
+ }
+ return Pair.create(sdk, module);
+ }
+
+ public static String constructPythonPathCommand(Collection<String> pythonPath, String command) {
+ final String path = Joiner.on(", ").join(Collections2.transform(pythonPath, new Function<String, String>() {
+ @Override
+ public String apply(String input) {
+ return "'" + input.replace("\\", "\\\\").replace("'", "\\'") + "'";
+ }
+ }));
+
+ return command.replace(WORKING_DIR_ENV, path);
}
public void setStatementsToExecute(String... statementsToExecute) {
@@ -196,21 +281,6 @@ public class PydevConsoleRunner extends AbstractConsoleRunnerWithHistory<PythonC
return actions;
}
- @NotNull
- public static PydevConsoleRunner createAndRun(@NotNull final Project project,
- @NotNull final Sdk sdk,
- @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;
- }
-
public void run() {
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
@Override
@@ -250,16 +320,7 @@ public class PydevConsoleRunner extends AbstractConsoleRunnerWithHistory<PythonC
Sdk sdk,
PyConsoleType consoleType,
String workingDirectory) {
- return create(project, sdk, consoleType, workingDirectory, Maps.<String, String>newHashMap());
- }
-
- @NotNull
- private static PydevConsoleRunner create(@NotNull final Project project,
- @NotNull final Sdk sdk,
- @NotNull final PyConsoleType consoleType,
- @Nullable final String workingDirectory,
- @NotNull final Map<String, String> environmentVariables) {
- return new PydevConsoleRunner(project, sdk, consoleType, workingDirectory, environmentVariables);
+ return new PydevConsoleRunner(project, sdk, consoleType, workingDirectory, Maps.<String, String>newHashMap(), new String[]{});
}
private static int[] findAvailablePorts(Project project, PyConsoleType consoleType) {
@@ -501,12 +562,6 @@ public class PydevConsoleRunner extends AbstractConsoleRunnerWithHistory<PythonC
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);
}
@@ -631,10 +686,7 @@ public class PydevConsoleRunner extends AbstractConsoleRunnerWithHistory<PythonC
return stopAction;
}
- private void clearContent(RunContentDescriptor descriptor) {
- Content content = getToolWindow().getContentManager().findContent(descriptor.getDisplayName());
- assert content != null;
- getToolWindow().getContentManager().removeContent(content, true);
+ protected void clearContent(RunContentDescriptor descriptor) {
}
private AnAction createConsoleStoppingAction(final AnAction generalStopAction) {
@@ -792,16 +844,6 @@ 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);
@@ -955,20 +997,7 @@ 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();
+ public static PythonConsoleRunnerFactory factory() {
+ return new PydevConsoleRunnerFactory();
}
}
diff --git a/python/src/com/jetbrains/python/console/PydevConsoleRunnerFactory.java b/python/src/com/jetbrains/python/console/PydevConsoleRunnerFactory.java
new file mode 100644
index 000000000000..5bed751d204e
--- /dev/null
+++ b/python/src/com/jetbrains/python/console/PydevConsoleRunnerFactory.java
@@ -0,0 +1,122 @@
+/*
+ * 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.google.common.collect.Maps;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.projectRoots.Sdk;
+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.util.PathMappingSettings;
+import com.jetbrains.python.buildout.BuildoutFacet;
+import com.jetbrains.python.run.PythonCommandLineState;
+import com.jetbrains.python.sdk.PythonEnvUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+/**
+* @author traff
+*/
+public class PydevConsoleRunnerFactory extends PythonConsoleRunnerFactory {
+ @Override
+ public PydevConsoleRunner createConsoleRunner(@NotNull Project project,
+ @Nullable Module contextModule) {
+ Pair<Sdk, Module> sdkAndModule = PydevConsoleRunner.findPythonSdkAndModule(project, contextModule);
+
+ Module module = sdkAndModule.second;
+ Sdk sdk = sdkAndModule.first;
+
+ assert sdk != null;
+
+ PathMappingSettings mappingSettings = PydevConsoleRunner.getMappings(project, sdk);
+
+ String[] setupFragment;
+
+ PyConsoleOptions.PyConsoleSettings settingsProvider = PyConsoleOptions.getInstance(project).getPythonConsoleSettings();
+ Collection<String> pythonPath = PythonCommandLineState.collectPythonPath(module, settingsProvider.addContentRoots(),
+ settingsProvider.addSourceRoots());
+
+ if (mappingSettings != null) {
+ pythonPath = mappingSettings.convertToRemote(pythonPath);
+ }
+
+ String customStartScript = settingsProvider == null ? "" : settingsProvider.getCustomStartScript();
+
+ if (customStartScript.trim().length() > 0) {
+ customStartScript = "\n" + customStartScript;
+ }
+
+ String selfPathAppend = PydevConsoleRunner.constructPythonPathCommand(pythonPath, customStartScript);
+
+ String workingDir = settingsProvider.getWorkingDirectory();
+ if (StringUtil.isEmpty(workingDir)) {
+ if (module != null && ModuleRootManager.getInstance(module).getContentRoots().length > 0) {
+ workingDir = ModuleRootManager.getInstance(module).getContentRoots()[0].getPath();
+ }
+ else {
+ if (ModuleManager.getInstance(project).getModules().length > 0) {
+ VirtualFile[] roots = ModuleRootManager.getInstance(ModuleManager.getInstance(project).getModules()[0]).getContentRoots();
+ if (roots.length > 0) {
+ workingDir = roots[0].getPath();
+ }
+ }
+ }
+ }
+
+ if (mappingSettings != null) {
+ workingDir = mappingSettings.convertToRemote(workingDir);
+ }
+
+ BuildoutFacet facet = null;
+ if (module != null) {
+ facet = BuildoutFacet.getInstance(module);
+ }
+
+ if (facet != null) {
+ List<String> path = facet.getAdditionalPythonPath();
+ if (mappingSettings != null) {
+ path = mappingSettings.convertToRemote(path);
+ }
+ String prependStatement = facet.getPathPrependStatement(path);
+ setupFragment = new String[]{prependStatement, selfPathAppend};
+ }
+ else {
+ setupFragment = new String[]{selfPathAppend};
+ }
+
+ Map<String, String> envs = Maps.newHashMap(settingsProvider.getEnvs());
+ String ipythonEnabled = PyConsoleOptions.getInstance(project).isIpythonEnabled() ? "True" : "False";
+ envs.put(PythonEnvUtil.IPYTHONENABLE, ipythonEnabled);
+
+
+ return createConsoleRunner(project, sdk, workingDir, envs, PyConsoleType.PYTHON, setupFragment);
+ }
+
+ protected PydevConsoleRunner createConsoleRunner(Project project,
+ Sdk sdk,
+ String workingDir,
+ Map<String, String> envs, PyConsoleType consoleType, String ... setupFragment) {
+ return new PydevConsoleRunner(project, sdk, consoleType, workingDir, envs, setupFragment);
+ }
+}
diff --git a/python/src/com/jetbrains/python/console/PythonConsoleRunnerFactory.java b/python/src/com/jetbrains/python/console/PythonConsoleRunnerFactory.java
new file mode 100644
index 000000000000..09638656df02
--- /dev/null
+++ b/python/src/com/jetbrains/python/console/PythonConsoleRunnerFactory.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.jetbrains.python.console;
+
+import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.project.Project;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+* @author traff
+*/
+public abstract class PythonConsoleRunnerFactory {
+ @NotNull
+ public static PythonConsoleRunnerFactory getInstance() {
+ return ServiceManager.getService(PythonConsoleRunnerFactory.class);
+ }
+ public abstract PydevConsoleRunner createConsoleRunner(@NotNull final Project project,
+ @Nullable Module contextModule);
+}
diff --git a/python/src/com/jetbrains/python/console/PythonConsoleToolWindow.java b/python/src/com/jetbrains/python/console/PythonConsoleToolWindow.java
index e8c50e49280a..177c3528496f 100644
--- a/python/src/com/jetbrains/python/console/PythonConsoleToolWindow.java
+++ b/python/src/com/jetbrains/python/console/PythonConsoleToolWindow.java
@@ -1,8 +1,14 @@
package com.jetbrains.python.console;
+import com.google.common.base.Function;
+import com.google.common.base.Predicates;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.Lists;
import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.SimpleToolWindowPanel;
+import com.intellij.openapi.util.ActionCallback;
+import com.intellij.openapi.util.Key;
import com.intellij.openapi.wm.ToolWindow;
import com.intellij.openapi.wm.ToolWindowManager;
import com.intellij.openapi.wm.ex.ToolWindowManagerEx;
@@ -11,20 +17,25 @@ 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 org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
+import java.util.List;
/**
* @author traff
*/
public class PythonConsoleToolWindow {
+ public static final Key<RunContentDescriptor> CONTENT_DESCRIPTOR = Key.create("CONTENT_DESCRIPTOR");
private final Project myProject;
private boolean myInitialized = false;
+ private ActionCallback myActivation = new ActionCallback();
+
public PythonConsoleToolWindow(Project project) {
myProject = project;
}
@@ -33,6 +44,17 @@ public class PythonConsoleToolWindow {
return project.getComponent(PythonConsoleToolWindow.class);
}
+ public List<RunContentDescriptor> getConsoleContentDescriptors() {
+ return FluentIterable.from(Lists.newArrayList(getToolWindow().getContentManager().getContents()))
+ .transform(new Function<Content, RunContentDescriptor>() {
+ @Override
+ public RunContentDescriptor apply(@Nullable Content input) {
+ return input != null ? input.getUserData(CONTENT_DESCRIPTOR) : null;
+ }
+ }).filter(
+ Predicates.notNull()).toList();
+ }
+
public void init(final @NotNull ToolWindow toolWindow, final @NotNull RunContentDescriptor contentDescriptor) {
addContent(toolWindow, contentDescriptor);
@@ -42,7 +64,7 @@ public class PythonConsoleToolWindow {
}
}
- private void doInit(final ToolWindow toolWindow) {
+ private void doInit(@NotNull final ToolWindow toolWindow) {
myInitialized = true;
toolWindow.setToHideOnEmptyContent(true);
@@ -58,7 +80,8 @@ public class PythonConsoleToolWindow {
if (window != null) {
boolean visible = window.isVisible();
if (visible && toolWindow.getContentManager().getContentCount() == 0) {
- RunPythonConsoleAction.runPythonConsole(myProject, null, toolWindow);
+ PydevConsoleRunner runner = PythonConsoleRunnerFactory.getInstance().createConsoleRunner(myProject, null);
+ runner.run();
}
}
}
@@ -98,10 +121,11 @@ public class PythonConsoleToolWindow {
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());
+
+ content.putUserData(CONTENT_DESCRIPTOR, contentDescriptor);
}
private static FocusListener createFocusListener(final ToolWindow toolWindow) {
@@ -124,4 +148,13 @@ public class PythonConsoleToolWindow {
private static JComponent getComponentToFocus(ToolWindow window) {
return window.getContentManager().getComponent();
}
+
+ public void initialized() {
+ myActivation.setDone();
+ }
+
+ public void activate(@NotNull Runnable runnable) {
+ myActivation.doWhenDone(runnable);
+ getToolWindow().activate(null);
+ }
}
diff --git a/python/src/com/jetbrains/python/console/PythonConsoleToolWindowFactory.java b/python/src/com/jetbrains/python/console/PythonConsoleToolWindowFactory.java
index f042a539bc22..2a49d5efedd3 100644
--- a/python/src/com/jetbrains/python/console/PythonConsoleToolWindowFactory.java
+++ b/python/src/com/jetbrains/python/console/PythonConsoleToolWindowFactory.java
@@ -15,10 +15,12 @@
*/
package com.jetbrains.python.console;
+import com.intellij.execution.console.LanguageConsoleView;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.wm.ToolWindow;
import com.intellij.openapi.wm.ToolWindowFactory;
+import org.jetbrains.annotations.NotNull;
/**
* @author traff
@@ -27,7 +29,14 @@ public class PythonConsoleToolWindowFactory implements ToolWindowFactory, DumbAw
public static final String ID = "Python Console";
@Override
- public void createToolWindowContent(Project project, ToolWindow toolWindow) {
- RunPythonConsoleAction.runPythonConsole(project, null, toolWindow);
+ public void createToolWindowContent(final @NotNull Project project, final @NotNull ToolWindow toolWindow) {
+ PydevConsoleRunner runner = PythonConsoleRunnerFactory.getInstance().createConsoleRunner(project, null);
+ runner.addConsoleListener(new PydevConsoleRunner.ConsoleListener() {
+ @Override
+ public void handleConsoleInitialized(LanguageConsoleView consoleView) {
+ PythonConsoleToolWindow.getInstance(project).initialized();
+ }
+ });
+ runner.run();
}
}
diff --git a/python/src/com/jetbrains/python/console/PythonConsoleView.java b/python/src/com/jetbrains/python/console/PythonConsoleView.java
index 699294eb1c8d..86cb0e98e05c 100644
--- a/python/src/com/jetbrains/python/console/PythonConsoleView.java
+++ b/python/src/com/jetbrains/python/console/PythonConsoleView.java
@@ -29,6 +29,7 @@ import com.intellij.execution.ui.ObservableConsoleView;
import com.intellij.ide.GeneralSettings;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
@@ -119,7 +120,7 @@ public class PythonConsoleView extends JPanel implements LanguageConsoleView, Ob
myExecuteActionHandler = consoleExecuteActionHandler;
}
- private void addSaveContentFocusListener(JComponent component){
+ private void addSaveContentFocusListener(JComponent component) {
component.addFocusListener(new FocusListener() {
@Override
public void focusGained(FocusEvent e) {
@@ -129,7 +130,8 @@ public class PythonConsoleView extends JPanel implements LanguageConsoleView, Ob
}
@Override
- public void focusLost(FocusEvent e) {}
+ public void focusLost(FocusEvent e) {
+ }
});
}
@@ -150,38 +152,53 @@ public class PythonConsoleView extends JPanel implements LanguageConsoleView, Ob
@Override
public void executeCode(final @NotNull String code, @Nullable final Editor editor) {
- ProgressManager.getInstance().run(new Task.Backgroundable(null, "Executing code in console...", false) {
+ showConsole(new Runnable() {
@Override
- public void run(@NotNull final ProgressIndicator indicator) {
- long time = System.currentTimeMillis();
- while (!myExecuteActionHandler.isEnabled() || !myExecuteActionHandler.canExecuteNow()) {
- if (indicator.isCanceled()) {
- break;
- }
- if (System.currentTimeMillis() - time > 1000) {
- if (editor != null) {
- UIUtil.invokeLaterIfNeeded(new Runnable() {
- @Override
- public void run() {
- HintManager.getInstance().showErrorHint(editor, myExecuteActionHandler.getCantExecuteMessage());
+ public void run() {
+ ProgressManager.getInstance().run(new Task.Backgroundable(null, "Executing code in console...", false) {
+ @Override
+ public void run(@NotNull final ProgressIndicator indicator) {
+ long time = System.currentTimeMillis();
+ while (!myExecuteActionHandler.isEnabled() || !myExecuteActionHandler.canExecuteNow()) {
+ if (indicator.isCanceled()) {
+ break;
+ }
+ if (System.currentTimeMillis() - time > 1000) {
+ if (editor != null) {
+ UIUtil.invokeLaterIfNeeded(new Runnable() {
+ @Override
+ public void run() {
+ HintManager.getInstance().showErrorHint(editor, myExecuteActionHandler.getCantExecuteMessage());
+ }
+ });
}
- });
+ return;
+ }
+ try {
+ Thread.sleep(300);
+ }
+ catch (InterruptedException ignored) {
+ }
+ }
+ if (!indicator.isCanceled()) {
+ doExecute(code);
}
- return;
- }
- try {
- Thread.sleep(300);
- }
- catch (InterruptedException ignored) {
}
- }
- if (!indicator.isCanceled()) {
- doExecute(code);
- }
+ });
}
});
}
+ private void showConsole(@NotNull Runnable runnable) {
+ PythonConsoleToolWindow toolWindow = PythonConsoleToolWindow.getInstance(myProject);
+ if (toolWindow != null && !ApplicationManager.getApplication().isUnitTestMode()) {
+ toolWindow.getToolWindow().activate(runnable);
+ }
+ else {
+ runnable.run();
+ }
+ }
+
private void doExecute(String code) {
String codeFragment = PyConsoleIndentUtil.normalize(code, myExecuteActionHandler.getCurrentIndentSize());
diff --git a/python/src/com/jetbrains/python/console/PythonToolWindowConsoleRunner.java b/python/src/com/jetbrains/python/console/PythonToolWindowConsoleRunner.java
new file mode 100644
index 000000000000..5c98bd5110b1
--- /dev/null
+++ b/python/src/com/jetbrains/python/console/PythonToolWindowConsoleRunner.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.jetbrains.python.console;
+
+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.intellij.execution.Executor;
+import com.intellij.execution.ui.RunContentDescriptor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.projectRoots.Sdk;
+import com.intellij.openapi.wm.ToolWindow;
+import com.intellij.openapi.wm.ToolWindowManager;
+import com.intellij.ui.content.Content;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author traff
+ */
+public class PythonToolWindowConsoleRunner extends PydevConsoleRunner {
+ private ToolWindow myToolWindow;
+
+ public PythonToolWindowConsoleRunner(@NotNull Project project,
+ @NotNull Sdk sdk,
+ @NotNull PyConsoleType consoleType,
+ @Nullable String workingDir, Map<String, String> environmentVariables,
+ String ... statementsToExecute) {
+ super(project, sdk, consoleType, workingDir, environmentVariables, statementsToExecute);
+ }
+
+ public ToolWindow getToolWindow() {
+ if (myToolWindow == null) {
+ myToolWindow = ToolWindowManager.getInstance(getProject()).getToolWindow(PythonConsoleToolWindowFactory.ID);
+ }
+ return myToolWindow;
+ }
+
+ @Override
+ protected void showConsole(Executor defaultExecutor, @NotNull RunContentDescriptor contentDescriptor) {
+ PythonConsoleToolWindow terminalView = PythonConsoleToolWindow.getInstance(getProject());
+ terminalView.init(getToolWindow(), contentDescriptor);
+ }
+
+ @Override
+ protected void clearContent(RunContentDescriptor descriptor) {
+ Content content = getToolWindow().getContentManager().findContent(descriptor.getDisplayName());
+ assert content != null;
+ getToolWindow().getContentManager().removeContent(content, true);
+ }
+
+ @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/PythonToolWindowConsoleRunnerFactory.java b/python/src/com/jetbrains/python/console/PythonToolWindowConsoleRunnerFactory.java
new file mode 100644
index 000000000000..240f3ab48cf2
--- /dev/null
+++ b/python/src/com/jetbrains/python/console/PythonToolWindowConsoleRunnerFactory.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.jetbrains.python.console;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.projectRoots.Sdk;
+
+import java.util.Map;
+
+/**
+ * @author traff
+ */
+public class PythonToolWindowConsoleRunnerFactory extends PydevConsoleRunnerFactory {
+ @Override
+ protected PydevConsoleRunner createConsoleRunner(Project project,
+ Sdk sdk,
+ String workingDir,
+ Map<String, String> envs, PyConsoleType consoleType, String ... setupFragment) {
+ return new PythonToolWindowConsoleRunner(project, sdk, consoleType, workingDir, envs, setupFragment);
+ }
+}
diff --git a/python/src/com/jetbrains/python/console/RunPythonConsoleAction.java b/python/src/com/jetbrains/python/console/RunPythonConsoleAction.java
deleted file mode 100644
index 566adea43c87..000000000000
--- a/python/src/com/jetbrains/python/console/RunPythonConsoleAction.java
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * 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.console;
-
-import com.google.common.base.Function;
-import com.google.common.base.Joiner;
-import com.google.common.collect.Collections2;
-import com.google.common.collect.Maps;
-import com.intellij.openapi.actionSystem.AnAction;
-import com.intellij.openapi.actionSystem.AnActionEvent;
-import com.intellij.openapi.actionSystem.CommonDataKeys;
-import com.intellij.openapi.actionSystem.LangDataKeys;
-import com.intellij.openapi.module.Module;
-import com.intellij.openapi.module.ModuleManager;
-import com.intellij.openapi.project.DumbAware;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.projectRoots.Sdk;
-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;
-import com.jetbrains.python.remote.PythonRemoteInterpreterManager;
-import com.jetbrains.python.run.PythonCommandLineState;
-import com.jetbrains.python.sdk.PySdkUtil;
-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;
-import java.util.Map;
-
-/**
- * @author oleg
- */
-public class RunPythonConsoleAction extends AnAction implements DumbAware {
-
- public static final String WORKING_DIR_ENV = "WORKING_DIR_AND_PYTHON_PATHS";
-
- public static final String CONSOLE_START_COMMAND = "import sys; print('Python %s on %s' % (sys.version, sys.platform))\n" +
- "sys.path.extend([" + WORKING_DIR_ENV + "])\n";
-
- public RunPythonConsoleAction() {
- super();
- getTemplatePresentation().setIcon(PythonIcons.Python.Python);
- }
-
- @Override
- public void update(final AnActionEvent e) {
- e.getPresentation().setVisible(true);
- e.getPresentation().setEnabled(false);
- final Project project = e.getData(CommonDataKeys.PROJECT);
- if (project != null) {
- Pair<Sdk, Module> sdkAndModule = findPythonSdkAndModule(project, e.getData(LangDataKeys.MODULE));
- if (sdkAndModule.first != null) {
- e.getPresentation().setEnabled(true);
- }
- }
- }
-
- public void actionPerformed(final AnActionEvent e) {
- final Project project = e.getData(CommonDataKeys.PROJECT);
- runPythonConsole(project, e.getData(LangDataKeys.MODULE), null);
- }
-
- @NotNull
- public static PydevConsoleRunner runPythonConsole(Project project, Module contextModule, @Nullable ToolWindow toolWindow) {
- assert project != null : "Project is null";
-
- Pair<Sdk, Module> sdkAndModule = findPythonSdkAndModule(project, contextModule);
-
- Module module = sdkAndModule.second;
- Sdk sdk = sdkAndModule.first;
-
- assert sdk != null;
-
- PathMappingSettings mappingSettings = getMappings(project, sdk);
-
- String[] setupFragment;
-
- PyConsoleOptions.PyConsoleSettings settingsProvider = PyConsoleOptions.getInstance(project).getPythonConsoleSettings();
- Collection<String> pythonPath = PythonCommandLineState.collectPythonPath(module, settingsProvider.addContentRoots(),
- settingsProvider.addSourceRoots());
-
- if (mappingSettings != null) {
- pythonPath = mappingSettings.convertToRemote(pythonPath);
- }
-
- String customStartScript = settingsProvider == null ? "" : settingsProvider.getCustomStartScript();
-
- if(customStartScript.trim().length() > 0){
- customStartScript = "\n" + customStartScript;
- }
-
- String selfPathAppend = constructPythonPathCommand(pythonPath, customStartScript);
-
- String workingDir = settingsProvider.getWorkingDirectory();
- if (StringUtil.isEmpty(workingDir)) {
- if (module != null && ModuleRootManager.getInstance(module).getContentRoots().length > 0) {
- workingDir = ModuleRootManager.getInstance(module).getContentRoots()[0].getPath();
- }
- else {
- if (ModuleManager.getInstance(project).getModules().length > 0) {
- VirtualFile[] roots = ModuleRootManager.getInstance(ModuleManager.getInstance(project).getModules()[0]).getContentRoots();
- if (roots.length > 0) {
- workingDir = roots[0].getPath();
- }
- }
- }
- }
-
- if (mappingSettings != null) {
- workingDir = mappingSettings.convertToRemote(workingDir);
- }
-
- BuildoutFacet facet = null;
- if (module != null) {
- facet = BuildoutFacet.getInstance(module);
- }
-
- if (facet != null) {
- List<String> path = facet.getAdditionalPythonPath();
- if (mappingSettings != null) {
- path = mappingSettings.convertToRemote(path);
- }
- String prependStatement = facet.getPathPrependStatement(path);
- setupFragment = new String[]{prependStatement, selfPathAppend};
- }
- else {
- setupFragment = new String[]{selfPathAppend};
- }
-
- Map<String, String> envs = Maps.newHashMap(settingsProvider.getEnvs());
- String ipythonEnabled = PyConsoleOptions.getInstance(project).isIpythonEnabled() ? "True" : "False";
- envs.put(PythonEnvUtil.IPYTHONENABLE, ipythonEnabled);
-
- return PydevConsoleRunner
- .createAndRun(project, sdk, PyConsoleType.PYTHON, workingDir, envs, toolWindow, setupFragment);
- }
-
- public static PathMappingSettings getMappings(Project project, Sdk sdk) {
- PathMappingSettings mappingSettings = null;
- if (PySdkUtil.isRemote(sdk)) {
- PythonRemoteInterpreterManager instance = PythonRemoteInterpreterManager.getInstance();
- if (instance != null) {
- mappingSettings =
- instance.setupMappings(project, (PyRemoteSdkAdditionalDataBase)sdk.getSdkAdditionalData(), null);
- }
- }
- return mappingSettings;
- }
-
- @NotNull
- private static Pair<Sdk, Module> findPythonSdkAndModule(Project project, Module contextModule) {
- Sdk sdk = null;
- Module module = null;
- PyConsoleOptions.PyConsoleSettings settings = PyConsoleOptions.getInstance(project).getPythonConsoleSettings();
- String sdkHome = settings.getSdkHome();
- if (sdkHome != null) {
- sdk = PythonSdkType.findSdkByPath(sdkHome);
- if (settings.getModuleName() != null) {
- module = ModuleManager.getInstance(project).findModuleByName(settings.getModuleName());
- }
- else {
- module = contextModule;
- if (module == null && ModuleManager.getInstance(project).getModules().length > 0) {
- module = ModuleManager.getInstance(project).getModules()[0];
- }
- }
- }
- if (sdk == null && settings.isUseModuleSdk()) {
- if (contextModule != null) {
- module = contextModule;
- }
- else if (settings.getModuleName() != null) {
- module = ModuleManager.getInstance(project).findModuleByName(settings.getModuleName());
- }
- if (module != null) {
- if (PythonSdkType.findPythonSdk(module) != null) {
- sdk = PythonSdkType.findPythonSdk(module);
- }
- }
- }
- else if (contextModule != null) {
- if (module == null) {
- module = contextModule;
- }
- if (sdk == null) {
- sdk = PythonSdkType.findPythonSdk(module);
- }
- }
-
- if (sdk == null) {
- for (Module m : ModuleManager.getInstance(project).getModules()) {
- if (PythonSdkType.findPythonSdk(m) != null) {
- sdk = PythonSdkType.findPythonSdk(m);
- module = m;
- break;
- }
- }
- }
- if (sdk == null) {
- if (PythonSdkType.getAllSdks().size() > 0) {
- //noinspection UnusedAssignment
- sdk = PythonSdkType.getAllSdks().get(0); //take any python sdk
- }
- }
- return Pair.create(sdk, module);
- }
-
- public static String constructPythonPathCommand(Collection<String> pythonPath, String command) {
- final String path = Joiner.on(", ").join(Collections2.transform(pythonPath, new Function<String, String>() {
- @Override
- public String apply(String input) {
- return "'" + input.replace("\\", "\\\\").replace("'", "\\'") + "'";
- }
- }));
-
- return command.replace(WORKING_DIR_ENV, path);
- }
-}
diff --git a/python/src/com/jetbrains/python/formatter/PyLanguageCodeStyleSettingsProvider.java b/python/src/com/jetbrains/python/formatter/PyLanguageCodeStyleSettingsProvider.java
index 32ad8a31b003..4acfcbd60f74 100644
--- a/python/src/com/jetbrains/python/formatter/PyLanguageCodeStyleSettingsProvider.java
+++ b/python/src/com/jetbrains/python/formatter/PyLanguageCodeStyleSettingsProvider.java
@@ -89,7 +89,8 @@ public class PyLanguageCodeStyleSettingsProvider extends LanguageCodeStyleSettin
BLANK_LINES);
}
else if (settingsType == SettingsType.WRAPPING_AND_BRACES_SETTINGS) {
- consumer.showStandardOptions("KEEP_LINE_BREAKS",
+ consumer.showStandardOptions("RIGHT_MARGIN",
+ "KEEP_LINE_BREAKS",
"WRAP_LONG_LINES",
"ALIGN_MULTILINE_PARAMETERS",
"ALIGN_MULTILINE_PARAMETERS_IN_CALLS");
diff --git a/python/src/com/jetbrains/python/inspections/PyStringFormatInspection.java b/python/src/com/jetbrains/python/inspections/PyStringFormatInspection.java
index 162fa0b9bc60..40efca3663a0 100644
--- a/python/src/com/jetbrains/python/inspections/PyStringFormatInspection.java
+++ b/python/src/com/jetbrains/python/inspections/PyStringFormatInspection.java
@@ -41,6 +41,7 @@ import java.util.Map;
import static com.jetbrains.python.inspections.PyStringFormatParser.filterSubstitutions;
import static com.jetbrains.python.inspections.PyStringFormatParser.parsePercentFormat;
+import static com.jetbrains.python.psi.PyUtil.as;
/**
* @author Alexey.Ivanov
@@ -416,9 +417,9 @@ public class PyStringFormatInspection extends PyInspection {
inspectValues(((PyParenthesizedExpression)rightExpression).getContainedExpression());
}
else {
- final PyType type = myTypeEvalContext.getType(rightExpression);
+ final PyClassType type = as(myTypeEvalContext.getType(rightExpression), PyClassType.class);
if (type != null) {
- if (myUsedMappingKeys.size() > 0 && !("dict".equals(type.getName()))) {
+ if (myUsedMappingKeys.size() > 0 && !PyABCUtil.isSubclass(type.getPyClass(), PyNames.MAPPING)) {
registerProblem(rightExpression, PyBundle.message("INSP.format.requires.mapping"));
return;
}
diff --git a/python/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesInspection.java b/python/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesInspection.java
index c0fb3c1d620d..4fd58629c516 100644
--- a/python/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesInspection.java
+++ b/python/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesInspection.java
@@ -69,7 +69,6 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.*;
-import java.util.HashSet;
import static com.jetbrains.python.inspections.quickfix.AddIgnoredIdentifierQuickFix.END_WILDCARD;
@@ -833,6 +832,9 @@ public class PyUnresolvedReferencesInspection extends PyInspection {
else {
actions.add(importFix);
}
+ if (ScopeUtil.getScopeOwner(node) instanceof PyFunction) {
+ actions.add(importFix.forLocalImport());
+ }
}
}
diff --git a/python/src/com/jetbrains/python/packaging/PyPIPackageUtil.java b/python/src/com/jetbrains/python/packaging/PyPIPackageUtil.java
index fbbdfa215e9c..2b8591f96d8e 100644
--- a/python/src/com/jetbrains/python/packaging/PyPIPackageUtil.java
+++ b/python/src/com/jetbrains/python/packaging/PyPIPackageUtil.java
@@ -239,8 +239,6 @@ public class PyPIPackageUtil {
if (connection instanceof HttpsURLConnection) {
((HttpsURLConnection)connection).setSSLSocketFactory(sslContext.getSocketFactory());
}
- connection.setConnectTimeout(5000);
- connection.setReadTimeout(5000);
InputStream is = connection.getInputStream();
Reader reader = new InputStreamReader(is);
try{
diff --git a/python/src/com/jetbrains/python/psi/impl/PyElementGeneratorImpl.java b/python/src/com/jetbrains/python/psi/impl/PyElementGeneratorImpl.java
index bb0e29f800a7..6356a1f92a0d 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyElementGeneratorImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyElementGeneratorImpl.java
@@ -20,6 +20,7 @@ import com.google.common.collect.Queues;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
@@ -285,12 +286,6 @@ public class PyElementGeneratorImpl extends PyElementGenerator {
throw new IllegalArgumentException("Invalid call expression text " + functionName);
}
- public PyImportStatement createImportStatementFromText(final LanguageLevel languageLevel,
- final String text) {
- final PsiFile dummyFile = createDummyFile(languageLevel, text);
- return (PyImportStatement)dummyFile.getFirstChild();
- }
-
@Override
public PyImportElement createImportElement(final LanguageLevel languageLevel, String name) {
return createFromText(languageLevel, PyImportElement.class, "from foo import " + name, new int[]{0, 6});
@@ -427,6 +422,23 @@ public class PyElementGeneratorImpl extends PyElementGenerator {
return createFromText(LanguageLevel.getDefault(), PsiWhiteSpace.class, " \n\n ");
}
+ @NotNull
+ @Override
+ public PyFromImportStatement createFromImportStatement(@NotNull LanguageLevel languageLevel, @NotNull String qualifier,
+ @NotNull String name, @Nullable String alias) {
+ final String asClause = StringUtil.isNotEmpty(alias) ? " as " + alias : "";
+ final String statement = "from " + qualifier + " import " + name + asClause;
+ return createFromText(languageLevel, PyFromImportStatement.class, statement);
+ }
+
+ @NotNull
+ @Override
+ public PyImportStatement createImportStatement(@NotNull LanguageLevel languageLevel, @NotNull String name, @Nullable String alias) {
+ final String asClause = StringUtil.isNotEmpty(alias) ? " as " + alias : "";
+ final String statement = "import " + name + asClause;
+ return createFromText(languageLevel, PyImportStatement.class, statement);
+ }
+
private static class CommasOnly extends NotNullPredicate<LeafPsiElement> {
@Override
protected boolean applyNotNull(@NotNull final LeafPsiElement input) {
diff --git a/python/src/com/jetbrains/python/psi/types/PyFunctionType.java b/python/src/com/jetbrains/python/psi/types/PyFunctionType.java
index 4b3adfd112f8..4bdbae69d83d 100644
--- a/python/src/com/jetbrains/python/psi/types/PyFunctionType.java
+++ b/python/src/com/jetbrains/python/psi/types/PyFunctionType.java
@@ -18,10 +18,12 @@ package com.jetbrains.python.psi.types;
import com.intellij.psi.PsiElement;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ProcessingContext;
+import com.intellij.util.containers.ContainerUtil;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.impl.PyBuiltinCache;
import com.jetbrains.python.psi.resolve.PyResolveContext;
+import com.jetbrains.python.psi.resolve.QualifiedResolveResult;
import com.jetbrains.python.psi.resolve.RatedResolveResult;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -30,6 +32,9 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import static com.jetbrains.python.psi.PyFunction.Modifier.STATICMETHOD;
+import static com.jetbrains.python.psi.PyUtil.as;
+
/**
* Type of a particular function that is represented as a {@link Callable} in the PSI tree.
*
@@ -74,20 +79,79 @@ public class PyFunctionType implements PyCallableType {
@Nullable PyExpression location,
@NotNull AccessDirection direction,
@NotNull PyResolveContext resolveContext) {
- final PyClassTypeImpl functionType = PyBuiltinCache.getInstance(getCallable()).getObjectType(PyNames.FAKE_FUNCTION);
- if (functionType == null) {
+ final PyClassType delegate = selectFakeType(location, resolveContext.getTypeEvalContext());
+ if (delegate == null) {
return Collections.emptyList();
}
- return functionType.resolveMember(name, location, direction, resolveContext);
+ return delegate.resolveMember(name, location, direction, resolveContext);
}
@Override
public Object[] getCompletionVariants(String completionPrefix, PsiElement location, ProcessingContext context) {
- final PyClassTypeImpl functionType = PyBuiltinCache.getInstance(getCallable()).getObjectType(PyNames.FAKE_FUNCTION);
- if (functionType == null) {
+ final TypeEvalContext typeEvalContext = TypeEvalContext.userInitiated(location.getContainingFile());
+ final PyClassType delegate;
+ if (location instanceof PyReferenceExpression) {
+ delegate = selectFakeType(((PyReferenceExpression)location).getQualifier(), typeEvalContext);
+ }
+ else {
+ delegate = PyBuiltinCache.getInstance(getCallable()).getObjectType(PyNames.FAKE_FUNCTION);
+ }
+ if (delegate == null) {
return ArrayUtil.EMPTY_OBJECT_ARRAY;
}
- return functionType.getCompletionVariants(completionPrefix, location, context);
+ return delegate.getCompletionVariants(completionPrefix, location, context);
+ }
+
+ /**
+ * Select either {@link PyNames#FAKE_FUNCTION} or {@link PyNames#FAKE_METHOD} fake class depending on concrete reference used and
+ * language level. Will fallback to fake function type.
+ */
+ @Nullable
+ private PyClassTypeImpl selectFakeType(@Nullable PyExpression location, @NotNull TypeEvalContext context) {
+ if (location instanceof PyReferenceExpression && isBoundMethodReference(((PyReferenceExpression)location), context)) {
+ return PyBuiltinCache.getInstance(getCallable()).getObjectType(PyNames.FAKE_METHOD);
+ }
+ return PyBuiltinCache.getInstance(getCallable()).getObjectType(PyNames.FAKE_FUNCTION);
+ }
+
+ private boolean isBoundMethodReference(@NotNull PyReferenceExpression location, @NotNull TypeEvalContext context) {
+ final PyFunction function = as(getCallable(), PyFunction.class);
+ final boolean isNonStaticMethod = function != null && function.getContainingClass() != null && function.getModifier() != STATICMETHOD;
+ if (isNonStaticMethod) {
+ // In Python 2 unbound methods have __method fake type
+ if (LanguageLevel.forElement(location).isOlderThan(LanguageLevel.PYTHON30)) {
+ return true;
+ }
+ final PyExpression qualifier;
+ if (location.isQualified()) {
+ qualifier = location.getQualifier();
+ }
+ else {
+ final PyResolveContext resolveContext = PyResolveContext.noImplicits().withTypeEvalContext(context);
+ final QualifiedResolveResult resolveResult = location.followAssignmentsChain(resolveContext);
+ final List<PyExpression> qualifiers = resolveResult.getQualifiers();
+ qualifier = ContainerUtil.isEmpty(qualifiers) ? null : qualifiers.get(qualifiers.size() - 1);
+ }
+ if (qualifier != null) {
+ //noinspection ConstantConditions
+ final PyType qualifierType = PyTypeChecker.toNonWeakType(context.getType(qualifier), context);
+ if (isInstanceType(qualifierType)) {
+ return true;
+ }
+ else if (qualifierType instanceof PyUnionType) {
+ for (PyType type : ((PyUnionType)qualifierType).getMembers()) {
+ if (isInstanceType(type)) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ private static boolean isInstanceType(@Nullable PyType type) {
+ return type instanceof PyClassType && !((PyClassType)type).isDefinition();
}
@Override
diff --git a/python/src/com/jetbrains/python/refactoring/PyRefactoringUtil.java b/python/src/com/jetbrains/python/refactoring/PyRefactoringUtil.java
index e4259d8581bb..fa2b4cf1204b 100644
--- a/python/src/com/jetbrains/python/refactoring/PyRefactoringUtil.java
+++ b/python/src/com/jetbrains/python/refactoring/PyRefactoringUtil.java
@@ -109,7 +109,7 @@ public class PyRefactoringUtil {
final PyElementGenerator generator = PyElementGenerator.getInstance(project);
final LanguageLevel langLevel = LanguageLevel.forElement(element1);
final PyExpression expression = generator.createFromText(langLevel, PyAssignmentStatement.class, "z=" + selection).getAssignedValue();
- if (PsiUtilCore.hasErrorElementChild(expression) || !(expression instanceof PyBinaryExpression)) {
+ if (!(expression instanceof PyBinaryExpression) || PsiUtilCore.hasErrorElementChild(expression)) {
return null;
}
final String parentText = parent.getText();
diff --git a/python/src/com/jetbrains/python/refactoring/PyReplaceExpressionUtil.java b/python/src/com/jetbrains/python/refactoring/PyReplaceExpressionUtil.java
index f4cb9e6a73f3..2cebb3ec2720 100644
--- a/python/src/com/jetbrains/python/refactoring/PyReplaceExpressionUtil.java
+++ b/python/src/com/jetbrains/python/refactoring/PyReplaceExpressionUtil.java
@@ -47,6 +47,15 @@ import static com.jetbrains.python.inspections.PyStringFormatParser.parsePercent
* @author Dennis.Ushakov
*/
public class PyReplaceExpressionUtil implements PyElementTypes {
+ /**
+ * This marker is added in cases where valid selection nevertheless breaks existing expression.
+ * It can happen in cases like (here {@code <start> and <end>} represent selection boundaries):
+ * <ul>
+ * <li>Selection conflicts with operator precedence: {@code n = 1 * <start>2 + 3<end>}</li>
+ * <li>Selection conflicts with operator associativity: {@code n = 1 + <start>2 + 3<end>}</li>
+ * <li>Part of string literal is selected: {@code s = 'green <start>eggs<end> and ham'}</li>
+ * </ul>
+ */
public static final Key<Pair<PsiElement, TextRange>> SELECTION_BREAKS_AST_NODE =
new Key<Pair<PsiElement, TextRange>>("python.selection.breaks.ast.node");
diff --git a/python/src/com/jetbrains/python/refactoring/inline/PyInlineLocalHandler.java b/python/src/com/jetbrains/python/refactoring/inline/PyInlineLocalHandler.java
index a582b1728d47..575399c61ceb 100644
--- a/python/src/com/jetbrains/python/refactoring/inline/PyInlineLocalHandler.java
+++ b/python/src/com/jetbrains/python/refactoring/inline/PyInlineLocalHandler.java
@@ -134,7 +134,7 @@ public class PyInlineLocalHandler extends InlineActionHandler {
if (editor != null && !ApplicationManager.getApplication().isUnitTestMode()) {
highlightManager.addOccurrenceHighlights(editor, refsToInline, attributes, true, null);
int occurrencesCount = refsToInline.length;
- String occurencesString = RefactoringBundle.message("occurences.string", occurrencesCount);
+ String occurencesString = RefactoringBundle.message("occurrences.string", occurrencesCount);
final String promptKey = "inline.local.variable.prompt";
final String question = RefactoringBundle.message(promptKey, localName) + " " + occurencesString;
RefactoringMessageDialog dialog = new RefactoringMessageDialog(REFACTORING_NAME, question, HELP_ID, "OptionPane.questionIcon", true, project);
diff --git a/python/src/com/jetbrains/python/refactoring/introduce/IntroduceHandler.java b/python/src/com/jetbrains/python/refactoring/introduce/IntroduceHandler.java
index 29fc44105857..00448c8b69bd 100644
--- a/python/src/com/jetbrains/python/refactoring/introduce/IntroduceHandler.java
+++ b/python/src/com/jetbrains/python/refactoring/introduce/IntroduceHandler.java
@@ -69,6 +69,11 @@ import static com.jetbrains.python.inspections.PyStringFormatParser.*;
abstract public class IntroduceHandler implements RefactoringActionHandler {
protected static PsiElement findAnchor(List<PsiElement> occurrences) {
PsiElement anchor = occurrences.get(0);
+ final Pair<PsiElement, TextRange> data = anchor.getUserData(PyReplaceExpressionUtil.SELECTION_BREAKS_AST_NODE);
+ // Search anchor in the origin file, not in dummy.py, if selection breaks statement and thus element was generated
+ if (data != null && occurrences.size() == 1) {
+ return PsiTreeUtil.getParentOfType(data.getFirst(), PyStatement.class);
+ }
next:
do {
final PyStatement statement = PsiTreeUtil.getParentOfType(anchor, PyStatement.class);
@@ -192,7 +197,7 @@ abstract public class IntroduceHandler implements RefactoringActionHandler {
String text = expression.getText();
final Pair<PsiElement, TextRange> selection = expression.getUserData(PyReplaceExpressionUtil.SELECTION_BREAKS_AST_NODE);
if (selection != null) {
- text = selection.getSecond().substring(text);
+ text = selection.getSecond().substring(selection.getFirst().getText());
}
if (expression instanceof PyCallExpression) {
final PyExpression callee = ((PyCallExpression)expression).getCallee();
diff --git a/python/src/com/jetbrains/python/refactoring/introduce/constant/PyIntroduceConstantHandler.java b/python/src/com/jetbrains/python/refactoring/introduce/constant/PyIntroduceConstantHandler.java
index af9ff583e3e4..44fdee8abdf7 100644
--- a/python/src/com/jetbrains/python/refactoring/introduce/constant/PyIntroduceConstantHandler.java
+++ b/python/src/com/jetbrains/python/refactoring/introduce/constant/PyIntroduceConstantHandler.java
@@ -24,6 +24,7 @@ import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
import com.jetbrains.python.codeInsight.imports.AddImportHelper;
import com.jetbrains.python.psi.PyExpression;
import com.jetbrains.python.psi.PyFile;
+import com.jetbrains.python.psi.PyParameterList;
import com.jetbrains.python.refactoring.PyReplaceExpressionUtil;
import com.jetbrains.python.refactoring.introduce.IntroduceHandler;
import com.jetbrains.python.refactoring.introduce.IntroduceOperation;
@@ -66,6 +67,11 @@ public class PyIntroduceConstantHandler extends IntroduceHandler {
}
@Override
+ protected boolean isValidIntroduceContext(PsiElement element) {
+ return super.isValidIntroduceContext(element) || PsiTreeUtil.getParentOfType(element, PyParameterList.class) != null;
+ }
+
+ @Override
protected String getHelpId() {
return "python.reference.introduceConstant";
}
diff --git a/python/src/com/jetbrains/python/run/PythonCommandLineState.java b/python/src/com/jetbrains/python/run/PythonCommandLineState.java
index a4d1718bb006..220939efc274 100644
--- a/python/src/com/jetbrains/python/run/PythonCommandLineState.java
+++ b/python/src/com/jetbrains/python/run/PythonCommandLineState.java
@@ -87,7 +87,7 @@ public abstract class PythonCommandLineState extends CommandLineState {
private Boolean myMultiprocessDebug = null;
public boolean isDebug() {
- return PyDebugRunner.PY_DEBUG_RUNNER.equals(getEnvironment().getRunnerId());
+ return PyDebugRunner.PY_DEBUG_RUNNER.equals(getEnvironment().getRunner().getRunnerId());
}
public static ServerSocket createServerSocket() throws ExecutionException {
@@ -171,23 +171,13 @@ public abstract class PythonCommandLineState extends CommandLineState {
* @throws ExecutionException
*/
protected ProcessHandler startProcess(CommandLinePatcher... patchers) throws ExecutionException {
-
-
GeneralCommandLine commandLine = generateCommandLine(patchers);
// Extend command line
- RunnerSettings runnerSettings = getRunnerSettings();
- String runnerId = getEnvironment().getRunnerId();
- if (runnerId != null) {
- PythonRunConfigurationExtensionsManager.getInstance().patchCommandLine(myConfig, runnerSettings, commandLine, runnerId);
- }
-
+ PythonRunConfigurationExtensionsManager.getInstance().patchCommandLine(myConfig, getRunnerSettings(), commandLine, getEnvironment().getRunner().getRunnerId());
Sdk sdk = PythonSdkType.findSdkByPath(myConfig.getInterpreterPath());
-
-
final ProcessHandler processHandler;
if (PySdkUtil.isRemote(sdk)) {
- assert sdk != null;
processHandler =
createRemoteProcessStarter().startRemoteProcess(sdk, commandLine, myConfig.getProject(), myConfig.getMappingSettings());
}
diff --git a/python/src/com/jetbrains/python/run/PythonRunner.java b/python/src/com/jetbrains/python/run/PythonRunner.java
index b95da7c62957..3007b0b7a5f9 100644
--- a/python/src/com/jetbrains/python/run/PythonRunner.java
+++ b/python/src/com/jetbrains/python/run/PythonRunner.java
@@ -59,9 +59,6 @@ public class PythonRunner extends DefaultProgramRunner {
else {
executionResult = state.execute(env.getExecutor(), this);
}
- if (executionResult == null) return null;
-
- final RunContentBuilder contentBuilder = new RunContentBuilder(this, executionResult, env);
- return contentBuilder.showRunContent(contentToReuse);
+ return executionResult == null ? null : new RunContentBuilder(executionResult, env).showRunContent(contentToReuse);
}
}
diff --git a/python/src/com/jetbrains/python/sdk/PythonSdkType.java b/python/src/com/jetbrains/python/sdk/PythonSdkType.java
index f194f359e1a9..58de09370d37 100644
--- a/python/src/com/jetbrains/python/sdk/PythonSdkType.java
+++ b/python/src/com/jetbrains/python/sdk/PythonSdkType.java
@@ -910,6 +910,16 @@ public class PythonSdkType extends SdkType {
return null;
}
+ @Nullable
+ public static Sdk findPython2Sdk(List<Sdk> sdks) {
+ Collections.sort(sdks, PreferredSdkComparator.INSTANCE);
+ for (Sdk sdk : sdks) {
+ if (!getLanguageLevelForSdk(sdk).isPy3K()) {
+ return sdk;
+ }
+ }
+ return null;
+ }
@Nullable
public static Sdk findLocalCPython(@Nullable Module module) {
@@ -997,7 +1007,7 @@ public class PythonSdkType extends SdkType {
public static boolean isIncompleteRemote(Sdk sdk) {
if (PySdkUtil.isRemote(sdk)) {
//noinspection ConstantConditions
- if (!((PyRemoteSdkAdditionalDataBase)sdk.getSdkAdditionalData()).isInitialized()) {
+ if (!((PyRemoteSdkAdditionalDataBase)sdk.getSdkAdditionalData()).isValid()) {
return true;
}
}
diff --git a/python/src/com/jetbrains/python/sdk/skeletons/PySkeletonRefresher.java b/python/src/com/jetbrains/python/sdk/skeletons/PySkeletonRefresher.java
index 284a125e8736..4e4a43102202 100644
--- a/python/src/com/jetbrains/python/sdk/skeletons/PySkeletonRefresher.java
+++ b/python/src/com/jetbrains/python/sdk/skeletons/PySkeletonRefresher.java
@@ -20,7 +20,6 @@ import com.google.common.collect.Lists;
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
import com.intellij.execution.ExecutionException;
import com.intellij.notification.Notification;
-import com.intellij.notification.NotificationListener;
import com.intellij.notification.NotificationType;
import com.intellij.notification.Notifications;
import com.intellij.openapi.application.ApplicationManager;
@@ -35,6 +34,7 @@ import com.intellij.openapi.util.Pair;
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;
import com.intellij.openapi.vfs.JarFileSystem;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
@@ -58,7 +58,6 @@ import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import javax.swing.event.HyperlinkEvent;
import java.awt.*;
import java.io.*;
import java.util.*;
@@ -164,18 +163,27 @@ public class PySkeletonRefresher {
else {
message = PyBundle.message("sdk.errorlog.$0.mods.fail.in.$1.sdks", module_errors, errors.size());
}
- Notifications.Bus.notify(
- new Notification(
- PythonSdkType.SKELETONS_TOPIC, PyBundle.message("sdk.some.skeletons.failed"), message,
- NotificationType.WARNING,
- new NotificationListener() {
- @Override
- public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) {
- new SkeletonErrorsDialog(errors, failedSdks).setVisible(true);
- }
- }
- )
- );
+ logErrors(errors, failedSdks, message);
+ }
+ }
+
+ private static void logErrors(@NotNull final Map<String, List<String>> errors, @NotNull final List<String> failedSdks,
+ @NotNull final String message) {
+ LOG.warn(PyBundle.message("sdk.some.skeletons.failed"));
+ LOG.warn(message);
+
+ if (failedSdks.size() > 0) {
+ LOG.warn(PyBundle.message("sdk.error.dialog.failed.sdks"));
+ LOG.warn(StringUtil.join(failedSdks, ", "));
+ }
+
+ if (errors.size() > 0) {
+ LOG.warn(PyBundle.message("sdk.error.dialog.failed.modules"));
+ for (String sdkName : errors.keySet()) {
+ for (String moduleName : errors.get(sdkName)) {
+ LOG.warn(moduleName);
+ }
+ }
}
}
diff --git a/python/src/com/jetbrains/python/sdk/skeletons/SkeletonErrorsDialog.form b/python/src/com/jetbrains/python/sdk/skeletons/SkeletonErrorsDialog.form
deleted file mode 100644
index c82d5fa91b00..000000000000
--- a/python/src/com/jetbrains/python/sdk/skeletons/SkeletonErrorsDialog.form
+++ /dev/null
@@ -1,61 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.jetbrains.python.sdk.skeletons.SkeletonErrorsDialog">
- <grid id="cbd77" binding="contentPane" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
- <margin top="10" left="10" bottom="10" right="10"/>
- <constraints>
- <xy x="48" y="54" width="436" height="409"/>
- </constraints>
- <properties/>
- <border type="none"/>
- <children>
- <grid id="94766" 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="1" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
- </constraints>
- <properties/>
- <border type="none"/>
- <children>
- <grid id="9538f" 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="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"/>
- <children>
- <component id="e7465" class="javax.swing.JButton" binding="buttonOK">
- <constraints>
- <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
- </constraints>
- <properties>
- <text value="OK"/>
- </properties>
- </component>
- </children>
- </grid>
- <scrollpane id="d5fbd" class="com.intellij.ui.components.JBScrollPane" binding="myScroller">
- <constraints>
- <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="7" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
- </constraints>
- <properties/>
- <border type="none"/>
- <children>
- <component id="10d56" class="javax.swing.JTextPane" binding="myMessagePane">
- <constraints/>
- <properties>
- <editable value="false"/>
- <enabled value="true"/>
- </properties>
- <clientProperties>
- <JEditorPane.honorDisplayProperties class="java.lang.Boolean" value="true"/>
- <caretAspectRatio class="java.lang.Float" value="0.04"/>
- </clientProperties>
- </component>
- </children>
- </scrollpane>
- </children>
- </grid>
- </children>
- </grid>
-</form>
diff --git a/python/src/com/jetbrains/python/sdk/skeletons/SkeletonErrorsDialog.java b/python/src/com/jetbrains/python/sdk/skeletons/SkeletonErrorsDialog.java
deleted file mode 100644
index f6c6b45ceb44..000000000000
--- a/python/src/com/jetbrains/python/sdk/skeletons/SkeletonErrorsDialog.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * 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.sdk.skeletons;
-
-import com.intellij.ui.components.JBScrollPane;
-import com.jetbrains.python.PyBundle;
-
-import javax.swing.*;
-import javax.swing.border.EmptyBorder;
-import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.util.List;
-import java.util.Map;
-
-public class SkeletonErrorsDialog extends JDialog {
- private JPanel contentPane;
- private JButton buttonOK;
- private JBScrollPane myScroller;
- private JTextPane myMessagePane;
-
- public SkeletonErrorsDialog(Map<String, List<String>> errors, List<String> failed_sdks) {
- setContentPane(contentPane);
- setModal(true);
- getRootPane().setDefaultButton(buttonOK);
-
- buttonOK.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- dispose();
- }
- });
-
- // fill data
- myMessagePane.setContentType("text/html");
- myMessagePane.setBorder(new EmptyBorder(0, 0, 0, 0));
- StringBuilder sb = new StringBuilder("<html><body style='margin: 4pt;' ");
- final Color foreground = getParent().getForeground();
- final Color background = getParent().getBackground();
- if (foreground != null && background != null) {
- sb.append("text='").append(getHTMLColor(foreground)).append("' ");
- sb.append("bgcolor='").append(getHTMLColor(background)).append("'");
- }
- sb.append(">");
-
- if (failed_sdks.size() > 0) {
- sb.append("<h1>").append(PyBundle.message("sdk.error.dialog.failed.sdks")).append("</h1>");
- sb.append("<ul>");
- for (String sdk_name : failed_sdks) {
- sb.append("<li>").append(sdk_name).append("</li>");
- }
- sb.append("</ul><br>");
- }
-
- if (errors.size() > 0) {
- sb.append("<h1>").append(PyBundle.message("sdk.error.dialog.failed.modules")).append("</h1>");
- for (String sdk_name : errors.keySet()) {
- sb.append("<b>").append(sdk_name).append("</b><br>");
- sb.append("<ul>");
- for (String module_name : errors.get(sdk_name)) {
- sb.append("<li>").append(module_name).append("</li>");
- }
- sb.append("</ul>");
- }
- sb.append(PyBundle.message("sdk.error.dialog.were.blacklisted"));
- }
-
- sb.append("</body></html>");
- myMessagePane.setText(sb.toString());
-
- setTitle(PyBundle.message("sdk.error.dialog.problems"));
-
- pack();
- setLocationRelativeTo(getParent());
- }
-
- private static String getHTMLColor(Color color) {
- StringBuilder sb = new StringBuilder("#");
- sb.append(Integer.toHexString(color.getRGB() & 0xffffff));
- return sb.toString();
- }
-}
diff --git a/python/src/com/jetbrains/python/testing/PyRerunFailedTestsAction.java b/python/src/com/jetbrains/python/testing/PyRerunFailedTestsAction.java
index cc468c5e40ac..0b922514e52e 100644
--- a/python/src/com/jetbrains/python/testing/PyRerunFailedTestsAction.java
+++ b/python/src/com/jetbrains/python/testing/PyRerunFailedTestsAction.java
@@ -72,7 +72,7 @@ public class PyRerunFailedTestsAction extends AbstractRerunFailedTestsAction {
public RunProfileState getState(@NotNull Executor executor, @NotNull ExecutionEnvironment env) throws ExecutionException {
final AbstractPythonRunConfiguration configuration = ((AbstractPythonRunConfiguration)getPeer());
return new FailedPythonTestCommandLineStateBase(configuration, env,
- (PythonTestCommandLineStateBase)configuration.getState(executor, env));
+ (PythonTestCommandLineStateBase)configuration.getState(executor, env));
}
}
diff --git a/python/testData/MockSdk2.7/python_stubs/__builtin__.py b/python/testData/MockSdk2.7/python_stubs/__builtin__.py
index ca174bbf6716..5ef056b2a62c 100644
--- a/python/testData/MockSdk2.7/python_stubs/__builtin__.py
+++ b/python/testData/MockSdk2.7/python_stubs/__builtin__.py
@@ -652,6 +652,19 @@ class __function(object):
self.__name__ = ''
+class __method(object):
+ '''A mock class representing method type.'''
+
+ def __init__(self):
+
+ self.im_class = None
+ self.im_self = None
+ self.im_func = None
+
+ self.__func__ = None
+ self.__self__ = None
+
+
class __namedtuple(tuple):
'''A mock base class for named tuples.'''
diff --git a/python/testData/MockSdk3.2/python_stubs/builtins.py b/python/testData/MockSdk3.2/python_stubs/builtins.py
index 88b74ab951ac..58fcaac8b763 100644
--- a/python/testData/MockSdk3.2/python_stubs/builtins.py
+++ b/python/testData/MockSdk3.2/python_stubs/builtins.py
@@ -613,14 +613,24 @@ class __function(object):
self.__dict__ = ''
self.__module__ = ''
- self.__annotations__ = {}
self.__defaults__ = {}
self.__globals__ = {}
- self.__kwdefaults__ = {}
self.__closure__ = None
self.__code__ = None
self.__name__ = ''
+ self.__annotations__ = {}
+ self.__kwdefaults__ = {}
+
+
+class __method(object):
+ '''A mock class representing method type.'''
+
+ def __init__(self):
+
+ self.__func__ = None
+ self.__self__ = None
+
class __namedtuple(tuple):
'''A mock base class for named tuples.'''
diff --git a/python/testData/__init__.py b/python/testData/__init__.py
new file mode 100644
index 000000000000..595e3818d699
--- /dev/null
+++ b/python/testData/__init__.py
@@ -0,0 +1 @@
+__author__ = 'traff'
diff --git a/python/testData/addImport/localFromImport.after.py b/python/testData/addImport/localFromImport.after.py
new file mode 100644
index 000000000000..92920f79cf9f
--- /dev/null
+++ b/python/testData/addImport/localFromImport.after.py
@@ -0,0 +1,6 @@
+def func():
+ for _ range(10):
+ from package.module import foo
+
+ foo
+# <ref> \ No newline at end of file
diff --git a/python/testData/addImport/localFromImport.py b/python/testData/addImport/localFromImport.py
new file mode 100644
index 000000000000..e93e2d145349
--- /dev/null
+++ b/python/testData/addImport/localFromImport.py
@@ -0,0 +1,4 @@
+def func():
+ for _ range(10):
+ foo
+# <ref> \ No newline at end of file
diff --git a/python/testData/addImport/localImport.after.py b/python/testData/addImport/localImport.after.py
new file mode 100644
index 000000000000..883e080132c9
--- /dev/null
+++ b/python/testData/addImport/localImport.after.py
@@ -0,0 +1,8 @@
+def func():
+ try:
+ import module
+
+ module
+# <ref>
+ except:
+ pass
diff --git a/python/testData/addImport/localImport.py b/python/testData/addImport/localImport.py
new file mode 100644
index 000000000000..942858492cb7
--- /dev/null
+++ b/python/testData/addImport/localImport.py
@@ -0,0 +1,6 @@
+def func():
+ try:
+ module
+# <ref>
+ except:
+ pass
diff --git a/python/testData/addImport/localImportInlineBranch.after.py b/python/testData/addImport/localImportInlineBranch.after.py
new file mode 100644
index 000000000000..c7f7d3881feb
--- /dev/null
+++ b/python/testData/addImport/localImportInlineBranch.after.py
@@ -0,0 +1,6 @@
+def func():
+ if True:
+ import module
+
+ module
+# <ref> \ No newline at end of file
diff --git a/python/testData/addImport/localImportInlineBranch.py b/python/testData/addImport/localImportInlineBranch.py
new file mode 100644
index 000000000000..89d4935d17b3
--- /dev/null
+++ b/python/testData/addImport/localImportInlineBranch.py
@@ -0,0 +1,3 @@
+def func():
+ if True: module
+# <ref> \ No newline at end of file
diff --git a/python/testData/addImport/localImportInlineFunctionBody.after.py b/python/testData/addImport/localImportInlineFunctionBody.after.py
new file mode 100644
index 000000000000..13d2a1e60805
--- /dev/null
+++ b/python/testData/addImport/localImportInlineFunctionBody.after.py
@@ -0,0 +1,5 @@
+def func():
+ import module
+
+ module
+# <ref> \ No newline at end of file
diff --git a/python/testData/addImport/localImportInlineFunctionBody.py b/python/testData/addImport/localImportInlineFunctionBody.py
new file mode 100644
index 000000000000..b76c83016192
--- /dev/null
+++ b/python/testData/addImport/localImportInlineFunctionBody.py
@@ -0,0 +1,2 @@
+def func(): module
+# <ref> \ No newline at end of file
diff --git a/python/testData/completion/boundMethodSpecialAttributes.py b/python/testData/completion/boundMethodSpecialAttributes.py
new file mode 100644
index 000000000000..02afa569bfbe
--- /dev/null
+++ b/python/testData/completion/boundMethodSpecialAttributes.py
@@ -0,0 +1,5 @@
+class MyClass(object):
+ def method(self):
+ pass
+
+MyClass().method.__<caret> \ No newline at end of file
diff --git a/python/testData/completion/lambdaSpecialAttributes.py b/python/testData/completion/lambdaSpecialAttributes.py
new file mode 100644
index 000000000000..0b0465eb2aa6
--- /dev/null
+++ b/python/testData/completion/lambdaSpecialAttributes.py
@@ -0,0 +1 @@
+(lambda: 42).__<caret> \ No newline at end of file
diff --git a/python/testData/completion/reassignedMethodSpecialAttributes.py b/python/testData/completion/reassignedMethodSpecialAttributes.py
new file mode 100644
index 000000000000..faf25e0022c7
--- /dev/null
+++ b/python/testData/completion/reassignedMethodSpecialAttributes.py
@@ -0,0 +1,6 @@
+class MyClass(object):
+ def method(self):
+ pass
+
+m = MyClass().method
+m.__<caret> \ No newline at end of file
diff --git a/python/testData/completion/staticMethodSpecialAttributes.py b/python/testData/completion/staticMethodSpecialAttributes.py
new file mode 100644
index 000000000000..84b0e751af43
--- /dev/null
+++ b/python/testData/completion/staticMethodSpecialAttributes.py
@@ -0,0 +1,6 @@
+class MyClass(object):
+ @staticmethod
+ def method(self):
+ pass
+
+MyClass().method.__<caret> \ No newline at end of file
diff --git a/python/testData/completion/unboundMethodSpecialAttributes.py b/python/testData/completion/unboundMethodSpecialAttributes.py
new file mode 100644
index 000000000000..b7e9b520de42
--- /dev/null
+++ b/python/testData/completion/unboundMethodSpecialAttributes.py
@@ -0,0 +1,5 @@
+class MyClass(object):
+ def method(self):
+ pass
+
+MyClass.method.__<caret> \ No newline at end of file
diff --git a/python/testData/completion/weakQualifierBoundMethodAttributes.py b/python/testData/completion/weakQualifierBoundMethodAttributes.py
new file mode 100644
index 000000000000..2433cfbfa054
--- /dev/null
+++ b/python/testData/completion/weakQualifierBoundMethodAttributes.py
@@ -0,0 +1,10 @@
+class MyClass(object):
+ def method(self):
+ pass
+
+if True:
+ inst = MyClass()
+else:
+ inst = unresolved
+
+inst.method.__<caret> \ No newline at end of file
diff --git a/python/testData/debug/Adder-0.1.egg b/python/testData/debug/Adder-0.1.egg
new file mode 100644
index 000000000000..eb98b6af646a
--- /dev/null
+++ b/python/testData/debug/Adder-0.1.egg
Binary files differ
diff --git a/python/testData/debug/Test_Resume.py b/python/testData/debug/Test_Resume.py
new file mode 100644
index 000000000000..dcec51cd4d27
--- /dev/null
+++ b/python/testData/debug/Test_Resume.py
@@ -0,0 +1,8 @@
+def foo(x):
+ print(x)
+
+foo(1)
+foo(2)
+
+
+
diff --git a/python/testData/debug/__init__.py b/python/testData/debug/__init__.py
new file mode 100644
index 000000000000..595e3818d699
--- /dev/null
+++ b/python/testData/debug/__init__.py
@@ -0,0 +1 @@
+__author__ = 'traff'
diff --git a/python/testData/debug/pycharm-debug.egg b/python/testData/debug/pycharm-debug.egg
new file mode 100644
index 000000000000..5a17292609c2
--- /dev/null
+++ b/python/testData/debug/pycharm-debug.egg
Binary files differ
diff --git a/python/testData/debug/test1.py b/python/testData/debug/test1.py
new file mode 100644
index 000000000000..f65495913ff4
--- /dev/null
+++ b/python/testData/debug/test1.py
@@ -0,0 +1,5 @@
+i = 0
+while True:
+ print(i)
+ i = i + 1
+
diff --git a/python/testData/debug/test2.py b/python/testData/debug/test2.py
new file mode 100644
index 000000000000..246363a5f482
--- /dev/null
+++ b/python/testData/debug/test2.py
@@ -0,0 +1,8 @@
+def foo(x):
+ y = x + 2
+ print(y)
+
+z = 1
+foo(z)
+z += 1
+print(z)
diff --git a/python/testData/debug/test3.py b/python/testData/debug/test3.py
new file mode 100644
index 000000000000..6122a530c610
--- /dev/null
+++ b/python/testData/debug/test3.py
@@ -0,0 +1,26 @@
+class A:
+ def __init__(self, z):
+ self.z = z
+
+ def foo(self, x):
+ y = 2 * x + self.z
+ return 1 + y
+
+
+def zoo(x):
+ y = int((x - 2) / (x - 1))
+
+ return A(y)
+
+print(zoo(2).foo(2))
+
+try:
+ try:
+ print(zoo(1).foo(2)) #we got ZeroDivision here
+ finally:
+ print(zoo(0).foo(2))
+except:
+ pass
+
+a = zoo(-1)
+print(a.foo(2)) \ No newline at end of file
diff --git a/python/testData/debug/test4.py b/python/testData/debug/test4.py
new file mode 100644
index 000000000000..b8b7e91501f2
--- /dev/null
+++ b/python/testData/debug/test4.py
@@ -0,0 +1,5 @@
+xval = 0
+xvalue1 = 1
+xvalue2 = 2
+print(xvalue1 + xvalue2)
+
diff --git a/python/testData/debug/test_continuation.py b/python/testData/debug/test_continuation.py
new file mode 100644
index 000000000000..5957e3db6e82
--- /dev/null
+++ b/python/testData/debug/test_continuation.py
@@ -0,0 +1,16 @@
+class Boo:
+ def bu(self, y):
+ return 1 + y
+
+
+class Foo:
+ def fu(self):
+ return Boo()
+
+x = 0
+print(x)
+x = Foo().fu()\
+.bu(x)
+print(x)
+x=2
+print(x) \ No newline at end of file
diff --git a/python/testData/debug/test_continuation2.py b/python/testData/debug/test_continuation2.py
new file mode 100644
index 000000000000..3b0246db511c
--- /dev/null
+++ b/python/testData/debug/test_continuation2.py
@@ -0,0 +1,8 @@
+x = 0
+print(x)
+x = 1+\
+2+\
+3
+print(x)
+x=2
+print(x) \ No newline at end of file
diff --git a/python/testData/debug/test_egg.py b/python/testData/debug/test_egg.py
new file mode 100644
index 000000000000..82bec29efee8
--- /dev/null
+++ b/python/testData/debug/test_egg.py
@@ -0,0 +1,4 @@
+from adder import adder
+
+x = adder.add(7, 9)
+print(x) \ No newline at end of file
diff --git a/python/testData/debug/test_exceptbreak.py b/python/testData/debug/test_exceptbreak.py
new file mode 100644
index 000000000000..46b0ebcb22b5
--- /dev/null
+++ b/python/testData/debug/test_exceptbreak.py
@@ -0,0 +1,8 @@
+def foo(x):
+ return 1/x
+
+def zoo(x):
+ res = foo(x)
+ return res
+
+print(zoo(0))
diff --git a/python/testData/debug/test_input.py b/python/testData/debug/test_input.py
new file mode 100644
index 000000000000..5ac9bacbf418
--- /dev/null
+++ b/python/testData/debug/test_input.py
@@ -0,0 +1,7 @@
+while True:
+ promt = "print command > "
+ try:
+ string = raw_input(promt)
+ except :
+ string = input(promt)
+ print ("command was " + string) \ No newline at end of file
diff --git a/python/testData/debug/test_multiprocess.py b/python/testData/debug/test_multiprocess.py
new file mode 100644
index 000000000000..5fc6be4625d8
--- /dev/null
+++ b/python/testData/debug/test_multiprocess.py
@@ -0,0 +1,13 @@
+from concurrent.futures import ProcessPoolExecutor
+def my_foo(arg_):
+ return arg_
+
+def main():
+ arg = ['Result:OK']
+ with ProcessPoolExecutor(1) as exec:
+ result = exec.map(my_foo, arg)
+ for i in result:
+ print(i)
+
+if __name__ == '__main__':
+ main() \ No newline at end of file
diff --git a/python/testData/debug/test_multithread.py b/python/testData/debug/test_multithread.py
new file mode 100644
index 000000000000..03c0811ded8b
--- /dev/null
+++ b/python/testData/debug/test_multithread.py
@@ -0,0 +1,24 @@
+try:
+ import thread
+except :
+ import _thread as thread
+
+import threading
+
+def bar(y):
+ z = 100 + y
+ print("Z=%d"%z)
+
+def foo(x):
+ y = x + 1
+ print("Y=%d"%y)
+
+ t = threading.Thread(target=bar, args=(y,))
+ t.start()
+
+
+id = thread.start_new_thread(foo, (1,))
+
+while True:
+ pass
+
diff --git a/python/testData/debug/test_remote.py b/python/testData/debug/test_remote.py
new file mode 100644
index 000000000000..8bccbeb44c4f
--- /dev/null
+++ b/python/testData/debug/test_remote.py
@@ -0,0 +1,19 @@
+import sys
+
+if __name__ == '__main__':
+ if len(sys.argv) < 2:
+ sys.stderr.write("Not enough arguments")
+ sys.exit(1)
+
+ port = int(sys.argv[1])
+
+ x = 0
+
+ from pydev import pydevd
+ pydevd.settrace('localhost', port=port, stdoutToServer=True, stderrToServer=True)
+
+ x = 1
+ x = 2
+ x = 3
+
+ print("OK")
diff --git a/python/testData/debug/test_runtoline.py b/python/testData/debug/test_runtoline.py
new file mode 100644
index 000000000000..804c56c4dcb4
--- /dev/null
+++ b/python/testData/debug/test_runtoline.py
@@ -0,0 +1,8 @@
+x = 0
+print(x)
+while x<2:
+ x+=1
+ print(x)
+
+x+=10
+print("x = %d" % x) \ No newline at end of file
diff --git a/python/testData/debug/test_stepOverCondition.py b/python/testData/debug/test_stepOverCondition.py
new file mode 100644
index 000000000000..1b41c605af36
--- /dev/null
+++ b/python/testData/debug/test_stepOverCondition.py
@@ -0,0 +1,4 @@
+x = 1
+y = 2
+y = x + y
+print(y) \ No newline at end of file
diff --git a/python/testData/debug/zipped_lib.zip b/python/testData/debug/zipped_lib.zip
new file mode 100644
index 000000000000..fe2ac045d579
--- /dev/null
+++ b/python/testData/debug/zipped_lib.zip
Binary files differ
diff --git a/python/testData/dotNet/PythonLibs.dll b/python/testData/dotNet/PythonLibs.dll
new file mode 100644
index 000000000000..cfdfa746d3a8
--- /dev/null
+++ b/python/testData/dotNet/PythonLibs.dll
Binary files differ
diff --git a/python/testData/dotNet/SingleNameSpace.dll b/python/testData/dotNet/SingleNameSpace.dll
new file mode 100644
index 000000000000..da6dacb065f6
--- /dev/null
+++ b/python/testData/dotNet/SingleNameSpace.dll
Binary files differ
diff --git a/python/testData/dotNet/__init__.py b/python/testData/dotNet/__init__.py
new file mode 100644
index 000000000000..595e3818d699
--- /dev/null
+++ b/python/testData/dotNet/__init__.py
@@ -0,0 +1 @@
+__author__ = 'traff'
diff --git a/python/testData/dotNet/expected.skeleton.Deep.py b/python/testData/dotNet/expected.skeleton.Deep.py
new file mode 100644
index 000000000000..52abbf6354d4
--- /dev/null
+++ b/python/testData/dotNet/expected.skeleton.Deep.py
@@ -0,0 +1,17 @@
+# encoding: utf-8
+# module SingleNameSpace.Some.Deep calls itself Deep
+# from SingleNameSpace, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
+# by generator 1.135
+# no doc
+# no imports
+
+# no functions
+# classes
+
+from object import object
+
+class WeHaveClass(object):
+ """ WeHaveClass() """
+ MyClass = None
+
+
diff --git a/python/testData/dotNet/expected.skeleton.SingleNameSpace.py b/python/testData/dotNet/expected.skeleton.SingleNameSpace.py
new file mode 100644
index 000000000000..b2048fd39e63
--- /dev/null
+++ b/python/testData/dotNet/expected.skeleton.SingleNameSpace.py
@@ -0,0 +1,22 @@
+# encoding: utf-8
+# module SingleNameSpace
+# from SingleNameSpace, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
+# by generator 1.135
+# no doc
+# no imports
+
+# no functions
+# classes
+
+from object import object
+
+class AnotherClass(object):
+ """ AnotherClass() """
+
+from object import object
+
+class MyClass(object):
+ """ MyClass() """
+
+# variables with complex values
+
diff --git a/python/testData/dotNet/expected.skeleton.java.py b/python/testData/dotNet/expected.skeleton.java.py
new file mode 100644
index 000000000000..1ba6b3a3825a
--- /dev/null
+++ b/python/testData/dotNet/expected.skeleton.java.py
@@ -0,0 +1,24 @@
+# encoding: utf-8
+# module com.just.like.java calls itself java
+# from PythonLibs, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
+# by generator 1.135
+# no doc
+# no imports
+
+# no functions
+# classes
+
+from object import object
+
+class LikeJavaClass(object):
+ """ LikeJavaClass() """
+ def likeJavaInstanceMethod(self, i):
+ """ likeJavaInstanceMethod(self: LikeJavaClass, i: int) -> int """
+ pass
+
+ @staticmethod
+ def likeJavaStaticMethod(i):
+ """ likeJavaStaticMethod(i: int) """
+ pass
+
+
diff --git a/python/testData/dotNet/import_class_from_module.py b/python/testData/dotNet/import_class_from_module.py
new file mode 100644
index 000000000000..bf36d0e586d7
--- /dev/null
+++ b/python/testData/dotNet/import_class_from_module.py
@@ -0,0 +1,6 @@
+import clr
+
+clr.AddReferenceByPartialName("PythonLibs")
+
+from c<caret>om.just.like.java import LikeJavaClass
+print LikeJavaClass \ No newline at end of file
diff --git a/python/testData/dotNet/import_class_from_module_alias.py b/python/testData/dotNet/import_class_from_module_alias.py
new file mode 100644
index 000000000000..92d82f81abaa
--- /dev/null
+++ b/python/testData/dotNet/import_class_from_module_alias.py
@@ -0,0 +1,6 @@
+import clr
+
+clr.AddReferenceByPartialName("PythonLibs")
+
+from c<caret>om.just.like.java import LikeJavaClass as MyClass
+print MyClass \ No newline at end of file
diff --git a/python/testData/dotNet/import_module_from_package.py b/python/testData/dotNet/import_module_from_package.py
new file mode 100644
index 000000000000..c31e92e05cc0
--- /dev/null
+++ b/python/testData/dotNet/import_module_from_package.py
@@ -0,0 +1,7 @@
+import clr
+
+clr.AddReferenceByPartialName("PythonLibs")
+
+
+from c<caret>om.just.like import java
+print java.LikeJavaClass \ No newline at end of file
diff --git a/python/testData/dotNet/import_several_classes_from_module.py b/python/testData/dotNet/import_several_classes_from_module.py
new file mode 100644
index 000000000000..08ab814b3238
--- /dev/null
+++ b/python/testData/dotNet/import_several_classes_from_module.py
@@ -0,0 +1,7 @@
+import clr
+
+clr.AddReferenceByPartialName("PythonLibs")
+
+from c<caret>om.just.like.java import LikeJavaClass
+
+print LikeJavaClass \ No newline at end of file
diff --git a/python/testData/dotNet/import_system.py b/python/testData/dotNet/import_system.py
new file mode 100644
index 000000000000..dbfc1feaa33d
--- /dev/null
+++ b/python/testData/dotNet/import_system.py
@@ -0,0 +1,2 @@
+from S<caret>ystem.Web import AspNetHostingPermission
+print AspNetHostingPermission \ No newline at end of file
diff --git a/python/testData/dotNet/inner_class.py b/python/testData/dotNet/inner_class.py
new file mode 100644
index 000000000000..9a22cf5af3cd
--- /dev/null
+++ b/python/testData/dotNet/inner_class.py
@@ -0,0 +1,6 @@
+import clr
+
+clr.AddReferenceByPartialName("SingleNameSpace")
+
+from <caret>SingleNameSpace.Some.Deep.WeHaveClass import MyClass
+print MyClass \ No newline at end of file
diff --git a/python/testData/dotNet/single_class.py b/python/testData/dotNet/single_class.py
new file mode 100644
index 000000000000..679e9471fe37
--- /dev/null
+++ b/python/testData/dotNet/single_class.py
@@ -0,0 +1,6 @@
+import clr
+
+clr.AddReferenceByPartialName("SingleNameSpace")
+
+from S<caret>ingleNameSpace import MyClass
+print MyClass \ No newline at end of file
diff --git a/python/testData/dotNet/testSkeleton.py b/python/testData/dotNet/testSkeleton.py
new file mode 100644
index 000000000000..c501ddff7a56
--- /dev/null
+++ b/python/testData/dotNet/testSkeleton.py
@@ -0,0 +1,6 @@
+import clr
+
+clr.AddReferenceByPartialName("PythonLibs")
+import <caret>com.just.like.java
+
+com.just.like.java.LikeJavaClass.likeJavaStaticMethod(1)
diff --git a/python/testData/dotNet/whole_namespace.py b/python/testData/dotNet/whole_namespace.py
new file mode 100644
index 000000000000..b07fa0e7c1e3
--- /dev/null
+++ b/python/testData/dotNet/whole_namespace.py
@@ -0,0 +1,6 @@
+import clr
+
+clr.AddReferenceByPartialName("SingleNameSpace")
+
+<caret>ingleNameSpace
+print SingleNameSpace.MyClass \ No newline at end of file
diff --git a/python/testData/inspections/PyStringFormatInspection/expected.xml b/python/testData/inspections/PyStringFormatInspection/expected.xml
index 62301ce56510..25e70285bd8d 100644
--- a/python/testData/inspections/PyStringFormatInspection/expected.xml
+++ b/python/testData/inspections/PyStringFormatInspection/expected.xml
@@ -160,4 +160,20 @@
<line>99</line>
<description>Too few arguments for format string</description>
</problem>
+ <problem>
+ <file>string-format.py</file>
+ <line>103</line>
+ <description>Unexpected type</description>
+ </problem>
+ <problem>
+ <file>string-format.py</file>
+ <line>104</line>
+ <description>Too few arguments for format string</description>
+ </problem>
+ <problem>
+ <file>string-format.py</file>
+ <line>105</line>
+ <description>Too many arguments for format string</description>
+ </problem>
+
</problems>
diff --git a/python/testData/inspections/PyStringFormatInspection/src/string-format.py b/python/testData/inspections/PyStringFormatInspection/src/string-format.py
index e60e4bb90911..972aaed6423a 100644
--- a/python/testData/inspections/PyStringFormatInspection/src/string-format.py
+++ b/python/testData/inspections/PyStringFormatInspection/src/string-format.py
@@ -96,4 +96,26 @@ print '%d' % string[:2]
my_tuple = (1,2,3,4,5,6,7,8)
print '%d, %d' % my_tuple[:7:3]
print '%d, %d, %d' % my_tuple[:7:3]
-print '%d, %d, %d, %d' % my_tuple[:7:3] \ No newline at end of file
+print '%d, %d, %d, %d' % my_tuple[:7:3]
+
+# PY-12801
+print '%d %s' % ((42,) + ('spam',))
+print '%d %s' % (('ham',) + ('spam',))
+print '%d %s' % ((42,) + ())
+print '%d' % ((42,) + ('spam',))
+
+# PY-11274
+import collections
+print '%(foo)s' % collections.OrderedDict(foo=None)
+
+class MyDict(collections.Mapping):
+ def __getitem__(self, key):
+ return 'spam'
+
+ def __iter__(self):
+ yield 'spam'
+
+ def __len__(self):
+ return 1
+
+print '%(foo)s' % MyDict()
diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/methodSpecialAttributes.py b/python/testData/inspections/PyUnresolvedReferencesInspection/methodSpecialAttributes.py
new file mode 100644
index 000000000000..7a60e533a15d
--- /dev/null
+++ b/python/testData/inspections/PyUnresolvedReferencesInspection/methodSpecialAttributes.py
@@ -0,0 +1,25 @@
+class MyClass(object):
+ def method(self):
+ pass
+
+ @staticmethod
+ def static_method():
+ pass
+
+
+# Unbound method still treated as __method in Python 2
+MyClass.method.__func__
+MyClass.method.<warning descr="Cannot find reference '__defaults__' in 'function'">__defaults__</warning>
+
+# Bound method with qualifier
+inst = MyClass()
+inst.method.__func__
+inst.method.<warning descr="Cannot find reference '__defaults__' in 'function'">__defaults__</warning>
+
+# Reassigned bound method without qualifier
+m = inst.method
+
+# Static method
+# This reference should be marked as unresolved, but such warnings are suppressed for methods with decorators
+inst.static_method.__func__
+inst.static_method.__defaults__
diff --git a/python/testData/refactoring/introduceConstant/fromParameterDefaultValue.after.py b/python/testData/refactoring/introduceConstant/fromParameterDefaultValue.after.py
new file mode 100644
index 000000000000..3f7191e54968
--- /dev/null
+++ b/python/testData/refactoring/introduceConstant/fromParameterDefaultValue.after.py
@@ -0,0 +1,5 @@
+a = 1 + 2
+
+
+def func(x=a + 3):
+ pass \ No newline at end of file
diff --git a/python/testData/refactoring/introduceConstant/fromParameterDefaultValue.py b/python/testData/refactoring/introduceConstant/fromParameterDefaultValue.py
new file mode 100644
index 000000000000..507a2df4f623
--- /dev/null
+++ b/python/testData/refactoring/introduceConstant/fromParameterDefaultValue.py
@@ -0,0 +1,2 @@
+def func(x=<selection>1 + 2</selection> + 3):
+ pass \ No newline at end of file
diff --git a/python/testData/refactoring/introduceVariable/selectionBreaksBinaryOperator.after.py b/python/testData/refactoring/introduceVariable/selectionBreaksBinaryOperator.after.py
new file mode 100644
index 000000000000..775927cedb39
--- /dev/null
+++ b/python/testData/refactoring/introduceVariable/selectionBreaksBinaryOperator.after.py
@@ -0,0 +1,3 @@
+def foo():
+ a = 2 + 3
+ print 1 + a \ No newline at end of file
diff --git a/python/testData/refactoring/introduceVariable/selectionBreaksBinaryOperator.py b/python/testData/refactoring/introduceVariable/selectionBreaksBinaryOperator.py
new file mode 100644
index 000000000000..c5eee8c9a423
--- /dev/null
+++ b/python/testData/refactoring/introduceVariable/selectionBreaksBinaryOperator.py
@@ -0,0 +1,2 @@
+def foo():
+ print 1 + <selection>2 + 3</selection> \ No newline at end of file
diff --git a/python/testData/testRunner/__init__.py b/python/testData/testRunner/__init__.py
new file mode 100644
index 000000000000..595e3818d699
--- /dev/null
+++ b/python/testData/testRunner/__init__.py
@@ -0,0 +1 @@
+__author__ = 'traff'
diff --git a/python/testData/testRunner/env/__init__.py b/python/testData/testRunner/env/__init__.py
new file mode 100644
index 000000000000..595e3818d699
--- /dev/null
+++ b/python/testData/testRunner/env/__init__.py
@@ -0,0 +1 @@
+__author__ = 'traff'
diff --git a/python/testData/testRunner/env/doc/__init__.py b/python/testData/testRunner/env/doc/__init__.py
new file mode 100644
index 000000000000..595e3818d699
--- /dev/null
+++ b/python/testData/testRunner/env/doc/__init__.py
@@ -0,0 +1 @@
+__author__ = 'traff'
diff --git a/python/testData/testRunner/env/doc/test1.py b/python/testData/testRunner/env/doc/test1.py
new file mode 100644
index 000000000000..3fd0252bdd55
--- /dev/null
+++ b/python/testData/testRunner/env/doc/test1.py
@@ -0,0 +1,39 @@
+def factorial(n):
+ """Return the factorial of n, an exact integer >= 0.
+
+ If the result is small enough to fit in an int, return an int.
+ Else return a long.
+
+ >>> [factorial(n) for n in range(6)]
+ [1, 1, 2, 6, 24, 120]
+ """
+
+ import math
+ if not n >= 0:
+ raise ValueError("n must be >= 0")
+ if math.floor(n) != n:
+ raise ValueError("n must be exact integer")
+ if n+1 == n: # catch a value like 1e300
+ raise OverflowError("n too large")
+ result = 1
+ factor = 2
+ while factor <= n:
+ result *= factor
+ factor += 1
+ return result
+
+class FirstGoodTest:
+ """
+ >>> [factorial(n) for n in range(6)]
+ [1, 1, 2, 6, 24, 120]
+ """
+ def test_passes(self):
+ pass
+
+class SecondGoodTest:
+ def test_passes(self):
+ """
+ >>> [factorial(n) for n in range(6)]
+ [1, 1, 2, 6, 24, 120]
+ """
+ pass \ No newline at end of file
diff --git a/python/testData/testRunner/env/doc/test2.py b/python/testData/testRunner/env/doc/test2.py
new file mode 100644
index 000000000000..e0c4619a94f6
--- /dev/null
+++ b/python/testData/testRunner/env/doc/test2.py
@@ -0,0 +1,39 @@
+def factorial(n):
+ """Return the factorial of n, an exact integer >= 0.
+
+ If the result is small enough to fit in an int, return an int.
+ Else return a long.
+
+ >>> [factorial(n) for n in range(6)]
+ [1, 1, 2, 6, 24, 120]
+ """
+
+ import math
+ if not n >= 0:
+ raise ValueError("n must be >= 0")
+ if math.floor(n) != n:
+ raise ValueError("n must be exact integer")
+ if n+1 == n: # catch a value like 1e300
+ raise OverflowError("n too large")
+ result = 1
+ factor = 2
+ while factor <= n:
+ result *= factor
+ factor += 1
+ return result
+
+class FirstGoodTest:
+ """
+ >>> [factorial(n) for n in range(6)]
+ [1, 1]
+ """
+ def test_passes(self):
+ pass
+
+class SecondGoodTest:
+ def test_passes(self):
+ """
+ >>> [factorial(n) for n in range(6)]
+ [1, 1, 2, 6]
+ """
+ pass \ No newline at end of file
diff --git a/python/testData/testRunner/env/nose/__init__.py b/python/testData/testRunner/env/nose/__init__.py
new file mode 100644
index 000000000000..595e3818d699
--- /dev/null
+++ b/python/testData/testRunner/env/nose/__init__.py
@@ -0,0 +1 @@
+__author__ = 'traff'
diff --git a/python/testData/testRunner/env/nose/test1.py b/python/testData/testRunner/env/nose/test1.py
new file mode 100644
index 000000000000..972270f800a2
--- /dev/null
+++ b/python/testData/testRunner/env/nose/test1.py
@@ -0,0 +1,11 @@
+#from unittest import TestCase
+
+class TestNose:
+ def testOne(self):
+ assert 4 == 2*2
+
+ def testTwo(self):
+ assert True
+
+def testThree():
+ assert 4 == 2*2
diff --git a/python/testData/testRunner/env/nose/test2.py b/python/testData/testRunner/env/nose/test2.py
new file mode 100644
index 000000000000..0a6f80ec7644
--- /dev/null
+++ b/python/testData/testRunner/env/nose/test2.py
@@ -0,0 +1,18 @@
+#from unittest import TestCase
+
+class TestNose:
+ def testOne(self):
+ assert 5 == 2*2
+
+ def testTwo(self):
+ assert True
+
+def testThree():
+ assert 4 == 2*2
+
+def test_evens():
+ for i in range(0, 5):
+ yield check_even, i, i*3
+
+def check_even(n, nn):
+ assert n % 2 == 0 or nn % 2 == 0 \ No newline at end of file
diff --git a/python/testData/testRunner/env/pytest/__init__.py b/python/testData/testRunner/env/pytest/__init__.py
new file mode 100644
index 000000000000..595e3818d699
--- /dev/null
+++ b/python/testData/testRunner/env/pytest/__init__.py
@@ -0,0 +1 @@
+__author__ = 'traff'
diff --git a/python/testData/testRunner/env/pytest/test1.py b/python/testData/testRunner/env/pytest/test1.py
new file mode 100644
index 000000000000..65016345eade
--- /dev/null
+++ b/python/testData/testRunner/env/pytest/test1.py
@@ -0,0 +1,9 @@
+class TestPyTest:
+ def testOne(self):
+ assert 4 == 2*2
+
+ def testTwo(self):
+ assert True
+
+def testThree():
+ assert 4 == 2*2
diff --git a/python/testData/testRunner/env/pytest/test2.py b/python/testData/testRunner/env/pytest/test2.py
new file mode 100644
index 000000000000..b6c7b0887aa9
--- /dev/null
+++ b/python/testData/testRunner/env/pytest/test2.py
@@ -0,0 +1,16 @@
+class TestPyTest:
+ def testOne(self):
+ assert 5 == 2*2
+
+ def testTwo(self):
+ assert True
+
+def testThree():
+ assert 4 == 2*2
+
+def test_evens():
+ for i in range(0, 5):
+ yield check_even, i, i*3
+
+def check_even(n, nn):
+ assert n % 2 == 0 or nn % 2 == 0 \ No newline at end of file
diff --git a/python/testData/testRunner/env/unit/__init__.py b/python/testData/testRunner/env/unit/__init__.py
new file mode 100644
index 000000000000..7c7597a4f4fb
--- /dev/null
+++ b/python/testData/testRunner/env/unit/__init__.py
@@ -0,0 +1 @@
+__author__ = 'ktisha'
diff --git a/python/testData/testRunner/env/unit/dependentTests/__init__.py b/python/testData/testRunner/env/unit/dependentTests/__init__.py
new file mode 100644
index 000000000000..595e3818d699
--- /dev/null
+++ b/python/testData/testRunner/env/unit/dependentTests/__init__.py
@@ -0,0 +1 @@
+__author__ = 'traff'
diff --git a/python/testData/testRunner/env/unit/dependentTests/test_my_class.py b/python/testData/testRunner/env/unit/dependentTests/test_my_class.py
new file mode 100644
index 000000000000..8c6a68e2b69e
--- /dev/null
+++ b/python/testData/testRunner/env/unit/dependentTests/test_my_class.py
@@ -0,0 +1,7 @@
+import unittest
+from testedCode.my_class import *
+
+class MyClassTest(unittest.TestCase):
+ def test_foo(self):
+ c = MyClass()
+ self.assertEquals("bar", c.foo())
diff --git a/python/testData/testRunner/env/unit/dependentTests/testedCode/__init__.py b/python/testData/testRunner/env/unit/dependentTests/testedCode/__init__.py
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/python/testData/testRunner/env/unit/dependentTests/testedCode/__init__.py
diff --git a/python/testData/testRunner/env/unit/dependentTests/testedCode/my_class.py b/python/testData/testRunner/env/unit/dependentTests/testedCode/my_class.py
new file mode 100644
index 000000000000..fbf4632343b7
--- /dev/null
+++ b/python/testData/testRunner/env/unit/dependentTests/testedCode/my_class.py
@@ -0,0 +1,4 @@
+class MyClass:
+ def foo(self):
+ return "bar"
+ \ No newline at end of file
diff --git a/python/testData/testRunner/env/unit/subfolder/__init__.py b/python/testData/testRunner/env/unit/subfolder/__init__.py
new file mode 100644
index 000000000000..595e3818d699
--- /dev/null
+++ b/python/testData/testRunner/env/unit/subfolder/__init__.py
@@ -0,0 +1 @@
+__author__ = 'traff'
diff --git a/python/testData/testRunner/env/unit/subfolder/test2.py b/python/testData/testRunner/env/unit/subfolder/test2.py
new file mode 100644
index 000000000000..b2c21b21d674
--- /dev/null
+++ b/python/testData/testRunner/env/unit/subfolder/test2.py
@@ -0,0 +1,7 @@
+import unittest
+
+class SubTest(unittest.TestCase):
+ def test_in_subfolder(self):
+ self.assertEquals("foo", "fo" + "o")
+
+ \ No newline at end of file
diff --git a/python/testData/testRunner/env/unit/test1.py b/python/testData/testRunner/env/unit/test1.py
new file mode 100644
index 000000000000..8b2daad79ca8
--- /dev/null
+++ b/python/testData/testRunner/env/unit/test1.py
@@ -0,0 +1,8 @@
+from unittest import TestCase
+
+class UTests(TestCase):
+ def testOne(self):
+ self.assertEqual(4, 2*2)
+
+ def testTwo(self):
+ self.assertTrue(False or True)
diff --git a/python/testData/testRunner/env/unit/test2.py b/python/testData/testRunner/env/unit/test2.py
new file mode 100644
index 000000000000..c8195292d31a
--- /dev/null
+++ b/python/testData/testRunner/env/unit/test2.py
@@ -0,0 +1,11 @@
+from unittest import TestCase
+
+class UTests(TestCase):
+ def testOne(self):
+ self.assertEqual(5, 2*2)
+
+ def testTwo(self):
+ self.assertTrue(False)
+
+ def testThree(self):
+ self.assertTrue(True)
diff --git a/python/testData/testRunner/env/unit/test_file.py b/python/testData/testRunner/env/unit/test_file.py
new file mode 100644
index 000000000000..9b2ed1629eb4
--- /dev/null
+++ b/python/testData/testRunner/env/unit/test_file.py
@@ -0,0 +1,12 @@
+import unittest
+
+class GoodTest(unittest.TestCase):
+ def test_passes(self):
+ self.assertEqual(2+2, 4)
+
+class BadTest(unittest.TestCase):
+ def test_fails(self):
+ self.assertEqual(2+2, 5)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/python/testData/testRunner/env/unit/test_folder/__init__.py b/python/testData/testRunner/env/unit/test_folder/__init__.py
new file mode 100644
index 000000000000..7c7597a4f4fb
--- /dev/null
+++ b/python/testData/testRunner/env/unit/test_folder/__init__.py
@@ -0,0 +1 @@
+__author__ = 'ktisha'
diff --git a/python/testData/testRunner/env/unit/test_folder/test1.py b/python/testData/testRunner/env/unit/test_folder/test1.py
new file mode 100644
index 000000000000..8b2daad79ca8
--- /dev/null
+++ b/python/testData/testRunner/env/unit/test_folder/test1.py
@@ -0,0 +1,8 @@
+from unittest import TestCase
+
+class UTests(TestCase):
+ def testOne(self):
+ self.assertEqual(4, 2*2)
+
+ def testTwo(self):
+ self.assertTrue(False or True)
diff --git a/python/testData/testRunner/env/unit/test_folder/test2.py b/python/testData/testRunner/env/unit/test_folder/test2.py
new file mode 100644
index 000000000000..c8195292d31a
--- /dev/null
+++ b/python/testData/testRunner/env/unit/test_folder/test2.py
@@ -0,0 +1,11 @@
+from unittest import TestCase
+
+class UTests(TestCase):
+ def testOne(self):
+ self.assertEqual(5, 2*2)
+
+ def testTwo(self):
+ self.assertTrue(False)
+
+ def testThree(self):
+ self.assertTrue(True)
diff --git a/python/testSrc/com/jetbrains/env/PyEnvSufficiencyTest.java b/python/testSrc/com/jetbrains/env/PyEnvSufficiencyTest.java
new file mode 100644
index 000000000000..83846a1bb5f5
--- /dev/null
+++ b/python/testSrc/com/jetbrains/env/PyEnvSufficiencyTest.java
@@ -0,0 +1,51 @@
+package com.jetbrains.env;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.testFramework.UsefulTestCase;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author traff
+ */
+public class PyEnvSufficiencyTest extends PyEnvTestCase {
+ private static final List<String> BASE_TAGS =
+ ImmutableList.<String>builder().add("python3", "django", "jython", "ipython", "ipython011", "ipython012", "nose", "pytest").build();
+
+ public void testSufficiency() {
+ if (UsefulTestCase.IS_UNDER_TEAMCITY && IS_ENV_CONFIGURATION) {
+ Set<String> tags = Sets.newHashSet();
+ List<String> roots = getPythonRoots();
+ if (roots.size() == 0) {
+ return; // not on env agent
+ }
+ for (String root : roots) {
+ tags.addAll(loadEnvTags(root));
+ }
+
+ List<String> missing = Lists.newArrayList();
+ for (String tag : necessaryTags()) {
+ if (!tags.contains(tag)) {
+ missing.add(tag);
+ }
+ }
+
+
+ assertEmpty("Agent is missing environments: " + StringUtil.join(missing, ", "), missing);
+ }
+ }
+
+ private static List<String> necessaryTags() {
+ if (SystemInfo.isWindows) {
+ return ImmutableList.<String>builder().addAll(BASE_TAGS).add("iron").build();
+ }
+ else {
+ return ImmutableList.<String>builder().addAll(BASE_TAGS).add("packaging").build();
+ }
+ }
+}
diff --git a/python/testSrc/com/jetbrains/env/PyEnvTaskRunner.java b/python/testSrc/com/jetbrains/env/PyEnvTaskRunner.java
new file mode 100644
index 000000000000..baabd5a5e5e1
--- /dev/null
+++ b/python/testSrc/com/jetbrains/env/PyEnvTaskRunner.java
@@ -0,0 +1,112 @@
+package com.jetbrains.env;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import com.jetbrains.python.sdk.PythonSdkType;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author traff
+ */
+public class PyEnvTaskRunner {
+ private final List<String> myRoots;
+
+ public PyEnvTaskRunner(List<String> roots) {
+ myRoots = roots;
+ }
+
+ public void runTask(PyTestTask testTask, String testName) {
+ boolean wasExecuted = false;
+
+ List<String> passedRoots = Lists.newArrayList();
+
+ for (String root : myRoots) {
+
+ if (!isSuitableForTask(PyEnvTestCase.loadEnvTags(root), testTask) || !shouldRun(root, testTask)) {
+ continue;
+ }
+
+ try {
+ testTask.setUp(testName);
+ wasExecuted = true;
+ if (isJython(root)) {
+ testTask.useLongTimeout();
+ }
+ else {
+ testTask.useNormalTimeout();
+ }
+ final String executable = getExecutable(root, testTask);
+ if (executable == null) {
+ throw new RuntimeException("Cannot find Python interpreter in " + root);
+ }
+ testTask.runTestOn(executable);
+ passedRoots.add(root);
+ }
+ catch (Throwable e) {
+ throw new RuntimeException(
+ PyEnvTestCase.joinStrings(passedRoots, "Tests passed environments: ") + "Test failed on " + getEnvType() + " environment " + root,
+ e);
+ }
+ finally {
+ try {
+ testTask.tearDown();
+ }
+ catch (Exception e) {
+ throw new RuntimeException("Couldn't tear down task", e);
+ }
+ }
+ }
+
+ if (!wasExecuted) {
+ throw new RuntimeException("test" +
+ testName +
+ " was not executed.\n" +
+ PyEnvTestCase.joinStrings(myRoots, "All roots: ") +
+ "\n" +
+ PyEnvTestCase.joinStrings(testTask.getTags(), "Required tags in tags.txt in root: "));
+ }
+ }
+
+ protected boolean shouldRun(String root, PyTestTask task) {
+ return true;
+ }
+
+ protected String getExecutable(String root, PyTestTask testTask) {
+ return PythonSdkType.getPythonExecutable(root);
+ }
+
+ protected String getEnvType() {
+ return "local";
+ }
+
+ private static boolean isSuitableForTask(List<String> tags, PyTestTask task) {
+ return isSuitableForTags(tags, task.getTags());
+ }
+
+ public static boolean isSuitableForTags(List<String> envTags, Set<String> taskTags) {
+ Set<String> necessaryTags = Sets.newHashSet(taskTags);
+
+ for (String tag : envTags) {
+ necessaryTags.remove(tag.trim());
+ }
+
+ for (String tag : taskTags) {
+ if (tag.startsWith("-")) { //do not run on envs with that tag
+ if (envTags.contains(tag.substring(1))) {
+ return false;
+ }
+ necessaryTags.remove(tag);
+ }
+ }
+
+ return necessaryTags.isEmpty();
+ }
+
+
+ protected static boolean isJython(@NotNull String sdkHome) {
+ return sdkHome.toLowerCase().contains("jython");
+ }
+}
diff --git a/python/testSrc/com/jetbrains/env/PyEnvTestCase.java b/python/testSrc/com/jetbrains/env/PyEnvTestCase.java
new file mode 100644
index 000000000000..853a5504de63
--- /dev/null
+++ b/python/testSrc/com/jetbrains/env/PyEnvTestCase.java
@@ -0,0 +1,201 @@
+package com.jetbrains.env;
+
+import com.google.common.collect.Lists;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.testFramework.UsefulTestCase;
+import com.intellij.util.SystemProperties;
+import com.intellij.util.ui.UIUtil;
+import com.jetbrains.python.fixtures.PyTestCase;
+import org.hamcrest.Matchers;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.junit.Assume;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+
+/**
+ * @author traff
+ */
+public abstract class PyEnvTestCase extends UsefulTestCase {
+ private static final Logger LOG = Logger.getInstance(PyEnvTestCase.class.getName());
+
+ private static final String TAGS_FILE = "tags.txt";
+ private static final String PYCHARM_PYTHON_ENVS = "PYCHARM_PYTHON_ENVS";
+ private static final String PYCHARM_PYTHON_VIRTUAL_ENVS = "PYCHARM_PYTHON_VIRTUAL_ENVS";
+
+ protected static final boolean IS_ENV_CONFIGURATION = System.getProperty("pycharm.env") != null;
+
+
+ public static final boolean RUN_REMOTE = SystemProperties.getBooleanProperty("pycharm.run_remote", false);
+
+ public static final boolean RUN_LOCAL = SystemProperties.getBooleanProperty("pycharm.run_local", true);
+
+ /**
+ * Tags that should exist between all tags, available on all interpreters for test to run.
+ * See {@link #PyEnvTestCase(String...)}
+ */
+ @Nullable
+ private final String[] myRequiredTags;
+
+ /**
+ * @param requiredTags tags that should exist on some interpreter for this test to run.
+ * if some of these tags do not exist on any interpreter, all test methods would be skipped using
+ * {@link org.junit.Assume}.
+ * See <a href="http://junit.sourceforge.net/javadoc/org/junit/Assume.html">Assume manual</a>.
+ * Check [IDEA-122939] and [TW-25043] as well.
+ */
+ @SuppressWarnings("JUnitTestCaseWithNonTrivialConstructors")
+ protected PyEnvTestCase(@NotNull final String... requiredTags) {
+ myRequiredTags = requiredTags.length > 0 ? requiredTags.clone() : null;
+
+ PyTestCase.initPlatformPrefix();
+ }
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ if (myRequiredTags != null) { // Ensure all tags exist between available interpreters
+ Assume.assumeThat(
+ "Can't find some tags between all available interpreter, test (all methods) will be skipped",
+ getAvailableTags(),
+ Matchers.hasItems(myRequiredTags)
+ );
+ }
+ }
+
+ /**
+ * @return all tags available between all interpreters
+ */
+ @NotNull
+ private static Collection<String> getAvailableTags() {
+ final Collection<String> allAvailableTags = new HashSet<String>();
+ for (final String pythonRoot : getPythonRoots()) {
+ allAvailableTags.addAll(loadEnvTags(pythonRoot));
+ }
+ return allAvailableTags;
+ }
+
+ @Override
+ protected void invokeTestRunnable(@NotNull final Runnable runnable) throws Exception {
+ if (runInWriteAction()) {
+ UIUtil.invokeAndWaitIfNeeded(new Runnable() {
+ public void run() {
+ ApplicationManager.getApplication().runWriteAction(runnable);
+ }
+ });
+ }
+ else {
+ runnable.run();
+ }
+ }
+
+ @Override
+ protected boolean runInDispatchThread() {
+ return false;
+ }
+
+ protected boolean runInWriteAction() {
+ return false;
+ }
+
+ public void runPythonTest(final PyTestTask testTask) {
+ runTest(testTask, getTestName(false));
+ }
+
+ public void runTest(@NotNull PyTestTask testTask, @NotNull String testName) {
+ if (notEnvConfiguration()) {
+ fail("Running under teamcity but not by Env configuration. Skipping.");
+ return;
+ }
+
+ List<String> roots = getPythonRoots();
+
+ if (roots.size() == 0) {
+ String msg = testName +
+ ": environments are not defined. Skipping. \nSpecify either " +
+ PYCHARM_PYTHON_ENVS +
+ " or " +
+ PYCHARM_PYTHON_VIRTUAL_ENVS +
+ " environment variable.";
+ LOG.warn(msg);
+ System.out.println(msg);
+ return;
+ }
+
+ doRunTests(testTask, testName, roots);
+ }
+
+ protected void doRunTests(PyTestTask testTask, String testName, List<String> roots) {
+ if (RUN_LOCAL) {
+ PyEnvTaskRunner taskRunner = new PyEnvTaskRunner(roots);
+
+ taskRunner.runTask(testTask, testName);
+ }
+ }
+
+
+ public static boolean notEnvConfiguration() {
+ return UsefulTestCase.IS_UNDER_TEAMCITY && !IS_ENV_CONFIGURATION;
+ }
+
+ public static List<String> getPythonRoots() {
+ List<String> roots = Lists.newArrayList();
+
+ String envs = System.getenv(PYCHARM_PYTHON_ENVS);
+ if (envs != null) {
+ roots.addAll(Lists.newArrayList(envs.split(File.pathSeparator)));
+ }
+
+ String virtualEnvs = System.getenv(PYCHARM_PYTHON_VIRTUAL_ENVS);
+
+ if (virtualEnvs != null) {
+ roots.addAll(readVirtualEnvRoots(virtualEnvs));
+ }
+ return roots;
+ }
+
+ protected static List<String> readVirtualEnvRoots(@NotNull String envs) {
+ List<String> result = Lists.newArrayList();
+ String[] roots = envs.split(File.pathSeparator);
+ for (String root : roots) {
+ File virtualEnvRoot = new File(root);
+ File[] virtualenvs = virtualEnvRoot.listFiles();
+ if (virtualenvs != null) {
+ for (File f : virtualenvs) {
+ result.add(f.getAbsolutePath());
+ }
+ } else {
+ LOG.error(root + " is not a directory of doesn't exist");
+ }
+ }
+
+ return result;
+ }
+
+ public static List<String> loadEnvTags(String env) {
+ List<String> envTags;
+
+ try {
+ File parent = new File(env);
+ if (parent.isFile()) {
+ parent = parent.getParentFile();
+ }
+ envTags = com.intellij.openapi.util.io.FileUtil.loadLines(new File(parent, TAGS_FILE));
+ }
+ catch (IOException e) {
+ envTags = Lists.newArrayList();
+ }
+ return envTags;
+ }
+
+ public static String joinStrings(Collection<String> roots, String rootsName) {
+ return roots.size() > 0 ? rootsName + StringUtil.join(roots, ", ") + "\n" : "";
+ }
+}
+
diff --git a/python/testSrc/com/jetbrains/env/PyExecutionFixtureTestTask.java b/python/testSrc/com/jetbrains/env/PyExecutionFixtureTestTask.java
new file mode 100644
index 000000000000..bdb426dde301
--- /dev/null
+++ b/python/testSrc/com/jetbrains/env/PyExecutionFixtureTestTask.java
@@ -0,0 +1,174 @@
+package com.jetbrains.env;
+
+import com.google.common.collect.Lists;
+import com.intellij.execution.process.ProcessHandler;
+import com.intellij.ide.util.projectWizard.EmptyModuleBuilder;
+import com.intellij.openapi.module.ModuleType;
+import com.intellij.openapi.module.ModuleTypeManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.projectRoots.Sdk;
+import com.intellij.openapi.vfs.LocalFileSystem;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.testFramework.LightProjectDescriptor;
+import com.intellij.testFramework.builders.ModuleFixtureBuilder;
+import com.intellij.testFramework.fixtures.*;
+import com.intellij.testFramework.fixtures.impl.ModuleFixtureBuilderImpl;
+import com.intellij.testFramework.fixtures.impl.ModuleFixtureImpl;
+import com.intellij.util.ui.UIUtil;
+import com.jetbrains.python.PythonModuleTypeBase;
+import com.jetbrains.python.PythonTestUtil;
+import com.jetbrains.python.sdk.InvalidSdkException;
+import com.jetbrains.python.sdkTools.PyTestSdkTools;
+import com.jetbrains.python.sdkTools.SdkCreationType;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.junit.Assert;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author traff
+ */
+public abstract class PyExecutionFixtureTestTask extends PyTestTask {
+ public static final int NORMAL_TIMEOUT = 30000;
+ public static final int LONG_TIMEOUT = 120000;
+ protected int myTimeout = NORMAL_TIMEOUT;
+ protected CodeInsightTestFixture myFixture;
+
+ public Project getProject() {
+ return myFixture.getProject();
+ }
+
+ public void useNormalTimeout() {
+ myTimeout = NORMAL_TIMEOUT;
+ }
+
+ public void useLongTimeout() {
+ myTimeout = LONG_TIMEOUT;
+ }
+
+ public void setUp(final String testName) throws Exception {
+ initFixtureBuilder();
+
+ final TestFixtureBuilder<IdeaProjectTestFixture> fixtureBuilder = IdeaTestFixtureFactory.getFixtureFactory().createFixtureBuilder(
+ testName);
+
+ myFixture = IdeaTestFixtureFactory.getFixtureFactory().createCodeInsightFixture(fixtureBuilder.getFixture());
+
+ UIUtil.invokeAndWaitIfNeeded(
+ new Runnable() {
+ @Override
+ public void run() {
+ ModuleFixtureBuilder moduleFixtureBuilder = fixtureBuilder.addModule(MyModuleFixtureBuilder.class);
+ moduleFixtureBuilder.addSourceContentRoot(myFixture.getTempDirPath());
+ moduleFixtureBuilder.addSourceContentRoot(getTestDataPath());
+ final List<String> contentRoots = getContentRoots();
+ for (String contentRoot : contentRoots) {
+ moduleFixtureBuilder.addContentRoot(getTestDataPath() + contentRoot);
+ }
+ }
+ }
+ );
+
+
+ myFixture.setUp();
+ myFixture.setTestDataPath(getTestDataPath());
+ }
+
+ protected List<String> getContentRoots() {
+ return Lists.newArrayList();
+ }
+
+ protected String getTestDataPath() {
+ return PythonTestUtil.getTestDataPath();
+ }
+
+ protected void initFixtureBuilder() {
+ IdeaTestFixtureFactory.getFixtureFactory().registerFixtureBuilder(MyModuleFixtureBuilder.class, MyModuleFixtureBuilderImpl.class);
+ }
+
+ public void tearDown() throws Exception {
+ if (myFixture != null) {
+ myFixture.tearDown();
+ myFixture = null;
+ }
+ }
+
+ @Nullable
+ protected LightProjectDescriptor getProjectDescriptor() {
+ return null;
+ }
+
+ protected void disposeProcess(ProcessHandler h) throws InterruptedException {
+ h.destroyProcess();
+ if (!waitFor(h)) {
+ new Throwable("Can't stop process").printStackTrace();
+ }
+ }
+
+ protected boolean waitFor(ProcessHandler p) throws InterruptedException {
+ return p.waitFor(myTimeout);
+ }
+
+ protected boolean waitFor(@NotNull Semaphore s) throws InterruptedException {
+ return waitFor(s, myTimeout);
+ }
+
+ protected static boolean waitFor(@NotNull Semaphore s, long timeout) throws InterruptedException {
+ return s.tryAcquire(timeout, TimeUnit.MILLISECONDS);
+ }
+
+ public static class MyModuleFixtureBuilderImpl extends ModuleFixtureBuilderImpl<ModuleFixture> implements MyModuleFixtureBuilder {
+ public MyModuleFixtureBuilderImpl(TestFixtureBuilder<? extends IdeaProjectTestFixture> fixtureBuilder) {
+ super(new PlatformPythonModuleType(), fixtureBuilder);
+ }
+
+ @Override
+ protected ModuleFixture instantiateFixture() {
+ return new ModuleFixtureImpl(this);
+ }
+ }
+
+ public static class PlatformPythonModuleType extends PythonModuleTypeBase<EmptyModuleBuilder> {
+ @NotNull
+ public static PlatformPythonModuleType getInstance() {
+ return (PlatformPythonModuleType)ModuleTypeManager.getInstance().findByID(PYTHON_MODULE);
+ }
+
+
+ @NotNull
+ @Override
+ public EmptyModuleBuilder createModuleBuilder() {
+ return new EmptyModuleBuilder() {
+ @Override
+ public ModuleType getModuleType() {
+ return getInstance();
+ }
+ };
+ }
+ }
+
+
+ /**
+ * Creates SDK by its path
+ *
+ * @param sdkHome path to sdk (probably obtained by {@link #runTestOn(String)})
+ * @param sdkCreationType SDK creation strategy (see {@link com.jetbrains.python.sdkTools.SdkCreationType} doc)
+ * @return sdk
+ */
+ @NotNull
+ protected Sdk createTempSdk(@NotNull final String sdkHome, @NotNull final SdkCreationType sdkCreationType)
+ throws InvalidSdkException, IOException {
+ final VirtualFile sdkHomeFile = LocalFileSystem.getInstance().findFileByPath(sdkHome);
+ Assert.assertNotNull("Interpreter file not found: " + sdkHome, sdkHomeFile);
+ return PyTestSdkTools.createTempSdk(sdkHomeFile, sdkCreationType, myFixture.getModule());
+ }
+
+
+ public interface MyModuleFixtureBuilder extends ModuleFixtureBuilder<ModuleFixture> {
+
+ }
+}
diff --git a/python/testSrc/com/jetbrains/env/PyTestTask.java b/python/testSrc/com/jetbrains/env/PyTestTask.java
new file mode 100644
index 000000000000..bfc1a688ebfa
--- /dev/null
+++ b/python/testSrc/com/jetbrains/env/PyTestTask.java
@@ -0,0 +1,81 @@
+package com.jetbrains.env;
+
+import com.google.common.collect.Sets;
+import com.intellij.openapi.util.io.FileUtil;
+
+import java.util.Set;
+
+/**
+ * @author traff
+ */
+public abstract class PyTestTask {
+ private String myWorkingFolder;
+ private String myScriptName;
+ private String myScriptParameters;
+
+ public void setWorkingFolder(String workingFolder) {
+ myWorkingFolder = workingFolder;
+ }
+
+ public void setScriptName(String scriptName) {
+ myScriptName = scriptName;
+ }
+
+ public void setScriptParameters(String scriptParameters) {
+ myScriptParameters = scriptParameters;
+ }
+
+ public void setUp(String testName) throws Exception {
+ }
+
+ public void tearDown() throws Exception {
+ }
+
+ /**
+ * Run test on certain SDK path.
+ * To create SDK from path, use {@link PyExecutionFixtureTestTask#createTempSdk(String, com.jetbrains.python.sdkTools.SdkCreationType)}
+ *
+ * @param sdkHome sdk path
+ */
+ public abstract void runTestOn(String sdkHome) throws Exception;
+
+ public void before() throws Exception {
+ }
+
+ public void testing() throws Exception {
+ }
+
+ public void after() throws Exception {
+ }
+
+ public void useNormalTimeout() {
+ }
+
+ public void useLongTimeout() {
+ }
+
+ public String getScriptName() {
+ return myScriptName;
+ }
+
+ public String getScriptPath() {
+ return getFilePath(myScriptName);
+ }
+
+ public String getFilePath(String scriptName) {
+ return FileUtil
+ .toSystemDependentName(myWorkingFolder.endsWith("/") ? myWorkingFolder + scriptName : myWorkingFolder + "/" + scriptName);
+ }
+
+ public String getScriptParameters() {
+ return myScriptParameters;
+ }
+
+ public String getWorkingFolder() {
+ return myWorkingFolder;
+ }
+
+ public Set<String> getTags() {
+ return Sets.newHashSet();
+ }
+}
diff --git a/python/testSrc/com/jetbrains/env/python/IPythonConsoleTest.java b/python/testSrc/com/jetbrains/env/python/IPythonConsoleTest.java
new file mode 100644
index 000000000000..a039344451d4
--- /dev/null
+++ b/python/testSrc/com/jetbrains/env/python/IPythonConsoleTest.java
@@ -0,0 +1,100 @@
+package com.jetbrains.env.python;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.ImmutableSet;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiErrorElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.jetbrains.env.PyEnvTestCase;
+import com.jetbrains.env.python.console.PyConsoleTask;
+import org.hamcrest.Matchers;
+import org.jetbrains.annotations.NotNull;
+import org.junit.Assert;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Set;
+
+/**
+ * @author traff
+ */
+public class IPythonConsoleTest extends PyEnvTestCase {
+ public void testQuestion() throws Exception {
+ runPythonTest(new IPythonTask() {
+ @Override
+ public void testing() throws Exception {
+ exec("import multiprocessing");
+ exec("multiprocessing?");
+ waitForOutput("Type:", "module");
+ }
+ });
+ }
+
+ public void testParsing() throws Exception {
+ runPythonTest(new IPythonTask() {
+ @Override
+ public void testing() throws Exception {
+ waitForReady();
+ addTextToEditor("sys?");
+ ApplicationManager.getApplication().runReadAction(new Runnable() {
+ @Override
+ public void run() {
+ PsiFile psi =
+ PsiDocumentManager.getInstance(getProject())
+ .getPsiFile(getConsoleView().getLanguageConsole().getConsoleEditor().getDocument());
+ Assert.assertThat("No errors expected", getErrors(psi), Matchers.empty());
+ }
+ });
+ }
+ });
+ }
+
+ @NotNull
+ private static Collection<String> getErrors(PsiFile psi) { //TODO: NotNull?
+ if (!PsiTreeUtil.hasErrorElements(psi)) {
+ return Collections.emptyList();
+ }
+
+ return Collections2.transform(PsiTreeUtil.findChildrenOfType(psi, PsiErrorElement.class), new Function<PsiErrorElement, String>() {
+ @Override
+ public String apply(PsiErrorElement input) {
+ return input.getErrorDescription();
+ }
+ });
+ }
+
+ public void testParsingNoIPython() throws Exception {
+ runPythonTest(new IPythonTask() {
+ @Override
+ public void testing() throws Exception {
+ waitForReady();
+ addTextToEditor("sys?");
+ ApplicationManager.getApplication().runReadAction(new Runnable() {
+ @Override
+ public void run() {
+ PsiFile psi =
+ PsiDocumentManager.getInstance(getProject()).getPsiFile(getConsoleView().getLanguageConsole().getConsoleEditor().getDocument());
+ //TreeUtil.ensureParsed(psi.getNode());
+ assertTrue(PsiTreeUtil.hasErrorElements(psi));
+ }
+ });
+
+ }
+
+ @Override
+ public Set<String> getTags() {
+ return ImmutableSet.of("-ipython");
+ }
+ });
+ }
+
+ private static class IPythonTask extends PyConsoleTask {
+ @Override
+ public Set<String> getTags() {
+ return ImmutableSet.of("ipython");
+ }
+ }
+}
diff --git a/python/testSrc/com/jetbrains/env/python/PyPackageRequirementsInspectionTest.java b/python/testSrc/com/jetbrains/env/python/PyPackageRequirementsInspectionTest.java
new file mode 100644
index 000000000000..8e3b75dd56a0
--- /dev/null
+++ b/python/testSrc/com/jetbrains/env/python/PyPackageRequirementsInspectionTest.java
@@ -0,0 +1,83 @@
+package com.jetbrains.env.python;
+
+import com.google.common.collect.ImmutableSet;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.projectRoots.Sdk;
+import com.intellij.openapi.roots.ModuleRootModificationUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.testFramework.PsiTestUtil;
+import com.jetbrains.env.PyEnvTestCase;
+import com.jetbrains.env.PyExecutionFixtureTestTask;
+import com.jetbrains.python.PythonTestUtil;
+import com.jetbrains.python.inspections.PyPackageRequirementsInspection;
+import com.jetbrains.python.sdkTools.SdkCreationType;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Set;
+
+/**
+ * @author vlan
+ */
+public class PyPackageRequirementsInspectionTest extends PyEnvTestCase {
+ public static final ImmutableSet<String> TAGS = ImmutableSet.of("requirements");
+
+ public void testPartiallySatisfiedRequirementsTxt() {
+ doTest("test1.py");
+ }
+
+ public void testPartiallySatisfiedSetupPy() {
+ doTest("test1.py");
+ }
+
+ public void testImportsNotInRequirementsTxt() {
+ doTest("test1.py");
+ }
+
+ public void testDuplicateInstallAndTests() {
+ doTest("test1.py");
+ }
+
+ private void doTest(@NotNull final String filename) {
+ final String dir = getTestName(false);
+ runPythonTest(new PyExecutionFixtureTestTask() {
+ @Override
+ protected String getTestDataPath() {
+ return PythonTestUtil.getTestDataPath() + "/inspections/PyPackageRequirementsInspection";
+ }
+
+ @Override
+ public void runTestOn(String sdkHome) throws Exception {
+ myFixture.enableInspections(PyPackageRequirementsInspection.class);
+ final Sdk sdk = createTempSdk(sdkHome, SdkCreationType.SDK_PACKAGES_ONLY);
+ final String perSdkDir = Integer.toHexString(System.identityHashCode(sdk));
+ final VirtualFile root = myFixture.copyDirectoryToProject(dir, perSdkDir);
+ assertNotNull(root);
+ final Module module = myFixture.getModule();
+ setupModuleSdk(module, sdk, root);
+ try {
+ final VirtualFile file = root.findFileByRelativePath(filename);
+ assertNotNull(file);
+ edt(new Runnable() {
+ @Override
+ public void run() {
+ myFixture.testHighlighting(true, true, true, file);
+ }
+ });
+ }
+ finally {
+ PsiTestUtil.removeAllRoots(module, sdk);
+ }
+ }
+
+ @Override
+ public Set<String> getTags() {
+ return TAGS;
+ }
+ });
+ }
+
+ private static void setupModuleSdk(@NotNull Module module, @NotNull Sdk sdk, @NotNull VirtualFile root) {
+ ModuleRootModificationUtil.setModuleSdk(module, sdk);
+ PsiTestUtil.addContentRoot(module, root);
+ }
+}
diff --git a/python/testSrc/com/jetbrains/env/python/PyPackagingTest.java b/python/testSrc/com/jetbrains/env/python/PyPackagingTest.java
new file mode 100644
index 000000000000..54afb702322b
--- /dev/null
+++ b/python/testSrc/com/jetbrains/env/python/PyPackagingTest.java
@@ -0,0 +1,164 @@
+package com.jetbrains.env.python;
+
+import com.google.common.collect.Sets;
+import com.intellij.openapi.projectRoots.Sdk;
+import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.testFramework.UsefulTestCase;
+import com.jetbrains.env.PyEnvTestCase;
+import com.jetbrains.env.PyExecutionFixtureTestTask;
+import com.jetbrains.env.PyTestTask;
+import com.jetbrains.python.packaging.*;
+import com.jetbrains.python.psi.LanguageLevel;
+import com.jetbrains.python.sdk.PythonSdkType;
+import com.jetbrains.python.sdk.flavors.PythonSdkFlavor;
+import com.jetbrains.python.sdk.flavors.VirtualEnvSdkFlavor;
+import com.jetbrains.python.sdkTools.SdkCreationType;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author vlan
+ */
+public class PyPackagingTest extends PyEnvTestCase {
+ @Override
+ public void runPythonTest(PyTestTask testTask) {
+ if (UsefulTestCase.IS_UNDER_TEAMCITY && SystemInfo.isWindows) {
+ return; //Don't run under Windows as after deleting from created virtualenvs original interpreter got spoiled
+ }
+
+ super.runPythonTest(testTask);
+ }
+
+ public void testGetPackages() {
+ runPythonTest(new PyPackagingTestTask() {
+ @Override
+ public void runTestOn(String sdkHome) throws Exception {
+ final Sdk sdk = createTempSdk(sdkHome, SdkCreationType.EMPTY_SDK);
+ List<PyPackage> packages = null;
+ try {
+ packages = ((PyPackageManagerImpl)PyPackageManager.getInstance(sdk)).getPackages();
+ }
+ catch (PyExternalProcessException e) {
+ final int retcode = e.getRetcode();
+ if (retcode != PyPackageManagerImpl.ERROR_NO_PIP && retcode != PyPackageManagerImpl.ERROR_NO_SETUPTOOLS) {
+ fail(String.format("Error for interpreter '%s': %s", sdk.getHomePath(), e.getMessage()));
+ }
+ }
+ if (packages != null) {
+ assertTrue(packages.size() > 0);
+ for (PyPackage pkg : packages) {
+ assertTrue(pkg.getName().length() > 0);
+ }
+ }
+ }
+ });
+ }
+
+ public void testCreateVirtualEnv() {
+ runPythonTest(new PyPackagingTestTask() {
+ @Override
+ public void runTestOn(String sdkHome) throws Exception {
+ final Sdk sdk = createTempSdk(sdkHome, SdkCreationType.EMPTY_SDK);
+ try {
+ final LanguageLevel languageLevel = PythonSdkType.getLanguageLevelForSdk(sdk);
+ // virtualenv >= 0.10 supports Python >= 2.6
+ if (languageLevel.isOlderThan(LanguageLevel.PYTHON26)) {
+ return;
+ }
+ final File tempDir = FileUtil.createTempDirectory(getTestName(false), null);
+ final File venvDir = new File(tempDir, "venv");
+ final String venvSdkHome = ((PyPackageManagerImpl)PyPackageManagerImpl.getInstance(sdk)).createVirtualEnv(venvDir.toString(),
+ false);
+ final Sdk venvSdk = createTempSdk(venvSdkHome, SdkCreationType.EMPTY_SDK);
+ assertNotNull(venvSdk);
+ assertTrue(PythonSdkType.isVirtualEnv(venvSdk));
+ assertInstanceOf(PythonSdkFlavor.getPlatformIndependentFlavor(venvSdk.getHomePath()), VirtualEnvSdkFlavor.class);
+ final List<PyPackage> packages = ((PyPackageManagerImpl)PyPackageManagerImpl.getInstance(venvSdk)).getPackages();
+ final PyPackage setuptools = findPackage("setuptools", packages);
+ assertNotNull(setuptools);
+ assertEquals("setuptools", setuptools.getName());
+ assertEquals(PyPackageManagerImpl.SETUPTOOLS_VERSION, setuptools.getVersion());
+ final PyPackage pip = findPackage("pip", packages);
+ assertNotNull(pip);
+ assertEquals("pip", pip.getName());
+ assertEquals(PyPackageManagerImpl.PIP_VERSION, pip.getVersion());
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ catch (PyExternalProcessException e) {
+ throw new RuntimeException(String.format("Error for interpreter '%s': %s", sdk.getHomePath(), e.getMessage()), e);
+ }
+ }
+ });
+ }
+
+ public void testInstallPackage() {
+ runPythonTest(new PyPackagingTestTask() {
+
+ @Override
+ public void runTestOn(String sdkHome) throws Exception {
+ final Sdk sdk = createTempSdk(sdkHome, SdkCreationType.EMPTY_SDK);
+ try {
+ final File tempDir = FileUtil.createTempDirectory(getTestName(false), null);
+ final File venvDir = new File(tempDir, "venv");
+ final String venvSdkHome = ((PyPackageManagerImpl)PyPackageManager.getInstance(sdk)).createVirtualEnv(venvDir.getPath(), false);
+ final Sdk venvSdk = createTempSdk(venvSdkHome, SdkCreationType.EMPTY_SDK);
+ assertNotNull(venvSdk);
+ final PyPackageManagerImpl manager = (PyPackageManagerImpl)PyPackageManager.getInstance(venvSdk);
+ final List<PyPackage> packages1 = manager.getPackages();
+ // TODO: Install Markdown from a local file
+ manager.install(list(PyRequirement.fromString("Markdown<2.2"),
+ new PyRequirement("httplib2")), Collections.<String>emptyList());
+ final List<PyPackage> packages2 = manager.getPackages();
+ final PyPackage markdown2 = findPackage("Markdown", packages2);
+ assertNotNull(markdown2);
+ assertTrue(markdown2.isInstalled());
+ final PyPackage pip1 = findPackage("pip", packages1);
+ assertNotNull(pip1);
+ assertEquals("pip", pip1.getName());
+ assertEquals(PyPackageManagerImpl.PIP_VERSION, pip1.getVersion());
+ manager.uninstall(list(pip1));
+ final List<PyPackage> packages3 = manager.getPackages();
+ final PyPackage pip2 = findPackage("pip", packages3);
+ assertNull(pip2);
+ }
+ catch (PyExternalProcessException e) {
+ new RuntimeException(String.format("Error for interpreter '%s': %s", sdk.getHomePath(), e.getMessage()), e);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
+ }
+
+ @Nullable
+ private static PyPackage findPackage(String name, List<PyPackage> packages) {
+ for (PyPackage pkg : packages) {
+ if (name.equals(pkg.getName())) {
+ return pkg;
+ }
+ }
+ return null;
+ }
+
+ private static <T> List<T> list(T... xs) {
+ return Arrays.asList(xs);
+ }
+
+
+ private abstract static class PyPackagingTestTask extends PyExecutionFixtureTestTask {
+ @Override
+ public Set<String> getTags() {
+ return Sets.newHashSet("packaging");
+ }
+ }
+}
diff --git a/python/testSrc/com/jetbrains/env/python/PythonConsoleTest.java b/python/testSrc/com/jetbrains/env/python/PythonConsoleTest.java
new file mode 100644
index 000000000000..4134b1697851
--- /dev/null
+++ b/python/testSrc/com/jetbrains/env/python/PythonConsoleTest.java
@@ -0,0 +1,130 @@
+package com.jetbrains.env.python;
+
+import com.google.common.collect.Sets;
+import com.jetbrains.env.PyEnvTestCase;
+import com.jetbrains.env.python.console.PyConsoleTask;
+import org.junit.Assert;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author traff
+ */
+public class PythonConsoleTest extends PyEnvTestCase {
+ public void testConsolePrint() throws Exception {
+ runPythonTest(new PyConsoleTask() {
+ @Override
+ public void testing() throws Exception {
+ exec("x = 96");
+ exec("x += 1");
+ exec("print(1)");
+ exec("print(x)");
+ waitForOutput("97");
+ }
+ });
+ }
+
+ public void testExecuteMultiline() throws Exception { //PY-4329
+ runPythonTest(new PyConsoleTask() {
+ @Override
+ public void testing() throws Exception {
+ exec("if True:\n" +
+ " x=1\n" +
+ "y=x+100\n" +
+ "for i in range(1):\n" +
+ " print(y)\n");
+ waitForOutput("101");
+ }
+
+ @Override
+ public Set<String> getTags() {
+ return Sets.newHashSet("-jython"); //jython doesn't support multiline execution: http://bugs.jython.org/issue2106
+ }
+ });
+ }
+
+ public void testInterruptAsync() throws Exception {
+ runPythonTest(new PyConsoleTask() {
+ @Override
+ public void testing() throws Exception {
+ exec("import time");
+ execNoWait("for i in range(10000):\n" +
+ " print(i)\n" +
+ " time.sleep(0.1)");
+ waitForOutput("3\n4\n5");
+ Assert.assertFalse(canExecuteNow());
+ interrupt();
+ waitForFinish();
+ waitForReady();
+ }
+
+ @Override
+ public Set<String> getTags() {
+ return Sets.newHashSet("-iron", "-jython");
+ }
+ });
+ }
+
+ public void testLineByLineInput() throws Exception {
+ runPythonTest(new PyConsoleTask() {
+ @Override
+ public void testing() throws Exception {
+ exec("x = 96");
+ exec("x +=1");
+ exec("if True:");
+ exec(" print(x)");
+ exec("");
+ exec("");
+ waitForOutput("97");
+ }
+ });
+ }
+
+
+ public void testVariablesView() throws Exception {
+ runPythonTest(new PyConsoleTask() {
+ @Override
+ public void testing() throws Exception {
+ exec("x = 1");
+ exec("print(x)");
+ waitForOutput("1");
+
+ assertTrue("Variable has wrong value",
+ hasValue("x", "1"));
+ }
+ });
+ }
+
+ public void testCompoundVariable() throws Exception {
+ runPythonTest(new PyConsoleTask() {
+ @Override
+ public void testing() throws Exception {
+ exec("x = [1, 2, 3]");
+ exec("print(x)");
+ waitForOutput("[1, 2, 3]");
+
+ List<String> values = getCompoundValueChildren(getValue("x"));
+ Collections.sort(values);
+ assertContainsElements(values, "1", "2", "3", "3");
+ }
+ });
+ }
+
+ public void testChangeVariable() throws Exception {
+ runPythonTest(new PyConsoleTask() {
+ @Override
+ public void testing() throws Exception {
+ exec("x = 1");
+ exec("print(x)");
+ waitForOutput("1");
+
+ setValue("x", "2");
+
+ assertTrue("Variable has wrong value",
+ hasValue("x", "2"));
+ }
+ });
+ }
+}
diff --git a/python/testSrc/com/jetbrains/env/python/PythonDebuggerTest.java b/python/testSrc/com/jetbrains/env/python/PythonDebuggerTest.java
new file mode 100644
index 000000000000..4372715371eb
--- /dev/null
+++ b/python/testSrc/com/jetbrains/env/python/PythonDebuggerTest.java
@@ -0,0 +1,579 @@
+package com.jetbrains.env.python;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import com.intellij.testFramework.fixtures.IdeaProjectTestFixture;
+import com.intellij.xdebugger.XDebuggerTestUtil;
+import com.jetbrains.env.PyEnvTestCase;
+import com.jetbrains.env.python.debug.PyDebuggerTask;
+import com.jetbrains.env.ut.PyUnitTestTask;
+import com.jetbrains.python.PythonHelpersLocator;
+import com.jetbrains.python.console.pydev.PydevCompletionVariant;
+import com.jetbrains.python.debugger.PyDebuggerException;
+import com.jetbrains.python.debugger.PyExceptionBreakpointProperties;
+import com.jetbrains.python.debugger.PyExceptionBreakpointType;
+import com.jetbrains.python.debugger.pydev.ProcessDebugger;
+import com.jetbrains.python.sdk.flavors.PythonSdkFlavor;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author traff
+ */
+
+public class PythonDebuggerTest extends PyEnvTestCase {
+ public void testBreakpointStopAndEval() throws Exception {
+ runPythonTest(new PyDebuggerTask("/debug", "test1.py") {
+ @Override
+ public void before() throws Exception {
+ toggleBreakpoint(getScriptPath(), 3);
+ }
+
+ @Override
+ public void testing() throws Exception {
+ waitForPause();
+
+ eval("i").hasValue("0");
+
+ resume();
+
+ waitForPause();
+
+ eval("i").hasValue("1");
+
+ resume();
+
+ waitForPause();
+
+ eval("i").hasValue("2");
+ }
+ });
+ }
+
+ public void testDebugger() {
+ runPythonTest(new PyUnitTestTask("", "test_debug.py") {
+ @Override
+ protected String getTestDataPath() {
+ return PythonHelpersLocator.getPythonCommunityPath() + "/helpers/pydev";
+ }
+
+ @Override
+ public void after() {
+ allTestsPassed();
+ }
+ });
+ }
+
+ public void testConditionalBreakpoint() throws Exception {
+ runPythonTest(new PyDebuggerTask("/debug", "test1.py") {
+ @Override
+ public void before() throws Exception {
+ toggleBreakpoint(getScriptPath(), 3);
+ XDebuggerTestUtil.setBreakpointCondition(getProject(), 3, "i == 1 or i == 11 or i == 111");
+ }
+
+ @Override
+ public void testing() throws Exception {
+ waitForPause();
+
+ eval("i").hasValue("1");
+
+ resume();
+
+ waitForPause();
+
+ eval("i").hasValue("11");
+
+ resume();
+
+ waitForPause();
+
+ eval("i").hasValue("111");
+ }
+ });
+ }
+
+ public void testDebugConsole() throws Exception {
+ runPythonTest(new PyDebuggerTask("/debug", "test1.py") {
+ @Override
+ public void before() throws Exception {
+ toggleBreakpoint(getScriptPath(), 3);
+ }
+
+ @Override
+ public void testing() throws Exception {
+ waitForPause();
+
+ eval("i").hasValue("0");
+
+ resume();
+
+ waitForPause();
+
+ consoleExec("'i=%d'%i");
+
+ waitForOutput("'i=1'");
+
+ consoleExec("x");
+
+ waitForOutput("name 'x' is not defined");
+
+ consoleExec("1-;");
+
+ waitForOutput("SyntaxError");
+
+ resume();
+ }
+
+ private void consoleExec(String command) {
+ myDebugProcess.consoleExec(command, new ProcessDebugger.DebugCallback<String>() {
+ @Override
+ public void ok(String value) {
+
+ }
+
+ @Override
+ public void error(PyDebuggerException exception) {
+ }
+ });
+ }
+ });
+ }
+
+
+ public void testDebugCompletion() throws Exception {
+ runPythonTest(new PyDebuggerTask("/debug", "test4.py") {
+ @Override
+ public void before() throws Exception {
+ toggleBreakpoint(getScriptPath(), 3);
+ }
+
+ @Override
+ public void testing() throws Exception {
+ waitForPause();
+
+ List<PydevCompletionVariant> list = myDebugProcess.getCompletions("xvalu");
+ assertEquals(2, list.size());
+ }
+ });
+ }
+
+ public void testBreakpointLogExpression() throws Exception {
+ runPythonTest(new PyDebuggerTask("/debug", "test1.py") {
+ @Override
+ public void before() throws Exception {
+ toggleBreakpoint(getScriptPath(), 3);
+ XDebuggerTestUtil.setBreakpointLogExpression(getProject(), 3, "'i = %d'%i");
+ }
+
+ @Override
+ public void testing() throws Exception {
+ waitForPause();
+ resume();
+ waitForOutput("i = 1");
+ }
+ });
+ }
+
+ public void testStepOver() throws Exception {
+ runPythonTest(new PyDebuggerTask("/debug", "test2.py") {
+ @Override
+ public void before() throws Exception {
+ toggleBreakpoint(getScriptPath(), 5);
+ }
+
+ @Override
+ public void testing() throws Exception {
+ waitForPause();
+ stepOver();
+ waitForPause();
+ stepOver();
+ waitForPause();
+ eval("z").hasValue("2");
+ }
+ });
+ }
+
+ public void testStepInto() throws Exception {
+ runPythonTest(new PyDebuggerTask("/debug", "test2.py") {
+ @Override
+ public void before() throws Exception {
+ toggleBreakpoint(getScriptPath(), 5);
+ }
+
+ @Override
+ public void testing() throws Exception {
+ waitForPause();
+ stepInto();
+ waitForPause();
+ eval("x").hasValue("1");
+ stepOver();
+ waitForPause();
+ eval("y").hasValue("3");
+ stepOver();
+ waitForPause();
+ eval("z").hasValue("1");
+ }
+ });
+ }
+
+ public void testSmartStepInto() throws Exception {
+ runPythonTest(new PyDebuggerTask("/debug", "test3.py") {
+ @Override
+ public void before() throws Exception {
+ toggleBreakpoint(getScriptPath(), 14);
+ }
+
+ @Override
+ public void testing() throws Exception {
+ waitForPause();
+ smartStepInto("foo");
+ waitForPause();
+ stepOver();
+ waitForPause();
+ eval("y").hasValue("4");
+ }
+ });
+ }
+
+ public void testSmartStepInto2() throws Exception {
+ runPythonTest(new PyDebuggerTask("/debug", "test3.py") {
+ @Override
+ public void before() throws Exception {
+ toggleBreakpoint(getScriptPath(), 18);
+ toggleBreakpoint(getScriptPath(), 25);
+ }
+
+ @Override
+ public void testing() throws Exception {
+ waitForPause();
+ toggleBreakpoint(getScriptPath(), 18);
+ smartStepInto("foo");
+ waitForPause();
+ eval("a.z").hasValue("1");
+ }
+ });
+ }
+
+ public void testInput() throws Exception {
+ runPythonTest(new PyDebuggerTask("/debug", "test_input.py") {
+ @Override
+ public void before() throws Exception {
+ }
+
+ @Override
+ public void testing() throws Exception {
+ waitForOutput("print command >");
+ input("GO!");
+ waitForOutput("command was GO!");
+ }
+
+ @Override
+ public Set<String> getTags() {
+ return ImmutableSet.of("-jython"); //can't run on jython
+ }
+ });
+ }
+
+ public void testRunToLine() throws Exception {
+ runPythonTest(new PyDebuggerTask("/debug", "test_runtoline.py") {
+ @Override
+ public void before() throws Exception {
+ toggleBreakpoint(getScriptPath(), 1);
+ toggleBreakpoint(getScriptPath(), 7);
+ }
+
+ @Override
+ public void testing() throws Exception {
+ waitForPause();
+ eval("x").hasValue("0");
+ runToLine(4);
+ eval("x").hasValue("1");
+ resume();
+ waitForPause();
+ eval("x").hasValue("12");
+ resume();
+
+ waitForOutput("x = 12");
+ }
+ });
+ }
+
+ private static void addExceptionBreakpoint(IdeaProjectTestFixture fixture, PyExceptionBreakpointProperties properties) {
+ XDebuggerTestUtil.addBreakpoint(fixture.getProject(), PyExceptionBreakpointType.class, properties);
+ }
+
+ public void testExceptionBreakpointOnTerminate() throws Exception {
+ runPythonTest(new PyDebuggerTask("/debug", "test_exceptbreak.py") {
+ @Override
+ public void before() throws Exception {
+ createExceptionBreak(myFixture, true, false, false);
+ }
+
+ @Override
+ public void testing() throws Exception {
+ waitForPause();
+ eval("__exception__[0].__name__").hasValue("'ZeroDivisionError'");
+ resume();
+ waitForTerminate();
+ }
+
+ @Override
+ public Set<String> getTags() {
+ return ImmutableSet.of("-iron");
+ }
+ });
+ }
+
+ private static void createExceptionBreak(IdeaProjectTestFixture fixture,
+ boolean notifyOnTerminate,
+ boolean notifyAlways,
+ boolean notifyOnFirst) {
+ XDebuggerTestUtil.removeAllBreakpoints(fixture.getProject());
+ XDebuggerTestUtil.setDefaultBreakpointEnabled(fixture.getProject(), PyExceptionBreakpointType.class, false);
+
+ PyExceptionBreakpointProperties properties = new PyExceptionBreakpointProperties("exceptions.ZeroDivisionError");
+ properties.setNotifyOnTerminate(notifyOnTerminate);
+ properties.setNotifyAlways(notifyAlways);
+ properties.setNotifyOnlyOnFirst(notifyOnFirst);
+ addExceptionBreakpoint(fixture, properties);
+ properties = new PyExceptionBreakpointProperties("builtins.ZeroDivisionError"); //for python 3
+ properties.setNotifyOnTerminate(notifyOnTerminate);
+ properties.setNotifyAlways(notifyAlways);
+ properties.setNotifyOnlyOnFirst(notifyOnFirst);
+ addExceptionBreakpoint(fixture, properties);
+ }
+
+ public void testExceptionBreakpointAlways() throws Exception {
+ runPythonTest(new PyDebuggerTask("/debug", "test_exceptbreak.py") {
+ @Override
+ public void before() throws Exception {
+ createExceptionBreak(myFixture, false, true, false);
+ }
+
+ @Override
+ public void testing() throws Exception {
+ waitForPause();
+ eval("__exception__[0].__name__").hasValue("'ZeroDivisionError'");
+ resume();
+ waitForPause();
+ resume();
+ waitForPause();
+ resume();
+ waitForTerminate();
+ }
+
+ @Override
+ public Set<String> getTags() {
+ return ImmutableSet.of("-pypy"); //TODO: fix it for Pypy
+ }
+ });
+ }
+
+ public void testExceptionBreakpointOnFirstRaise() throws Exception {
+ runPythonTest(new PyDebuggerTask("/debug", "test_exceptbreak.py") {
+ @Override
+ public void before() throws Exception {
+ createExceptionBreak(myFixture, false, false, true);
+ }
+
+ @Override
+ public void testing() throws Exception {
+ waitForPause();
+ eval("__exception__[0].__name__").hasValue("'ZeroDivisionError'");
+ resume();
+ waitForTerminate();
+ }
+
+ @Override
+ public Set<String> getTags() {
+ return ImmutableSet.of("-iron");
+ }
+ });
+ }
+
+ public void testMultithreading() throws Exception {
+ runPythonTest(new PyDebuggerTask("/debug", "test_multithread.py") {
+ @Override
+ public void before() throws Exception {
+ toggleBreakpoint(getScriptPath(), 9);
+ toggleBreakpoint(getScriptPath(), 13);
+ }
+
+ @Override
+ public void testing() throws Exception {
+ waitForPause();
+ eval("y").hasValue("2");
+ resume();
+ waitForPause();
+ eval("z").hasValue("102");
+ resume();
+ }
+
+ @Override
+ public Set<String> getTags() {
+ return ImmutableSet.of("-pypy"); //TODO: fix that for PyPy
+ }
+ });
+ }
+
+ public void testEggDebug() throws Exception {
+ runPythonTest(new PyDebuggerTask("/debug", "test_egg.py") {
+ @Override
+ public void before() throws Exception {
+ String egg = getFilePath("Adder-0.1.egg");
+ toggleBreakpointInEgg(egg, "adder/adder.py", 2);
+ PythonSdkFlavor flavor = PythonSdkFlavor.getFlavor(getRunConfiguration().getSdkHome());
+ if (flavor != null) {
+ flavor.initPythonPath(Lists.newArrayList(egg), getRunConfiguration().getEnvs());
+ }
+ else {
+ getRunConfiguration().getEnvs().put("PYTHONPATH", egg);
+ }
+ }
+
+ @Override
+ public void testing() throws Exception {
+ waitForPause();
+ eval("ret").hasValue("16");
+ resume();
+ }
+
+ @Override
+ public Set<String> getTags() {
+ return ImmutableSet.of("-jython"); //TODO: fix that for Jython if anybody needs it
+ }
+ });
+ }
+
+ public void testStepOverConditionalBreakpoint() throws Exception {
+ runPythonTest(new PyDebuggerTask("/debug", "test_stepOverCondition.py") {
+ @Override
+ public void before() throws Exception {
+ toggleBreakpoint(getScriptPath(), 1);
+ toggleBreakpoint(getScriptPath(), 2);
+ XDebuggerTestUtil.setBreakpointCondition(getProject(), 2, "y == 3");
+ }
+
+ @Override
+ public void testing() throws Exception {
+ waitForPause();
+ stepOver();
+ waitForPause();
+ eval("y").hasValue("2");
+ }
+ });
+ }
+
+ public void testMultiprocess() throws Exception {
+ runPythonTest(new PyDebuggerTask("/debug", "test_multiprocess.py") {
+ @Override
+ protected void init() {
+ setMultiprocessDebug(true);
+ }
+
+ @Override
+ public void before() throws Exception {
+ toggleBreakpoint(getScriptPath(), 9);
+ }
+
+ @Override
+ public void testing() throws Exception {
+ waitForPause();
+
+ eval("i").hasValue("'Result:OK'");
+
+ resume();
+
+ waitForOutput("Result:OK");
+ }
+
+ @Override
+ public Set<String> getTags() {
+ return Sets.newHashSet("python3");
+ }
+ });
+ }
+
+
+ //TODO: fix me as I don't work properly sometimes (something connected with process termination on agent)
+ //public void testResume() throws Exception {
+ // runPythonTest(new PyDebuggerTask("/debug", "Test_Resume.py") {
+ // @Override
+ // public void before() throws Exception {
+ // toggleBreakpoint(getScriptPath(), 2);
+ // }
+ //
+ // @Override
+ // public void testing() throws Exception {
+ // waitForPause();
+ // eval("x").hasValue("1");
+ // resume();
+ // waitForPause();
+ // eval("x").hasValue("2");
+ // resume();
+ // }
+ // });
+ //}
+
+
+ //TODO: first fix strange hanging of that test
+ //public void testRemoteDebug() throws Exception {
+ // runPythonTest(new PyRemoteDebuggerTask("/debug", "test_remote.py") {
+ // @Override
+ // public void before() throws Exception {
+ // }
+ //
+ // @Override
+ // public void testing() throws Exception {
+ // waitForPause();
+ // eval("x").hasValue("0");
+ // stepOver();
+ // waitForPause();
+ // eval("x").hasValue("1");
+ // stepOver();
+ // waitForPause();
+ // eval("x").hasValue("2");
+ // resume();
+ // }
+ //
+ // @Override
+ // protected void checkOutput(ProcessOutput output) {
+ // assertEmpty(output.getStderr());
+ // assertEquals("OK", output.getStdout().trim());
+ // }
+ //
+ // @Override
+ // public void after() throws Exception {
+ // stopDebugServer();
+ // }
+ // });
+ //}
+
+ //TODO: That doesn't work now: case from test_continuation.py and test_continuation2.py are treated differently by interpreter
+ // (first line is executed in first case and last line in second)
+
+ //public void testBreakOnContinuationLine() throws Exception {
+ // runPythonTest(new PyDebuggerTask("/debug", "test_continuation.py") {
+ // @Override
+ // public void before() throws Exception {
+ // toggleBreakpoint(getScriptPath(), 13);
+ // }
+ //
+ // @Override
+ // public void testing() throws Exception {
+ // waitForPause();
+ // eval("x").hasValue("0");
+ // stepOver();
+ // waitForPause();
+ // eval("x").hasValue("1");
+ // stepOver();
+ // waitForPause();
+ // eval("x").hasValue("2");
+ // }
+ // });
+ //}
+}
+
diff --git a/python/testSrc/com/jetbrains/env/python/PythonGeneratorTest.java b/python/testSrc/com/jetbrains/env/python/PythonGeneratorTest.java
new file mode 100644
index 000000000000..273cb3f94011
--- /dev/null
+++ b/python/testSrc/com/jetbrains/env/python/PythonGeneratorTest.java
@@ -0,0 +1,24 @@
+package com.jetbrains.env.python;
+
+import com.jetbrains.env.PyEnvTestCase;
+import com.jetbrains.env.ut.PyUnitTestTask;
+import com.jetbrains.python.PythonHelpersLocator;
+
+/**
+ * @author traff
+ */
+public class PythonGeneratorTest extends PyEnvTestCase{
+ public void testGenerator() {
+ runPythonTest(new PyUnitTestTask("", "test_generator.py") {
+ @Override
+ protected String getTestDataPath() {
+ return PythonHelpersLocator.getPythonCommunityPath() + "/helpers";
+ }
+
+ @Override
+ public void after() {
+ allTestsPassed();
+ }
+ });
+ }
+}
diff --git a/python/testSrc/com/jetbrains/env/python/PythonSkeletonsTest.java b/python/testSrc/com/jetbrains/env/python/PythonSkeletonsTest.java
new file mode 100644
index 000000000000..c6b150f31359
--- /dev/null
+++ b/python/testSrc/com/jetbrains/env/python/PythonSkeletonsTest.java
@@ -0,0 +1,202 @@
+package com.jetbrains.env.python;
+
+import com.google.common.collect.ImmutableSet;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleUtil;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.projectRoots.Sdk;
+import com.intellij.openapi.vfs.LocalFileSystem;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiFile;
+import com.jetbrains.env.PyEnvTestCase;
+import com.jetbrains.env.PyExecutionFixtureTestTask;
+import com.jetbrains.env.PyTestTask;
+import com.jetbrains.python.PythonFileType;
+import com.jetbrains.python.PythonTestUtil;
+import com.jetbrains.python.documentation.PythonDocumentationProvider;
+import com.jetbrains.python.inspections.unresolvedReference.PyUnresolvedReferencesInspection;
+import com.jetbrains.python.psi.*;
+import com.jetbrains.python.psi.impl.PyBuiltinCache;
+import com.jetbrains.python.psi.resolve.PythonSdkPathCache;
+import com.jetbrains.python.psi.types.PyType;
+import com.jetbrains.python.psi.types.TypeEvalContext;
+import com.jetbrains.python.sdk.PythonSdkType;
+import com.jetbrains.python.sdk.skeletons.PySkeletonRefresher;
+import com.jetbrains.python.sdk.skeletons.SkeletonVersionChecker;
+import com.jetbrains.python.sdkTools.SdkCreationType;
+import com.jetbrains.python.toolbox.Maybe;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.File;
+import java.util.Set;
+
+/**
+ * Heavyweight integration tests of skeletons of Python binary modules.
+ * <p/>
+ * An environment test environment must have a 'skeletons' tag in order to be compatible with this test case. No specific packages are
+ * required currently. Both Python 2 and Python 3 are OK. All platforms are OK. At least one Python 2.6+ environment is required.
+ *
+ * @author vlan
+ */
+public class PythonSkeletonsTest extends PyEnvTestCase {
+ public static final ImmutableSet<String> TAGS = ImmutableSet.of("skeletons");
+
+ public void testBuiltins() {
+ runTest(new SkeletonsTask() {
+ @Override
+ public void runTestOn(@NotNull Sdk sdk) {
+ // Check the builtin skeleton header
+ final Project project = myFixture.getProject();
+ final PyFile builtins = PyBuiltinCache.getBuiltinsForSdk(project, sdk);
+ assertNotNull(builtins);
+ final VirtualFile virtualFile = builtins.getVirtualFile();
+ assertNotNull(virtualFile);
+ assertTrue(virtualFile.isInLocalFileSystem());
+ final String path = virtualFile.getPath();
+ final PySkeletonRefresher.SkeletonHeader header = PySkeletonRefresher.readSkeletonHeader(new File(path));
+ assertNotNull(header);
+ final int version = header.getVersion();
+ assertTrue("Header version must be > 0, currently it is " + version, version > 0);
+ assertEquals(SkeletonVersionChecker.BUILTIN_NAME, header.getBinaryFile());
+
+ // Run inspections on a file that uses builtins
+ myFixture.configureByFile(getTestName(false) + ".py");
+
+
+ PsiFile expr = myFixture.getFile();
+
+ final Module module = ModuleUtil.findModuleForPsiElement(expr);
+
+ final Sdk sdkFromModule = PythonSdkType.findPythonSdk(module);
+ assertNotNull(sdkFromModule);
+
+ final Sdk sdkFromPsi = PyBuiltinCache.findSdkForFile(expr.getContainingFile());
+ final PyFile builtinsFromSdkCache = PythonSdkPathCache.getInstance(project, sdkFromPsi).getBuiltins().getBuiltinsFile();
+ assertNotNull(builtinsFromSdkCache);
+ assertEquals(builtins, builtinsFromSdkCache);
+
+ final PyFile builtinsFromPsi = PyBuiltinCache.getInstance(expr).getBuiltinsFile();
+ assertNotNull(builtinsFromPsi);
+ assertEquals(builtins, builtinsFromPsi);
+
+ myFixture.enableInspections(PyUnresolvedReferencesInspection.class);
+ edt(new Runnable() {
+ @Override
+ public void run() {
+ myFixture.checkHighlighting(true, false, false);
+ }
+ });
+ }
+ });
+ }
+
+ // PY-4349
+ public void testFakeNamedTuple() {
+ runTest(new SkeletonsTask() {
+ @Override
+ protected void runTestOn(@NotNull Sdk sdk) {
+ final LanguageLevel languageLevel = PythonSdkType.getLanguageLevelForSdk(sdk);
+ // Named tuples have been introduced in Python 2.6
+ if (languageLevel.isOlderThan(LanguageLevel.PYTHON26)) {
+ return;
+ }
+
+ // XXX: A workaround for invalidating VFS cache with the test file copied to our temp directory
+ LocalFileSystem.getInstance().refresh(false);
+
+ // Run inspections on code that uses named tuples
+ myFixture.configureByFile(getTestName(false) + ".py");
+ myFixture.enableInspections(PyUnresolvedReferencesInspection.class);
+
+ edt(new Runnable() {
+ @Override
+ public void run() {
+ myFixture.checkHighlighting(true, false, false);
+ }
+ });
+ }
+ });
+ }
+
+ public void testKnownPropertiesTypes() {
+ runTest(new SkeletonsTask() {
+ @Override
+ protected void runTestOn(@NotNull Sdk sdk) {
+ myFixture.configureByText(PythonFileType.INSTANCE,
+ "expr = slice(1, 2).start\n");
+ final PyExpression expr = myFixture.findElementByText("expr", PyExpression.class);
+ final TypeEvalContext context = TypeEvalContext.codeAnalysis(myFixture.getFile());
+ ApplicationManager.getApplication().runReadAction(new Runnable() {
+ @Override
+ public void run() {
+ final PyType type = context.getType(expr);
+ final String actualType = PythonDocumentationProvider.getTypeName(type, context);
+ assertEquals("int", actualType);
+ }
+ });
+ }
+ });
+ }
+
+ // PY-9797
+ public void testReadWriteDeletePropertyDefault() {
+ runTest(new SkeletonsTask() {
+ @Override
+ protected void runTestOn(@NotNull Sdk sdk) {
+ final LanguageLevel languageLevel = PythonSdkType.getLanguageLevelForSdk(sdk);
+ // We rely on int.real property that is not explicitly annotated in the skeletons generator
+ if (languageLevel.isOlderThan(LanguageLevel.PYTHON26)) {
+ return;
+ }
+ final Project project = myFixture.getProject();
+ final PyFile builtins = PyBuiltinCache.getBuiltinsForSdk(project, sdk);
+ assertNotNull(builtins);
+ ApplicationManager.getApplication().runReadAction(new Runnable() {
+ @Override
+ public void run() {
+ final PyClass cls = builtins.findTopLevelClass("int");
+ assertNotNull(cls);
+ final Property prop = cls.findProperty("real", true);
+ assertNotNull(prop);
+ assertIsNotNull(prop.getGetter());
+ assertIsNotNull(prop.getSetter());
+ assertIsNotNull(prop.getDeleter());
+ }
+ });
+ }
+
+ private void assertIsNotNull(Maybe<Callable> accessor) {
+ if (accessor.isDefined()) {
+ assertNotNull(accessor.valueOrNull());
+ }
+ }
+ });
+ }
+
+
+ private void runTest(@NotNull PyTestTask task) {
+ runPythonTest(task);
+ }
+
+
+ private abstract class SkeletonsTask extends PyExecutionFixtureTestTask {
+ @Override
+ protected String getTestDataPath() {
+ return PythonTestUtil.getTestDataPath() + "/skeletons/";
+ }
+
+ @Override
+ public void runTestOn(String sdkHome) throws Exception {
+ final Sdk sdk = createTempSdk(sdkHome, SdkCreationType.SDK_PACKAGES_AND_SKELETONS);
+ runTestOn(sdk);
+ }
+
+ @Override
+ public Set<String> getTags() {
+ return TAGS;
+ }
+
+ protected abstract void runTestOn(@NotNull Sdk sdk);
+ }
+}
diff --git a/python/testSrc/com/jetbrains/env/python/console/PyConsoleTask.java b/python/testSrc/com/jetbrains/env/python/console/PyConsoleTask.java
new file mode 100644
index 000000000000..9a242934042d
--- /dev/null
+++ b/python/testSrc/com/jetbrains/env/python/console/PyConsoleTask.java
@@ -0,0 +1,380 @@
+package com.jetbrains.env.python.console;
+
+import com.google.common.collect.Lists;
+import com.intellij.execution.console.LanguageConsoleView;
+import com.intellij.execution.process.ProcessAdapter;
+import com.intellij.execution.process.ProcessEvent;
+import com.intellij.openapi.application.Result;
+import com.intellij.openapi.application.WriteAction;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.projectRoots.Sdk;
+import com.intellij.openapi.util.Disposer;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.util.ui.UIUtil;
+import com.intellij.xdebugger.frame.XValueChildrenList;
+import com.jetbrains.env.PyExecutionFixtureTestTask;
+import com.jetbrains.python.console.*;
+import com.jetbrains.python.console.pydev.ConsoleCommunicationListener;
+import com.jetbrains.python.debugger.PyDebugValue;
+import com.jetbrains.python.debugger.PyDebuggerException;
+import com.jetbrains.python.sdkTools.SdkCreationType;
+import org.jetbrains.annotations.NotNull;
+import org.junit.Assert;
+
+import java.util.List;
+import java.util.concurrent.Semaphore;
+
+/**
+ * @author traff
+ */
+public class PyConsoleTask extends PyExecutionFixtureTestTask {
+ private boolean myProcessCanTerminate;
+
+ protected PyConsoleProcessHandler myProcessHandler;
+ protected PydevConsoleCommunication myCommunication;
+
+ private boolean shouldPrintOutput = false;
+ private PythonConsoleView myConsoleView;
+ private Semaphore mySemaphore;
+ private Semaphore mySemaphore0;
+ private PydevConsoleExecuteActionHandler myExecuteHandler;
+
+ public PyConsoleTask() {
+ setWorkingFolder(getTestDataPath());
+ }
+
+ public PythonConsoleView getConsoleView() {
+ return myConsoleView;
+ }
+
+ @Override
+ public void setUp(final String testName) throws Exception {
+ UIUtil.invokeAndWaitIfNeeded(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ if (myFixture == null) {
+ PyConsoleTask.super.setUp(testName);
+ }
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
+ }
+
+ @NotNull
+ protected String output() {
+ return myConsoleView.getConsole().getHistoryViewer().getDocument().getText();
+ }
+
+ public void setProcessCanTerminate(boolean processCanTerminate) {
+ myProcessCanTerminate = processCanTerminate;
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ UIUtil.invokeAndWaitIfNeeded(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ if (myConsoleView != null) {
+ disposeConsole();
+ }
+ PyConsoleTask.super.tearDown();
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
+ }
+
+ private void disposeConsole() throws InterruptedException {
+ if (myCommunication != null) {
+ UIUtil.invokeAndWaitIfNeeded(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ myCommunication.close();
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ }
+ myCommunication = null;
+ }
+ });
+ }
+
+ disposeConsoleProcess();
+
+ if (myConsoleView != null) {
+ new WriteAction() {
+ @Override
+ protected void run(@NotNull Result result) throws Throwable {
+ Disposer.dispose(myConsoleView);
+ myConsoleView = null;
+ }
+ }.execute();
+ }
+ }
+
+ @Override
+ public void runTestOn(final String sdkHome) throws Exception {
+ final Project project = getProject();
+
+ final Sdk sdk = createTempSdk(sdkHome, SdkCreationType.EMPTY_SDK);
+
+ setProcessCanTerminate(false);
+
+ PydevConsoleRunner consoleRunner = PydevConsoleRunner.create(project, sdk, PyConsoleType.PYTHON, getWorkingFolder());
+ before();
+
+ mySemaphore0 = new Semaphore(0);
+
+ consoleRunner.addConsoleListener(new PydevConsoleRunner.ConsoleListener() {
+ @Override
+ public void handleConsoleInitialized(LanguageConsoleView consoleView) {
+ mySemaphore0.release();
+ }
+ });
+
+ consoleRunner.run();
+
+ waitFor(mySemaphore0);
+
+ mySemaphore = new Semaphore(0);
+
+ myConsoleView = consoleRunner.getConsoleView();
+ myProcessHandler = (PyConsoleProcessHandler)consoleRunner.getProcessHandler();
+
+ myExecuteHandler = (PydevConsoleExecuteActionHandler)consoleRunner.getConsoleExecuteActionHandler();
+
+ myCommunication = consoleRunner.getPydevConsoleCommunication();
+
+ myCommunication.addCommunicationListener(new ConsoleCommunicationListener() {
+ @Override
+ public void commandExecuted(boolean more) {
+ mySemaphore.release();
+ }
+
+ @Override
+ public void inputRequested() {
+ }
+ });
+
+ myProcessHandler.addProcessListener(new ProcessAdapter() {
+ @Override
+ public void processTerminated(ProcessEvent event) {
+ if (event.getExitCode() != 0 && !myProcessCanTerminate) {
+ Assert.fail("Process terminated unexpectedly\n" + output());
+ }
+ }
+ });
+
+ OutputPrinter myOutputPrinter = null;
+ if (shouldPrintOutput) {
+ myOutputPrinter = new OutputPrinter();
+ myOutputPrinter.start();
+ }
+
+ waitForOutput("PyDev console");
+
+ try {
+ testing();
+ after();
+ }
+ finally {
+ setProcessCanTerminate(true);
+
+ if (myOutputPrinter != null) {
+ myOutputPrinter.stop();
+ }
+
+ disposeConsole();
+ }
+ }
+
+ private void disposeConsoleProcess() throws InterruptedException {
+ myProcessHandler.destroyProcess();
+
+ waitFor(myProcessHandler);
+
+ if (!myProcessHandler.isProcessTerminated()) {
+ if (!waitFor(myProcessHandler)) {
+ if (!myProcessHandler.isProcessTerminated()) {
+ throw new RuntimeException("Cannot stop console process");
+ }
+ }
+ }
+ myProcessHandler = null;
+ }
+
+ /**
+ * Waits until all passed strings appear in output.
+ * If they don't appear in time limit, then exception is raised.
+ *
+ * @param string
+ * @throws InterruptedException
+ */
+ public void waitForOutput(String... string) throws InterruptedException {
+ int count = 0;
+ while (true) {
+ List<String> missing = Lists.newArrayList();
+ String out = output();
+ boolean flag = true;
+ for (String s : string) {
+ if (!out.contains(s)) {
+ flag = false;
+ missing.add(s);
+ }
+ }
+ if (flag) {
+ break;
+ }
+ if (count > 10) {
+ Assert.fail("Strings: <--\n" + StringUtil.join(missing, "\n---\n") + "-->" + "are not present in output.\n" + output());
+ }
+ Thread.sleep(2000);
+ count++;
+ }
+ }
+
+ protected void waitForReady() throws InterruptedException {
+ int count = 0;
+ while (!myExecuteHandler.isEnabled() || !canExecuteNow()) {
+ if (count > 10) {
+ Assert.fail("Console is not ready");
+ }
+ Thread.sleep(300);
+ count++;
+ }
+ }
+
+ protected boolean canExecuteNow() {
+ return myExecuteHandler.canExecuteNow();
+ }
+
+ public void setShouldPrintOutput(boolean shouldPrintOutput) {
+ this.shouldPrintOutput = shouldPrintOutput;
+ }
+
+ private class OutputPrinter {
+ private Thread myThread;
+ private int myLen = 0;
+
+ public void start() {
+ myThread = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ doJob();
+ }
+ });
+ myThread.setDaemon(true);
+ myThread.start();
+ }
+
+ private void doJob() {
+ try {
+ while (true) {
+ printToConsole();
+
+ Thread.sleep(500);
+ }
+ }
+ catch (Exception ignored) {
+ }
+ }
+
+ private synchronized void printToConsole() {
+ String s = output();
+ if (s.length() > myLen) {
+ System.out.print(s.substring(myLen));
+ }
+ myLen = s.length();
+ }
+
+ public void stop() {
+ printToConsole();
+ myThread.interrupt();
+ }
+ }
+
+ protected void exec(String command) throws InterruptedException {
+ waitForReady();
+ int p = mySemaphore.availablePermits();
+ myConsoleView.executeInConsole(command);
+ mySemaphore.acquire(p + 1);
+ //waitForOutput(">>> " + command);
+ }
+
+ protected boolean hasValue(String varName, String value) throws PyDebuggerException {
+ PyDebugValue val = getValue(varName);
+ return val != null && value.equals(val.getValue());
+ }
+
+ protected void setValue(String varName, String value) throws PyDebuggerException {
+ PyDebugValue val = getValue(varName);
+ myCommunication.changeVariable(val, value);
+ }
+
+ protected PyDebugValue getValue(String varName) throws PyDebuggerException {
+ XValueChildrenList l = myCommunication.loadFrame();
+
+ if (l == null) {
+ return null;
+ }
+ for (int i = 0; i < l.size(); i++) {
+ String name = l.getName(i);
+ if (varName.equals(name)) {
+ return (PyDebugValue)l.getValue(i);
+ }
+ }
+
+ return null;
+ }
+
+ protected List<String> getCompoundValueChildren(PyDebugValue value) throws PyDebuggerException {
+ XValueChildrenList list = myCommunication.loadVariable(value);
+ List<String> result = Lists.newArrayList();
+ for (int i = 0; i<list.size(); i++) {
+ result.add(((PyDebugValue)list.getValue(i)).getValue());
+ }
+ return result;
+ }
+
+ protected void input(String text) {
+ myConsoleView.executeInConsole(text);
+ }
+
+ protected void waitForFinish() throws InterruptedException {
+ waitFor(mySemaphore);
+ }
+
+ protected void execNoWait(final String command) {
+ UIUtil.invokeLaterIfNeeded(new Runnable() {
+ @Override
+ public void run() {
+ myConsoleView.executeCode(command, null);
+ }
+ });
+ }
+
+ protected void interrupt() {
+ myCommunication.interrupt();
+ }
+
+
+ public void addTextToEditor(final String text) {
+ UIUtil.invokeAndWaitIfNeeded(new Runnable() {
+ @Override
+ public void run() {
+ getConsoleView().getLanguageConsole().setInputText(text);
+ PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
+ }
+ }
+ );
+ }
+}
diff --git a/python/testSrc/com/jetbrains/env/python/debug/PyBaseDebuggerTask.java b/python/testSrc/com/jetbrains/env/python/debug/PyBaseDebuggerTask.java
new file mode 100644
index 000000000000..38eed736c7ef
--- /dev/null
+++ b/python/testSrc/com/jetbrains/env/python/debug/PyBaseDebuggerTask.java
@@ -0,0 +1,361 @@
+package com.jetbrains.env.python.debug;
+
+import com.google.common.collect.Sets;
+import com.intellij.openapi.application.Result;
+import com.intellij.openapi.application.WriteAction;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.JarFileSystem;
+import com.intellij.openapi.vfs.LocalFileSystem;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.ui.UIUtil;
+import com.intellij.xdebugger.*;
+import com.intellij.xdebugger.frame.XValue;
+import com.jetbrains.env.PyExecutionFixtureTestTask;
+import com.jetbrains.python.console.PythonDebugLanguageConsoleView;
+import com.jetbrains.python.debugger.PyDebugProcess;
+import com.jetbrains.python.debugger.PyDebugValue;
+import com.jetbrains.python.debugger.PyDebuggerException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.junit.Assert;
+
+import java.io.PrintWriter;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Set;
+import java.util.concurrent.Semaphore;
+
+/**
+ * @author traff
+ */
+public abstract class PyBaseDebuggerTask extends PyExecutionFixtureTestTask {
+ private Set<Pair<String, Integer>> myBreakpoints = Sets.newHashSet();
+ protected PyDebugProcess myDebugProcess;
+ protected XDebugSession mySession;
+ protected Semaphore myPausedSemaphore;
+ protected Semaphore myTerminateSemaphore;
+ protected boolean shouldPrintOutput = false;
+ protected boolean myProcessCanTerminate;
+
+ protected void waitForPause() throws InterruptedException, InvocationTargetException {
+ Assert.assertTrue("Debugger didn't stopped within timeout\nOutput:" + output(), waitFor(myPausedSemaphore));
+
+ XDebuggerTestUtil.waitForSwing();
+ }
+
+ protected void waitForTerminate() throws InterruptedException, InvocationTargetException {
+ setProcessCanTerminate(true);
+
+ Assert.assertTrue("Debugger didn't terminated within timeout\nOutput:" + output(), waitFor(myTerminateSemaphore));
+ XDebuggerTestUtil.waitForSwing();
+ }
+
+ protected void runToLine(int line) throws InvocationTargetException, InterruptedException {
+ XDebugSession currentSession = XDebuggerManager.getInstance(getProject()).getCurrentSession();
+ XSourcePosition position = currentSession.getCurrentPosition();
+
+
+ currentSession.runToPosition(XDebuggerUtil.getInstance().createPosition(position.getFile(), line), false);
+
+ waitForPause();
+ }
+
+ protected void resume() {
+ XDebugSession currentSession = XDebuggerManager.getInstance(getProject()).getCurrentSession();
+
+ Assert.assertTrue(currentSession.isSuspended());
+ Assert.assertEquals(0, myPausedSemaphore.availablePermits());
+
+ currentSession.resume();
+ }
+
+ protected void stepOver() {
+ XDebugSession currentSession = XDebuggerManager.getInstance(getProject()).getCurrentSession();
+
+ Assert.assertTrue(currentSession.isSuspended());
+ Assert.assertEquals(0, myPausedSemaphore.availablePermits());
+
+ currentSession.stepOver(false);
+ }
+
+ protected void stepInto() {
+ XDebugSession currentSession = XDebuggerManager.getInstance(getProject()).getCurrentSession();
+
+ Assert.assertTrue(currentSession.isSuspended());
+ Assert.assertEquals(0, myPausedSemaphore.availablePermits());
+
+ currentSession.stepInto();
+ }
+
+ protected void smartStepInto(String funcName) {
+ XDebugSession currentSession = XDebuggerManager.getInstance(getProject()).getCurrentSession();
+
+ Assert.assertTrue(currentSession.isSuspended());
+ Assert.assertEquals(0, myPausedSemaphore.availablePermits());
+
+ myDebugProcess.startSmartStepInto(funcName);
+ }
+
+ @NotNull
+ protected String output() {
+ if (mySession != null && mySession.getConsoleView() != null) {
+ PythonDebugLanguageConsoleView pydevConsoleView = (PythonDebugLanguageConsoleView)mySession.getConsoleView();
+ if (pydevConsoleView != null) {
+ return XDebuggerTestUtil.getConsoleText(pydevConsoleView.getTextConsole());
+ }
+ }
+ return "Console output not available.";
+ }
+
+ protected void input(String text) {
+ PrintWriter pw = new PrintWriter(myDebugProcess.getProcessHandler().getProcessInput());
+ pw.println(text);
+ pw.flush();
+ }
+
+ private void outputContains(String substring) {
+ Assert.assertTrue(output().contains(substring));
+ }
+
+ public void setProcessCanTerminate(boolean processCanTerminate) {
+ myProcessCanTerminate = processCanTerminate;
+ }
+
+ protected void clearAllBreakpoints() {
+
+ UIUtil.invokeAndWaitIfNeeded(new Runnable() {
+ @Override
+ public void run() {
+ XDebuggerTestUtil.removeAllBreakpoints(getProject());
+ }
+ });
+ }
+
+ /**
+ * Toggles breakpoint
+ *
+ * @param file getScriptPath() or path to script
+ * @param line starting with 0
+ */
+ protected void toggleBreakpoint(final String file, final int line) {
+ UIUtil.invokeAndWaitIfNeeded(new Runnable() {
+ @Override
+ public void run() {
+ doToggleBreakpoint(file, line);
+ }
+ });
+
+ addOrRemoveBreakpoint(file, line);
+ }
+
+ private void addOrRemoveBreakpoint(String file, int line) {
+ if (myBreakpoints.contains(Pair.create(file, line))) {
+ myBreakpoints.remove(Pair.create(file, line));
+ }
+ else {
+ myBreakpoints.add(Pair.create(file, line));
+ }
+ }
+
+ protected void toggleBreakpointInEgg(final String file, final String innerPath, final int line) {
+ UIUtil.invokeAndWaitIfNeeded(new Runnable() {
+ @Override
+ public void run() {
+ VirtualFile f = LocalFileSystem.getInstance().findFileByPath(file);
+ Assert.assertNotNull(f);
+ final VirtualFile jarRoot = JarFileSystem.getInstance().getJarRootForLocalFile(f);
+ Assert.assertNotNull(jarRoot);
+ VirtualFile innerFile = jarRoot.findFileByRelativePath(innerPath);
+ Assert.assertNotNull(innerFile);
+ XDebuggerTestUtil.toggleBreakpoint(getProject(), innerFile, line);
+ }
+ });
+
+ addOrRemoveBreakpoint(file, line);
+ }
+
+ public boolean canPutBreakpointAt(Project project, String file, int line) {
+ VirtualFile vFile = LocalFileSystem.getInstance().findFileByPath(file);
+ Assert.assertNotNull(vFile);
+ return XDebuggerUtil.getInstance().canPutBreakpointAt(project, vFile, line);
+ }
+
+ private void doToggleBreakpoint(String file, int line) {
+ Assert.assertTrue(canPutBreakpointAt(getProject(), file, line));
+ XDebuggerTestUtil.toggleBreakpoint(getProject(), LocalFileSystem.getInstance().findFileByPath(file), line);
+ }
+
+ protected Variable eval(String name) throws InterruptedException {
+ Assert.assertTrue("Eval works only while suspended", mySession.isSuspended());
+ XValue var = XDebuggerTestUtil.evaluate(mySession, name).first;
+ Assert.assertNotNull("There is no variable named " + name, var);
+ return new Variable(var);
+ }
+
+ protected void setVal(String name, String value) throws InterruptedException, PyDebuggerException {
+ XValue var = XDebuggerTestUtil.evaluate(mySession, name).first;
+ myDebugProcess.changeVariable((PyDebugValue)var, value);
+ }
+
+ public void waitForOutput(String ... string) throws InterruptedException {
+ long started = System.currentTimeMillis();
+
+ while (!containsOneOf(output(), string)) {
+ if (System.currentTimeMillis() - started > myTimeout) {
+ Assert.fail("None of '" + StringUtil.join(string, ", ") + "'" + " is not present in output.\n" + output());
+ }
+ Thread.sleep(2000);
+ }
+ }
+
+ protected boolean containsOneOf(String output, String[] strings) {
+ for (String s: strings) {
+ if (output.contains(s)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+
+ public void setShouldPrintOutput(boolean shouldPrintOutput) {
+ this.shouldPrintOutput = shouldPrintOutput;
+ }
+
+ @Override
+ public void setUp(final String testName) throws Exception {
+ UIUtil.invokeAndWaitIfNeeded(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ if (myFixture == null) {
+ PyBaseDebuggerTask.super.setUp(testName);
+ }
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ UIUtil.invokeAndWaitIfNeeded(new Runnable() {
+ public void run() {
+ try {
+ if (mySession != null) {
+ finishSession();
+ }
+ PyBaseDebuggerTask.super.tearDown();
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
+ }
+
+ protected void finishSession() throws InterruptedException {
+ disposeDebugProcess();
+
+ if (mySession != null) {
+ new WriteAction() {
+ protected void run(Result result) throws Throwable {
+ mySession.stop();
+ }
+ }.execute();
+
+ waitFor(mySession.getDebugProcess().getProcessHandler()); //wait for process termination after session.stop() which is async
+
+ XDebuggerTestUtil.disposeDebugSession(mySession);
+ mySession = null;
+ myDebugProcess = null;
+ myPausedSemaphore = null;
+ }
+ }
+
+ protected abstract void disposeDebugProcess() throws InterruptedException;
+
+ protected void doTest(@Nullable OutputPrinter myOutputPrinter) throws InterruptedException {
+ try {
+ testing();
+ after();
+ }
+ catch (Throwable e) {
+ throw new RuntimeException(output(), e);
+ }
+ finally {
+ clearAllBreakpoints();
+
+ setProcessCanTerminate(true);
+
+ if (myOutputPrinter != null) {
+ myOutputPrinter.stop();
+ }
+
+ finishSession();
+ }
+ }
+
+ protected static class Variable {
+ private final XTestValueNode myValueNode;
+
+ public Variable(XValue value) throws InterruptedException {
+ myValueNode = XDebuggerTestUtil.computePresentation(value);
+ }
+
+ public Variable hasValue(String value) {
+ Assert.assertEquals(value, myValueNode.myValue);
+ return this;
+ }
+
+ public Variable hasType(String type) {
+ Assert.assertEquals(type, myValueNode.myType);
+ return this;
+ }
+
+ public Variable hasName(String name) {
+ Assert.assertEquals(name, myValueNode.myName);
+ return this;
+ }
+ }
+
+ public class OutputPrinter {
+ private Thread myThread;
+
+ public void start() {
+ myThread = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ doJob();
+ }
+ });
+ myThread.setDaemon(true);
+ myThread.start();
+ }
+
+ private void doJob() {
+ int len = 0;
+ try {
+ while (true) {
+ String s = output();
+ if (s.length() > len) {
+ System.out.print(s.substring(len));
+ }
+ len = s.length();
+
+ Thread.sleep(500);
+ }
+ }
+ catch (Exception e) {
+ }
+ }
+
+ public void stop() {
+ myThread.interrupt();
+ }
+ }
+}
diff --git a/python/testSrc/com/jetbrains/env/python/debug/PyDebuggerTask.java b/python/testSrc/com/jetbrains/env/python/debug/PyDebuggerTask.java
new file mode 100644
index 000000000000..7de13d1ebed6
--- /dev/null
+++ b/python/testSrc/com/jetbrains/env/python/debug/PyDebuggerTask.java
@@ -0,0 +1,211 @@
+package com.jetbrains.env.python.debug;
+
+import com.intellij.execution.*;
+import com.intellij.execution.configurations.ConfigurationFactory;
+import com.intellij.execution.configurations.RunProfile;
+import com.intellij.execution.executors.DefaultDebugExecutor;
+import com.intellij.execution.process.KillableColoredProcessHandler;
+import com.intellij.execution.process.ProcessAdapter;
+import com.intellij.execution.process.ProcessEvent;
+import com.intellij.execution.process.ProcessHandler;
+import com.intellij.execution.runners.ExecutionEnvironment;
+import com.intellij.openapi.application.Result;
+import com.intellij.openapi.application.WriteAction;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Key;
+import com.intellij.xdebugger.*;
+import com.jetbrains.python.debugger.PyDebugProcess;
+import com.jetbrains.python.debugger.PyDebugRunner;
+import com.jetbrains.python.run.PythonCommandLineState;
+import com.jetbrains.python.run.PythonConfigurationType;
+import com.jetbrains.python.run.PythonRunConfiguration;
+import org.jetbrains.annotations.NotNull;
+import org.junit.Assert;
+
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.util.concurrent.Semaphore;
+
+/**
+ * @author traff
+ */
+public class PyDebuggerTask extends PyBaseDebuggerTask {
+
+ private boolean myMultiprocessDebug = false;
+ private PythonRunConfiguration myRunConfiguration;
+
+ public PyDebuggerTask() {
+ init();
+ }
+
+ public PyDebuggerTask(String workingFolder, String scriptName, String scriptParameters) {
+ setWorkingFolder(getTestDataPath() + workingFolder);
+ setScriptName(scriptName);
+ setScriptParameters(scriptParameters);
+ init();
+ }
+
+ public PyDebuggerTask(String workingFolder, String scriptName) {
+ this(workingFolder, scriptName, null);
+ }
+
+ protected void init() {
+
+ }
+
+ public void runTestOn(String sdkHome) throws Exception {
+ final Project project = getProject();
+
+ final ConfigurationFactory factory = PythonConfigurationType.getInstance().getConfigurationFactories()[0];
+
+
+ final RunnerAndConfigurationSettings settings =
+ RunManager.getInstance(project).createRunConfiguration("test", factory);
+
+ myRunConfiguration = (PythonRunConfiguration)settings.getConfiguration();
+
+ myRunConfiguration.setSdkHome(sdkHome);
+ myRunConfiguration.setScriptName(getScriptPath());
+ myRunConfiguration.setWorkingDirectory(getWorkingFolder());
+ myRunConfiguration.setScriptParameters(getScriptParameters());
+
+ new WriteAction() {
+ @Override
+ protected void run(Result result) throws Throwable {
+ RunManagerEx.getInstanceEx(project).addConfiguration(settings, false);
+ RunManagerEx.getInstanceEx(project).setSelectedConfiguration(settings);
+ Assert.assertSame(settings, RunManagerEx.getInstanceEx(project).getSelectedConfiguration());
+ }
+ }.execute();
+
+ final PyDebugRunner runner = (PyDebugRunner)ProgramRunnerUtil.getRunner(DefaultDebugExecutor.EXECUTOR_ID, settings);
+ Assert.assertTrue(runner.canRun(DefaultDebugExecutor.EXECUTOR_ID, myRunConfiguration));
+
+ final Executor executor = DefaultDebugExecutor.getDebugExecutorInstance();
+ final ExecutionEnvironment env = new ExecutionEnvironment(executor, runner, settings, project);
+
+ final PythonCommandLineState pyState = (PythonCommandLineState)myRunConfiguration.getState(executor, env);
+
+ assert pyState != null;
+ pyState.setMultiprocessDebug(isMultiprocessDebug());
+
+ final ServerSocket serverSocket;
+ try {
+ //noinspection SocketOpenedButNotSafelyClosed
+ serverSocket = new ServerSocket(0);
+ }
+ catch (IOException e) {
+ throw new ExecutionException("Failed to find free socket port", e);
+ }
+
+
+ final int serverLocalPort = serverSocket.getLocalPort();
+ final RunProfile profile = env.getRunProfile();
+
+ before();
+
+ setProcessCanTerminate(false);
+
+ myTerminateSemaphore = new Semaphore(0);
+
+ new WriteAction<ExecutionResult>() {
+ @Override
+ protected void run(@NotNull Result<ExecutionResult> result) throws Throwable {
+ final ExecutionResult res =
+ pyState.execute(executor, PyDebugRunner.createCommandLinePatchers(myFixture.getProject(), pyState, profile, serverLocalPort));
+
+ mySession = XDebuggerManager.getInstance(getProject()).
+ startSession(runner, env, env.getContentToReuse(), new XDebugProcessStarter() {
+ @NotNull
+ public XDebugProcess start(@NotNull final XDebugSession session) {
+ myDebugProcess =
+ new PyDebugProcess(session, serverSocket, res.getExecutionConsole(), res.getProcessHandler(), isMultiprocessDebug());
+
+ myDebugProcess.getProcessHandler().addProcessListener(new ProcessAdapter() {
+
+ @Override
+ public void onTextAvailable(ProcessEvent event, Key outputType) {
+ }
+
+ @Override
+ public void processTerminated(ProcessEvent event) {
+ myTerminateSemaphore.release();
+ if (event.getExitCode() != 0 && !myProcessCanTerminate) {
+ Assert.fail("Process terminated unexpectedly\n" + output());
+ }
+ }
+ });
+
+
+ myDebugProcess.getProcessHandler().startNotify();
+
+ return myDebugProcess;
+ }
+ });
+ result.setResult(res);
+ }
+ }.execute().getResultObject();
+
+ OutputPrinter myOutputPrinter = null;
+ if (shouldPrintOutput) {
+ myOutputPrinter = new OutputPrinter();
+ myOutputPrinter.start();
+ }
+
+
+ myPausedSemaphore = new Semaphore(0);
+
+
+ mySession.addSessionListener(new XDebugSessionAdapter() {
+ @Override
+ public void sessionPaused() {
+ if (myPausedSemaphore != null) {
+ myPausedSemaphore.release();
+ }
+ }
+ });
+
+ doTest(myOutputPrinter);
+ }
+
+ public PythonRunConfiguration getRunConfiguration() {
+ return myRunConfiguration;
+ }
+
+ private boolean isMultiprocessDebug() {
+ return myMultiprocessDebug;
+ }
+
+ public void setMultiprocessDebug(boolean multiprocessDebug) {
+ myMultiprocessDebug = multiprocessDebug;
+ }
+
+ @Override
+ protected void disposeDebugProcess() throws InterruptedException {
+ if (myDebugProcess != null) {
+ ProcessHandler processHandler = myDebugProcess.getProcessHandler();
+
+ myDebugProcess.stop();
+
+ waitFor(processHandler);
+
+ if (!processHandler.isProcessTerminated()) {
+ killDebugProcess();
+ if (!waitFor(processHandler)) {
+ new Throwable("Cannot stop debugger process").printStackTrace();
+ }
+ }
+ }
+ }
+
+ private void killDebugProcess() {
+ if (myDebugProcess.getProcessHandler() instanceof KillableColoredProcessHandler) {
+ KillableColoredProcessHandler h = (KillableColoredProcessHandler)myDebugProcess.getProcessHandler();
+
+ h.killProcess();
+ }
+ else {
+ myDebugProcess.getProcessHandler().destroyProcess();
+ }
+ }
+}
diff --git a/python/testSrc/com/jetbrains/env/python/dotNet/PyIronPythonTest.java b/python/testSrc/com/jetbrains/env/python/dotNet/PyIronPythonTest.java
new file mode 100644
index 000000000000..a6f9dd68971d
--- /dev/null
+++ b/python/testSrc/com/jetbrains/env/python/dotNet/PyIronPythonTest.java
@@ -0,0 +1,145 @@
+package com.jetbrains.env.python.dotNet;
+
+import com.intellij.openapi.application.ReadAction;
+import com.intellij.openapi.application.Result;
+import com.jetbrains.env.PyEnvTestCase;
+import com.jetbrains.python.psi.PyFile;
+import org.jetbrains.annotations.NotNull;
+import org.junit.Assert;
+
+/**
+ * IronPython.NET specific tests
+ *
+ * @author Ilya.Kazakevich
+ */
+public class PyIronPythonTest extends PyEnvTestCase {
+
+ /**
+ * IronPython tag
+ */
+ static final String IRON_TAG = "iron";
+
+ public PyIronPythonTest() {
+ super(IRON_TAG);
+ }
+
+ /**
+ * Tests skeleton generation
+ */
+ public void testSkeletons() throws Exception {
+ runPythonTest(new SkeletonTestTask(
+ "dotNet/expected.skeleton.java.py",
+ "com.just.like.java",
+ "testSkeleton.py",
+ null
+ ));
+ }
+
+ /**
+ * Tests skeleton generation with "from" statements
+ */
+ public void testClassFromModule() throws Exception {
+ runPythonTest(new SkeletonTestTask(
+ "dotNet/expected.skeleton.java.py",
+ "com.just.like.java",
+ "import_class_from_module.py",
+ null
+ ));
+ }
+
+ /**
+ * Tests skeleton generation when imported as alias
+ */
+ public void testClassFromModuleAlias() throws Exception {
+ runPythonTest(new SkeletonTestTask(
+ "dotNet/expected.skeleton.java.py",
+ "com.just.like.java",
+ "import_class_from_module_alias.py",
+ null
+ ));
+ }
+
+ /**
+ * Tests skeleton generation when module is imported
+ */
+ public void testModuleFromPackage() throws Exception {
+ runPythonTest(new SkeletonTestTask(
+ "dotNet/expected.skeleton.java.py",
+ "com.just.like.java",
+ "import_module_from_package.py",
+ null
+ ));
+ }
+
+ /**
+ * Tests skeleton generation when several classes are imported
+ */
+ public void testSeveralClasses() throws Exception {
+ runPythonTest(new SkeletonTestTask(
+ "dotNet/expected.skeleton.java.py",
+ "com.just.like.java",
+ "import_several_classes_from_module.py",
+ "com.just.like.java.LikeJavaClass"
+ ));
+ }
+
+ /**
+ * Tests skeletons for built-in classes. We can't compare files (CLR class may be changed from version to version),
+ * but we are sure there should be class System.Web.AspNetHostingPermissionLevel which is part of public API
+ */
+ public void testImportBuiltInSystem() throws Exception {
+ final SkeletonTestTask task = new SkeletonTestTask(
+ null,
+ "System.Web",
+ "import_system.py",
+ null
+ );
+ runPythonTest(task);
+ final PyFile skeleton = task.getGeneratedSkeleton();
+ new ReadAction() {
+ @Override
+ protected void run(@NotNull Result result) throws Throwable {
+ Assert.assertNotNull("System.Web does not contain class AspNetHostingPermissionLevel. Error generating stub? It has classes " +
+ skeleton.getTopLevelClasses(),
+ skeleton.findTopLevelClass("AspNetHostingPermissionLevel"));
+ }
+ }.execute();
+
+ }
+
+ /**
+ * Test importing of inner classes
+ */
+ public void testImportInnerClass() throws Exception {
+ runPythonTest(new SkeletonTestTask(
+ "dotNet/expected.skeleton.Deep.py",
+ "SingleNameSpace.Some.Deep",
+ "inner_class.py",
+ null
+ ));
+ }
+
+ /**
+ * Test importing of the whole namespace
+ */
+ public void testWholeNameSpace() throws Exception {
+ runPythonTest(new SkeletonTestTask(
+ "dotNet/expected.skeleton.SingleNameSpace.py",
+ "SingleNameSpace",
+ "whole_namespace.py",
+ null
+ ));
+ }
+
+ /**
+ * Test importing of single class
+ */
+ public void testSingleClass() throws Exception {
+ runPythonTest(new SkeletonTestTask(
+ "dotNet/expected.skeleton.SingleNameSpace.py",
+ "SingleNameSpace",
+ "single_class.py",
+ null
+ ));
+ }
+}
diff --git a/python/testSrc/com/jetbrains/env/python/dotNet/SkeletonTestTask.java b/python/testSrc/com/jetbrains/env/python/dotNet/SkeletonTestTask.java
new file mode 100644
index 000000000000..e10916cbe7de
--- /dev/null
+++ b/python/testSrc/com/jetbrains/env/python/dotNet/SkeletonTestTask.java
@@ -0,0 +1,142 @@
+package com.jetbrains.env.python.dotNet;
+
+import com.google.common.collect.Sets;
+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.progress.Task;
+import com.intellij.openapi.progress.util.AbstractProgressIndicatorBase;
+import com.intellij.openapi.projectRoots.Sdk;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.util.ui.UIUtil;
+import com.jetbrains.env.PyExecutionFixtureTestTask;
+import com.jetbrains.python.PyBundle;
+import com.jetbrains.python.PyNames;
+import com.jetbrains.python.inspections.quickfix.GenerateBinaryStubsFix;
+import com.jetbrains.python.inspections.unresolvedReference.PyUnresolvedReferencesInspection;
+import com.jetbrains.python.psi.PyFile;
+import com.jetbrains.python.sdk.InvalidSdkException;
+import com.jetbrains.python.sdk.PythonSdkType;
+import com.jetbrains.python.sdkTools.SdkCreationType;
+import org.hamcrest.Matchers;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.junit.Assert;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Set;
+
+/**
+ * Task for test that checks skeleton generation
+ *
+ * @author Ilya.Kazakevich
+ */
+class SkeletonTestTask extends PyExecutionFixtureTestTask {
+
+ /**
+ * Tags for this task to run
+ */
+ private static final Set<String> IRON_TAGS = Sets.newHashSet(PyIronPythonTest.IRON_TAG);
+ /**
+ * Number of seconds we wait for skeleton generation external process (should be enough)
+ */
+ private static final int SECONDS_TO_WAIT_FOR_SKELETON_GENERATION = 20;
+
+ @Nullable
+ private final String myExpectedSkeletonFile;
+ @NotNull
+ private final String myModuleNameToBeGenerated;
+ @NotNull
+ private final String mySourceFileToRunGenerationOn;
+ @NotNull
+ private final String myUseQuickFixWithThisModuleOnly;
+ private PyFile myGeneratedSkeleton;
+
+ /**
+ * @param expectedSkeletonFile if you want test to compare generated result with some file, provide its name.
+ * Pass null if you do not want to compare result with anything (you may do it yourself with {@link #getGeneratedSkeleton()})
+ * @param moduleNameToBeGenerated name of module you think we should generate in dotted notation (like "System.Web" or "com.myModule").
+ * System will wait for skeleton file for this module to be generated
+ * @param sourceFileToRunGenerationOn Source file where we should run "generate stubs" on. Be sure to place "caret" on appropriate place!
+ * @param useQuickFixWithThisModuleOnly If there are several quick fixes in code, you may run fix only on this module.
+ * Pass null if you are sure there would be only one quickfix
+ */
+ SkeletonTestTask(@Nullable final String expectedSkeletonFile,
+ @NotNull final String moduleNameToBeGenerated,
+ @NotNull final String sourceFileToRunGenerationOn,
+ @Nullable final String useQuickFixWithThisModuleOnly) {
+ myExpectedSkeletonFile = expectedSkeletonFile;
+ myModuleNameToBeGenerated = moduleNameToBeGenerated.replace('.', '/');
+ mySourceFileToRunGenerationOn = sourceFileToRunGenerationOn;
+ myUseQuickFixWithThisModuleOnly = useQuickFixWithThisModuleOnly != null ? useQuickFixWithThisModuleOnly : "";
+ }
+
+
+ @Override
+ public void runTestOn(@NotNull final String sdkHome) throws IOException, InvalidSdkException {
+ final Sdk sdk = createTempSdk(sdkHome, SdkCreationType.SDK_PACKAGES_ONLY);
+ final File skeletonsPath = new File(PythonSdkType.getSkeletonsPath(PathManager.getSystemPath(), sdk.getHomePath()));
+ File skeletonFileOrDirectory = new File(skeletonsPath, myModuleNameToBeGenerated); // File with module skeleton
+
+ // Module may be stored in "moduleName.py" or "moduleName/__init__.py"
+ if (skeletonFileOrDirectory.isDirectory()) {
+ skeletonFileOrDirectory = new File(skeletonFileOrDirectory, PyNames.INIT_DOT_PY);
+ }
+ else {
+ skeletonFileOrDirectory = new File(skeletonFileOrDirectory.getAbsolutePath() + PyNames.DOT_PY);
+ }
+
+ final File skeletonFile = skeletonFileOrDirectory;
+
+ if (skeletonFile.exists()) { // To make sure we do not reuse it
+ assert skeletonFile.delete() : "Failed to delete file " + skeletonFile;
+ }
+
+ myFixture.copyFileToProject("dotNet/" + mySourceFileToRunGenerationOn, mySourceFileToRunGenerationOn); // File that uses CLR library
+ myFixture.copyFileToProject("dotNet/PythonLibs.dll", "PythonLibs.dll"); // Library itself
+ myFixture.copyFileToProject("dotNet/SingleNameSpace.dll", "SingleNameSpace.dll"); // Another library
+ myFixture.configureByFile(mySourceFileToRunGenerationOn);
+ myFixture.enableInspections(PyUnresolvedReferencesInspection.class); // This inspection should suggest us to generate stubs
+
+
+ UIUtil.invokeAndWaitIfNeeded(new Runnable() {
+ @Override
+ public void run() {
+ PsiDocumentManager.getInstance(myFixture.getProject()).commitAllDocuments();
+ final String intentionName = PyBundle.message("sdk.gen.stubs.for.binary.modules", myUseQuickFixWithThisModuleOnly);
+ final IntentionAction intention = myFixture.findSingleIntention(intentionName);
+ Assert.assertNotNull("No intention found to generate skeletons!", intention);
+ Assert.assertThat("Intention should be quick fix to run", intention, Matchers.instanceOf(QuickFixWrapper.class));
+ final LocalQuickFix quickFix = ((QuickFixWrapper)intention).getFix();
+ Assert.assertThat("Quick fix should be 'generate binary skeletons' fix to run", quickFix,
+ Matchers.instanceOf(GenerateBinaryStubsFix.class));
+ final Task fixTask = ((GenerateBinaryStubsFix)quickFix).getFixTask(myFixture.getFile());
+ fixTask.run(new AbstractProgressIndicatorBase());
+ }
+ });
+
+ FileUtil.copy(skeletonFile, new File(myFixture.getTempDirPath(), skeletonFile.getName()));
+ if (myExpectedSkeletonFile != null) {
+ myFixture.checkResultByFile(skeletonFile.getName(), myExpectedSkeletonFile, false);
+ }
+ myGeneratedSkeleton = (PyFile)myFixture.configureByFile(skeletonFile.getName());
+ }
+
+
+ @Override
+ public Set<String> getTags() {
+ return Collections.unmodifiableSet(IRON_TAGS);
+ }
+
+ /**
+ * @return File for generated skeleton. Call it after {@link #runTestOn(String)} only!
+ */
+ @NotNull
+ PyFile getGeneratedSkeleton() {
+ return myGeneratedSkeleton;
+ }
+}
diff --git a/python/testSrc/com/jetbrains/env/python/dotNet/package-info.java b/python/testSrc/com/jetbrains/env/python/dotNet/package-info.java
new file mode 100644
index 000000000000..e56e6203b98d
--- /dev/null
+++ b/python/testSrc/com/jetbrains/env/python/dotNet/package-info.java
@@ -0,0 +1,5 @@
+/**
+ * IronPython tests. Install IronPython, .NET and add "iron" to "tags.txt" file. Check for more info: http://confluence.jetbrains.com/display/PYINT/Env+Tests
+ * @author Ilya.Kazakevich
+ */
+package com.jetbrains.env.python.dotNet; \ No newline at end of file
diff --git a/python/testSrc/com/jetbrains/env/python/testing/PythonDocTestingTest.java b/python/testSrc/com/jetbrains/env/python/testing/PythonDocTestingTest.java
new file mode 100644
index 000000000000..411b6049350a
--- /dev/null
+++ b/python/testSrc/com/jetbrains/env/python/testing/PythonDocTestingTest.java
@@ -0,0 +1,66 @@
+package com.jetbrains.env.python.testing;
+
+import com.jetbrains.env.PyEnvTestCase;
+import com.jetbrains.env.ut.PyDocTestTask;
+
+/**
+ * User : catherine
+ */
+public class PythonDocTestingTest extends PyEnvTestCase{
+ public void testUTRunner() {
+ runPythonTest(new PyDocTestTask("/testRunner/env/doc", "test1.py") {
+
+ @Override
+ public void after() {
+ assertEquals(3, allTestsCount());
+ assertEquals(3, passedTestsCount());
+ allTestsPassed();
+ }
+ });
+ }
+
+ public void testClass() {
+ runPythonTest(new PyDocTestTask("/testRunner/env/doc", "test1.py::FirstGoodTest") {
+
+ @Override
+ public void after() {
+ assertEquals(1, allTestsCount());
+ assertEquals(1, passedTestsCount());
+ }
+ });
+ }
+
+ public void testMethod() {
+ runPythonTest(new PyDocTestTask("/testRunner/env/doc", "test1.py::SecondGoodTest::test_passes") {
+
+ @Override
+ public void after() {
+ assertEquals(1, allTestsCount());
+ assertEquals(1, passedTestsCount());
+ }
+ });
+ }
+
+ public void testFunction() {
+ runPythonTest(new PyDocTestTask("/testRunner/env/doc", "test1.py::factorial") {
+
+ @Override
+ public void after() {
+ assertEquals(1, allTestsCount());
+ assertEquals(1, passedTestsCount());
+ }
+ });
+ }
+
+ public void testUTRunner2() {
+ runPythonTest(new PyDocTestTask("/testRunner/env/doc", "test2.py") {
+
+ @Override
+ public void after() {
+ assertEquals(3, allTestsCount());
+ assertEquals(1, passedTestsCount());
+ assertEquals(2, failedTestsCount());
+ }
+ });
+ }
+}
diff --git a/python/testSrc/com/jetbrains/env/python/testing/PythonNoseTestingTest.java b/python/testSrc/com/jetbrains/env/python/testing/PythonNoseTestingTest.java
new file mode 100644
index 000000000000..33250ae17fa4
--- /dev/null
+++ b/python/testSrc/com/jetbrains/env/python/testing/PythonNoseTestingTest.java
@@ -0,0 +1,33 @@
+package com.jetbrains.env.python.testing;
+
+import com.jetbrains.env.PyEnvTestCase;
+import com.jetbrains.env.ut.PyNoseTestTask;
+
+/**
+ * User : catherine
+ */
+public class PythonNoseTestingTest extends PyEnvTestCase{
+ public void testNoseRunner() {
+ runPythonTest(new PyNoseTestTask("/testRunner/env/nose", "test1.py") {
+
+ @Override
+ public void after() {
+ assertEquals(3, allTestsCount());
+ assertEquals(3, passedTestsCount());
+ allTestsPassed();
+ }
+ });
+ }
+
+ public void testNoseRunner2() {
+ runPythonTest(new PyNoseTestTask("/testRunner/env/nose", "test2.py") {
+
+ @Override
+ public void after() {
+ assertEquals(8, allTestsCount());
+ assertEquals(5, passedTestsCount());
+ assertEquals(3, failedTestsCount());
+ }
+ });
+ }
+}
diff --git a/python/testSrc/com/jetbrains/env/python/testing/PythonPyTestingTest.java b/python/testSrc/com/jetbrains/env/python/testing/PythonPyTestingTest.java
new file mode 100644
index 000000000000..ab3dee60c5b0
--- /dev/null
+++ b/python/testSrc/com/jetbrains/env/python/testing/PythonPyTestingTest.java
@@ -0,0 +1,33 @@
+package com.jetbrains.env.python.testing;
+
+import com.jetbrains.env.PyEnvTestCase;
+import com.jetbrains.env.ut.PyTestTestTask;
+
+/**
+ * User : catherine
+ */
+public class PythonPyTestingTest extends PyEnvTestCase{
+ public void testPytestRunner() {
+ runPythonTest(new PyTestTestTask("/testRunner/env/pytest", "test1.py") {
+
+ @Override
+ public void after() {
+ assertEquals(3, allTestsCount());
+ assertEquals(3, passedTestsCount());
+ allTestsPassed();
+ }
+ });
+ }
+
+ public void testPytestRunner2() {
+ runPythonTest(new PyTestTestTask("/testRunner/env/pytest", "test2.py") {
+
+ @Override
+ public void after() {
+ assertEquals(8, allTestsCount());
+ assertEquals(5, passedTestsCount());
+ assertEquals(3, failedTestsCount());
+ }
+ });
+ }
+}
diff --git a/python/testSrc/com/jetbrains/env/python/testing/PythonUnitTestingTest.java b/python/testSrc/com/jetbrains/env/python/testing/PythonUnitTestingTest.java
new file mode 100644
index 000000000000..682eb8160285
--- /dev/null
+++ b/python/testSrc/com/jetbrains/env/python/testing/PythonUnitTestingTest.java
@@ -0,0 +1,78 @@
+package com.jetbrains.env.python.testing;
+
+import com.jetbrains.env.PyEnvTestCase;
+import com.jetbrains.env.ut.PyUnitTestTask;
+import junit.framework.Assert;
+
+/**
+ * @author traff
+ */
+public class PythonUnitTestingTest extends PyEnvTestCase{
+ public void testUTRunner() {
+ runPythonTest(new PyUnitTestTask("/testRunner/env/unit", "test1.py") {
+
+ @Override
+ public void after() {
+ Assert.assertEquals(2, allTestsCount());
+ Assert.assertEquals(2, passedTestsCount());
+ allTestsPassed();
+ }
+ });
+ }
+
+ public void testUTRunner2() {
+ runPythonTest(new PyUnitTestTask("/testRunner/env/unit", "test2.py") {
+
+ @Override
+ public void after() {
+ assertEquals(3, allTestsCount());
+ assertEquals(1, passedTestsCount());
+ assertEquals(2, failedTestsCount());
+ }
+ });
+ }
+
+ public void testClass() {
+ runPythonTest(new PyUnitTestTask("/testRunner/env/unit", "test_file.py::GoodTest") {
+
+ @Override
+ public void after() {
+ assertEquals(1, allTestsCount());
+ assertEquals(1, passedTestsCount());
+ }
+ });
+ }
+
+ public void testMethod() {
+ runPythonTest(new PyUnitTestTask("/testRunner/env/unit", "test_file.py::GoodTest::test_passes") {
+
+ @Override
+ public void after() {
+ assertEquals(1, allTestsCount());
+ assertEquals(1, passedTestsCount());
+ }
+ });
+ }
+
+ public void testFolder() {
+ runPythonTest(new PyUnitTestTask("/testRunner/env/unit", "test_folder/") {
+
+ @Override
+ public void after() {
+ assertEquals(5, allTestsCount());
+ assertEquals(3, passedTestsCount());
+ }
+ });
+ }
+
+ public void testDependent() {
+ runPythonTest(new PyUnitTestTask("/testRunner/env/unit", "dependentTests/test_my_class.py") {
+
+ @Override
+ public void after() {
+ assertEquals(1, allTestsCount());
+ assertEquals(1, passedTestsCount());
+ }
+ });
+ }
+}
diff --git a/python/testSrc/com/jetbrains/env/ut/PyDocTestTask.java b/python/testSrc/com/jetbrains/env/ut/PyDocTestTask.java
new file mode 100644
index 000000000000..e8228d767287
--- /dev/null
+++ b/python/testSrc/com/jetbrains/env/ut/PyDocTestTask.java
@@ -0,0 +1,24 @@
+package com.jetbrains.env.ut;
+
+import com.intellij.execution.configurations.ConfigurationFactory;
+import com.intellij.openapi.project.Project;
+import com.jetbrains.python.testing.PythonTestConfigurationType;
+
+/**
+ * User : catherine
+ */
+public abstract class PyDocTestTask extends PyUnitTestTask {
+ public PyDocTestTask(String workingFolder, String scriptName, String scriptParameters) {
+ super(workingFolder, scriptName, scriptParameters);
+ }
+
+ public PyDocTestTask(String workingFolder, String scriptName) {
+ this(workingFolder, scriptName, null);
+ }
+
+ public void runTestOn(String sdkHome) throws Exception {
+ final Project project = getProject();
+ final ConfigurationFactory factory = PythonTestConfigurationType.getInstance().PY_DOCTEST_FACTORY;
+ runConfiguration(factory, sdkHome, project);
+ }
+}
diff --git a/python/testSrc/com/jetbrains/env/ut/PyNoseTestTask.java b/python/testSrc/com/jetbrains/env/ut/PyNoseTestTask.java
new file mode 100644
index 000000000000..e130dd5717a4
--- /dev/null
+++ b/python/testSrc/com/jetbrains/env/ut/PyNoseTestTask.java
@@ -0,0 +1,32 @@
+package com.jetbrains.env.ut;
+
+import com.google.common.collect.ImmutableSet;
+import com.intellij.execution.configurations.ConfigurationFactory;
+import com.intellij.openapi.project.Project;
+import com.jetbrains.python.testing.PythonTestConfigurationType;
+
+import java.util.Set;
+
+/**
+ * User : catherine
+ */
+public abstract class PyNoseTestTask extends PyUnitTestTask {
+ public PyNoseTestTask(String workingFolder, String scriptName, String scriptParameters) {
+ super(workingFolder, scriptName, scriptParameters);
+ }
+
+ public PyNoseTestTask(String workingFolder, String scriptName) {
+ this(workingFolder, scriptName, null);
+ }
+
+ public void runTestOn(String sdkHome) throws Exception {
+ final Project project = getProject();
+ final ConfigurationFactory factory = PythonTestConfigurationType.getInstance().PY_NOSETEST_FACTORY;
+ runConfiguration(factory, sdkHome, project);
+ }
+
+ @Override
+ public Set<String> getTags() {
+ return ImmutableSet.of("nose");
+ }
+}
diff --git a/python/testSrc/com/jetbrains/env/ut/PyTestTestTask.java b/python/testSrc/com/jetbrains/env/ut/PyTestTestTask.java
new file mode 100644
index 000000000000..1e4261188206
--- /dev/null
+++ b/python/testSrc/com/jetbrains/env/ut/PyTestTestTask.java
@@ -0,0 +1,40 @@
+package com.jetbrains.env.ut;
+
+import com.google.common.collect.ImmutableSet;
+import com.intellij.execution.configurations.ConfigurationFactory;
+import com.intellij.openapi.project.Project;
+import com.jetbrains.python.testing.AbstractPythonTestRunConfiguration;
+import com.jetbrains.python.testing.PythonTestConfigurationType;
+import com.jetbrains.python.testing.pytest.PyTestRunConfiguration;
+
+import java.util.Set;
+
+/**
+ * User : catherine
+ */
+public abstract class PyTestTestTask extends PyUnitTestTask {
+ public PyTestTestTask(String workingFolder, String scriptName, String scriptParameters) {
+ super(workingFolder, scriptName, scriptParameters);
+ }
+
+ public PyTestTestTask(String workingFolder, String scriptName) {
+ this(workingFolder, scriptName, null);
+ }
+
+ public void runTestOn(String sdkHome) throws Exception {
+ final Project project = getProject();
+ final ConfigurationFactory factory = PythonTestConfigurationType.getInstance().PY_PYTEST_FACTORY;
+ runConfiguration(factory, sdkHome, project);
+ }
+
+ @Override
+ public Set<String> getTags() {
+ return ImmutableSet.of("pytest");
+ }
+
+ protected void configure(AbstractPythonTestRunConfiguration config) {
+ if (config instanceof PyTestRunConfiguration)
+ ((PyTestRunConfiguration)config).setTestToRun(getScriptPath());
+ }
+
+}
diff --git a/python/testSrc/com/jetbrains/env/ut/PyUnitTestTask.java b/python/testSrc/com/jetbrains/env/ut/PyUnitTestTask.java
new file mode 100644
index 000000000000..01401ca1ca9a
--- /dev/null
+++ b/python/testSrc/com/jetbrains/env/ut/PyUnitTestTask.java
@@ -0,0 +1,241 @@
+package com.jetbrains.env.ut;
+
+import com.google.common.collect.Lists;
+import com.intellij.execution.*;
+import com.intellij.execution.configurations.ConfigurationFactory;
+import com.intellij.execution.executors.DefaultRunExecutor;
+import com.intellij.execution.process.ProcessAdapter;
+import com.intellij.execution.process.ProcessEvent;
+import com.intellij.execution.process.ProcessHandler;
+import com.intellij.execution.runners.ExecutionEnvironment;
+import com.intellij.execution.runners.ExecutionEnvironmentBuilder;
+import com.intellij.execution.runners.ProgramRunner;
+import com.intellij.execution.testframework.Filter;
+import com.intellij.execution.testframework.sm.runner.SMTestProxy;
+import com.intellij.execution.testframework.sm.runner.ui.SMTRunnerConsoleView;
+import com.intellij.execution.testframework.sm.runner.ui.TestResultsViewer;
+import com.intellij.execution.ui.RunContentDescriptor;
+import com.intellij.openapi.application.Result;
+import com.intellij.openapi.application.WriteAction;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Disposer;
+import com.intellij.openapi.util.Key;
+import com.intellij.util.ui.UIUtil;
+import com.intellij.xdebugger.XDebuggerTestUtil;
+import com.jetbrains.env.PyExecutionFixtureTestTask;
+import com.jetbrains.python.sdk.PythonEnvUtil;
+import com.jetbrains.python.sdk.flavors.JythonSdkFlavor;
+import com.jetbrains.python.sdk.flavors.PythonSdkFlavor;
+import com.jetbrains.python.testing.AbstractPythonTestRunConfiguration;
+import com.jetbrains.python.testing.PythonTestConfigurationType;
+import org.jetbrains.annotations.NotNull;
+import org.junit.Assert;
+
+/**
+ * @author traff
+ */
+public abstract class PyUnitTestTask extends PyExecutionFixtureTestTask {
+
+ protected ProcessHandler myProcessHandler;
+ private boolean shouldPrintOutput = false;
+ private SMTestProxy.SMRootTestProxy myTestProxy;
+ private boolean mySetUp = false;
+ private SMTRunnerConsoleView myConsoleView;
+ private RunContentDescriptor myDescriptor;
+ private StringBuilder myOutput;
+
+ public PyUnitTestTask() {
+ }
+
+ public PyUnitTestTask(String workingFolder, String scriptName, String scriptParameters) {
+ setWorkingFolder(getTestDataPath() + workingFolder);
+ setScriptName(scriptName);
+ setScriptParameters(scriptParameters);
+ }
+
+ public PyUnitTestTask(String workingFolder, String scriptName) {
+ this(workingFolder, scriptName, null);
+ }
+
+ @Override
+ public void setUp(final String testName) throws Exception {
+ UIUtil.invokeAndWaitIfNeeded(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ if (myFixture == null) {
+ PyUnitTestTask.super.setUp(testName);
+ mySetUp = true;
+ }
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
+ }
+
+ @NotNull
+ protected String output() {
+ return myOutput.toString();
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ UIUtil.invokeAndWaitIfNeeded(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ if (mySetUp) {
+ if (myConsoleView != null) {
+ Disposer.dispose(myConsoleView);
+ myConsoleView = null;
+ }
+ if (myDescriptor != null) {
+ Disposer.dispose(myDescriptor);
+ myDescriptor = null;
+ }
+
+
+ PyUnitTestTask.super.tearDown();
+
+ mySetUp = false;
+ }
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ );
+ }
+
+ @Override
+ public void runTestOn(String sdkHome) throws Exception {
+ final Project project = getProject();
+ final ConfigurationFactory factory = PythonTestConfigurationType.getInstance().PY_UNITTEST_FACTORY;
+ runConfiguration(factory, sdkHome, project);
+ }
+
+ protected void runConfiguration(ConfigurationFactory factory, String sdkHome, final Project project) throws Exception {
+ final RunnerAndConfigurationSettings settings =
+ RunManager.getInstance(project).createRunConfiguration("test", factory);
+
+ AbstractPythonTestRunConfiguration config = (AbstractPythonTestRunConfiguration)settings.getConfiguration();
+
+
+ config.setSdkHome(sdkHome);
+ config.setScriptName(getScriptPath());
+ config.setWorkingDirectory(getWorkingFolder());
+
+ PythonSdkFlavor sdk = PythonSdkFlavor.getFlavor(sdkHome);
+
+
+ if (sdk instanceof JythonSdkFlavor) {
+ config.setInterpreterOptions(JythonSdkFlavor.getPythonPathCmdLineArgument(Lists.<String>newArrayList(getWorkingFolder())));
+ }
+ else {
+ PythonEnvUtil.addToPythonPath(config.getEnvs(), getWorkingFolder());
+ }
+
+
+ configure(config);
+
+ new WriteAction() {
+ @Override
+ protected void run(@NotNull Result result) throws Throwable {
+ RunManagerEx.getInstanceEx(project).addConfiguration(settings, false);
+ RunManagerEx.getInstanceEx(project).setSelectedConfiguration(settings);
+ Assert.assertSame(settings, RunManagerEx.getInstanceEx(project).getSelectedConfiguration());
+ }
+ }.execute();
+
+ final ExecutionEnvironment environment = ExecutionEnvironmentBuilder.create(DefaultRunExecutor.getRunExecutorInstance(), settings).build();
+ //noinspection ConstantConditions
+ Assert.assertTrue(environment.getRunner().canRun(DefaultRunExecutor.EXECUTOR_ID, config));
+
+ before();
+
+ final com.intellij.util.concurrency.Semaphore s = new com.intellij.util.concurrency.Semaphore();
+ s.down();
+
+ myOutput = new StringBuilder();
+
+ UIUtil.invokeAndWaitIfNeeded(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ environment.getRunner().execute(environment, new ProgramRunner.Callback() {
+ @Override
+ public void processStarted(RunContentDescriptor descriptor) {
+ myDescriptor = descriptor;
+ myProcessHandler = myDescriptor.getProcessHandler();
+ myProcessHandler.addProcessListener(new ProcessAdapter() {
+ @Override
+ public void onTextAvailable(ProcessEvent event, Key outputType) {
+ myOutput.append(event.getText());
+ }
+ });
+ myConsoleView = (com.intellij.execution.testframework.sm.runner.ui.SMTRunnerConsoleView)descriptor.getExecutionConsole();
+ myTestProxy = myConsoleView.getResultsViewer().getTestsRootNode();
+ myConsoleView.getResultsViewer().addEventsListener(new TestResultsViewer.SMEventsAdapter() {
+ @Override
+ public void onTestingFinished(TestResultsViewer sender) {
+ s.up();
+ }
+ });
+ }
+ });
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
+
+ Assert.assertTrue(s.waitFor(60000));
+
+ XDebuggerTestUtil.waitForSwing();
+
+ assertFinished();
+
+ Assert.assertTrue(output(), allTestsCount() > 0);
+
+ after();
+
+ disposeProcess(myProcessHandler);
+ }
+
+ protected void configure(AbstractPythonTestRunConfiguration config) {
+ }
+
+ public void allTestsPassed() {
+ Assert.assertEquals(output(), 0, myTestProxy.getChildren(Filter.NOT_PASSED).size());
+ Assert.assertEquals(output(), 0, failedTestsCount());
+ }
+
+ public int failedTestsCount() {
+ return myTestProxy.collectChildren(NOT_SUIT.and(Filter.FAILED_OR_INTERRUPTED)).size();
+ }
+
+ public int passedTestsCount() {
+ return myTestProxy.collectChildren(NOT_SUIT.and(Filter.PASSED)).size();
+ }
+
+ public void assertFinished() {
+ Assert.assertTrue("State is " + myTestProxy.getMagnitudeInfo().getTitle() + "\n" + output(),
+ myTestProxy.wasLaunched() && !myTestProxy.wasTerminated());
+ }
+
+ public int allTestsCount() {
+ return myTestProxy.collectChildren(NOT_SUIT).size();
+ }
+
+ public static final Filter<SMTestProxy> NOT_SUIT = new Filter<SMTestProxy>() {
+ @Override
+ public boolean shouldAccept(SMTestProxy test) {
+ return !test.isSuite();
+ }
+ };
+}
diff --git a/python/testSrc/com/jetbrains/python/PyAddImportTest.java b/python/testSrc/com/jetbrains/python/PyAddImportTest.java
index 01f83847aa56..f95187aff819 100644
--- a/python/testSrc/com/jetbrains/python/PyAddImportTest.java
+++ b/python/testSrc/com/jetbrains/python/PyAddImportTest.java
@@ -17,8 +17,13 @@ package com.jetbrains.python;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
+import com.intellij.psi.PsiPolyVariantReference;
import com.jetbrains.python.codeInsight.imports.AddImportHelper;
+import com.jetbrains.python.fixtures.PyResolveTestCase;
import com.jetbrains.python.fixtures.PyTestCase;
+import com.jetbrains.python.psi.PyElement;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
/**
* @author yole
@@ -53,4 +58,46 @@ public class PyAddImportTest extends PyTestCase {
}.execute();
myFixture.checkResultByFile("addImport/" + getTestName(true) + ".after.py");
}
+
+ // PY-6020
+ public void testLocalFromImport() {
+ doAddLocalImport("foo", "package.module");
+ }
+
+ // PY-6020
+ public void testLocalImport() {
+ doAddLocalImport("module", null);
+ }
+
+ // PY-13668
+ public void testLocalImportInlineFunctionBody() {
+ testLocalImport();
+ }
+
+ // PY-13668
+ public void testLocalImportInlineBranch() {
+ testLocalImport();
+ }
+
+ /**
+ * Add local import statement
+ * @param name reference name in corresponding import element
+ * @param qualifier if not {@code null} form {@code from qualifier import name} will be used, otherwise {@code import name}
+ */
+ private void doAddLocalImport(@NotNull final String name, @Nullable final String qualifier) {
+ myFixture.configureByFile("addImport/" + getTestName(true) + ".py");
+ new WriteCommandAction(myFixture.getProject(), myFixture.getFile()) {
+ @Override
+ protected void run(Result result) throws Throwable {
+ final PsiPolyVariantReference reference = PyResolveTestCase.findReferenceByMarker(myFixture.getFile());
+ if (qualifier != null) {
+ AddImportHelper.addLocalFromImportStatement((PyElement)reference.getElement(), qualifier, name);
+ }
+ else {
+ AddImportHelper.addLocalImportStatement((PyElement)reference.getElement(), name);
+ }
+ }
+ }.execute();
+ myFixture.checkResultByFile("addImport/" + getTestName(true) + ".after.py");
+ }
}
diff --git a/python/testSrc/com/jetbrains/python/PyTypeTest.java b/python/testSrc/com/jetbrains/python/PyTypeTest.java
index 88243f065a3b..b0e41bcffddc 100644
--- a/python/testSrc/com/jetbrains/python/PyTypeTest.java
+++ b/python/testSrc/com/jetbrains/python/PyTypeTest.java
@@ -829,6 +829,12 @@ public class PyTypeTest extends PyTestCase {
" pass\n");
}
+ // PY-12801
+ public void testTupleConcatenation() {
+ doTest("(int, bool, str)",
+ "expr = (1,) + (True, 'spam') + ()");
+ }
+
private static TypeEvalContext getTypeEvalContext(@NotNull PyExpression element) {
return TypeEvalContext.userInitiated(element.getContainingFile()).withTracing();
}
diff --git a/python/testSrc/com/jetbrains/python/PythonCompletionTest.java b/python/testSrc/com/jetbrains/python/PythonCompletionTest.java
index f365eea4da34..a1366ac2e17a 100644
--- a/python/testSrc/com/jetbrains/python/PythonCompletionTest.java
+++ b/python/testSrc/com/jetbrains/python/PythonCompletionTest.java
@@ -626,23 +626,85 @@ public class PythonCompletionTest extends PyTestCase {
}
// PY-4073
- public void testSpecialFunctionAttributes() throws Exception {
- setLanguageLevel(LanguageLevel.PYTHON27);
- try {
- List<String> suggested = doTestByText("def func(): pass; func.func_<caret>");
- assertNotNull(suggested);
- assertContainsElements(suggested,
- "func_defaults", "func_globals", "func_closure",
- "func_code", "func_name", "func_doc", "func_dict");
-
- suggested = doTestByText("def func(): pass; func.__<caret>");
- assertNotNull(suggested);
- assertContainsElements(suggested, "__defaults__", "__globals__", "__closure__",
- "__code__", "__name__", "__doc__", "__dict__", "__module__");
- assertDoesntContain(suggested, "__annotations__", "__kwdefaults__");
- }
- finally {
- setLanguageLevel(null);
- }
+ public void testFunctionSpecialAttributes() {
+ runWithLanguageLevel(LanguageLevel.PYTHON27, new Runnable() {
+ @Override
+ public void run() {
+ List<String> suggested = doTestByText("def func(): pass; func.func_<caret>");
+ assertNotNull(suggested);
+ assertContainsElements(suggested, PyNames.LEGACY_FUNCTION_SPECIAL_ATTRIBUTES);
+
+ suggested = doTestByText("def func(): pass; func.__<caret>");
+ assertNotNull(suggested);
+ assertContainsElements(suggested, PyNames.FUNCTION_SPECIAL_ATTRIBUTES);
+ assertDoesntContain(suggested, PyNames.PY3_ONLY_FUNCTION_SPECIAL_ATTRIBUTES);
+ }
+ });
+ }
+
+ // PY-9342
+ public void testBoundMethodSpecialAttributes() {
+ List<String> suggested = doTestByText("{}.update.im_<caret>");
+ assertNotNull(suggested);
+ assertContainsElements(suggested, PyNames.LEGACY_METHOD_SPECIAL_ATTRIBUTES);
+
+ suggested = doTestByText("{}.update.__<caret>");
+ assertNotNull(suggested);
+ assertContainsElements(suggested, PyNames.METHOD_SPECIAL_ATTRIBUTES);
+ assertDoesntContain(suggested, PyNames.FUNCTION_SPECIAL_ATTRIBUTES);
+ }
+
+ // PY-9342
+ public void testWeakQualifierBoundMethodAttributes() {
+ assertUnderscoredMethodSpecialAttributesSuggested();
+ }
+
+ private void assertUnderscoredMethodSpecialAttributesSuggested() {
+ myFixture.configureByFile("completion/" + getTestName(true) + ".py");
+ myFixture.completeBasic();
+ final List<String> suggested = myFixture.getLookupElementStrings();
+ assertNotNull(suggested);
+ assertContainsElements(suggested, PyNames.METHOD_SPECIAL_ATTRIBUTES);
+ assertDoesntContain(suggested, PyNames.FUNCTION_SPECIAL_ATTRIBUTES);
+ }
+
+ // PY-9342
+ public void testUnboundMethodSpecialAttributes() {
+ runWithLanguageLevel(LanguageLevel.PYTHON27, new Runnable() {
+ @Override
+ public void run() {
+ assertUnderscoredMethodSpecialAttributesSuggested();
+ }
+ });
+ runWithLanguageLevel(LanguageLevel.PYTHON32, new Runnable() {
+ @Override
+ public void run() {
+ assertUnderscoredFunctionAttributesSuggested();
+ }
+ });
+ }
+
+ // PY-9342
+ public void testStaticMethodSpecialAttributes() {
+ assertUnderscoredFunctionAttributesSuggested();
+ }
+
+ // PY-9342
+ public void testLambdaSpecialAttributes() {
+ assertUnderscoredFunctionAttributesSuggested();
+ }
+
+ // PY-9342
+ public void testReassignedMethodSpecialAttributes() {
+ assertUnderscoredMethodSpecialAttributesSuggested();
+ }
+
+ private void assertUnderscoredFunctionAttributesSuggested() {
+ myFixture.configureByFile("completion/" + getTestName(true) + ".py");
+ myFixture.completeBasic();
+ final List<String> suggested = myFixture.getLookupElementStrings();
+ assertNotNull(suggested);
+ assertContainsElements(suggested, PyNames.FUNCTION_SPECIAL_ATTRIBUTES);
+ assertDoesntContain(suggested, PyNames.METHOD_SPECIAL_ATTRIBUTES);
}
}
diff --git a/python/testSrc/com/jetbrains/python/fixtures/PyCommandLineTestCase.java b/python/testSrc/com/jetbrains/python/fixtures/PyCommandLineTestCase.java
index bbaf31252c3e..65815c112b2e 100644
--- a/python/testSrc/com/jetbrains/python/fixtures/PyCommandLineTestCase.java
+++ b/python/testSrc/com/jetbrains/python/fixtures/PyCommandLineTestCase.java
@@ -20,16 +20,15 @@ import com.intellij.execution.ExecutionException;
import com.intellij.execution.Executor;
import com.intellij.execution.configurations.ConfigurationFactory;
import com.intellij.execution.configurations.ConfigurationType;
-import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.executors.DefaultDebugExecutor;
import com.intellij.execution.executors.DefaultRunExecutor;
-import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.runners.ExecutionEnvironmentBuilder;
import com.intellij.openapi.project.Project;
import com.jetbrains.python.PythonHelpersLocator;
import com.jetbrains.python.debugger.PyDebugRunner;
import com.jetbrains.python.run.AbstractPythonRunConfiguration;
import com.jetbrains.python.run.PythonCommandLineState;
+import org.jetbrains.annotations.NotNull;
import java.util.List;
@@ -59,11 +58,9 @@ public abstract class PyCommandLineTestCase extends PyTestCase {
protected List<String> buildRunCommandLine(AbstractPythonRunConfiguration configuration) {
try {
- final Executor executor = DefaultRunExecutor.getRunExecutorInstance();
- ExecutionEnvironment env = new ExecutionEnvironmentBuilder(myFixture.getProject(), executor).setRunProfile(configuration).build();
- final PythonCommandLineState state = (PythonCommandLineState)configuration.getState(executor, env);
- final GeneralCommandLine generalCommandLine = state.generateCommandLine();
- return generalCommandLine.getParametersList().getList();
+ PythonCommandLineState state = getState(configuration, DefaultRunExecutor.getRunExecutorInstance());
+ assert state != null;
+ return state.generateCommandLine().getParametersList().getList();
}
catch (ExecutionException e) {
throw new RuntimeException(e);
@@ -72,15 +69,21 @@ public abstract class PyCommandLineTestCase extends PyTestCase {
protected List<String> buildDebugCommandLine(AbstractPythonRunConfiguration configuration) {
try {
- final Executor executor = DefaultDebugExecutor.getDebugExecutorInstance();
- ExecutionEnvironment env = new ExecutionEnvironmentBuilder(myFixture.getProject(), executor).setRunProfile(configuration).build();
- final PythonCommandLineState state = (PythonCommandLineState)configuration.getState(executor, env);
- final GeneralCommandLine generalCommandLine =
- state.generateCommandLine(PyDebugRunner.createCommandLinePatchers(configuration.getProject(), state, configuration, PORT));
- return generalCommandLine.getParametersList().getList();
+ PythonCommandLineState state = getState(configuration, DefaultDebugExecutor.getDebugExecutorInstance());
+ assert state != null;
+ return state.generateCommandLine(PyDebugRunner.createCommandLinePatchers(configuration.getProject(), state, configuration, PORT))
+ .getParametersList()
+ .getList();
}
catch (ExecutionException e) {
throw new RuntimeException(e);
}
}
+
+
+ private static PythonCommandLineState getState(@NotNull AbstractPythonRunConfiguration configuration, @NotNull Executor executor) throws ExecutionException {
+ return (PythonCommandLineState)ExecutionEnvironmentBuilder.create(executor, configuration)
+ .build()
+ .getState();
+ }
}
diff --git a/python/testSrc/com/jetbrains/python/fixtures/PyTestCase.java b/python/testSrc/com/jetbrains/python/fixtures/PyTestCase.java
index 45d582a783a8..99da2a43aea1 100644
--- a/python/testSrc/com/jetbrains/python/fixtures/PyTestCase.java
+++ b/python/testSrc/com/jetbrains/python/fixtures/PyTestCase.java
@@ -18,6 +18,8 @@ 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.find.findUsages.CustomUsageSearcher;
+import com.intellij.find.findUsages.FindUsagesOptions;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.module.Module;
@@ -33,6 +35,7 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiReference;
+import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.testFramework.LightProjectDescriptor;
import com.intellij.testFramework.PlatformTestCase;
import com.intellij.testFramework.TestDataPath;
@@ -42,6 +45,10 @@ import com.intellij.testFramework.fixtures.IdeaProjectTestFixture;
import com.intellij.testFramework.fixtures.IdeaTestFixtureFactory;
import com.intellij.testFramework.fixtures.TestFixtureBuilder;
import com.intellij.testFramework.fixtures.impl.LightTempDirTestFixtureImpl;
+import com.intellij.usageView.UsageInfo;
+import com.intellij.usages.Usage;
+import com.intellij.usages.rules.PsiElementUsage;
+import com.intellij.util.CommonProcessors.CollectProcessor;
import com.jetbrains.python.PythonHelpersLocator;
import com.jetbrains.python.PythonMockSdk;
import com.jetbrains.python.PythonModuleTypeBase;
@@ -55,6 +62,9 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
/**
* @author yole
@@ -184,6 +194,36 @@ public abstract class PyTestCase extends UsefulTestCase {
myFixture.getEditor().getCaretModel().moveToOffset(element.getTextOffset());
}
+ /**
+ * Finds all usages of element. Works much like method in {@link com.intellij.testFramework.fixtures.CodeInsightTestFixture#findUsages(com.intellij.psi.PsiElement)},
+ * but supports {@link com.intellij.find.findUsages.CustomUsageSearcher} and {@link com.intellij.psi.search.searches.ReferencesSearch} as well
+ *
+ * @param element what to find
+ * @return usages
+ */
+ @NotNull
+ protected Collection<PsiElement> findUsage(@NotNull final PsiElement element) {
+ final Collection<PsiElement> result = new ArrayList<PsiElement>();
+ final CollectProcessor<Usage> usageCollector = new CollectProcessor<Usage>();
+ for (final CustomUsageSearcher searcher : CustomUsageSearcher.EP_NAME.getExtensions()) {
+ searcher.processElementUsages(element, usageCollector, new FindUsagesOptions(myFixture.getProject()));
+ }
+ for (final Usage usage : usageCollector.getResults()) {
+ if (usage instanceof PsiElementUsage) {
+ result.add(((PsiElementUsage)usage).getElement());
+ }
+ }
+ for (final PsiReference reference : ReferencesSearch.search(element).findAll()) {
+ result.add(reference.getElement());
+ }
+
+ for (final UsageInfo info : myFixture.findUsages(element)) {
+ result.add(info.getElement());
+ }
+
+ return result;
+ }
+
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 a0a2a1232b2e..3451712f6bcd 100644
--- a/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java
+++ b/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java
@@ -371,6 +371,11 @@ public class PyUnresolvedReferencesInspectionTest extends PyInspectionTestCase {
doMultiFileTest();
}
+ // PY-9342
+ public void testMethodSpecialAttributes() {
+ doTest();
+ }
+
// PY-11472
public void testUnusedImportBeforeStarImport() {
doMultiFileTest();
diff --git a/python/testSrc/com/jetbrains/python/refactoring/PyIntroduceConstantTest.java b/python/testSrc/com/jetbrains/python/refactoring/PyIntroduceConstantTest.java
index 769e72077461..a54c68a0db09 100644
--- a/python/testSrc/com/jetbrains/python/refactoring/PyIntroduceConstantTest.java
+++ b/python/testSrc/com/jetbrains/python/refactoring/PyIntroduceConstantTest.java
@@ -51,7 +51,7 @@ public class PyIntroduceConstantTest extends PyIntroduceTestCase {
public void testSuggestUniqueNames() { // PY-4409
doTestSuggestions(PyExpression.class, "S1");
}
-
+
public void testSuggestUniqueNamesGlobalScope() { // PY-4409
doTestSuggestions(PyExpression.class, "S1");
}
@@ -60,6 +60,11 @@ public class PyIntroduceConstantTest extends PyIntroduceTestCase {
doTestInplace(null);
}
+ // PY-13484
+ public void testFromParameterDefaultValue() {
+ doTest();
+ }
+
@Override
protected String getTestDataPath() {
return super.getTestDataPath() + "/refactoring/introduceConstant";
diff --git a/python/testSrc/com/jetbrains/python/refactoring/PyIntroduceVariableTest.java b/python/testSrc/com/jetbrains/python/refactoring/PyIntroduceVariableTest.java
index f2117977cbf3..33a191f2b9a0 100644
--- a/python/testSrc/com/jetbrains/python/refactoring/PyIntroduceVariableTest.java
+++ b/python/testSrc/com/jetbrains/python/refactoring/PyIntroduceVariableTest.java
@@ -245,6 +245,8 @@ public class PyIntroduceVariableTest extends PyIntroduceTestCase {
}
}
+ public void testSelectionBreaksBinaryOperator() {doTest();}
+
private void doTestCannotPerform() {
boolean thrownExpectedException = false;
try {
diff --git a/python/testSrc/com/jetbrains/python/sdkTools/PyTestSdkTools.java b/python/testSrc/com/jetbrains/python/sdkTools/PyTestSdkTools.java
new file mode 100644
index 000000000000..2d97e747f00b
--- /dev/null
+++ b/python/testSrc/com/jetbrains/python/sdkTools/PyTestSdkTools.java
@@ -0,0 +1,142 @@
+package com.jetbrains.python.sdkTools;
+
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.projectRoots.Sdk;
+import com.intellij.openapi.projectRoots.SdkModificator;
+import com.intellij.openapi.projectRoots.impl.SdkConfigurationUtil;
+import com.intellij.openapi.roots.ModuleRootModificationUtil;
+import com.intellij.openapi.roots.OrderRootType;
+import com.intellij.openapi.roots.ProjectRootManager;
+import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.testFramework.UsefulTestCase;
+import com.jetbrains.python.sdk.InvalidSdkException;
+import com.jetbrains.python.sdk.PythonSdkType;
+import com.jetbrains.python.sdk.skeletons.PySkeletonRefresher;
+import com.jetbrains.python.sdk.skeletons.SkeletonVersionChecker;
+import org.hamcrest.Matchers;
+import org.jetbrains.annotations.NotNull;
+import org.junit.Assert;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * Engine to create SDK for tests.
+ * See {@link #createTempSdk(com.intellij.openapi.vfs.VirtualFile, SdkCreationType, com.intellij.openapi.module.Module)}
+ *
+ * @author Ilya.Kazakevich
+ */
+public final class PyTestSdkTools {
+
+ private static final Sdk[] NO_SDK = new Sdk[0];
+
+ private PyTestSdkTools() {
+
+ }
+
+ /**
+ * Creates SDK by its path and associates it with module.
+ *
+ * @param sdkHome path to sdk
+ * @param sdkCreationType SDK creation strategy (see {@link SdkCreationType} doc)
+ * @return sdk
+ */
+ @NotNull
+ public static Sdk createTempSdk(@NotNull final VirtualFile sdkHome,
+ @NotNull final SdkCreationType sdkCreationType,
+ @NotNull final Module module
+ )
+ throws InvalidSdkException, IOException {
+ final Ref<Sdk> ref = Ref.create();
+ UsefulTestCase.edt(new Runnable() {
+
+ @Override
+ public void run() {
+ final Sdk sdk = SdkConfigurationUtil.setupSdk(NO_SDK, sdkHome, PythonSdkType.getInstance(), true, null, null);
+ Assert.assertNotNull("Failed to create SDK on " + sdkHome, sdk);
+ ref.set(sdk);
+ }
+ });
+ final Sdk sdk = ref.get();
+ if (sdkCreationType != SdkCreationType.EMPTY_SDK) {
+ generateTempSkeletonsOrPackages(sdk, sdkCreationType == SdkCreationType.SDK_PACKAGES_AND_SKELETONS, module);
+ }
+ UsefulTestCase.edt(new Runnable() {
+ @Override
+ public void run() {
+ SdkConfigurationUtil.addSdk(sdk);
+ }
+ });
+ return sdk;
+ }
+
+
+ /**
+ * Adds installed eggs to SDK, generates skeletons (optionally) and associates it with modle.
+ *
+ * @param sdk sdk to process
+ * @param addSkeletons add skeletons or only packages
+ * @param module module to associate with
+ * @throws InvalidSdkException bas sdk
+ * @throws IOException failed to read eggs
+ */
+ private static void generateTempSkeletonsOrPackages(@NotNull final Sdk sdk,
+ final boolean addSkeletons,
+ @NotNull final Module module)
+ throws InvalidSdkException, IOException {
+ final Project project = module.getProject();
+ ModuleRootModificationUtil.setModuleSdk(module, sdk);
+
+ UsefulTestCase.edt(new Runnable() {
+ @Override
+ public void run() {
+ ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ @Override
+ public void run() {
+ ProjectRootManager.getInstance(project).setProjectSdk(sdk);
+ }
+ });
+ }
+ });
+
+
+ final SdkModificator modificator = sdk.getSdkModificator();
+ modificator.removeRoots(OrderRootType.CLASSES);
+
+ for (final String path : PythonSdkType.getSysPathsFromScript(sdk.getHomePath())) {
+ PythonSdkType.addSdkRoot(modificator, path);
+ }
+ if (!addSkeletons) {
+ UsefulTestCase.edt(new Runnable() {
+ @Override
+ public void run() {
+ modificator.commitChanges();
+ }
+ });
+ return;
+ }
+
+ final File tempDir = FileUtil.createTempDirectory(PyTestSdkTools.class.getName(), null);
+ final File skeletonsDir = new File(tempDir, PythonSdkType.SKELETON_DIR_NAME);
+ FileUtil.createDirectory(skeletonsDir);
+ final String skeletonsPath = skeletonsDir.toString();
+ PythonSdkType.addSdkRoot(modificator, skeletonsPath);
+
+ UsefulTestCase.edt(new Runnable() {
+ @Override
+ public void run() {
+ modificator.commitChanges();
+ }
+ });
+
+ final SkeletonVersionChecker checker = new SkeletonVersionChecker(0);
+ final PySkeletonRefresher refresher = new PySkeletonRefresher(project, null, sdk, skeletonsPath, null, null);
+ final List<String> errors = refresher.regenerateSkeletons(checker, null);
+ Assert.assertThat("Errors found", errors, Matchers.empty());
+ }
+}
diff --git a/python/testSrc/com/jetbrains/python/sdkTools/SdkCreationType.java b/python/testSrc/com/jetbrains/python/sdkTools/SdkCreationType.java
new file mode 100644
index 000000000000..231f243f564e
--- /dev/null
+++ b/python/testSrc/com/jetbrains/python/sdkTools/SdkCreationType.java
@@ -0,0 +1,20 @@
+package com.jetbrains.python.sdkTools;
+
+/**
+ * SDK creation type
+ * @author Ilya.Kazakevich
+ */
+public enum SdkCreationType {
+ /**
+ * SDK only (no packages nor skeletons)
+ */
+ EMPTY_SDK,
+ /**
+ * SDK + installed packages from syspath
+ */
+ SDK_PACKAGES_ONLY,
+ /**
+ * SDK + installed packages from syspath + skeletons
+ */
+ SDK_PACKAGES_AND_SKELETONS
+}
diff --git a/python/testSrc/com/jetbrains/python/sdkTools/package-info.java b/python/testSrc/com/jetbrains/python/sdkTools/package-info.java
new file mode 100644
index 000000000000..8b8fb74b9167
--- /dev/null
+++ b/python/testSrc/com/jetbrains/python/sdkTools/package-info.java
@@ -0,0 +1,6 @@
+/**
+ * Engine to create SDK in tests.
+ * See {@link com.jetbrains.python.sdkTools.PyTestSdkTools}
+ * @author Ilya.Kazakevich
+ */
+package com.jetbrains.python.sdkTools; \ No newline at end of file
diff --git a/python/testSrc/python-community-tests.iml b/python/testSrc/python-community-tests.iml
index 6511d8860c87..61980340a64f 100644
--- a/python/testSrc/python-community-tests.iml
+++ b/python/testSrc/python-community-tests.iml
@@ -16,6 +16,9 @@
<orderEntry type="module" module-name="python-ide-community" />
<orderEntry type="module" module-name="python-helpers" scope="RUNTIME" />
<orderEntry type="library" name="Groovy" level="project" />
+ <orderEntry type="module" module-name="xdebugger-impl" scope="TEST" />
+ <orderEntry type="module" module-name="python-pydev" scope="TEST" />
+ <orderEntry type="module" module-name="smRunner" scope="TEST" />
</component>
</module>
diff --git a/resources-en/src/messages/AntBundle.properties b/resources-en/src/messages/AntBundle.properties
index 8c98c67e4997..118b946b5441 100644
--- a/resources-en/src/messages/AntBundle.properties
+++ b/resources-en/src/messages/AntBundle.properties
@@ -188,3 +188,5 @@ intention.configure.highlighting.family.name=Configure highlighting
intention.configure.highlighting.text=Configure highlighting
build.file.properties.maximum.stack.size.label=Maximum &stack size (Mb):
run.execution.tab.ant.command.line.hint=Use "-J" prefix to specify JVM arguments
+file.type.not.supported=''{0}'' has unsupported format
+file.type.xml.not.supported=''{0}'' has unsupported xml format. Probably missing doctype.
diff --git a/resources-en/src/messages/DebuggerBundle.properties b/resources-en/src/messages/DebuggerBundle.properties
index f245bb59ddaa..c9802d35cb44 100644
--- a/resources-en/src/messages/DebuggerBundle.properties
+++ b/resources-en/src/messages/DebuggerBundle.properties
@@ -193,9 +193,9 @@ label.compound.renderer.configurable.use.default.renderer=Use default renderer
label.compound.renderer.configurable.use.expression=Use following expression:
label.compound.renderer.configurable.use.expression.list=Use list of expressions:
label.compound.renderer.configurable.apply.to=Apply renderer to objects of type (fully-qualified name):
-label.compound.renderer.configurable.when.rendering=When rendering the node
-label.compound.renderer.configurable.when.expanding=When expanding the node
-label.compound.renderer.configurable.test.can.expand=Test if the node can be expanded (optional):
+label.compound.renderer.configurable.when.rendering=When rendering a node
+label.compound.renderer.configurable.when.expanding=When expanding a node
+label.compound.renderer.configurable.test.can.expand=Test if a node can be expanded (optional):
title.compound.renderer.configurable.choose.renderer.reference.type=Renderer Reference Type
text.base.renderer.configurable.no.class.patterns=No class patterns configured
button.add=Add
diff --git a/resources-en/src/search/searchableOptions.xml b/resources-en/src/search/searchableOptions.xml
index 86e76b805242..d95b6a1cce81 100644
--- a/resources-en/src/search/searchableOptions.xml
+++ b/resources-en/src/search/searchableOptions.xml
@@ -4906,10 +4906,6 @@
<option name="data" hit="Data View" />
<option name="view" hit="Data View" />
<option name="database" hit="Database" />
- <option name="explicit" hit="Explicit parameter patterns (RegExp):" />
- <option name="parameter" hit="Explicit parameter patterns (RegExp):" />
- <option name="patterns" hit="Explicit parameter patterns (RegExp):" />
- <option name="regexp" hit="Explicit parameter patterns (RegExp):" />
<option name="column" hit="Include column names" />
<option name="include" hit="Include column names" />
<option name="names" hit="Include column names" />
diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml
index 726049771790..20536b2a6a61 100644
--- a/resources/src/META-INF/IdeaPlugin.xml
+++ b/resources/src/META-INF/IdeaPlugin.xml
@@ -40,6 +40,11 @@
<component>
<implementation-class>com.intellij.compiler.classFilesIndex.api.index.ClassFilesIndexFeaturesHolder</implementation-class>
</component>
+
+ <component>
+ <interface-class>com.intellij.psi.RefResolveService</interface-class>
+ <implementation-class>com.intellij.psi.RefResolveServiceImpl</implementation-class>
+ </component>
</project-components>
<extensionPoints>
@@ -241,6 +246,10 @@
<extensionPoint name="lang.psiAugmentProvider" interface="com.intellij.psi.augment.PsiAugmentProvider"/>
<extensionPoint name="custom.exception.handler" interface="com.intellij.codeInsight.CustomExceptionHandler"/>
+
+ <extensionPoint name="refactoring.moveInnerClassUsagesHandler" beanClass="com.intellij.lang.LanguageExtensionPoint">
+ <with attribute="implementationClass" implements="com.intellij.refactoring.move.moveInner.MoveInnerClassUsagesHandler"/>
+ </extensionPoint>
</extensionPoints>
<extensions defaultExtensionNs="com.intellij">
@@ -1370,6 +1379,7 @@
<stubIndex implementation="com.intellij.psi.impl.java.stubs.index.JavaMethodParameterTypesIndex"/>
<fileBasedIndex implementation="com.intellij.codeInspection.bytecodeAnalysis.BytecodeAnalysisIndex"/>
+ <fileBasedIndex implementation="com.intellij.psi.RefQueueIndex"/>
<stubElementTypeHolder class="com.intellij.psi.impl.java.stubs.JavaStubElementTypes"/>
@@ -1536,6 +1546,7 @@
<nonProjectFileWritingAccessExtension
implementation="com.intellij.codeInsight.ExternalAnnotationsNonProjectFileWritingAccessExtension"/>
<lang.inspectionSuppressor language="JAVA" implementationClass="com.intellij.codeInspection.SuppressManagerImpl"/>
+ <refactoring.moveInnerClassUsagesHandler language="JAVA" implementationClass="com.intellij.refactoring.move.moveInner.MoveInnerClassJavaUsagesHandler" id="java"/>
</extensions>
<actions>
diff --git a/resources/src/idea/JavaActions.xml b/resources/src/idea/JavaActions.xml
index 81a791f42208..bcfa7f37dda1 100644
--- a/resources/src/idea/JavaActions.xml
+++ b/resources/src/idea/JavaActions.xml
@@ -162,6 +162,9 @@
<action id="Debugger.ViewText" class="com.intellij.debugger.actions.ViewTextAction">
<add-to-group group-id="XDebugger.ValueGroup" anchor="last"/>
</action>
+ <action id="Debugger.ShowReferring" internal="true" class="com.intellij.debugger.actions.ShowReferringObjectsAction">
+ <add-to-group group-id="XDebugger.ValueGroup" anchor="last"/>
+ </action>
<action id="Debugger.CopyValue" class="com.intellij.debugger.actions.CopyValueAction"/>
<action id="Debugger.CompareValueWithClipboard" class="com.intellij.debugger.actions.CompareValueWithClipboardAction"/>
<action id="Debugger.CustomizeThreadsView" class="com.intellij.debugger.actions.CustomizeThreadsViewAction">
diff --git a/resources/src/idea/RichPlatformPlugin.xml b/resources/src/idea/RichPlatformPlugin.xml
index 93aa37c999c8..2b1794d236a3 100644
--- a/resources/src/idea/RichPlatformPlugin.xml
+++ b/resources/src/idea/RichPlatformPlugin.xml
@@ -393,6 +393,9 @@
<xi:include href="/META-INF/DesignerCorePlugin.xml" xpointer="xpointer(/idea-plugin/*)">
<xi:fallback/>
</xi:include>
+ <xi:include href="/META-INF/dvcs.xml" xpointer="xpointer(/idea-plugin/*)">
+ <xi:fallback/>
+ </xi:include>
<xi:include href="/META-INF/XmlPlugin.xml" xpointer="xpointer(/idea-plugin/*)"/>
<xi:include href="/META-INF/RegExpPlugin.xml" xpointer="xpointer(/idea-plugin/*)"/>
diff --git a/spellchecker/src/com/intellij/spellchecker/inspections/SpellCheckingInspection.java b/spellchecker/src/com/intellij/spellchecker/inspections/SpellCheckingInspection.java
index 1f2244995f68..e932a002beb1 100644
--- a/spellchecker/src/com/intellij/spellchecker/inspections/SpellCheckingInspection.java
+++ b/spellchecker/src/com/intellij/spellchecker/inspections/SpellCheckingInspection.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,7 +39,6 @@ import javax.swing.*;
import java.awt.*;
import java.util.Set;
-
public class SpellCheckingInspection extends LocalInspectionTool {
public static final String SPELL_CHECKING_INSPECTION_TOOL_NAME = "SpellCheckingInspection";
@@ -161,14 +160,9 @@ public class SpellCheckingInspection extends LocalInspectionTool {
tokenizer.tokenize(element, consumer);
}
-
private static void addBatchDescriptor(PsiElement element, int offset, @NotNull TextRange textRange, @NotNull ProblemsHolder holder) {
- final SpellcheckingStrategy strategy = getSpellcheckingStrategy(element, element.getLanguage());
-
- SpellCheckerQuickFix[] fixes = strategy != null
- ? strategy.getBatchFixes(element, offset, textRange)
- : SpellcheckingStrategy.getDefaultBatchFixes();
- final ProblemDescriptor problemDescriptor = createProblemDescriptor(element, offset, textRange, holder, fixes, false);
+ SpellCheckerQuickFix[] fixes = SpellcheckingStrategy.getDefaultBatchFixes();
+ ProblemDescriptor problemDescriptor = createProblemDescriptor(element, offset, textRange, holder, fixes, false);
holder.registerProblem(problemDescriptor);
}
@@ -221,7 +215,6 @@ public class SpellCheckingInspection extends LocalInspectionTool {
final JPanel panel = new JPanel(new BorderLayout());
panel.add(verticalBox, BorderLayout.NORTH);
return panel;
-
}
private static class MyTokenConsumer extends TokenConsumer implements Consumer<TextRange> {
diff --git a/spellchecker/src/com/intellij/spellchecker/jetbrains.dic b/spellchecker/src/com/intellij/spellchecker/jetbrains.dic
index bb2388b83709..45610cdbdf1c 100644
--- a/spellchecker/src/com/intellij/spellchecker/jetbrains.dic
+++ b/spellchecker/src/com/intellij/spellchecker/jetbrains.dic
@@ -96,6 +96,7 @@ dbcp
dealloc
deallocate
deannotate
+debuggable
decompile
decompiled
decompiler
diff --git a/spellchecker/src/com/intellij/spellchecker/quickfixes/RenameTo.java b/spellchecker/src/com/intellij/spellchecker/quickfixes/RenameTo.java
index 206a5f9510e2..ad742c5a1510 100644
--- a/spellchecker/src/com/intellij/spellchecker/quickfixes/RenameTo.java
+++ b/spellchecker/src/com/intellij/spellchecker/quickfixes/RenameTo.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.
@@ -102,11 +102,7 @@ public class RenameTo extends ShowSuggestions implements SpellCheckerQuickFix {
} else if (ApplicationManager.getApplication().isUnitTestMode()) { // TextEditorComponent / FiledEditorManagerImpl give away the data in real life
map.put(
CommonDataKeys.PSI_ELEMENT.getName(),
- new TextEditorPsiDataProvider().getData(
- CommonDataKeys.PSI_ELEMENT.getName(),
- editor,
- containingFile.getVirtualFile()
- )
+ new TextEditorPsiDataProvider().getData(CommonDataKeys.PSI_ELEMENT.getName(), editor, editor.getCaretModel().getCurrentCaret())
);
}
diff --git a/spellchecker/src/com/intellij/spellchecker/tokenizer/SpellcheckingStrategy.java b/spellchecker/src/com/intellij/spellchecker/tokenizer/SpellcheckingStrategy.java
index 95cd1e0f0f4c..6d28563e062c 100644
--- a/spellchecker/src/com/intellij/spellchecker/tokenizer/SpellcheckingStrategy.java
+++ b/spellchecker/src/com/intellij/spellchecker/tokenizer/SpellcheckingStrategy.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.
@@ -72,15 +72,11 @@ public class SpellcheckingStrategy {
public static SpellCheckerQuickFix[] getDefaultRegularFixes(boolean useRename, String wordWithTypo) {
return new SpellCheckerQuickFix[]{
- (useRename ? new RenameTo(wordWithTypo) : new ChangeTo(wordWithTypo)),
+ useRename ? new RenameTo(wordWithTypo) : new ChangeTo(wordWithTypo),
new AcceptWordAsCorrect(wordWithTypo)
};
}
- public SpellCheckerQuickFix[] getBatchFixes(PsiElement element, int offset, @NotNull TextRange textRange) {
- return getDefaultBatchFixes();
- }
-
public static SpellCheckerQuickFix[] getDefaultBatchFixes() {
return BATCH_FIXES;
}
diff --git a/xml/dom-impl/src/com/intellij/util/xml/ui/DomUIFactoryImpl.java b/xml/dom-impl/src/com/intellij/util/xml/ui/DomUIFactoryImpl.java
index 168b6a514b0a..fd431be7061c 100644
--- a/xml/dom-impl/src/com/intellij/util/xml/ui/DomUIFactoryImpl.java
+++ b/xml/dom-impl/src/com/intellij/util/xml/ui/DomUIFactoryImpl.java
@@ -196,12 +196,12 @@ public class DomUIFactoryImpl extends DomUIFactory {
}
@Override
- public void registerCustomControl(Class aClass, Function<DomWrapper<String>, BaseControl> creator) {
+ public void registerCustomControl(@NotNull Class aClass, Function<DomWrapper<String>, BaseControl> creator) {
myCustomControlCreators.put(aClass, creator);
}
@Override
- public void registerCustomCellEditor(final Class aClass, final Function<DomElement, TableCellEditor> creator) {
+ public void registerCustomCellEditor(@NotNull final Class aClass, final Function<DomElement, TableCellEditor> creator) {
myCustomCellEditorCreators.put(aClass, creator);
}
diff --git a/xml/dom-openapi/src/com/intellij/util/xml/ui/DomUIFactory.java b/xml/dom-openapi/src/com/intellij/util/xml/ui/DomUIFactory.java
index 2184ff8ca2b7..0b035728157b 100644
--- a/xml/dom-openapi/src/com/intellij/util/xml/ui/DomUIFactory.java
+++ b/xml/dom-openapi/src/com/intellij/util/xml/ui/DomUIFactory.java
@@ -119,9 +119,9 @@ public abstract class DomUIFactory {
public abstract BaseControl createTextControl(DomWrapper<String> wrapper, final boolean commitOnEveryChange);
- public abstract void registerCustomControl(Class aClass, Function<DomWrapper<String>, BaseControl> creator);
+ public abstract void registerCustomControl(@NotNull Class aClass, Function<DomWrapper<String>, BaseControl> creator);
- public abstract void registerCustomCellEditor(Class aClass, Function<DomElement, TableCellEditor> creator);
+ public abstract void registerCustomCellEditor(@NotNull Class aClass, Function<DomElement, TableCellEditor> creator);
@Nullable
public abstract BaseControl createCustomControl(final Type type, DomWrapper<String> wrapper, final boolean commitOnEveryChange);
diff --git a/xml/impl/src/com/intellij/codeInsight/template/emmet/ZenCodingTemplate.java b/xml/impl/src/com/intellij/codeInsight/template/emmet/ZenCodingTemplate.java
index f27903a49b5b..4b50a0cbdb01 100644
--- a/xml/impl/src/com/intellij/codeInsight/template/emmet/ZenCodingTemplate.java
+++ b/xml/impl/src/com/intellij/codeInsight/template/emmet/ZenCodingTemplate.java
@@ -548,6 +548,9 @@ public class ZenCodingTemplate extends CustomLiveTemplateBase {
}
}
}
+ else if(result.getPrefixMatcher().getPrefix().isEmpty()) {
+ result.restartCompletionOnPrefixChange(StandardPatterns.string().longerThan(0));
+ }
}
}
}
diff --git a/xml/impl/src/com/intellij/codeInsight/template/emmet/generators/XmlZenCodingGenerator.java b/xml/impl/src/com/intellij/codeInsight/template/emmet/generators/XmlZenCodingGenerator.java
index c1732a306120..b0165652173e 100644
--- a/xml/impl/src/com/intellij/codeInsight/template/emmet/generators/XmlZenCodingGenerator.java
+++ b/xml/impl/src/com/intellij/codeInsight/template/emmet/generators/XmlZenCodingGenerator.java
@@ -100,12 +100,16 @@ public abstract class XmlZenCodingGenerator extends ZenCodingGenerator {
PsiElement prevVisibleLeaf = callback.getContext();
while (prevVisibleLeaf != null) {
TextRange textRange = prevVisibleLeaf.getTextRange();
- if (textRange.getEndOffset() <= startOffset) {
+ final int endOffset = textRange.getEndOffset();
+ if (endOffset > currentOffset) {
+ continue;
+ }
+ if (endOffset <= startOffset) {
break;
}
IElementType prevType = prevVisibleLeaf.getNode().getElementType();
if (prevType == XmlTokenType.XML_TAG_END || prevType == XmlTokenType.XML_EMPTY_ELEMENT_END) {
- startOffset = textRange.getEndOffset();
+ startOffset = endOffset;
break;
}
prevVisibleLeaf = PsiTreeUtil.prevVisibleLeaf(prevVisibleLeaf);
diff --git a/xml/impl/src/org/jetbrains/builtInWebServer/DefaultWebServerRootsProvider.java b/xml/impl/src/org/jetbrains/builtInWebServer/DefaultWebServerRootsProvider.java
index b5621295957d..ca233b417249 100644
--- a/xml/impl/src/org/jetbrains/builtInWebServer/DefaultWebServerRootsProvider.java
+++ b/xml/impl/src/org/jetbrains/builtInWebServer/DefaultWebServerRootsProvider.java
@@ -89,7 +89,7 @@ final class DefaultWebServerRootsProvider extends WebServerRootsProvider {
public PathInfo getRoot(@NotNull VirtualFile file, @NotNull Project project) {
AccessToken token = ReadAction.start();
try {
- VirtualFile root = null;
+ VirtualFile root;
ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex();
if (fileIndex.isInSourceContent(file)) {
root = fileIndex.getSourceRootForFile(file);
@@ -100,6 +100,10 @@ final class DefaultWebServerRootsProvider extends WebServerRootsProvider {
else if (fileIndex.isInLibraryClasses(file)) {
root = fileIndex.getClassRootForFile(file);
}
+ else {
+ // excluded
+ return null;
+ }
assert root != null : file.getPresentableUrl();
return new PathInfo(file, root, getModuleNameQualifier(project, fileIndex.getModuleForFile(file)));
}
diff --git a/xml/relaxng/src/resources/html5-schema/html5-svg-mathml.rnc b/xml/relaxng/src/resources/html5-schema/html5-svg-mathml.rnc
index fadc971d2bb4..fe154b8f57bf 100644
--- a/xml/relaxng/src/resources/html5-schema/html5-svg-mathml.rnc
+++ b/xml/relaxng/src/resources/html5-schema/html5-svg-mathml.rnc
@@ -10,8 +10,6 @@ common.elem.phrasing |= math
SVG.foreignObject.content |=
( math
- | html.elem
- | body.elem
| common.inner.flow
)
diff --git a/xml/relaxng/src/resources/html5-schema/html5/applications.rnc b/xml/relaxng/src/resources/html5-schema/html5/applications.rnc
index ac07294db29c..2a592fbbd781 100755
--- a/xml/relaxng/src/resources/html5-schema/html5/applications.rnc
+++ b/xml/relaxng/src/resources/html5-schema/html5/applications.rnc
@@ -377,6 +377,7 @@ datatypes w = "http://whattf.org/datatype-draft"
| common.attrs.aria.role.combobox
| common.attrs.aria.role.dialog
| common.attrs.aria.role.directory
+ | common.attrs.aria.role.group
| common.attrs.aria.role.heading
| common.attrs.aria.role.img
| common.attrs.aria.role.link
@@ -425,7 +426,16 @@ datatypes w = "http://whattf.org/datatype-draft"
( common.attrs
& ( common.attrs.aria.role.presentation
| common.attrs.aria.role.menuitem
+ | common.attrs.aria.role.button
)?
)
summary.inner =
- ( common.inner.phrasing )
+ ( common.inner.phrasing
+ | h1.elem
+ | h2.elem
+ | h3.elem
+ | h4.elem
+ | h5.elem
+ | h6.elem
+ | hgroup.elem
+ )
diff --git a/xml/relaxng/src/resources/html5-schema/html5/aria.rnc b/xml/relaxng/src/resources/html5-schema/html5/aria.rnc
index b1035a0fa2a6..cf412e5f4ace 100755
--- a/xml/relaxng/src/resources/html5-schema/html5/aria.rnc
+++ b/xml/relaxng/src/resources/html5-schema/html5/aria.rnc
@@ -133,15 +133,7 @@ common.attrs.aria.implicit.toolbar |=
& aria.prop.activedescendant?
)
-common.attrs.aria.implicit.columnheader |=
- ( aria.prop.sort?
- & aria.prop.readonly?
- & aria.prop.required?
- & aria.state.selected?
- & aria.state.expanded?
- )
-
-common.attrs.aria.implicit.rowheader |=
+common.attrs.aria.implicit.column-or-row-header |=
( aria.prop.sort?
& aria.prop.readonly?
& aria.prop.required?
diff --git a/xml/relaxng/src/resources/html5-schema/html5/block.rnc b/xml/relaxng/src/resources/html5-schema/html5/block.rnc
index 2fd2d233c71b..de3b5a54ee2d 100755
--- a/xml/relaxng/src/resources/html5-schema/html5/block.rnc
+++ b/xml/relaxng/src/resources/html5-schema/html5/block.rnc
@@ -112,6 +112,7 @@ datatypes w = "http://whattf.org/datatype-draft"
& ol.attrs.reversed?
& ol.attrs.type?
& ( ( common.attrs.aria.role.directory
+ | common.attrs.aria.role.group
| common.attrs.aria.role.list
| common.attrs.aria.role.listbox
| common.attrs.aria.role.menu
diff --git a/xml/relaxng/src/resources/html5-schema/html5/common.rnc b/xml/relaxng/src/resources/html5-schema/html5/common.rnc
index 9f1e65673bd2..09afb1454233 100755
--- a/xml/relaxng/src/resources/html5-schema/html5/common.rnc
+++ b/xml/relaxng/src/resources/html5-schema/html5/common.rnc
@@ -113,9 +113,7 @@ common.attrs =
)
common.attrs.basic =
- ( ( common.attrs.id
- | common.attrs.xml-id
- )? # REVISIT assuming only either one is allowed
+ ( common.attrs.id?
& common.attrs.class?
& common.attrs.title?
& common.attrs.base?
@@ -125,10 +123,6 @@ common.attrs.basic =
attribute id {
common.data.id
}
- common.attrs.xml-id =
- attribute xml:id {
- xsd:NCName
- } & XMLonly
common.attrs.class =
attribute class {
common.data.tokens
@@ -387,6 +381,10 @@ common.attrs.other =
common.data.keylabellist =
w:keylabellist
+## List of Source Sizes
+ common.data.source.size.list =
+ w:source-size-list
+
## Microdata Properties
common.data.microdata-properties =
list { w:microdata-property+ }
@@ -466,7 +464,7 @@ common.attrs.aria.implicit.article = ( notAllowed )
common.attrs.aria.implicit.banner = ( notAllowed )
common.attrs.aria.implicit.button = ( notAllowed )
common.attrs.aria.implicit.checkbox = ( notAllowed )
-common.attrs.aria.implicit.columnheader = ( notAllowed )
+common.attrs.aria.implicit.column-or-row-header = ( notAllowed )
common.attrs.aria.implicit.combobox = ( notAllowed )
common.attrs.aria.implicit.complementary = ( notAllowed )
common.attrs.aria.implicit.contentinfo = ( notAllowed )
@@ -486,7 +484,6 @@ common.attrs.aria.implicit.option = ( notAllowed )
common.attrs.aria.implicit.progressbar = ( notAllowed )
common.attrs.aria.implicit.radio = ( notAllowed )
common.attrs.aria.implicit.region = ( notAllowed )
-common.attrs.aria.implicit.rowheader = ( notAllowed )
common.attrs.aria.implicit.section = ( notAllowed )
common.attrs.aria.implicit.select = ( notAllowed )
common.attrs.aria.implicit.slider = ( notAllowed )
diff --git a/xml/relaxng/src/resources/html5-schema/html5/core-scripting.rnc b/xml/relaxng/src/resources/html5-schema/html5/core-scripting.rnc
index bef6bf107423..eb08c2ed5bb7 100755
--- a/xml/relaxng/src/resources/html5-schema/html5/core-scripting.rnc
+++ b/xml/relaxng/src/resources/html5-schema/html5/core-scripting.rnc
@@ -15,6 +15,7 @@ datatypes w = "http://whattf.org/datatype-draft"
( common.attrs
& script.attrs.type?
& script.attrs.language? # restricted in Schematron
+ & embedded.content.attrs.crossorigin?
& ( common.attrs.aria.role.presentation
| common.attrs.aria.role.menuitem
)?
@@ -29,6 +30,7 @@ datatypes w = "http://whattf.org/datatype-draft"
& script.attrs.type?
& script.attrs.charset?
& script.attrs.language? # restricted in Schematron
+ & embedded.content.attrs.crossorigin?
& ( common.attrs.aria.role.presentation
| common.attrs.aria.role.menuitem
)?
diff --git a/xml/relaxng/src/resources/html5-schema/html5/embed.rnc b/xml/relaxng/src/resources/html5-schema/html5/embed.rnc
index 51a2f0acb7a6..be4204914fa8 100755
--- a/xml/relaxng/src/resources/html5-schema/html5/embed.rnc
+++ b/xml/relaxng/src/resources/html5-schema/html5/embed.rnc
@@ -15,12 +15,15 @@ namespace local = ""
img.attrs =
( common.attrs
& img.attrs.src
+ & img.attrs.srcset?
+ & img.attrs.sizes?
& img.attrs.alt? # ARIA: if alt empty, only allowed role value is "presentation"; check in assertions
& img.attrs.height?
& img.attrs.width?
& img.attrs.usemap?
& img.attrs.ismap?
& img.attrs.border? # obsolete
+ & embedded.content.attrs.crossorigin?
& ( common.attrs.aria.implicit.img
| common.attrs.aria
)?
@@ -29,6 +32,14 @@ namespace local = ""
attribute src {
common.data.uri.non-empty
}
+ img.attrs.srcset =
+ attribute srcset {
+ string
+ } & v5only
+ img.attrs.sizes =
+ attribute sizes {
+ common.data.source.size.list
+ } & v5only
img.attrs.alt =
attribute alt {
text
@@ -58,6 +69,54 @@ namespace local = ""
common.elem.phrasing |= img.elem
+## Image with multiple sources: <picture>
+
+ picture.elem =
+ element picture { picture.inner & picture.attrs }
+ & v5only
+ picture.attrs =
+ ( common.attrs )
+ picture.inner =
+ ( ( source.picture.elem*
+ & common.elem.script-supporting*
+ ),
+ ( img.elem
+ & common.elem.script-supporting*
+ )
+ )
+
+ common.elem.phrasing |= picture.elem
+
+## Picture source: <source srcset>
+
+ source.picture.elem =
+ element source { source.picture.inner & source.picture.attrs }
+ source.picture.attrs =
+ ( common.attrs
+ & source.picture.attrs.media?
+ & source.picture.attrs.srcset
+ & source.picture.attrs.sizes?
+ & source.picture.attrs.type?
+ )
+ source.picture.attrs.media =
+ attribute media {
+ common.data.mediaquery
+ }
+ source.picture.attrs.srcset =
+ attribute srcset {
+ string
+ }
+ source.picture.attrs.sizes =
+ attribute sizes {
+ common.data.source.size.list
+ }
+ source.picture.attrs.type =
+ attribute type {
+ common.data.mimetype
+ }
+ source.picture.inner =
+ ( empty )
+
## Plug-ins: <embed>
embed.elem =
@@ -72,6 +131,7 @@ namespace local = ""
& ( common.attrs.aria.landmark.application
| common.attrs.aria.landmark.document
| common.attrs.aria.role.img
+ | common.attrs.aria.role.presentation
)?
)
embed.attrs.src =
@@ -292,6 +352,7 @@ namespace local = ""
& ( common.attrs.aria.landmark.application
| common.attrs.aria.landmark.document
| common.attrs.aria.role.img
+ | common.attrs.aria.role.presentation
)?
)
object.attrs.data =
@@ -370,6 +431,7 @@ namespace local = ""
& ( common.attrs.aria.landmark.application
| common.attrs.aria.landmark.document
| common.attrs.aria.role.img
+ | common.attrs.aria.role.presentation
)?
)
iframe.attrs.src =
@@ -548,7 +610,7 @@ namespace local = ""
w:string "allowfullscreen" | w:string ""
} & v5only
iframe.inner =
- ( text )
+ ( ( text & HTMLonly ) | empty )
common.elem.phrasing |= iframe.elem
@@ -655,3 +717,10 @@ namespace local = ""
( empty )
common.elem.phrasing |= area.elem
+
+## Attributes Common to Embedded Content
+
+ embedded.content.attrs.crossorigin =
+ attribute crossorigin {
+ w:string "anonymous" | w:string "use-credentials" | w:string ""
+ } & v5only
diff --git a/xml/relaxng/src/resources/html5-schema/html5/legacy.rnc b/xml/relaxng/src/resources/html5-schema/html5/legacy.rnc
index e64f77068455..3d6f1c1930ef 100644
--- a/xml/relaxng/src/resources/html5-schema/html5/legacy.rnc
+++ b/xml/relaxng/src/resources/html5-schema/html5/legacy.rnc
@@ -812,6 +812,12 @@ datatypes w = "http://whattf.org/datatype-draft"
}
object.attrs &= object.attrs.border?
+ table.attrs.border =
+ attribute border {
+ string
+ }
+ table.attrs &= table.attrs.border?
+
## cellpadding attribute
table.attrs.cellpadding =
diff --git a/xml/relaxng/src/resources/html5-schema/html5/media.rnc b/xml/relaxng/src/resources/html5-schema/html5/media.rnc
index 04072ecc1036..28cbb630bb39 100755
--- a/xml/relaxng/src/resources/html5-schema/html5/media.rnc
+++ b/xml/relaxng/src/resources/html5-schema/html5/media.rnc
@@ -14,6 +14,7 @@ datatypes w = "http://whattf.org/datatype-draft"
& media.attrs.loop?
& media.attrs.mediagroup?
& media.attrs.muted?
+ & embedded.content.attrs.crossorigin?
)
media.attrs.autoplay =
attribute autoplay {
@@ -48,7 +49,6 @@ datatypes w = "http://whattf.org/datatype-draft"
( common.attrs
& source.attrs.src
& source.attrs.type?
- & source.attrs.media?
& ( common.attrs.aria.role.presentation
| common.attrs.aria.role.menuitem
)?
@@ -61,10 +61,6 @@ datatypes w = "http://whattf.org/datatype-draft"
attribute type {
common.data.mimetype
}
- source.attrs.media =
- attribute media {
- common.data.mediaquery
- }
source.inner =
( empty )
diff --git a/xml/relaxng/src/resources/html5-schema/html5/meta.rnc b/xml/relaxng/src/resources/html5-schema/html5/meta.rnc
index b5e810a0d46f..898a130ec6ed 100755
--- a/xml/relaxng/src/resources/html5-schema/html5/meta.rnc
+++ b/xml/relaxng/src/resources/html5-schema/html5/meta.rnc
@@ -164,6 +164,7 @@ datatypes w = "http://whattf.org/datatype-draft"
& shared-hyperlink.attrs.type?
& link.attrs.sizes?
# link.attrs.title included in common.attrs
+ & embedded.content.attrs.crossorigin?
& ( common.attrs.aria.role.link
| common.attrs.aria.role.presentation
| common.attrs.aria.role.menuitem
diff --git a/xml/relaxng/src/resources/html5-schema/html5/microdata.rnc b/xml/relaxng/src/resources/html5-schema/html5/microdata.rnc
index 076a4ded1dad..91616c846147 100644
--- a/xml/relaxng/src/resources/html5-schema/html5/microdata.rnc
+++ b/xml/relaxng/src/resources/html5-schema/html5/microdata.rnc
@@ -25,7 +25,7 @@ common.attrs.microdata =
}
common.attrs.microdata.itemtype =
attribute itemtype {
- common.data.uri.absolute
+ list { common.data.uri.absolute+ }
}
common.attrs.microdata.itemid =
attribute itemid {
@@ -58,6 +58,7 @@ base.attrs &= common.attrs.microdata
& shared-hyperlink.attrs.type?
& link.attrs.sizes?
# link.attrs.title included in common.attrs
+ & embedded.content.attrs.crossorigin?
& ( common.attrs.aria.role.link
| common.attrs.aria.role.presentation
| common.attrs.aria.role.menuitem
diff --git a/xml/relaxng/src/resources/html5-schema/html5/rdfa.rnc b/xml/relaxng/src/resources/html5-schema/html5/rdfa.rnc
index b8513d716093..3c849d98a954 100644
--- a/xml/relaxng/src/resources/html5-schema/html5/rdfa.rnc
+++ b/xml/relaxng/src/resources/html5-schema/html5/rdfa.rnc
@@ -1,5 +1,5 @@
nonRDFaLite = empty
-# #####################################################################
+# #####################################################################
## RELAX NG Schema for HTML 5: RDFa 1.1 and RDFa Lite 1.1 #
# #####################################################################
@@ -9,12 +9,12 @@ nonRDFaLite = empty
common.data.rdfa.safecurie =
xsd:string {
- pattern = "\[(([\i-[:]][\c-[:]]*)?:)?[^\s]+\]"
- minLength = "3"
+ pattern = "\[(([\i-[:]][\c-[:]]*)?:?)[^\s]*\]"
+ minLength = "2"
}
common.data.rdfa.curie =
xsd:string {
- pattern = "(([\i-[:]][\c-[:]]*)?:)?[^\s]+"
+ pattern = "(([\i-[:]][\c-[:]]*)?:)[^\s]*"
minLength = "1"
}
common.data.rdfa.term =
@@ -182,15 +182,11 @@ link.rdfa.attrs.metadata =
& common.attrs.present
& common.attrs.other
& ( ( common.attrs.rdfa.property
- & ( link.attrs.rel
- | common.attrs.rdfa.rel
- )?
+ & link.attrs.rel?
)
|
( common.attrs.rdfa.property?
- & ( link.attrs.rel
- | common.attrs.rdfa.rel
- )
+ & link.attrs.rel
)
)
& link.attrs.href
@@ -208,6 +204,11 @@ link.rdfa.attrs.metadata =
& shared-hyperlink.attrs.type?
& link.attrs.sizes?
# link.attrs.title included in common.attrs
+ & embedded.content.attrs.crossorigin?
+ & ( common.attrs.aria.role.link
+ | common.attrs.aria.role.presentation
+ | common.attrs.aria.role.menuitem
+ )?
)
link.rdfa.attrs.phrasing =
( common.attrs.basic
@@ -215,9 +216,7 @@ link.rdfa.attrs.phrasing =
& common.attrs.present
& common.attrs.other
& common.attrs.rdfa.property
- & ( link.attrs.rel
- | common.attrs.rdfa.rel
- )?
+ & link.attrs.rel?
& ( ( common.attrs.rdfa.resource
& link.attrs.href?
)
@@ -239,6 +238,11 @@ link.rdfa.attrs.phrasing =
& shared-hyperlink.attrs.type?
& link.attrs.sizes?
# link.attrs.title included in common.attrs
+ & embedded.content.attrs.crossorigin?
+ & ( common.attrs.aria.role.link
+ | common.attrs.aria.role.presentation
+ | common.attrs.aria.role.menuitem
+ )?
)
common.elem.metadata |= link.rdfa.elem.metadata
common.elem.phrasing |= link.rdfa.elem.phrasing
diff --git a/xml/relaxng/src/resources/html5-schema/html5/tables.rnc b/xml/relaxng/src/resources/html5-schema/html5/tables.rnc
index 2aecbcfc7a4e..b6021dac22dd 100755
--- a/xml/relaxng/src/resources/html5-schema/html5/tables.rnc
+++ b/xml/relaxng/src/resources/html5-schema/html5/tables.rnc
@@ -50,13 +50,8 @@ datatypes w = "http://whattf.org/datatype-draft"
element table { table.inner & table.attrs }
table.attrs =
( common.attrs
- & table.attrs.border?
& common.attrs.aria?
)
- table.attrs.border =
- attribute border {
- string
- }
table.inner =
( caption.elem?
, common.elem.script-supporting*
@@ -84,9 +79,7 @@ datatypes w = "http://whattf.org/datatype-draft"
element caption { caption.inner & caption.attrs }
caption.attrs =
( common.attrs
- & ( common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
+ & common.attrs.aria?
)
caption.inner =
( common.inner.flow )
@@ -100,9 +93,7 @@ datatypes w = "http://whattf.org/datatype-draft"
element colgroup { colgroup.inner & colgroup.attrs }
colgroup.attrs =
( common.attrs
- & ( common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
+ & common.attrs.aria?
)
colgroup.attrs.span =
attribute span {
@@ -122,9 +113,7 @@ datatypes w = "http://whattf.org/datatype-draft"
col.attrs =
( common.attrs
& col.attrs.span?
- & ( common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
+ & common.attrs.aria?
)
col.attrs.span =
attribute span {
@@ -139,9 +128,7 @@ datatypes w = "http://whattf.org/datatype-draft"
element thead { thead.inner & thead.attrs }
thead.attrs =
( common.attrs
- & ( common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
+ & common.attrs.aria?
)
thead.inner =
( tr.elem*
@@ -154,9 +141,7 @@ datatypes w = "http://whattf.org/datatype-draft"
element tfoot { tfoot.inner & tfoot.attrs }
tfoot.attrs =
( common.attrs
- & ( common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
+ & common.attrs.aria?
)
tfoot.inner =
( tr.elem*
@@ -169,9 +154,7 @@ datatypes w = "http://whattf.org/datatype-draft"
element tbody { tbody.inner & tbody.attrs }
tbody.attrs =
( common.attrs
- & ( common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
+ & common.attrs.aria?
)
tbody.inner =
( tr.elem*
@@ -253,7 +236,9 @@ datatypes w = "http://whattf.org/datatype-draft"
& tables.attrs.scope?
& tables.attrs.headers?
# & tables.attrs.alignment
- & common.attrs.aria?
+ & ( common.attrs.aria?
+ | common.attrs.aria.implicit.column-or-row-header
+ )
)
th.inner =
( common.inner.flow )
diff --git a/xml/relaxng/src/resources/html5-schema/legacy/legacy.rnc b/xml/relaxng/src/resources/html5-schema/legacy/legacy.rnc
index e64f77068455..3d6f1c1930ef 100644
--- a/xml/relaxng/src/resources/html5-schema/legacy/legacy.rnc
+++ b/xml/relaxng/src/resources/html5-schema/legacy/legacy.rnc
@@ -812,6 +812,12 @@ datatypes w = "http://whattf.org/datatype-draft"
}
object.attrs &= object.attrs.border?
+ table.attrs.border =
+ attribute border {
+ string
+ }
+ table.attrs &= table.attrs.border?
+
## cellpadding attribute
table.attrs.cellpadding =
diff --git a/xml/relaxng/src/resources/html5-schema/svg11/svg-basic-font.rnc b/xml/relaxng/src/resources/html5-schema/svg11/svg-basic-font.rnc
index 32eb1460f564..94f5b7fa3121 100644
--- a/xml/relaxng/src/resources/html5-schema/svg11/svg-basic-font.rnc
+++ b/xml/relaxng/src/resources/html5-schema/svg11/svg-basic-font.rnc
@@ -97,7 +97,7 @@ grammar {
attribute overline-thickness { Number.datatype }?
a:documentation [ "\x{a}" ~ " glyph: Glyph Element\x{a}" ~ " " ]
SVG.glyph.class = notAllowed
- SVG.glyph.content = SVG.Description.class*, SVG.glyph.class*
+ SVG.glyph.content = SVG.Description.class* | SVG.glyph.class*
glyph = element glyph { attlist.glyph, SVG.glyph.content }
attlist.glyph &=
SVG.Core.attrib,
@@ -120,7 +120,7 @@ grammar {
]
SVG.missing-glyph.class = notAllowed
SVG.missing-glyph.content =
- SVG.Description.class*, SVG.missing-glyph.class*
+ SVG.Description.class* | SVG.missing-glyph.class*
missing-glyph =
element missing-glyph {
attlist.missing-glyph, SVG.missing-glyph.content
diff --git a/xml/relaxng/src/resources/html5-schema/svg11/svg-conditional.rnc b/xml/relaxng/src/resources/html5-schema/svg11/svg-conditional.rnc
index 22f3cc23b1d9..ecb3e154aded 100644
--- a/xml/relaxng/src/resources/html5-schema/svg11/svg-conditional.rnc
+++ b/xml/relaxng/src/resources/html5-schema/svg11/svg-conditional.rnc
@@ -62,8 +62,7 @@ grammar {
| SVG.Conditional.class
| SVG.Image.class
| SVG.Shape.class
- | SVG.Hyperlink.class
- | SVG.Extensibility.class)*
+ | SVG.Hyperlink.class)*
switch = element switch { attlist.switch, SVG.switch.content }
attlist.switch &=
SVG.Core.attrib,
diff --git a/xml/relaxng/src/resources/html5-schema/svg11/svg-extensibility.rnc b/xml/relaxng/src/resources/html5-schema/svg11/svg-extensibility.rnc
index 2f075b4c2cec..ba3316ad160b 100644
--- a/xml/relaxng/src/resources/html5-schema/svg11/svg-extensibility.rnc
+++ b/xml/relaxng/src/resources/html5-schema/svg11/svg-extensibility.rnc
@@ -57,3 +57,14 @@ foreignElement =
| text
| foreignElement)*
}
+SVG.a.content &= SVG.Extensibility.class*
+SVG.defs.content &= SVG.Extensibility.class*
+SVG.glyph.content &= SVG.Extensibility.class*
+SVG.g.content &= SVG.Extensibility.class*
+SVG.marker.content &= SVG.Extensibility.class*
+SVG.mask.content &= SVG.Extensibility.class*
+SVG.missing-glyph.content &= SVG.Extensibility.class*
+SVG.pattern.content &= SVG.Extensibility.class*
+SVG.svg.content &= SVG.Extensibility.class*
+SVG.switch.content &= SVG.Extensibility.class*
+SVG.symbol.content &= SVG.Extensibility.class*
diff --git a/xml/relaxng/src/resources/patches/0004_ping.patch b/xml/relaxng/src/resources/patches/0004_ping.patch
index 6f825ac4a2e0..4e47a934c7d6 100644
--- a/xml/relaxng/src/resources/patches/0004_ping.patch
+++ b/xml/relaxng/src/resources/patches/0004_ping.patch
@@ -7,7 +7,7 @@
- shared-hyperlink.attrs.ping =
- attribute ping {
- common.data.uris
-- } & v5only & nonW3C
+- } & v5only
## Emphatic Stress: <em>
diff --git a/xml/relaxng/src/resources/patches/patch_build.patch b/xml/relaxng/src/resources/patches/patch_build.patch
index ba4c30769bd0..88e4148c2420 100644
--- a/xml/relaxng/src/resources/patches/patch_build.patch
+++ b/xml/relaxng/src/resources/patches/patch_build.patch
@@ -1,7 +1,8 @@
-diff -r dd84d714a0da build.py
---- a/build.py Fri Oct 25 13:00:39 2013 +0900
-+++ b/build.py Fri Jan 24 13:53:06 2014 +0400
-@@ -147,8 +147,8 @@
+diff --git a/build.py b/build.py
+index ac7ecb3..db7de9c 100755
+--- a/build.py
++++ b/build.py
+@@ -153,13 +153,13 @@ dependencyJars = runDependencyJars + buildOnlyDependencyJars
moduleNames = [
"syntax",
@@ -10,9 +11,18 @@ diff -r dd84d714a0da build.py
+ # "util",
+ # "xmlparser",
"validator",
+- "jing-trang",
+- "htmlparser",
+- "nu-validator-site",
+- "tests",
++ # "jing-trang",
++ # "htmlparser",
++ # "nu-validator-site",
++ # "tests",
]
-@@ -875,19 +875,19 @@
+ javaSafeNamePat = re.compile(r'[^a-zA-Z0-9]')
+@@ -926,19 +926,19 @@ def downloadDependencies():
downloadDependency(url, md5sum)
def buildAll():
@@ -42,36 +52,5 @@ diff -r dd84d714a0da build.py
+ # buildXmlParser()
+ # buildValidator()
- def hgCloneOrUpdate(mod, baseUrl):
+ def gitCloneOrUpdate(mod, baseUrl):
if os.path.exists(mod):
-@@ -925,18 +925,18 @@
- # XXX root dir
- for mod in moduleNames:
- hgCloneOrUpdate(mod, hgRoot)
-- gitCloneOrUpdate("nu-validator-site", gitRoot)
-- runCmd('"%s" co http://jing-trang.googlecode.com/svn/branches/validator-nu jing-trang' % (svnCmd))
-- hgCloneOrUpdate("htmlparser", parserHgRoot)
-- testsRemote = "https://github.com/validator/tests.git"
-- testsBranch = "master"
-- testsDir = "tests"
-- if os.path.exists(testsDir):
-- os.chdir(testsDir)
-- runCmd('"%s" pull %s %s' % (gitCmd, testsRemote, testsBranch))
-- os.chdir("..")
-- else:
-- runCmd('"%s" clone %s %s' % (gitCmd, testsRemote, testsDir))
-+ # gitCloneOrUpdate("nu-validator-site", gitRoot)
-+ # runCmd('"%s" co http://jing-trang.googlecode.com/svn/branches/validator-nu jing-trang' % (svnCmd))
-+ # hgCloneOrUpdate("htmlparser", parserHgRoot)
-+ # testsRemote = "https://github.com/validator/tests.git"
-+ # testsBranch = "master"
-+ # testsDir = "tests"
-+ # if os.path.exists(testsDir):
-+ # os.chdir(testsDir)
-+ # runCmd('"%s" pull %s %s' % (gitCmd, testsRemote, testsBranch))
-+ # os.chdir("..")
-+ # else:
-+ # runCmd('"%s" clone %s %s' % (gitCmd, testsRemote, testsDir))
-
- def selfUpdate():
- hgCloneOrUpdate("build", hgRoot)
diff --git a/xml/relaxng/src/resources/update_html5_schema.sh b/xml/relaxng/src/resources/update_html5_schema.sh
index 299129868253..20d28e53762e 100755
--- a/xml/relaxng/src/resources/update_html5_schema.sh
+++ b/xml/relaxng/src/resources/update_html5_schema.sh
@@ -11,9 +11,9 @@ mkdir temp
cd temp
echo ">>>>> Preparing validator build"
-hg clone https://bitbucket.org/validator/build build
+git clone https://github.com/validator/build build
cd build
-hg import "$PATCHES/patch_build.patch" --no-commit
+git apply "$PATCHES/patch_build.patch"
cd ..
echo
diff --git a/xml/tests/src/com/intellij/psi/formatter/XmlFormatterTestCase.java b/xml/tests/src/com/intellij/psi/formatter/XmlFormatterTestCase.java
index d0600b52b34f..064fb0e7efbf 100644
--- a/xml/tests/src/com/intellij/psi/formatter/XmlFormatterTestCase.java
+++ b/xml/tests/src/com/intellij/psi/formatter/XmlFormatterTestCase.java
@@ -27,7 +27,7 @@ public abstract class XmlFormatterTestCase extends FormatterTestCase{
public void testDontKeepLineBreaksInText() throws Throwable {
final CodeStyleSettings settings = getSettings();
final XmlCodeStyleSettings xmlSettings = settings.getCustomSettings(XmlCodeStyleSettings.class);
- settings.RIGHT_MARGIN = 15;
+ settings.setDefaultRightMargin(15);
settings.HTML_KEEP_LINE_BREAKS_IN_TEXT = false;
xmlSettings.XML_KEEP_LINE_BREAKS_IN_TEXT = false;
diff --git a/xml/xml-psi-api/src/com/intellij/psi/XmlRecursiveElementWalkingVisitor.java b/xml/xml-psi-api/src/com/intellij/psi/XmlRecursiveElementWalkingVisitor.java
new file mode 100644
index 000000000000..490eb62eb75e
--- /dev/null
+++ b/xml/xml-psi-api/src/com/intellij/psi/XmlRecursiveElementWalkingVisitor.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.
+ */
+
+/*
+ * @author max
+ */
+package com.intellij.psi;
+
+import java.util.List;
+
+public class XmlRecursiveElementWalkingVisitor extends XmlElementVisitor {
+ private final boolean myVisitAllFileRoots;
+ private final PsiWalkingState myWalkingState = new PsiWalkingState(this){};
+
+ public XmlRecursiveElementWalkingVisitor() {
+ this(false);
+ }
+
+ public XmlRecursiveElementWalkingVisitor(final boolean visitAllFileRoots) {
+ myVisitAllFileRoots = visitAllFileRoots;
+ }
+
+ @Override
+ public void visitElement(final PsiElement element) {
+ myWalkingState.elementStarted(element);
+ }
+
+ @Override
+ public void visitFile(final PsiFile file) {
+ if (myVisitAllFileRoots) {
+ final FileViewProvider viewProvider = file.getViewProvider();
+ final List<PsiFile> allFiles = viewProvider.getAllFiles();
+ if (allFiles.size() > 1) {
+ if (file == viewProvider.getPsi(viewProvider.getBaseLanguage())) {
+ for (PsiFile lFile : allFiles) {
+ lFile.acceptChildren(this);
+ }
+ return;
+ }
+ }
+ }
+
+ super.visitFile(file);
+ }
+} \ No newline at end of file
diff --git a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/xml/XmlAttributeReference.java b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/xml/XmlAttributeReference.java
index 44eec73d35f7..96408374c669 100644
--- a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/xml/XmlAttributeReference.java
+++ b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/xml/XmlAttributeReference.java
@@ -22,7 +22,6 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiReference;
import com.intellij.psi.meta.PsiMetaOwner;
import com.intellij.psi.xml.XmlAttribute;
-import com.intellij.psi.xml.XmlTag;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.xml.XmlAttributeDescriptor;
@@ -35,12 +34,7 @@ public class XmlAttributeReference implements PsiReference {
private final NullableLazyValue<XmlAttributeDescriptor> myDescriptor = new NullableLazyValue<XmlAttributeDescriptor>() {
@Override
protected XmlAttributeDescriptor compute() {
- XmlTag parent = myAttribute.getParent();
- final XmlElementDescriptor descr = parent.getDescriptor();
- if (descr != null) {
- return descr.getAttributeDescriptor(myAttribute);
- }
- return null;
+ return myAttribute.getDescriptor();
}
};
private final XmlAttributeImpl myAttribute;